2

I've been learning currying in Lua and came across the following code:

function addup(x)
  local sum = 0
  local function f(n)
    if type(n) == "number" then
      sum = sum + n
      return f
    else
      return sum
    end
  end
  return f(x)
end

print(addup (1) (2) (3) ())  --> 6
print(addup (4) (5) (6) ())  --> 15

I assume that the (1) (2) (3) () part means that the values are passed to the function in succession rather than simultaneously. My problem is that I can't quite figure out how exactly these values are passed and how the function manipulates them. So the first value goes to x, but what happens to the second? Is it passed as n into the inner function? Then where goes the third one?

My other problem is with the line:

return f

Here a function returns itself without any value or even parentheses. I know that you can pass in a string or a table to a function omitting the parentheses but it is not the case here. So what's going on?

I looked in the manuals but didn't find anything on either of these features. I'd really appreciate an explanation or a link to a manual that covers this in detail. Thanks.

Update: link to the tutorial I referred to - http://lua-users.org/wiki/CurriedLua

As it was pointed out in one of the anwsers, there is no (x)(y) syntax in lua. What it is, is a series of function calls. This wasn't actually mentioned in the tutorial but was my assumption which turned out to be wrong, so I edited this bit out.

The issue is solved. Thank you for all your answers, they were very helpful.

2
  • please link the tutorial you referred to Commented Jun 23, 2020 at 6:03
  • That example is actually wrong. You can't do, for example add5=addup(5); print(add5 (3) ()); print(add5 (2) (), as it would print 8 and 10 instead of 8 and 7. Commented Jun 23, 2020 at 10:45

4 Answers 4

2

There is no (x)(y) syntax in Lua. That's why you don't find anything in the manual. (x)(y) on its own will cause a syntax error

addup (1) (2) (3) () is a sequence of function calls. To understand this you have to carefully read addup's code and realize that a function call is nothing but a function value followed by the call operator and that functions are just values that you can return as any other type.

This expression is evaluated from left to right.

The call operator () operates on the value to its left. So first we evaluate addup(1) which calls the global function addup.

addup defines a local number value local sum = 0 and a local function value f.

local function f(n)
    if type(n) == "number" then
      sum = sum + n
      return f
    else
      return sum
    end
  end

and then returns the return value of that function called with addup's argument x

return f(x)

sum is an upvalue to f, that's a value that was in scope where f was defined. so every time you call f it has access to sum.

So n becomes x in function f. As n is a number value f will add n to sum and return a itself f.

So addup(1) evaluates to a reference to f, a function value with the upvalue sum == 1.

Now we have this returned function value to the left of (2) which is another function call to f. This time n is 2. Again it is a number so it will be added to sum and f will return itself again.

Now f is called with (3). Same as above.

Finally f is called with (). This time n is nil and f returns sum. So addup (1) (2) (3) () ultimately evaluates to 6 befor it is handed to print.

Not sure where you got that example from but doesn't make too much sense to me. There are simpler ways to explain upvalues and closures. Code like that is unecessarily hard to read.

Sign up to request clarification or add additional context in comments.

Comments

2

something like this, by analogy:

local _L = {}
function addup(x)
  local sum = 0
  _L["f"] = function (n)
    if type(n) == "number" then
      sum = sum + n
      return _L["f"]
    else
      return sum
    end
  end
  return _L["f"](x)
end

print(addup (1) (2) (3) ())  --> 6
print(addup (4) (5) (6) ())  --> 15

"return f" - returns a reference to a function inside the local namespace, which is just a table.

Comments

2

addup is only called once. the returned function, f, is what is called each time after addup (1)

sum is an upvalue to f once f is defined each call to f updates the same sum variable. this is how the function remembers the running total.

heres another way to write the first sequence

local sumfunction = addup(1) --Creates the function and also calls it with `1` first time sum is updated
sumfunction(2)               --Calls function with `2` updating the sum
sumfunction(3)               --Calls function with `3` updating the sum again.
print(sumfunction())         --Called with no arg causing the function to return the sum

done like this the return value of f could be removed completely, with a change to addup and 1 more call.

The return value is needed to chain the calls like in the original code addup (1) (2) (3) () otherwise the syntax is invalid.

Comments

2

Here a function returns itself without any value or even parentheses. I know that you can pass in a string or a table to a function omitting the parentheses but it is not the case here. So what's going on?

In Lua, functions are just values.

You can call them like this:

print("Hello, World!")

but you can also assign them to variables like this:

foo = print
foo("Hello, World!")

or pass them into other functions as arguments and return them:

function call_twice(f)
   return function()
      f()
      f()
   end
end

call_twice(function()
   print("Hello, World!")
end)

in fact,

local function foo() return 42 end

is just an alternative way of writing

local foo
foo = function() return 42 end

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.