how to call a local function by its name?

classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

how to call a local function by its name?

Dmitry V. Zaitsev
example with table of functions:

local T = {}
function T.func1() print("func1") end
function T.func2() print("func2") end

local fn = { "func1", "func2", "func3" }

for i = 1, 3 do
local func_name = fn[i]
pcall(T[func_name])
end

it is work, but I'm interested in the ability to call a local function:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

for i = 1, 3 do
local func_name = fn[i]
pcall(func_name) -- ???
end

of course, I get an error "attempt to call a string value".
Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Brigham Toskin
Other than a name-to-function mapping table (like in your first example), I don't think there's a way to do this directly. You could use loadstring() to invoke a function by name, it has to be visible form the compiled function's context, which won't have access to your locals. It would also be inefficient, if you have to do this a lot.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
example with table of functions:

local T = {}
function T.func1() print("func1") end
function T.func2() print("func2") end

local fn = { "func1", "func2", "func3" }

for i = 1, 3 do
local func_name = fn[i]
pcall(T[func_name])
end

it is work, but I'm interested in the ability to call a local function:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

for i = 1, 3 do
local func_name = fn[i]
pcall(func_name) -- ???
end

of course, I get an error "attempt to call a string value".



--
Brigham Toskin
Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Nagaev Boris
In reply to this post by Dmitry V. Zaitsev
Hello Dmitry

On Mon, Jun 8, 2015 at 6:56 PM, Dmitry V. Zaitsev <[hidden email]> wrote:

> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }

Replace this line with

local fn = { func1, func, func3 }

>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".


Normally a local variable can't be accessed by its name as a string.
The workaround is debug.getlocal [1]

[1] http://www.lua.org/pil/23.1.1.html


--


Best regards,
Boris Nagaev

Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Paul K-2
In reply to this post by Dmitry V. Zaitsev
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:

> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".

Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Brigham Toskin
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin
Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Dmitry V. Zaitsev
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin

Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Brigham Toskin
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin
Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

aryajur
Is there a problem doing it this way: ?

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

On Mon, Jun 8, 2015 at 12:49 PM, Brigham Toskin <[hidden email]> wrote:
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin

Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Dmitry V. Zaitsev
if change "pcall(_ENV[func_name])" to "print(pcall(_ENV[func_name]))", then:

false attempt to call a nil value
false attempt to call a nil value
false attempt to call a nil value

2015-06-08 23:18 GMT+03:00 Milind Gupta <[hidden email]>:
Is there a problem doing it this way: ?

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

On Mon, Jun 8, 2015 at 12:49 PM, Brigham Toskin <[hidden email]> wrote:
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin


Reply | Threaded
Open this post in threaded view
|

Re: how to call a local function by its name?

Oliver Kroth
In reply to this post by aryajur
Yes,

the "local" in front of "func1" and "func2" has the effect that the names "func1" and "func2" are NOT members of _ENV. Instead they are converted to registers, i.e. anonymous stack offsets. Removing the "local":

function func1() print("
local func1") end
function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

should print

local func1
local func2

until you change the string literals, too :-)
pcall (null), which happens with calling pcall( _ENV( fn[3] ) is captured and returns false pus a string saying "attempt to call a nil value", which is ignored

--
Oliver


Am 08.06.2015 um 22:18 schrieb Milind Gupta:
Is there a problem doing it this way: ?

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

On Mon, Jun 8, 2015 at 12:49 PM, Brigham Toskin <[hidden email]> wrote:
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin


Reply | Threaded
Open this post in threaded view
|

[Proposal] _LOCAL was: Re: how to call a local function by its name?

Soni "They/Them" L.
I wish you could access your own locals with an _LOCAL[idx] that would be faster than debug.getlocal...

Not sure how that'd work if you local x = _LOCAL, or called a function with _LOCAL...

On 08/06/15 05:53 PM, Oliver Kroth wrote:
Yes,

the "local" in front of "func1" and "func2" has the effect that the names "func1" and "func2" are NOT members of _ENV. Instead they are converted to registers, i.e. anonymous stack offsets. Removing the "local":

function func1() print("
local func1") end
function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

should print

local func1
local func2

until you change the string literals, too :-)
pcall (null), which happens with calling pcall( _ENV( fn[3] ) is captured and returns false pus a string saying "attempt to call a nil value", which is ignored

--
Oliver


Am 08.06.2015 um 22:18 schrieb Milind Gupta:
Is there a problem doing it this way: ?

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

On Mon, Jun 8, 2015 at 12:49 PM, Brigham Toskin <[hidden email]> wrote:
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin



-- 
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.
Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Soni "They/Them" L.


On 08/06/15 06:05 PM, Soni L. wrote:
I wish you could access your own locals with an _LOCAL[idx] that would be faster than debug.getlocal...

Not sure how that'd work if you local x = _LOCAL, or called a function with _LOCAL...
Actually I do know, _LOCAL tables would be like any other tables, but heavily optimized for this kind of stuff, and it'd be part of the function's call stack entry thingy. The GC can take care of the rest.

-- 
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.

-- 
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.
Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Nagaev Boris
On Mon, Jun 8, 2015 at 9:09 PM, Soni L. <[hidden email]> wrote:

>
>
> On 08/06/15 06:05 PM, Soni L. wrote:
>
> I wish you could access your own locals with an _LOCAL[idx] that would be
> faster than debug.getlocal...
>
> Not sure how that'd work if you local x = _LOCAL, or called a function with
> _LOCAL...
>
> Actually I do know, _LOCAL tables would be like any other tables, but
> heavily optimized for this kind of stuff, and it'd be part of the function's
> call stack entry thingy. The GC can take care of the rest.

More things should not be used than are necessary.


>
>
> --
> Disclaimer: these emails are public and can be accessed from <TODO: get a
> non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.
>
>
> --
> Disclaimer: these emails are public and can be accessed from <TODO: get a
> non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.



--


Best regards,
Boris Nagaev

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Brigham Toskin
In reply to this post by Soni "They/Them" L.
Well you could implement this now with a metatable. It would probably just be faster as a global function getlocalbyname(name). Of course, this would be in terms of the debug interfaces, so it doesn't meet your "faster than debug.getlocal" requirement.

And consider the following: what happens if you insert a new key to the locals table?
> _LOCAL.foo = unpack -- allocates a local foo?
> _LOCAL[foo] = print -- allocates a local "named" by a function key?
> _LOCAL[1] = "bar" -- ???

On Mon, Jun 8, 2015 at 2:05 PM, Soni L. <[hidden email]> wrote:
I wish you could access your own locals with an _LOCAL[idx] that would be faster than debug.getlocal...

Not sure how that'd work if you local x = _LOCAL, or called a function with _LOCAL...

On 08/06/15 05:53 PM, Oliver Kroth wrote:
Yes,

the "local" in front of "func1" and "func2" has the effect that the names "func1" and "func2" are NOT members of _ENV. Instead they are converted to registers, i.e. anonymous stack offsets. Removing the "local":

function func1() print("
local func1") end
function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

should print

local func1
local func2

until you change the string literals, too :-)
pcall (null), which happens with calling pcall( _ENV( fn[3] ) is captured and returns false pus a string saying "attempt to call a nil value", which is ignored

--
Oliver


Am 08.06.2015 um 22:18 schrieb Milind Gupta:
Is there a problem doing it this way: ?

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

On Mon, Jun 8, 2015 at 12:49 PM, Brigham Toskin <[hidden email]> wrote:
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin



-- 
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.



--
Brigham Toskin
Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Soni "They/Them" L.


On 08/06/15 06:20 PM, Brigham Toskin wrote:
Well you could implement this now with a metatable. It would probably just be faster as a global function getlocalbyname(name). Of course, this would be in terms of the debug interfaces, so it doesn't meet your "faster than debug.getlocal" requirement.

And consider the following: what happens if you insert a new key to the locals table?
> _LOCAL.foo = unpack -- allocates a local foo?
errors ("attempt to use non-integer local")
> _LOCAL[foo] = print -- allocates a local "named" by a function key?
if "foo" is a number, see below
> _LOCAL[1] = "bar" -- ???
sets local (or temporary) 1 to "bar", whatever local (or temporary) 1 is. Or if local 1 is invalid, errors ("attempt to use out of bounds local")

On Mon, Jun 8, 2015 at 2:05 PM, Soni L. <[hidden email]> wrote:
I wish you could access your own locals with an _LOCAL[idx] that would be faster than debug.getlocal...

Not sure how that'd work if you local x = _LOCAL, or called a function with _LOCAL...

On 08/06/15 05:53 PM, Oliver Kroth wrote:
Yes,

the "local" in front of "func1" and "func2" has the effect that the names "func1" and "func2" are NOT members of _ENV. Instead they are converted to registers, i.e. anonymous stack offsets. Removing the "local":

function func1() print("
local func1") end
function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

should print

local func1
local func2

until you change the string literals, too :-)
pcall (null), which happens with calling pcall( _ENV( fn[3] ) is captured and returns false pus a string saying "attempt to call a nil value", which is ignored

--
Oliver


Am 08.06.2015 um 22:18 schrieb Milind Gupta:
Is there a problem doing it this way: ?

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2" }

for i = 1, 3 do
local func_name = fn[i]
pcall(_ENV[func_name])
end

On Mon, Jun 8, 2015 at 12:49 PM, Brigham Toskin <[hidden email]> wrote:
If it makes sense, you may be able to cache these as locals and/or upvalues in some cases for a speed bump. You'll have to decide if it fits your project architecture though, i.e. used several times after lookup, rather than completely dynamical at each call site.

On Mon, Jun 8, 2015 at 12:25 PM, Dmitry Zaitsev <[hidden email]> wrote:
Thanks to all. Indeed, the search for local names was rather slow in the case of frequent use, so I will use the table of functions from the first example.

2015-06-08 22:18 GMT+03:00 Brigham Toskin <[hidden email]>:
Oh, reflection. Yeah, forgot about that. Still, probably a bad idea to do this in a loop or frequently-called code, unless you're sure it won't bottleneck your code.

On Mon, Jun 8, 2015 at 12:13 PM, Paul K <[hidden email]> wrote:
> it is work, but I'm interested in the ability to call a local function:

You can iterate over local variables to find the one with the name you need:

local function func1() print("local func1") end
local function func2() print("local func2") end

local fn = { "func1", "func2", "func3" }

local function name2value(target)
  for i = 1, math.huge do
    local name, value = debug.getlocal(2, i)
    if not name then return end
    if name == target then return value end
  end
end

for i = 1, 3 do
  local func_name = fn[i]
  pcall(name2value(func_name) or error("can't find local "..func_name))
end

Paul.

On Mon, Jun 8, 2015 at 11:56 AM, Dmitry V. Zaitsev <[hidden email]> wrote:
> example with table of functions:
>
> local T = {}
> function T.func1() print("func1") end
> function T.func2() print("func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(T[func_name])
> end
>
> it is work, but I'm interested in the ability to call a local function:
>
> local function func1() print("local func1") end
> local function func2() print("local func2") end
>
> local fn = { "func1", "func2", "func3" }
>
> for i = 1, 3 do
> local func_name = fn[i]
> pcall(func_name) -- ???
> end
>
> of course, I get an error "attempt to call a string value".




--
Brigham Toskin




--
Brigham Toskin



-- 
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.



--
Brigham Toskin

-- 
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.
Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Coda Highland
In reply to this post by Soni "They/Them" L.
On Mon, Jun 8, 2015 at 2:09 PM, Soni L. <[hidden email]> wrote:

>
>
> On 08/06/15 06:05 PM, Soni L. wrote:
>
> I wish you could access your own locals with an _LOCAL[idx] that would be
> faster than debug.getlocal...
>
> Not sure how that'd work if you local x = _LOCAL, or called a function with
> _LOCAL...
>
> Actually I do know, _LOCAL tables would be like any other tables, but
> heavily optimized for this kind of stuff, and it'd be part of the function's
> call stack entry thingy. The GC can take care of the rest.

function locals()
return setmetatable({ [0]={} }, {
    __index = function(t, k)
            local ki = t[0][k]
            assert(ki, "attempt to read nonexistent local")
            local ln, lv = debug.getlocal(2, ki)
            assert(ln == k, "inconsistent state")
            return ln
        end,
    __newindex = function(t, k, v)
            local ki = t[0][k]
            if not ki then
                local i = 0
                while true do
                    i = i + 1
                    local ln, lv = debug.getlocal(2, i)
                    if ln == k then
                        ki = i
                        break
                    elif not ln then
                        break
                    end
                end
                assert(ki, "attempt to assign nonexistent local")
            end
            debug.setlocal(2, ki, v)
        end
})
end

_LOCAL = locals()

Untested... but that's about as good as you're going to get.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Hisham
In reply to this post by Soni "They/Them" L.
On 8 June 2015 at 18:09, Soni L. <[hidden email]> wrote:

>
>
> On 08/06/15 06:05 PM, Soni L. wrote:
>
> I wish you could access your own locals with an _LOCAL[idx] that would be
> faster than debug.getlocal...
>
> Not sure how that'd work if you local x = _LOCAL, or called a function with
> _LOCAL...
>
> Actually I do know, _LOCAL tables would be like any other tables, but
> heavily optimized for this kind of stuff, and it'd be part of the function's
> call stack entry thingy. The GC can take care of the rest.

Come up with a proof-of-concept implementation (including of course
tests to show it's correct and benchmarks to show that your heavy
optimizations are worth it), and then I'm sure the Lua authors will
give it due consideration. :)

-- Hisham

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Soni "They/Them" L.
In reply to this post by Coda Highland


On 08/06/15 06:40 PM, Coda Highland wrote:

> On Mon, Jun 8, 2015 at 2:09 PM, Soni L. <[hidden email]> wrote:
>>
>> On 08/06/15 06:05 PM, Soni L. wrote:
>>
>> I wish you could access your own locals with an _LOCAL[idx] that would be
>> faster than debug.getlocal...
>>
>> Not sure how that'd work if you local x = _LOCAL, or called a function with
>> _LOCAL...
>>
>> Actually I do know, _LOCAL tables would be like any other tables, but
>> heavily optimized for this kind of stuff, and it'd be part of the function's
>> call stack entry thingy. The GC can take care of the rest.
> function locals()
> return setmetatable({ [0]={} }, {
>      __index = function(t, k)
>              local ki = t[0][k]
>              assert(ki, "attempt to read nonexistent local")
>              local ln, lv = debug.getlocal(2, ki)
>              assert(ln == k, "inconsistent state")
>              return ln
>          end,
>      __newindex = function(t, k, v)
>              local ki = t[0][k]
>              if not ki then
>                  local i = 0
>                  while true do
>                      i = i + 1
>                      local ln, lv = debug.getlocal(2, i)
>                      if ln == k then
>                          ki = i
>                          break
>                      elif not ln then
>                          break
>                      end
>                  end
>                  assert(ki, "attempt to assign nonexistent local")
>              end
>              debug.setlocal(2, ki, v)
>          end
> })
> end
>
> _LOCAL = locals()
>
> Untested... but that's about as good as you're going to get.
>
> /s/ Adam
>
Not faster than debug.getlocal, cannot be passed around, cannot be
indexed with NUMBERS, doesn't give access to varargs... What else? (I
guess the varargs part would be really awesome tbh, just changing
varargs on the fly, accessing them at 0 (or at least little) cost,
etc... Can debug.setlocal() be used to set varargs?)

--
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Coda Highland
On Mon, Jun 8, 2015 at 3:14 PM, Soni L. <[hidden email]> wrote:

>
>
> On 08/06/15 06:40 PM, Coda Highland wrote:
>>
>> On Mon, Jun 8, 2015 at 2:09 PM, Soni L. <[hidden email]> wrote:
>>>
>>>
>>> On 08/06/15 06:05 PM, Soni L. wrote:
>>>
>>> I wish you could access your own locals with an _LOCAL[idx] that would be
>>> faster than debug.getlocal...
>>>
>>> Not sure how that'd work if you local x = _LOCAL, or called a function
>>> with
>>> _LOCAL...
>>>
>>> Actually I do know, _LOCAL tables would be like any other tables, but
>>> heavily optimized for this kind of stuff, and it'd be part of the
>>> function's
>>> call stack entry thingy. The GC can take care of the rest.
>>
>> function locals()
>> return setmetatable({ [0]={} }, {
>>      __index = function(t, k)
>>              local ki = t[0][k]
>>              assert(ki, "attempt to read nonexistent local")
>>              local ln, lv = debug.getlocal(2, ki)
>>              assert(ln == k, "inconsistent state")
>>              return ln
>>          end,
>>      __newindex = function(t, k, v)
>>              local ki = t[0][k]
>>              if not ki then
>>                  local i = 0
>>                  while true do
>>                      i = i + 1
>>                      local ln, lv = debug.getlocal(2, i)
>>                      if ln == k then
>>                          ki = i
>>                          break
>>                      elif not ln then
>>                          break
>>                      end
>>                  end
>>                  assert(ki, "attempt to assign nonexistent local")
>>              end
>>              debug.setlocal(2, ki, v)
>>          end
>> })
>> end
>>
>> _LOCAL = locals()
>>
>> Untested... but that's about as good as you're going to get.
>>
>> /s/ Adam
>>
> Not faster than debug.getlocal, cannot be passed around, cannot be indexed
> with NUMBERS, doesn't give access to varargs... What else? (I guess the
> varargs part would be really awesome tbh, just changing varargs on the fly,
> accessing them at 0 (or at least little) cost, etc... Can debug.setlocal()
> be used to set varargs?)
>

I started working on that before you sent the e-mail with the extra
constraints on it.

Adding indexing by numbers would be near-trivially easy -- in fact I
was GOING to do that before I realized it wasn't necessary and would
just add overhead. And indexing by numbers would trivially enable
varargs.

I MIGHT be able to optimize matters a little bit further if I can
memoize _LOCAL across function invocations, but that could potentially
be fragile; there's research I'd have to do first.

Regardless, asking for better performance out of this is rather silly
-- when would you EVER be in a situation where you're not implementing
a debugger and reflection is the only answer you can come up with for
how to do something?

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: [Proposal] _LOCAL was: Re: how to call a local function by its name?

Andrew Starks
In reply to this post by Soni "They/Them" L.


On Monday, June 8, 2015, Soni L. <[hidden email]> wrote:


On 08/06/15 06:40 PM, Coda Highland wrote:
On Mon, Jun 8, 2015 at 2:09 PM, Soni L. <[hidden email]> wrote:

On 08/06/15 06:05 PM, Soni L. wrote:

I wish you could access your own locals with an _LOCAL[idx] that would be
faster than debug.getlocal...

Not sure how that'd work if you local x = _LOCAL, or called a function with
_LOCAL...

Actually I do know, _LOCAL tables would be like any other tables, but
heavily optimized for this kind of stuff, and it'd be part of the function's
call stack entry thingy. The GC can take care of the rest.
function locals()
return setmetatable({ [0]={} }, {
     __index = function(t, k)
             local ki = t[0][k]
             assert(ki, "attempt to read nonexistent local")
             local ln, lv = debug.getlocal(2, ki)
             assert(ln == k, "inconsistent state")
             return ln
         end,
     __newindex = function(t, k, v)
             local ki = t[0][k]
             if not ki then
                 local i = 0
                 while true do
                     i = i + 1
                     local ln, lv = debug.getlocal(2, i)
                     if ln == k then
                         ki = i
                         break
                     elif not ln then
                         break
                     end
                 end
                 assert(ki, "attempt to assign nonexistent local")
             end
             debug.setlocal(2, ki, v)
         end
})
end

_LOCAL = locals()

Untested... but that's about as good as you're going to get.

/s/ Adam

Not faster than debug.getlocal, cannot be passed around, cannot be indexed with NUMBERS, doesn't give access to varargs... What else? (I guess the varargs part would be really awesome tbh, just changing varargs on the fly, accessing them at 0 (or at least little) cost, etc... Can debug.setlocal() be used to set varargs?)

--
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.



Perhaps instead, you could ask for a more general "state" table. This is achievable, right now, more or less? It would rely on __index, of course.  
12