Lua multiple assignment with tables - lua

This code:
function foo()
return 1, 2, 3
end
bar = {}
bar = {a, b, c = foo()}
produces:
bar.a = nil
bar.b = nil
bar.c = 1
How can this be written so that you get:
bar.a = 1
bar.b = 2
bar.c = 3
without having to write something like this:
function foo()
return 1, 2, 3
end
bar = {}
a, b, c = foo()
bar = {a = a, b = b, c = c}

BLUF
There's no straight forward or elegant way to do this. You'll have to do it manually like this
local r = { f() } --> store all returned values in r
local bar = { }
local c = string.byte 'a' --> start with 'a'
for _, v in ipairs(r) do
local t = string.char(c)
bar[t] = v --> assign each value to respective letter
c = c + 1
end
If you'd had a, b, c = foo() you'd get all the three values assigned to the three variables. However, you've
bar = { a, b, c = foo() }
This table constructor expression will get interpreted as the keys a, b, c getting inserted into the table, with only the last key having an associated value (aside: keys with no associated value are taken as nil; hence a and b never get inserted). Since there's only one variable to take the values returned by foo, except the first everything else it returns are discarded.
Alternatively bar = { foo() } will assign all values returned by foo as array values of bar. However, the key to access these would [1], [2], etc. and not 'a', 'b', etc.
Read below to know when the returned values get discarded and when they don't.
TL;DR
All returned values are retained only when the function call is the last/only expression in a list of expressions; elsewhere all except the first are discarded.
Function call as a statement
In Lua, when we return multiple results from a function, all of them get discarded if the function call is a statement by itself.
foo()
will discard all three return values.
Function call in an expression
If it's used in an expression, only the first will be retained and everything else will be discarded.
x = foo() - 1
print(x) -- prints 0; the values 2, 3 are discarded
Function call in an expression list
The entire list of values returned is retained only when the call appears as the last/only item in a list of expressions. Such list of expressions occur at four places in Lua:
Multiple assignment
E.g. local a, b, c, d = 0, f(). Here b, c, d get the values 1, 2, 3 respectively.
Table constructor
E.g. local t = { 0, f() }. All values returned by f are put into t following the first 0.
Function call arguments
E.g. g(a, f()). g would receive 4, not 2, arguments. a and the three values from f.
return statement
E.g. return 'a', f(). Additional to the string 'a', all values returned by f will be received at the calling end.
In all these situations, had f appeared not as the last expression in the list or wasn't the only expression, then all values it returned except the first would've been discarded.
Multiple assignment statement
In the multiple assignment statement, when the number of values assigned is lesser than number of variables, the extra variables be assigned to nil. When it's the other way around i.e if the number of variables are lesser, the extra values are discarded.
a, b, c = 1, 2 -- a = 1, b = 2, c = nil
a, b, c = 1, 2, 3, 4 -- 4 gets discarded

bar = {}
bar.a, bar.b, bar.c = foo()

bar = {}
local abc = foo()
bar.a, bar.b, bar.c = abc, abc, abc
Simply bar.a, bar.b, bar.c = foo() will only set bar.a to foo(), the other two will be set to nil because they get set to the second and third values respectively, and you've only given one value.

If you can, have foo() return a table formatted the right way.
function foo()
return {a = 1, b = 2, c = 3}
end
bar = foo()

Related

Inconsistent (apparently) behaviour with static members in F#

The following first 2 F# snippets get different results, but I find this a little inconsistent, even though I understand that members and values have different semantics. I would expect both of them getting the same results (the second one, as they have a similar value syntax).
IMHO the third snippet, which explicitly defines a get method, should be differentiated from the first.
Am I alone?
let mutable b = 0
type A = A with
static member B =
b <- b + 1
b
printfn "%d" A.B
printfn "%d" A.B
printfn "%d" A.B
//1
//2
//3
let mutable b = 0
type A = A
let _b =
b <- b + 1
b
type A with
static member B = _b
printfn "%d" A.B
printfn "%d" A.B
printfn "%d" A.B
//1
//1
//1
let mutable b = 0
type A = A with
static member B
with get() =
b <- b + 1
b
printfn "%d" A.B
printfn "%d" A.B
printfn "%d" A.B
//1
//2
//3
EDIT
I agree with Tomas, the syntax is a little misleading. However I can see where the dilemma is: while the value syntax is F#/functional, the member notation must replicate the .NET/Object Oriented behaviour.
For those interested, value-behaving static member can be a pattern:
type MyType = MyType
let private myValueBehavingStaticPropertyValue =
... potentially heavy workflow
type MyType with
static member MyValueBehavingStaticProperty = myValueBehavingStaticPropertyValue
with this, the 'potentially heavy workflow' is not repeated every time we read the property
I think your question is a good one. The definition of a static property is syntactically very similar to definition of a value - so I can see why you think the two should behave the same.
This is slightly misleading, because behind the senes, properties have a getter method that is evaluated each time the property is accessed. As a minimal example, in the following, accessing A1.B twice prints "hi" twice:
type A1 = A1 with
static member B =
printfn "hi"
A1.B; A1.B
There is actually a more verbose syntax for properties in F#, which reveals what is going on - the fact that B is actually backed by a get() method that is invoked by the compiled code behind the scenes:
type A2 = A2 with
static member B
with get() = printfn "hi"
A2.B; A2.B
Now, you would never actually do this in practice, but you can even invoke the method (which is hidden from IntelliSense) directly:
A2.get_B(); A2.get_B()
The following first 2 F# snippets get different results, but I find this a little inconsistent, even though I understand that members and values have different semantics. I would expect both of them getting the same results (the second one, as they have a similar value syntax).
You're expecting that evaluating _b caused it to re-evaluate itself, but that's not how values evaluate in F#. If I define let x = 12 it doesn't re-evaluate what x is each time I access it.
That's why it always prints 1. When _b is first accessed, it is evaluated once and that's it.
IMHO the third snippet, which explicitly defines a get method, should be differentiated from the first.
Why? It's no different than the first snippet. An F# property defined like so:
type A =
static member X = 12
Is compiled with a getter just like if you define it explicitly.
Your second version is not equivalent to either the first or the third. This is:
let mutable b = 0
type A = A
let _b () =
b <- b + 1
b
type A with
static member B = _b ()
printfn "%d" A.B
printfn "%d" A.B
printfn "%d" A.B
//1
//2
//3
_b here is identified as a function and not a value (as in your case) and so is invoked each time you call the static member via A.B. So I would say this apparent inconsistency is only apparent as long as one confuses identifiers of values (which are only evaluated once) versus functions (which are evaluated only and each time they are invoked).
In this snippet:
let mutable b = 0
type A = A
let _b =
b <- b + 1
b
type A with
static member B = _b
printfn "%d" A.B
printfn "%d" A.B
printfn "%d" A.B
_b gets the value 1, regardless of everything that comes after it. _b will never get re-evaluated. So while the property A.B itself is re-evaluated all the time, it will just return the value _b that is set already set in stone.

Using a variable as arithmetic operator in Lua

I want to use a variable that references an arithmetic operator within an if statement expression as shown below:
str = { '>60', '>60', '>-60', '=0' }
del = 75
function decode_prog(var1, var2)
op = string.sub(var1, 1, 1)
vb = tonumber(string.sub(var1, 2, 3))
if var2 op vb then
print("condition met")
else
print('condition not meet')
end
end
for i = 1, #str do
decode_prog(str[i], del)
end
When the above code executes, it should either print "condition met" or "condition not met" based on the result of the operation, however I am instead receiving an error.
You cannot substitute a native Lua operator with a variable that references a function, the only way to go about what you are attempted to do is to create a set of functions within an associative array and set the index as a reference to the respective operation you want to conduct.
Looking at your list, you have a greater than (>) and equal to (=). We create a table for these operations that takes two parameters as follows.
local operators = {
[">"] = function(x, y) return x > y end,
["="] = function(x, y) return x == y end,
-- Add more operations as required.
}
You can then invoke the respective function from the decode_prog function by obtaining the operation character from the string, along with the numeric value itself - this is possible because you can obtain the function from the associative array where the index is the string of the operation we want to conduct.
local result = operators[op](var2, number)
This calls upon the operators array, uses the op to determine which index we need to go to for our appropriate operation, and returns the value.
Final Code:
str = { '>60', '>60', '>-60', '=0' }
del = 75
local operators = {
[">"] = function(x, y) return x > y end,
["="] = function(x, y) return x == y end,
}
function decode_prog(var1, var2)
local op = string.sub(var1, 1, 1) -- Fetch the arithmetic operator we intend to use.
local number = tonumber(string.sub(var1, 2)) -- Strip the operator from the number string and convert the result to a numeric value.
local result = operators[op](var2, number) -- Invoke the respective function from the operators table based on what character we see at position one.
if result then
print("condition met")
else
print('condition not meet')
end
end
for i = 1, #str do
decode_prog(str[i], del)
end
I can't make much sense of your code or what you want to achieve doing that but if could simply use load.
You build your expression as a string and run it. Of course you should take care of two character operators like >= which I did not and you should validate your input.
local str={'>60','>60','>-60','=0'}
local del=75
function decode_prog(var1, var2)
local operator = var1:sub(1,1):gsub("=", "==")
local expr = string.format("return %d %s %s", var2,operator, var1:sub(2))
print(string.format("condition %smet", load(expr)() and "" or "not "))
end
for i,v in ipairs(str) do
decode_prog(v, del)
end
A very simple way would be to add a condition for each supported operator:
function decode_prog(var1, var2)
op = string.sub(var1, 1, 1)
vb = tonumber(string.sub(var1, 2)) --remove the last argument and use tonumber()
if vb == nil then return end --if the string does not contain number
if (op == ">" and var2 > vb) or (op == "=" and var2 == vb) --[[add more conditions here]] then
print("condition met")
else
print("condition not met")
end
end
I changed the vb=string.sub(var1,2,3) line too.
This form vb = tonumber(string.sub(var1, 2)) will allow use of numbers that have any number of digits and added tonumber() which will allow us to catch not-a-number errors when comparison would probably fail.
Then I added a logic to determine what the operator is and if the condition is met.
Operator limitations:
This will only work with operators that are one character and operator such as >= will not be possible unless you use a different character for it. ≥ will not play nicely, since it is multiple characters.

What is the "type signature" of pairs() in Lua?

Looking at the chapter 7.1 – Iterators and Closures from "Programming in Lua" it seems like the the for foo in bar loop takes requires bar to be of type (using Java typesto express it) Supplier<Tuple> and the the for-in will keep calling bar until it returns nil.
So for something like:
for k,v in pairs( tables ) do
print( 'key: '..k..', value: '..v )
end
that implies pairs has a type of Function<Table,Supplier<Tuple>>.
I want to create a function that behaves like pairs except it skips tuples where the first argument starts with an underscore (ie _).
local function mypairs( list )
local --[[ Supplier<Tuple> ]] pairIterator = pairs( list )
return --[[ Supplier<Tuple> ]] function ()
while true do
local key, value = pairIterator()
if key == nil then
return nil
elseif key:sub(1,1) ~= '_' then
return key, value
end
end
end
end
however it doesn't work since
--[[should be: Supplier<Table>]] pairIterator = pairs({ c=3; b=2; a=1 })
when I call it
pairIterator()
it returns
stdin:1: bad argument #1 to 'pairIterator' (table expected, got no value)
stack traceback:
[C]: in function 'pairIterator'
stdin:1: in main chunk
[C]: in ?
but
pairIterator({ c=3; b=2; a=1 })
returns
Lua>pairIterator({ c=3; b=2; a=1 })
c 3
Your basic problem is that you're using Java logic on Lua problems. Java and Lua are different languages with different constructs, and it's important to recognize that.
pairs does not have a return value; it has multiple return values. This is a concept that Java completely lacks. A Tuple is a single value that can store and manipulate multiple values. A Lua function can return multiple values. This is syntactically and semantically distinct from returning a table containing multiple values.
The iterator-based for statement takes multiple values as its input, not a table or container of multiple values. Specifically, it stores 3 values: an iterator function, a state value (which you use to preserve state between calls), and an initial value.
So, if you want to mimic pairs's behavior, you need to be able to store and manipulate its multiple return values.
Your first step is to store what pairs actually returns:
local f, s, var = pairs(list)
You are creating a new iterator function. So you need to return that, but you also need to return the s and var that pairs returns. Your return statement needs to look like this:
return function (s, var)
--[[Contents discussed below]]
end, s, var --Returning what `pairs` would return.
Now, inside your function, you need to call f with s and var. This function will return the key/value pair. And you need to process them correctly:
return function (s, var)
repeat
local key, value = f(s, var)
if(type(key) ~= "string") then
--Non-string types can't have an `_` in them.
--And no need to special-case `nil`.
return key, value
elseif(key:sub(1, 1) ~= '_') then
return key, value
end
until true
end, s, var --Returning what `pairs` would return.
pairs() returns three separate values:
a function to call with parameters (table, key) that returns a key and value
the table you passed to it
the first 'key' value to pass to the function (nil for pairs(), 0 for ipairs())
So something like this:
for k,v in pairs({a=1, b=13, c=169}) do print(k, v) end
Can be done like this:
local f,t,k = pairs({a=1, b=13, c=169})
local v
print('first k: '..tostring(k))
k,v = f(t, k)
while k ~= nil do
print('k: '..tostring(k)..', v: '..tostring(v))
k,v = f(t, k)
end
Results:
first k: nil
k: c, v: 169
k: b, v: 13
k: a, v: 1
And you don't have to take an argument, this has manual if statements for each value:
function mypairs()
-- the function returned should take the table and an index, and
-- return the next value you expect AND the next index to pass to
-- get the value after. return nil and nil to end
local myfunc = function(t, val)
if val == 0 then return 1, 'first' end
if val == 1 then return 2, 'second' end
if val == 2 then return 3, 'third' end
return nil, nil
end
-- returns a function, the table, and the first value to pass
-- to the function
return myfunc, nil, 0
end
for i,v in mypairs() do
print('i: '..tostring(i)..', v: '..tostring(v))
end
-- output:
-- i: 1, v: first
-- i: 2, v: second
-- i: 3, v: third
For your mypairs(list) you can just keep calling the function returned from pairs as long as the key has an underscore to get the next value:
local function mypairs( list )
local f,t,k = pairs(list)
return function(t,k)
local a,b = f(t, k)
while type(a) == 'string' and a:sub(1,1) == '_' do a,b = f(t,a) end
return a,b
end, t, k
end
local list = {a=5, _b=11, c = 13, _d=69}
for k,v in mypairs(list) do print(k, v) end
-- output:
-- c 13
-- a 5
The docs you link to have an iterator that only returns one value and pairs() returns 2, but you could return more if you want. The for ... in ... construct will only execute the body if the first value is non-nil. Here's a version that also returns the keys that were skipped, the body isn't executed if you don't end up with an actual value though so you might not see all the _ keys:
local function mypairs( list )
local f,t,k = pairs(list)
return function(t,k)
local skipped = {}
local a,b = f(t, k)
while type(a) == 'string' and a:sub(1,1) == '_' do
table.insert(skipped, a)
a,b = f(t,a)
end
return a,b,skipped
end, t, k
end
local list = {a=5, _b=11, c = 13, _d=69}
for k,v,skipped in mypairs(list) do
for i,s in ipairs(skipped) do
print('Skipped: '..s)
end
print(k, v)
end

F#: Why do two ref or boxed values holding equivalent value types equate to the same cell or obj?

let i = ref 123
let j = ref 123
i = j // true
Similarly:
let i = box 123
let j = box 123
i = j // true
Presumably, i and j are not actually pointing to the same exact place in memory...??
I get around this (odd?) behavior in the second case by doing:
obj.ReferenceEquals (i, j) // false
What is the proper equality test for the first case?
EDIT:
I see that calling obj.ReferenceEquals works in the first case, as well.
Can someone out there explain to me why I have to call this function, though? Why can't I just use the = operator?
The (=) operator calls GenericEqualityObj. It first checks the types of the args (for arrays, assignability to IStructuralEquatable, and a few other special cases) and the final case calls obj.Equals. Equals is overridden by ValueType (which int derives) to do bit comparison. That explains why (box 123) = (box 123) is true.
Ref cells are represented using records, by default records are structurally comparable\equatable

Ocaml: calling recursive function again

So I have a recursive function that takes in 2 ints, and a out_channel and basically prints line(a,a+1). It should do this until value of a is equal to b. I.e if a = 1, b = 5
line(1,2)
line(2,3)
...line(4,5)
> let rec print_line (out:out_channel)(a:int)(b:int) : unit =
if (a < b) then output_string out ("line("^string_of_int(a)^","^string_of_int(a+1)^")\n")
> ;;
I want to make it recursive where it keeps printing the line(a,a+1) until a is no longer less than b. How exactly do I call it again?
Any help would be appreciated.
So: first check whether a >= b in which case you are done and can return (). Otherwise print one line (the way you did) followed by recursive call to your function, with incremented a. So altogether:
let rec print_line (out:out_channel)(a:int)(b:int) : unit =
if a >= b then
()
else (
output_string out ("line("^string_of_int(a)^","^string_of_int(a+1)^")\n");
print_line out (a + 1) b
)

Resources