Currying in Lua
I'm pretty new to Lua so please excuse any obvious oversights.
- Is there a consensus on the right way to curry an existing function (and I don't mean nested partial applications like
curry(curry(f,1),2), butcurry(f)(1)(2)). Are there any good libraries that do this? - Is there any possibility of curried functions being built into Lua? Or does it conflict with other fundamental language constructs, like varargs or something.
- One particular case that drives me crazy it that it seems really annoying to pass methods around, e.g. as a callback. It’s very easy to carry a function
a.faround, but it seems in order to pass the methoda:fyou have to writefunction(args) a:f(args) end. With currying, this wouldn’t be a problem since a:f would be syntax sugar fora.f(a). This seems to be far more intuitive and (at least to me) the “obvious” way the language should behave. Without currying, is there a simple way around this?
9 comments · 90% upvoted · other discussions
If you know the number of arguments a function uses, you can curry it the obvious way:
And use it like so:
You could define a curry5 or curry10 similarly, if you needed to. But you need to know how many arguments you are going to curry.
I see no problem with that, other than the one I mentioned before: there's no standard way to know the number of arguments a given function uses (you could do that using the debug library, but that is not supposed to be used in production code).
The way I usually overcome that particular problem is by allowing not only a callback, but also some arguments. Then I can pass the function and its "self". In other words, I end up passing
a.f, a.I'm not certain I agree with that.
a:fonly exists in Lua on the syntax layer; when it reaches the semantic layer the call is already indistinguishable from a.f(a, ...).smog_alado 2 points · Sep 2017
I could see
a:fbeing syntactic sugar forfunction (...) return a.f(a, ...) end.I the reason this wasn't added to the language yet is that it is too "magical" and would require some clever tricks on the compiler to avoid slowing down regular method calls.
flappypengujn [OP] 1 points · Sep 2017
I was hoping there would be a way to avoid defining special curry functions for every case, or passing in the argument length into the function. Now that I think about it though, as you mention that's probably impossible because Lua functions don't have a fixed argument list length.
I agree with what you said, but I'm arguing that a:f should syntactically mean something else instead of
a.f(a, ...). Namely, the following seems sensible to me:should expand to
(where [ ] is a placeholder for code),
and
a:fshould expand toa.f(a).Not only is this way more intuitive (you can use
a:feverywhere in the same way you would usea.f), but it also seems to capture the semantics of methods better: methods are just regular functions that can be "interpreted" as first being bound to an object, then accepting arguments like a normal function. That's exactly when currying should be used.smog_alado 2 points · Sep 2017
That proposed
function a:fsyntax would be a breaking change (unlike just adding thea:fsyntax sugar) but I imagine you already know that...I am not sure that having methods be automatically curried is more intuitive or natural in Lua-land. For example when we call string methods like
s:sub(1,2)it will end up callingstring.sub(s,1,2)andstring.subis a function implemented in C that just happens to takesas its first argument and it doesn't do currying or know how to do so.BTW, this reminds me of another thing. For Lua it is very important that all language features are available for C functions using the C-API. If we were to add currying to Lua and modify the VM to better support currying we would also have to think of a way to support currying on the C side of things. (one example of this philosophy is how Lua has
pcallinstead oftry/catchblocks)