"Attempt to index local..." Why am I getting this error? - lua

I'm new to Lua and trying to get things sorted in my head. I tried this code:
function newCarousel(images)
local slideToImage = function()
print("ah!")
end
end
local testSlide = newCarousel(myImages)
testSlide.slideToImage()
Which gave me this error:
Attempt to index local "testSlide" (a nil value)...
Why is this?

Because newCarousel returns nothing, so testSlide is nil, so when you try to index it (testSlide.slideToImage is exactly equivalent to testSlide["slideToImage"]) you get an error.
I would recommend reading Programming in Lua. You may be able to work out the language's syntax, semantics, and idioms by trial and error, but it'll take you a lot longer.

If you want to be able to do testSlide.slideToImage() you have to modify newCarousel so that it returns a table with a function inside it. The simplest implementation is the following:
function newCarousel(images)
local t = {}
t.slideToImage = function()
print("ah!")
end
return t
end
You can even build t and return it on a single step; the following code is equivalent to the one above:
function newCarousel(images)
return {
slideToImage = function()
print("ah!")
end
}
end

The code you've got now, as Mud stated, doesn't return anything. (This is not Scheme or Ruby or the like where the last expression is the return value.) Further, you seem to be thinking that newCarousel is an object. It isn't. It's a function. When you've finished calling newCarousel it's over. It's done its work, whatever that may be (which in your case is creating a local variable that is promptly dropped and returning nil).
Correct code for this would look more like:
function newCarousel(images)
return function()
print("ah!")
end
end
local testSlide = newCarousel(myImages)
testSlide()
Here I now have newCarousel creating an (anonymous) function and immediately returning it. This anonymous function is bound to testSlide so I can invoke it any time I like for as long as testSlide remains in scope.
It's instructive to look at the generated code when playing with Lua. First let's look at what luac churns out for your code:
main <junk.lua:0,0> (8 instructions, 32 bytes at 0xeb6540)
0+ params, 2 slots, 0 upvalues, 1 local, 3 constants, 1 function
1 [5] CLOSURE 0 0 ; 0xeb6720
2 [1] SETGLOBAL 0 -1 ; newCarousel
3 [7] GETGLOBAL 0 -1 ; newCarousel
4 [7] GETGLOBAL 1 -2 ; myImages
5 [7] CALL 0 2 2
6 [8] GETTABLE 1 0 -3 ; "slideToImage"
7 [8] CALL 1 1 1
8 [8] RETURN 0 1
function <junk.lua:1,5> (2 instructions, 8 bytes at 0xeb6720)
1 param, 2 slots, 0 upvalues, 2 locals, 0 constants, 1 function
1 [4] CLOSURE 1 0 ; 0xeb6980
2 [5] RETURN 0 1
function <junk.lua:2,4> (4 instructions, 16 bytes at 0xeb6980)
0 params, 2 slots, 0 upvalues, 0 locals, 2 constants, 0 functions
1 [3] GETGLOBAL 0 -1 ; print
2 [3] LOADK 1 -2 ; "ah!"
3 [3] CALL 0 2 1
4 [4] RETURN 0 1
In your code the mainline creates a closure, binds it to the name newCarousel, gets that value, gets the value of myImages and does a call. This corresponds to local testSlide = newCarousel(myImages). Next it gets the slideToImage value from the local table (testSlide). The problem here is that testSlide isn't a table, it's nil. This is where your error message is coming from. This isn't the only error, mind you, but it's the first one the runtime sees and is what's making everything choke. If you'd returned an actual function from newCarousel you'd get a different error. If, for example, I'd added the line return slideToImage to the newCarousel function, the error message would have been "attempt to index local 'testSlide' (a function value)".

Related

lua: global var vs table entry var

In lua when u have a function in a table, what is the difference between declaring a global variable within the function vs declaring the variable as an entry in the table (if any)? The variable is x in the example below.
i.e.
dog={x=33,
func=function(self)
self.x=self.x*self.x
end
}
cat={func=function()
x=33
x=x*x
end
}
In dog I can use the properties of self to call the function with dog:func() instead of dog.func(dog). But outside of that, is there anything performance-wise to take into consideration in choosing between the two? The examples work a bit different when called in a loop, but outside of that?
Well, I heard that the two first rules about optimization are "Don't do it!" and "Don't do it yet!".
There is an official document exposing some ways to optimize Lua code and I recommend it. The most important rule is to prefer local variables to global variables because global variables are 30% slower than local ones.
The first thing we can do with the previous code is to compile it and check the bytecode instructions to understand what happen at the execution time. I stored the first function inside "test-1.lua" and the second one in "test-2.lua".
> cat test-1.lua
dog={x=33,
func=function(self)
self.x=self.x*self.x
end
}
function TEST ()
dog:func()
end
> luac54 -l -s test-1.lua
#
#(part of output omitted for clarity)
#
# Function: dog.func
#
function <test-1.lua:2,4> (6 instructions at 0000000000768740)
1 param, 3 slots, 0 upvalues, 1 local, 1 constant, 0 functions
1 [3] GETFIELD 1 0 0 ; "x"
2 [3] GETFIELD 2 0 0 ; "x"
3 [3] MUL 1 1 2
4 [3] MMBIN 1 2 8 ; __mul
5 [3] SETFIELD 0 0 1 ; "x"
6 [4] RETURN0
#
# Function: TEST (function to call dog.func)
#
function <test-1.lua:7,9> (4 instructions at 00000000000a8a90)
0 params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
1 [8] GETTABUP 0 0 0 ; _ENV "dog"
2 [8] SELF 0 0 1k ; "func"
3 [8] CALL 0 2 1 ; 1 in 0 out
4 [9] RETURN0
So, if we want to execute TEST 10 times, we will need to execute at least 10*(4+6) bytecode instructions, that's said 100 bytecode instructions.
> cat test-2.lua
cat={func=function()
x=x*x
end
}
x=33
function TEST ()
cat.func()
end
> luac54 -l -s test-2.lua
#
#(part of output omitted for clarity)
#
# Function: cat.func
#
function <test-2.lua:1,3> (6 instructions at 00000000001b87f0)
0 params, 2 slots, 1 upvalue, 0 locals, 1 constant, 0 functions
1 [2] GETTABUP 0 0 0 ; _ENV "x"
2 [2] GETTABUP 1 0 0 ; _ENV "x"
3 [2] MUL 0 0 1
4 [2] MMBIN 0 1 8 ; __mul
5 [2] SETTABUP 0 0 0 ; _ENV "x"
6 [3] RETURN0
#
# Function: TEST (function to call cat.func)
#
function <test-2.lua:8,10> (4 instructions at 00000000001b8a80)
0 params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
1 [9] GETTABUP 0 0 0 ; _ENV "cat"
2 [9] GETFIELD 0 0 1 ; "func"
3 [9] CALL 0 1 1 ; 0 in 0 out
4 [10] RETURN0
So, if we want to execute TEST 10 times, we will need to execute at least 10*(4+6) bytecode instructions, that's said 100 bytecode instructions.... which is exactly the same as the first version!
Obviously, all the bytecode instructions does not take the same time to execute. Some instructions will spend much more time in the C runtime the other ones. The addition of two integer might be much faster than allocating a new table and initialize some fields. At that point, we could try to do a dirty-and-pointless microbenchmark to give us an idea.
One might copy and paste this code in a Lua interpreter:
> cat dirty-and-pointess-benchmark.lua
dog={x=33,
func=function(self)
self.x=self.x*self.x
end
}
cat={func=function()
x=x*x
end
}
x=33
function StartMeasure ()
StartTime = os.clock()
end
function StopMeasure (TestName)
local Duration = os.clock() - StartTime
print(string.format("%s: %f sec", TestName, Duration))
end
function DoTest1 (Count)
for Index = 1, Count do
dog:func()
end
end
function DoTest2 (Count)
for Index = 1, Count do
cat.func()
end
end
COUNT = 5000000000
StartMeasure()
DoTest1(COUNT)
StopMeasure("VERSION_1")
StartMeasure()
DoTest2(COUNT)
StopMeasure("VERSION_2")
This code give this results on my computer:
VERSION_1: 246.816000 sec
VERSION_2: 250.412000 sec
Obviously, the difference is probably negligible for the most of the programs. We should always try to spend more time on writing correct programs and less time to do micro-benchmarks.
The two code snippets do very different things. dog.func sets self.x to the square of its previous value. cat.func sets the global x to 1089. You can't really compare performance between two things whose functionality are so different.
First of all you should change
cat={func=function()
x=33
x=x*x
end
}
to
x=33
cat={func=function()
x=x*x
end
}
Now we have the same operations.
If I run both functions 10000 times I end up with cat.func() a few percent slower than dog:func()
This does not surprise as indexing locals is faster than indexing globals.
To speed up cat you could do something like this:
x=33
cat={func=function()
local _x = x
x = _x*_x
end
}
The fastest solution is probably
dog={x=33,
func=function(self)
local x = self.x
self.x = x*x
end
}
and you could even gain more speed by making your tables and x local.
Usually you don't win anything significant doing things like that.
Premature optimiziation is a big no-no and you should ask yourself what problem you're actually trying to solve.
It also doesn't make sense to squeeze the last percent out of your code if you do not even know enough Lua to write a simple benchmark for your code... just a thought.

In Lua Random number generation issue

We are performing task as Accept a number as the seed value for math.randomseed(), and generate a random integer (interval [1,6]) using math.random() during each iteration of a loop, and continue the loop till the number is 6.
For which we had written code as
i = io.read()
local count = 0
math.randomseed(i)
for x = 1, 4 do
value = math.random(1, 6)
print(value)
count = count + 1
end
print(count)
We failed to pass test because
Input (stdin)
Run as Custom Input
0
Your Output (stdout)
3
5
5
6
2
Expected Output
3
5
5
6
4
Please help us
OP code seems to be having loop problems. I encourage the OP to read the Lua documentation about Control Structures, where Lua's while, repeat until, and goto are described, as well as the following manual section about Lua's For Statement. It is difficult to write any program in any language without understanding the fundamental control structures of the language.
OP problem can be solved in a variety of ways.
Using for
-- for version
i = io.read()
math.randomseed(i)
local count
for i = 1, math.huge do
local value = math.random(1, 6)
print(value)
count = i
if value == 6 then break end
end
print(count)
Here math.huge is the largest representable number in Lua, typically the special value inf, making this effectively an infinite loop. The variable i keeps track of how many random numbers have been generated, but since i will not be visible outside of the loop, the count variable is needed to copy the value of i so that it can be printed at the end.
Using while
-- while version
i = io.read()
math.randomseed(i)
local value = math.random(1, 6)
local count = 1
while value < 6 do
print(value)
count = count + 1
value = math.random(1, 6)
end
print(value)
print(count)
Here the looping construct begins with a test, so a test value must be created before the loop begins. This means that the count must be initialized to 1 before the loop begins, and it also means that the call to math.random will be duplicated. Not pretty.
Using repeat until
-- repeat until version
i = io.read()
math.randomseed(i)
local count = 0
repeat
local value = math.random(1, 6)
print(value)
count = count + 1
until value == 6
print(count)
Here the test comes at the end of the loop construct. This allows the code to call math.random only once.
Using goto
-- goto version
i = io.read()
math.randomseed(i)
local count = 0
::loop::
local value = math.random(1, 6)
print(value)
count = count + 1
if value < 6 then goto loop end
print(count)
You probably should not use goto to solve this problem, but you can. You have to be careful with goto in Lua; you can't jump into a block, out of a function, or into the scope of a local variable.
As you can see, there are some subtleties to these looping constructs, and using them requires some familiarity with the details.
All four versions produce identical outputs for the same inputs:
$ lua loops.lua
42
2
5
3
2
2
4
6
7

Why top-bottom and bottom-up work differently in my code of Lua?

I make a code of dynamic program. It is about searching the smallest number of calculations in three ways : divided by 3, divided by 2, or subtracted by 1 to a given number to make it 1.
First, I made a function 'one' with top-bottom way. But when I put 1,000,000 in there, it results stack overflow.
Second, I made a function 'two' with bottom-up way. It works with the input 1,000,000 well.
local num = io.read("*n")
local memo = {
[0] = 0,
[1] = 0
}
function one(n)
if memo[n] == nil then
if n % 3 == 0 then
memo[n] = 1 + math.min(one(n-1), one(n//3))
elseif n % 2 == 0 then
memo[n] = 1 + math.min(one(n-1), one(n//2))
else
memo[n] = 1 + one(n-1)
end
end
return memo[n]
end
local last = 1
function two(n)
if memo[n] == nil then
for i = last + 1, n do
if i % 3 == 0 then
memo[i] = 1 + math.min(two(i-1), two(i//3))
elseif i % 2 == 0 then
memo[i] = 1 + math.min(two(i-1), two(i//2))
else
memo[i] = 1 + two(i-1)
end
end
last = n
end
return memo[n]
end
print(two(num))
I don't know why this happened. Isn't it work quiet similarly?
You get a stack overflow from top-bottom because no lower numbers are defined.
Lets go through the both functions if we provide an input of 5, I added print lines to the code to help illustrate how code is running.
I will start with function two.
Undefined: 5 -- This is the first call.
Undefined: 2 -- first value once in the for loop.
%2: 2 -- Enter mod 2 block.
Defined: 1 -- Second call. (now 2 calls deep)
Defined: 1 -- Third call. (still 2 calls deep)
Undefined: 3 -- Next value in First calls for loop. (back to 1 deep)
%3: 3 -- Enter mod 3 block.
Defined: 2 -- Forth call. (now 2 calls deep)
Defined: 1 -- Fifth call. (still 2 calls deep)
Undefined: 4 -- Next value in First calls for loop. (back to 1 deep)
%2: 4 -- Enter mod 4 block.
Defined: 3 -- Sixth call. (now 2 calls deep)
Defined: 2 -- Seventh call. (still 2 calls deep)
Undefined: 5 -- Next value in First calls for loop. (back to 1 deep)
else: 5 -- Enter else block.
Defined: 4 -- Eighth call. (still 2 calls deep)
3 -- return from initial call.
As you can see every iteration of the loop as the previous values already defined so they return immediately and it do not really perform recursion more than 2 calls deep.
Here is the output for function one:
Undefined: 5 -- This is the first call.
else: 5 -- Enter the else block.
Undefined: 4 -- Second call. (now 2 calls deep)
%2: 4 -- Enter mod 2 block.
Undefined: 3 -- Third call. (now 3 calls deep)
%3: 3 -- Enter mod 3 block.
Undefined: 2 -- Forth call. (now 4 calls deep)
%2: 2 -- Enter mod 2 block.
Defined: 1 -- Fifth call. (now 5 calls deep)
Defined: 1 -- Sixth call. (still 5 calls deep)
Defined: 1 -- Seventh call. (Second call from value 3)
Defined: 2 -- Eighth call. (Second call from value 4)
3 -- return from initial call.
Here each call has to go deeper and deeper as no lower values are defined.
This results in the stack overflow.
function two is not really recursive like function one, you could just do memo[i-1] and memo[i/2] as they are garenteed to be to have already been processed.

Functional impact of declaring local variables via function parameters

In writing some one-off Lua code for an answer, I found myself code golfing to fit a function on a single line. While this code did not fit on one line...
foo=function(a,b) local c=bob; some_code_using_c; return c; end
...I realized that I could just make it fit by converting it to:
foo=function(a,b,c) c=bob; some_code_using_c; return c; end
Are there any performance or functional implications of using a function parameter to declare a function-local variable (assuming I know that a third argument will never be passed to the function) instead of using local? Do the two techniques ever behave differently?
Note: I included semicolons in the above for clarity of concept and to aid those who do not know Lua's handling of whitespace. I am aware that they are not necessary; if you follow the link above you will see that the actual code does not use them.
Edit Based on #Oka's answer, I compared the bytecode generated by these two functions, in separate files:
function foo(a,b)
local c
return function() c=a+b+c end
end
function foo(a,b,c)
-- this line intentionally blank
return function() c=a+b+c end
end
Ignoring addresses, the byte code report is identical (except for the number of parameters listed for the function).
You can go ahead and look at the Lua bytecode generated by using luac -l -l -p my_file.lua, comparing instruction sets and register layouts.
On my machine:
function foo (a, b)
local c = a * b
return c + 2
end
function bar (a, b, c)
c = a * b
return c + 2
end
Produces:
function <f.lua:1,4> (4 instructions at 0x80048fe0)
2 params, 4 slots, 0 upvalues, 3 locals, 1 constant, 0 functions
1 [2] MUL 2 0 1
2 [3] ADD 3 2 -1 ; - 2
3 [3] RETURN 3 2
4 [4] RETURN 0 1
constants (1) for 0x80048fe0:
1 2
locals (3) for 0x80048fe0:
0 a 1 5
1 b 1 5
2 c 2 5
upvalues (0) for 0x80048fe0:
function <f.lua:6,9> (4 instructions at 0x800492b8)
3 params, 4 slots, 0 upvalues, 3 locals, 1 constant, 0 functions
1 [7] MUL 2 0 1
2 [8] ADD 3 2 -1 ; - 2
3 [8] RETURN 3 2
4 [9] RETURN 0 1
constants (1) for 0x800492b8:
1 2
locals (3) for 0x800492b8:
0 a 1 5
1 b 1 5
2 c 1 5
upvalues (0) for 0x800492b8:
Not very much difference, is there? If I'm not mistaken, there's just a slightly different declaration location specified for each c, and the difference in the params size, as one might expect.

NodeMCU/Lua performance issues

I'm adding some code to the ws2812 module to be able to have some kind of reusable buffer where we could store led values.
The current version is there.
I've two problems.
First I wanted to have some "OO-style" interface. So I did:
local buffer = ws2812.newBuffer(300);
for j = 0,299 do
buffer:set(j, 255, 255, 255)
end
buffer:write(pin);
The probleme here is that buffer:set is resolved at each loop turn, which is costly (this loop takes ~20.2ms):
8 [2] FORPREP 1 6 ; to 15
9 [3] SELF 5 0 -7 ; "set"
10 [3] MOVE 7 4
11 [3] LOADK 8 -8 ; 255
12 [3] LOADK 9 -8 ; 255
13 [3] LOADK 10 -8 ; 255
14 [3] CALL 5 6 1
15 [2] FORLOOP 1 -7 ; to 9
I found a workaround for this problem which doesn't look "nice":
local buffer = ws2812.newBuffer(300);
local set = getmetatable(buffer).set;
for j = 0,299 do
set(buffer, j, 255, 255, 255)
end
buffer:write(pin);
It works well (4.3ms for the loop, more than 4 times faster), but it's more like a hack. :/ Is there a better way to "cache" the buffer:set resolution?
Second question, in my C code, I use:
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer");
Which gives back my buffer ptr and check if it is really a ws2812.buffer. But this call is sloooooow: on my ESP8266, ~50us. If it's done on each call (for my 300 time buffer:set for example), it's ~15ms!
Is there a better way to fetch some user data and check its type, or should I add some "canary" at the beginning of my structure to do my own check (which will almost be "free" compared to 50us...)?
To make it look less of a hack you could try using
local set = buffer.set
This is essentially the same code, but without the getmetatable as the metatable is used implicitly through the __index metamethod.
On our project we made our own implementation of luaL_checkudata.
One option - as you similarly suggested - was to use a wrapper object that holds the type. As all userdata was assumed to be wrapped in the wrapper we could use it to get and confirm the type of the userdata. But there was no benchmarking done and testing metatables was used instead.
I would say testing the metatables is slower than the wrapping since luaL_checkudata does a lot of work to get and test the metatables and with wrapping we have access to the type directly. However benchmarking will tell for sure.

Resources