How can I get a function's name by its pointer in Lua? - debugging

In Lua I've created a pretty printer for my tables/objects. However, when a function is displayed, it's shown as a pointer.
I've been reading up on Lua Introspection but when I introspect the function with debug.getinfo() it won't return the function's name. This seems to be due to a scoping issue but I'm not sure how to get around it.
What is the best way to get a function's name using its pointer? (I understand functions are first class citizens in Lua and that they can be created anonymously, that's fine)

when you create the functions, register them in a table, using them as keys.
local tableNames = {}
function registerFunction(f, name)
tableNames[f] = name
end
function getFunctionName(f)
return tableNames[f]
end
...
function foo()
..
end
registerFunction(foo, "foo")
...
getFunctionName(foo) -- will return "foo"

For some reason, it seems to work only with number parameters (that is, active functions on the stack).
The script
function a() return debug.getinfo(1,'n') end
function prettyinfo(info)
for k,v in pairs(info) do print(k,v) end
end
prettyinfo(a())
prints
name a
namewhat global
but if I change the last line to
prettyinfo(debug.getinfo(a, 'n'))
it gives me only an empty string:
namewhat

Related

How to use a certain set of values for typing in Python

I need to specify a certain set of values as the expected return type for my function. Let's say there was defined some class called Scene which has attribute name which is supposed to be a string which may end only with "1K", "2K" or "4K". Now I want to write a function which takes this class as an argument and returns the last 2 characters of its name as a string. Is there a way to specify this function return type like a set of exact string values using built-in modules in Python 3.7.7? Something like this:
def scene_resolution(sc : Scene): -> any value in {'1K', '2K', '4K'}: # return type?
res = sc.name[-2:]
assert res in {'1K', '2K', '4K'}
return res
I know about using Literal from typing_extensions, but unfortunately it works only with Python 3.8 and higher, and the API of the soft I'm dealing with uses Python 3.7.7. I've also tried to make something with enum.Enum but could not make it work properly.
Do you have any suggestions?
UPD. The only way I found so far is to define some function that returns the set I need and use its name as expected return type. Not sure whether it is correct way and a good practice, but at least it works.

Inner function performance in lua

I have a list with special users and normal users. Special users have their own special func, while normal users use a standard func.
I came up with this code design, but I feel that this is not optimal (performance wise).
So my question is: How would I get the best performance when calling inner functions like the example below?
if something then
CallFunc(var)
end
Special/normal user logic
function CallFunc(var)
if table[name] then
table[name](var)
else
Standard_Func(var)
end
end
local table = {
["name1"] = function(var) Spec_Func1(var) end,
["name2"] = function(var) Spec_Func2(var) end,
["name3"] = function(var) Spec_Func3(var) end,
...
--40 more different names and different funcs
}
Special user funcs
function Spec_Func1(var)
--lots of code
end
function Spec_Func2(var)
--lots of code
end
...
--more funcs
EDIT:
see #hjpotter92's answer:
I cant find the user in the table.
local function_lookups = {
name1 = Spec_Func1, --this doesnt let me find the user
--name1 = 1 --this does let me find the user (test)
}
if function_lookups[name] then --this fails to find the user
--do something
end
You do not need another anonymous function. Simply use the lookup table as follows:
local function_lookups = {
name1 = Spec_Func1,
name2 = Spec_Func2,
name3 = Spec_Func3,
...
--40 more different names and different funcs
}
Do not use the variable name table. It is a library available in Lua itself, and you are overwriting it.
You don't need a special function at all! You can use a generic function that's behaviour depends on the caller! Lemme explain with a piece of code:
local Special = {Peter=function(caller)end} --Put the special users' functions in here
function Action(caller)
if Special[caller] then
Special[caller](caller)
else
print("Normal Action!")
end
end
So whenever a user does a certain action, you can fire this function and pass a caller argument, the function then does the work behind the scenes determining if the caller is special, and if so what to do.
This makes your code clean. It also makes it easier to add more than 2 user statuses!

"That name is not valid" for my VBA function in Excel/Mac

A simple VBA function. When I try to use it in my worksheet, all I get, no matter what I do, is "That name is not valid". I'm out of ideas.
Sub FindABV(temperature)
With Worksheets("Sheet1")
.Range("C28").GoalSeek _
Goal:=temperature, _
ChangingCell:=.Range("B28")
End With
FindABV = .Range("B28").Value
End Sub
I've tried creating a new Module to put it in. No change.
And no error indications from the code editor.
The Sub procedure performs a task and then returns control to the calling code, but it does not return a value to the calling code.
See more here.
This said, you cannot set a procedure equal to something:
FindABV = .Range("B28").Value
because that name is not valid (you cannot say that a procedure is equal to a certain value, it doesn't make sense). You probably wanted to use a Function to return the value of that cell calculated by the Goal Seeker depending on the input temperature that you pass by the function:
Function FindABV(temperature)
With Worksheets("Sheet1")
.Range("C28").GoalSeek _
Goal:=temperature, _
ChangingCell:=.Range("B28")
End With
FindABV = .Range("B28").Value '<-- return the value
End Function
However, be careful: if =FindABV(temperature) lies on Sheet1.Range("B28"), you will have a circular reference because your function will try to have the value of itself.
Your code will not deliver the results you want. If you want to have the Function work for different values than the ones stored in B28 and C28 you'll have to write it more like this:
Public Function FindABV(goalCell As Range, changeCell As Range, temperature As Double)
goalCell.GoalSeek Goal:=temperature, ChangingCell:=changeCell
FindABV = changeCell
End Function
But this doesn't matter in any case because GoalSeek actually changes the value in the ChangingCell which Excel will not do if it is called from within a Function.

Is there a hook for when anonymous classes are assigned to a constant?

I've been practicing some Ruby meta-programming recently, and was wondering about assigning anonymous classes to constants.
In Ruby, it is possible to create an anonymous class as follows:
anonymous_class = Class.new # => #<Class:0x007f9c5afb21d0>
New instances of this class can be created:
an_instance = anonymous_class.new # => #<#<Class:0x007f9c5afb21d0>:0x007f9c5afb0330>
Now, when the anonymous class is assigned to a constant, the class now has a proper name:
Foo = anonymous_class # => Foo
And the previously created instance is now also an instance of that class:
an_instance # => #<Foo:0x007f9c5afb0330>
My question: Is there a hook method for the moment when an anonymous class is assigned to a constant?
There are many hooks methods in Ruby, but I couldn't find this one.
Let's take a look at how constant assignment works internally. The code that follows is extracted from a source tarball of ruby-1.9.3-p0. First we look at the definition of the VM instruction setconstant (which is used to assign constants):
# /insns.def, line 239
DEFINE_INSN
setconstant
(ID id)
(VALUE val, VALUE cbase)
()
{
vm_check_if_namespace(cbase);
rb_const_set(cbase, id, val);
INC_VM_STATE_VERSION();
}
No chance to place a hook in vm_check_if_namespace or INC_VM_STATE_VERSION here. So we look at rb_const_set (variable.c:1886), the function that is called everytime a constant is assigned:
# /variable.c, line 1886
void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
VALUE visibility = CONST_PUBLIC;
# ...
check_before_mod_set(klass, id, val, "constant");
if (!RCLASS_CONST_TBL(klass)) {
RCLASS_CONST_TBL(klass) = st_init_numtable();
}
else {
# [snip], won't be called on first assignment
}
rb_vm_change_state();
ce = ALLOC(rb_const_entry_t);
ce->flag = (rb_const_flag_t)visibility;
ce->value = val;
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
}
I removed all the code that was not even called the first time a constant was assigned inside a module. I then looked into all the functions called by this one and didn't find a single point where we could place a hook from Ruby code. This means the hard truth is, unless I missed something, that there is no way to hook a constant assignment (at least in MRI).
Update
To clarify: The anonymous class does not magically get a new name as soon as it is assigned (as noted correctly in Andrew's answer). Rather, the constant name along with the object ID of the class is stored in Ruby's internal constant lookup table. If, after that, the name of the class is requested, it can now be resolved to a proper name (and not just Class:0xXXXXXXXX...).
So the best you can do to react to this assignment is to check the name of the class in a loop of a background worker thread until it is non-nil (which is a huge waste of resources, IMHO).
Anonymous classes don't actually get their name when they're assigned to a constant. They actually get it when they're next asked what their name is.
I'll try to find a reference for this. Edit: Can't find one, sorry.

Defining Lua methods as initialization

In the Lua language, I am able to define functions in a table with something such as
table = { myfunction = function(x) return x end }
I wondered if I can created methods this way, instead of having to do it like
function table:mymethod() ... end
I am fairly sure it is possible to add methods this way, but I am unsure of the proper name of this technique, and I cannot find it looking for "lua" and "methods" or such.
My intention is to pass a table to a function such as myfunction({data= stuff, name = returnedName, ?method?init() = stuff}).
Unfortunately I have tried several combinations with the colon method declaration but none of them is valid syntax.
So...anyone here happens to know?
Sure: table:method() is just syntactic sugar for table.method(self), but you have to take care of the self argument. If you do
tab={f=function(x)return x end }
then tab:f(x) won't work, as this actually is tab.f(tab,x) and thus will return tab instead of x.
You might take a look on the lua users wiki on object orientation or PiL chapter 16.

Resources