Is the % for upvalue in Lua 5.x deleted - lua

I'm learning Lua from a book, which is a bit old.
I've tried searching the web, but because of the use of the # sign in my search I get really confusing results.
It says that in order to use upvalue you need to use the % sign.
But when I write it in my code I get an error.
Account.new = function (starting_balance)
local self = {}
local balance = starting_balance
self.withdraw = function (v)
%balance = %balance - v;
end
return self
end
error is : unexpected symbol near '%'
Is there a new way to handle upvalues in Lua 5.x ?

Since Lua 5.0, there is no more such thing as a "upvalue sign". An upvalue is a local to the environment a function is declared in, and as such can simply be accessed as any other local variable.
In your case: just use balance instead of %balance.
From Lua 5.1, % is used as modulo operator.
A good but slightly outdated book is the online available version of Programming in Lua, and of course, the reference manual.

Must be a very old book!
The % as upvalue notation was removed in Lua 5.0. (Released 2003)
Since 5.0, Lua has lexical scoping;
that is, upvalues are automatic:
do
local balance = 0
function deposit ( v )
balance = balance + v
return balance
end
end
print ( deposit ( 5 ) )
Output:
5

I'd go with the closure http://www.lua.org/pil/6.1.html#closures

Related

Why does _VERSION return "Luau" instead of "Lua 5.1" and why does += operator suddenly work?

I found out the _VERSION returns "Luau" instead of "Lua 5.1". I also found out continue and the += operator works
print(_VERSION) -- Luau
value = 0
value += 1
print(value) -- Doesn't return a syntax error
for k, v in ipairs({1, 2, 3, 4}) do
if k == 1 then
continue -- This works?
end
print(v)
end
prints
1
2
3
4
I also messed around with it and realized type annotation works.
function foo(x: number, y: string): boolean
local k: string = y:rep(x)
return k == "a"
end
doesn't throw a syntax error.
I also found out table.find, table.create and math.clamp is removed in Lua 5.4 as well as typeof function
I also realized binary literal print(0b10) returns 2 in Lua 5.1 but throws an error in Lua 5.4, along with print(1_000) which returns 1000 in Lua 5.1, but doesn't work in Lua 5.4
Why does these suddenly work on Lua 5.1? Did not expect it to work Lua 5.1
When I switched to Lua 5.4, _VERSION returns "Lua 5.4" instead and continue doesn't work and typeof was removed (How do I check types in Lua 5.4?).
What's going on?
And why does Lua 5.4 remove the += , continue operator and why does _VERSION return Luau in Lua 5.1?
Simple as: it's not Lua 5.1.
It's Luau, a language derived from Lua 5.1 and backwards-compatible with it. That's why your usual 5.1 code works, and why you can use some new features. Luau is maintained by Roblox. Its source code is published under MIT license.
As for Lua 5.4, see its Reference Manual to know what to expect from it.

Use of _ENV in Lua function does not have effect

I'm reviewing some toy examples from Lua and I found the following one over there with respect to environments:
M = {} -- the module
complex = {} -- global complex numbers registry
mt = {} --metatable for complex numbers
function new (r, i)
local cp = {}
cp = {r=r, i=i}
return setmetatable(cp,mt)
end
M.new = new -- add 'new' to the module
function M.op (...)
--Why does not it work?
local _ENV = complex
return ...
end
function M.add (c1, c2)
return new(c1.r + c2.r, c1.i + c2.i)
end
function M.tostring (c)
return string.format("(%g,%g)", c.r, c.i) --to avoid +-
end
mt.__tostring = M.tostring
mt.__add = M.add
complex.a = M.new(4,3)
complex.b = N.new(6,2)
--nil
M.op(a+b)
--It works
M,op(complex.a+complex.b)
The use of _ENV has no effect. However, if I use complex = _G, both lines work. How do set a local environment for M.op. I'm not asking for specific libraries, I just want to know why it does not work and how to fix it.
M.op(a+b)
This line doesn't do what you expect, because it uses values of a and b that are available when this method is called. It doesn't matter that you set _ENV value inside the method, as by the time the control gets there, the values referenced by a and b have already been retrieved and since both values are nil in your code, you probably get "attempt to perform arithmetic on global..." error.
how to fix it.
I'm not sure what exactly you want to fix, as you already reference the example that works. If you assign complex.a you can't assume that a will have the same value without mapping complex table to _ENV.

why __gc didn't work when collecting garbage for table?

Recently, I was learning about garbage collection. I have coded an example. The code is as follows:
mytablea {"1","2","3"}
print(collectgarbage("count"))
for i = 1, 500000 do
table.insert(mytable, i)
end
debug.setmetatable(mytable, {_gc = function ()print("dead")end})
mytable = nil
print(collectgarbage("count"))
print(collectgarbage("collect"))
print(collectgarbage("count"))
I'm confused about why there is no output in my terminal (__gc doesn't seem to work). But after finishing the call collectgarbage, its memory does decrease! I wonder if lua 5.1 didn't support this on table or if something is wrong with my linux (maybe some bug in my ubuntu).
The correct metatable entry is __gc, not _gc.
In any case, Lua 5.1 does not support gc metamethods for tables.
Lua 5.1 does not support __gc (note, it's two underscores, not one) on tables.
If possible move to a newer version of Lua (i.e. 5.2 or 5.3) to get support.
If you really need it; you can use the undocumented newproxy function to get a userdata to attach a __gc to instead:
do
local p = newproxy(false);
debug.setmetatable(p, {__gc = function() print("dead") end})
local t = {some_key = p}
end
collectgarbage()
collectgarbage()
I use this in projects where I need lua 5.1 compatibility, e.g. https://github.com/wahern/cqueues/blob/3f2fc57a07bb9e658f4d53ccc60ba8177e3f1236/src/dns.resolvers.lua#L53

LuaDate Metamethods Issue with Lua 5.1.4

i'm new in Lua and want to use LuaDate Library for my Project on a OpenWrt System.
It seems, that Metamethods not working correctly with Lua 5.1.4, which is the version
installed in OpenWrt Backfire. If i try the following code with Lua 5.1.5 on osx:
date = require('date')
print(date('2013-12-14T00:07:04') < date('2013-12-14T12:07:01'))
true is printed. If i run the code on OpenWrt with LUA 5.1.4, a error is thrown:
lua: test.lua:3: attempt to compare two table values
stack traceback:
test.lua:3: in main chunk
[C]: ?
Is it possible, to fix this issue? For example call the Metamethods directly?
You are getting a table from the date lib, You can use < for nothing but numbers. Better to get key names and value names of a simple date value to understand which members it has.
for k, v in pairs(date("2013-12-14T00:07:04")) do
print("KEY: "..k..", VALUE: "..v)
end
After getting keys and values, you can use something like this:
local d = date("2013-12-14T00:07:04")
local num = 0
num = d.seconds
num = num + d.minutes * 60
num = num + d.hours * 3600
if (num < 1500) return end

Hello metatable.__len world

A beginner's question about Lua and metatables, with a example as simple as an Hello‑World, involving the len event, which unfortunately does not returns the expected result (I'm using Lua 5.1 installed from Ubuntu's official repository).
The case
Here is the example:
Test_Type = {};
function Test_Type.__len (o)
return 1;
end;
function new_test ()
local result = {};
setmetatable(result, Test_Type);
return result;
end;
do
local a_test = new_test();
print (#a_test);
print(getmetatable(a_test).__len(a_test));
end;
And the result I get:
0
1
I was expecting the first print statement to display 1, but it displays 0, to my big surprise.
What did I missed?
According to Lua Reference Manual — Metatables and Metamethods, the # is equivalent to this:
function len_event (op)
if type(op) == "string" then
return strlen(op) -- primitive string length
else
local h = metatable(op).__len
if h then
return (h(op)) -- call handler with the operand
elseif type(op) == "table" then
return #op -- primitive table length
else -- no handler available: error
error(···)
end
end
end
So print (#a_test); and print(getmetatable(a_test).__len(a_test)); should result into the same, isn't it?
By the way, why is the above excerpt from the Reference Manual refers to metatable(op) while it should be getmetatable(op)? At least I've tried print(metatable(a_test).__len(a_test));, and it ends into an error.
Answer
As Nneonneo noticed, this is an issue with the Lua version in use. Lua 5.2 seems to be required for the above to work.
From http://lua-users.org/wiki/LuaFaq:
Why doesn't the __gc and __len metamethods work on tables?
__len on tables is scheduled to be supported in 5.2. See LuaFiveTwo.
Since you're using 5.1, __len on tables does not work. Indeed, running your code on Lua 5.2 produces
1
1
as expected.

Resources