Load behavior () when the piece function returns zero

From the Lua 5.1 documentation for load() :

Loads a piece using the func function to get its fragments. Each call to func should return a string that combines with the previous results. The return of an empty string, nil , or no value signals the completion of the block.

From my testing, this is actually not the case. Or rather, the documentation is minimal to be misleading.

Consider this example script:

 function make_loader(return_at) local x = 0 return function() x = x + 1 if x == return_at then return 'return true' end return nil end end x = 0 repeat x = x + 1 until not load(make_loader(x))() print(x) 

The output is the number of consecutive calls to the function returned by make_loader() , which returned nil before load() releases and returns a function that returns nothing.

It can be expected that the output here will be “1” if the documentation is to be taken at face value. However, the output is "3". This means that the load() argument is called until it returns nil three times before load() releases.

On the other hand, if the chunk function returns a string immediately, and then nil on subsequent calls, it takes only one nil to stop loading:

 function make_loader() local x = 0 return { fn=function() x = x + 1 if x == 1 then return 'return true' end return nil end, get_x=function() return x end } end loader = make_loader() load(loader.fn) print(loader.get_x()) 

Prints "2", as you would expect.

So my question is: wrong documentation? For some reason, is this behavior desirable? Is this just a bug in load() ? (This seems to be intentional, but I cannot find any documentation explaining why.)

+6
source share
2 answers

This is a bug in 5.1. It was fixed in 5.2, but we could not include the fix in 5.1.

+6
source

I get slightly different results from yours, but they still don't quite match the docs:

 function make_loader(return_at) local x = 0 return function() x = x + 1 print("make_loader", return_at, x) if x == return_at then return 'return true' end return nil end end for i = 1, 4 do load(make_loader(i)) end 

This returns the following results:

 make_loader 1 1 make_loader 1 2 make_loader 2 1 make_loader 2 2 make_loader 2 3 make_loader 3 1 make_loader 3 2 make_loader 4 1 make_loader 4 2 

For 1 it is called twice because the first was return true , and the second was zero. For 2 it is called three times because the first was nil , then return true , and then nil again. For all other values, it is called twice: it seems that the very first nil ignored, and the function is called at least once.

If this is true, the documentation should reflect this. I looked at the source code, but did not see anything that could explain why the first returned nil ignored (I also tested with an empty string and didn't matter with the same result).

+3
source

Source: https://habr.com/ru/post/946619/


All Articles