Short form of lambdas for zero arguments and unused arguments proposal

79 views
Skip to first unread message

ivan.y...@gmail.com

unread,
Aug 21, 2024, 2:03:24 AMAug 21
to elixir-lang-core
I realize it might be controversial, but I truly enjoy short form lambdas in any language I touch and Elixir is one of them. Yet I think there's a couple of use cases that are uncovered. One is when you need to encode a zero argument lambda returning a value and the second one is when there are more arguments than actually used:

iex(1)> &(&2 + 1)

error: capture argument &2 cannot be defined without &1 (you cannot skip arguments, all arguments must be numbered)

└─ iex:1


** (CompileError) cannot compile code (errors have been logged)


iex(1)> &(1)

error: capture argument &1 must be used within the capture operator &

└─ iex:1


** (CompileError) cannot compile code (errors have been logged)


I think both of these cases would be handled if we let explicitly defining the arity of lambda: &2(&2 + 1) or something like that. Since nested lambdas are not allowed anyways, this should work (unless I'm missing something). And we'd assume if there's no access to the variables, it would be a zero argument function, so &(1) would work too.

This should be fundamentally possible, since I can do this:

iex(9)> fn () -> :ok end

#Function<43.105768164/0 in :erl_eval.expr/6>

iex(10)> fn (_a, b) -> b * 2 end

#Function<41.105768164/2 in :erl_eval.expr/6>


So I assume it boils down to parsing? Either way, I'd love to see that in Elixir and I'm willing to contribute some time to get it implemented if the community approves it.

Ben Wilson

unread,
Aug 22, 2024, 1:19:37 PMAug 22
to elixir-lang-core
Hey Ivan,

You're just missing the introductory &

iex(1)> & &1 + 1
#Function<42.105768164/1 in :erl_eval.expr/6>

Ivan Yurov

unread,
Aug 23, 2024, 2:06:05 AMAug 23
to elixir-l...@googlegroups.com
The lambdas I want to be able to create using short notation are in the second block of code in the original posting. They are slightly less obvious than  & &1 + 1.
As far as I understand, there's no way to compose them using short form, unless I'm missing something. The idea to supply a number of arguments along with introductory & is probably not gonna fly — it would look too similar to argument itself, although there shouldn't be any ambiguity with parsing since nested short form lambdas are not allowed anyways. Maybe &/2 which would be consistent with captures?


--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/g2tQI1FjcNU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/11ca2681-4b0e-4875-ac48-455a5e684f6en%40googlegroups.com.


--
Kind regards,
Ivan Yurov

José Valim

unread,
Aug 23, 2024, 2:16:47 AMAug 23
to elixir-l...@googlegroups.com
Thank you for the proposal.

Some would already say the capture syntax is already too concise (and they would always prefer fn instead), and the proposal would introduce ambiguity to them, given that &2 would have different meanings depending on where it is located. One of the big rules in Elixir is that, when we give syntax affordances, such as the capture operator, we keep its usage rules clear and this extension would violate that (in my opinion).

You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAAoaZy4gPokWC7urFA7sjqHzL%3DyVKdkHqGd6PM_Sc5o0MDtVGg%40mail.gmail.com.

Ivan Yurov

unread,
Aug 23, 2024, 5:53:11 PMAug 23
to elixir-l...@googlegroups.com
I agree it's controversial, but it's certainly not too short: here's the example of how Scala does it https://docs.scala-lang.org/scala3/book/fun-anonymous-functions.html, if I remember correctly Haskell has something like that as well, but it might be powered by currying, so not exactly related to lambda notation.

Can you give some examples of where it could be ambiguous, please? I agree that declaring arity explicitly along the introductory & might be cumbersome (yet if it's optional, then no harm to existing code is done), but how about zero argument lambdas? I understand that &1 would be ambiguous, but &(1) wouldn't. Or am I missing something? Perhaps other special uses of &?

José Valim

unread,
Aug 23, 2024, 6:20:06 PMAug 23
to elixir-l...@googlegroups.com
It is ambiguous in the sense it now requires context. when I see &2, I will no longer know what it means without also analyzing its surrounding context. It means that every time I scan &2 in a line, I need to think which one of its two uses is being applied.

Ivan Yurov

unread,
Aug 23, 2024, 7:44:43 PMAug 23
to elixir-l...@googlegroups.com
Right. Sorry, please ignore the proposal to use &X to denote arity, the intent was to rather test the idea to be able to do that in general, not a particular syntax that would facilitate that. Using &/X might be a better candidate since it reflects the arity just the same way function capture does (minus function name, which totally makes sense in case of an anonymous function). Yet there might be way better candidates which can be discovered through discussion I'm sure, if the community is in favor of such extension in principle.

Michael Neumann

unread,
Aug 24, 2024, 3:25:36 AMAug 24
to elixir-l...@googlegroups.com

Hi,

You could use a function that manipulates your function:

def shift_args(f), do: fn _x, y -> f(y) end

Now, with that, your proposed:

&(&2 + 1)

becomes

shift_args(&(&1 + 1))

This is just food for thought. In my opinion, it's often better to just resort to good old functions:

fn _, x -> x + 1 end

In Haskell, you get away with "end" due to indentation sensitivity, and they use the "\" to construct a lambda (it looks like Greek lambda letter :)

\_, x -> x + 1

Or uncurried:

\_ -> \x -> x + 1

So if at all, I would like of a way to reuse or "fn" literal without the verbose "end". That likely requires parenthesis, so you really would only save one character in the end.

You might also try to mess around with macros. So I think something like below could work:

f(_2 + 1, arity: 2)

The macro "f" would translate that into:

fn _, arg_2 -> arg_2 + 1 end

Just be aware that you'd need to do the variable substitution correctly :).

Regards,

Michael


Ivan Yurov <ivan.y...@gmail.com> schrieb am Sa., 24. Aug. 2024, 01:44:
Right. Sorry, please ignore the proposal to use &X to denote arity, the intent was to rather test the idea to be able to do that in general, not a particular syntax that would facilitate that. Using &/X might be a better candidate since it reflects the arity just the same way function capture does (minus function name, which totally makes sense in case of an anonymous function). Yet there might be way better candidates which can be discovered through discussion I'm sure, if the community is in favor of such extension in principle.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

Bruce Tate

unread,
Aug 24, 2024, 11:19:18 AMAug 24
to elixir-l...@googlegroups.com
This is so important, not on a case by case basis but in aggregate. 

-bt



--

Regards,
Bruce Tate
CEO

Reply all
Reply to author
Forward
0 new messages