torimus

torimus

Hello.

I’m relatively new to Elixir, but not to programming generally.

In the learning process I’ve been recently struck with following inconsistency, at “capturing” an anonymous function with & operator:

iex> &(:just_return_this_atom)
** (CompileError) iex:350: invalid args for &, expected an expression in the format of &Mod.fun/arity, &local/arity or a capture containing at least one argument as &1, got: :just_return_this_atom

I’ve read the docs, where the limitation is stated:

The only restrictions when creating anonymous functions is that at least one placeholder must be present, i.e. it must contain at least &1 , and that block expressions are not supported:

What is the rationale behind this limitation ? I’ve already searched some mailing lists but so far no satisfactory explanation has been found.

I’m aware by choosing unary ampersand operator for converting both - normal expression and function name with arity - to Function instance, already did introduced ambiguity itself. In addition, by choosing slash operator both - for arithmetic division and separator between function name and its arity, only made it worse.

As far as I know, function_name/arity_num is not even valid token itself and does exist only for the sole purpose of capturing with &. Just in this single special case.

Are there some plans, work in core dev to fix above described inconsistency in some major release, like 2.0 ? Or find it as unsolvable problem without breaking backward compatibility and accepting damage has been already done ?

I’d probably need dive deeper into Elixir’s parser, but so far I’d imagine it could be handled with fixing operators precedence incl. parens and capturing function_name/arity_num would always require explicit enclosing in parens.

Showing Posts 1 to 6

rodrigues

rodrigues

Hi @torimus, welcome to the forum!

I don’t know why it’s like this, if there’s any technical reason, but I suspect it’s intentional, a language design choice.

For some time I also liked the idea of the capture operator working without &1, but now I see it potentially bringing confusion, this ends up helping to bring clarity and consistency to elixir code IMO.

Some meta examples where I see it becoming cryptic or misleading:

# this "lispy wrapping" could become very confusing, specially for beginners
[&(42), &(nil), &([]), &(:foo), &(@foo), &(foo), ...]

# & easily unnoticeable
[&%{foo: :bar}, &"wut", &[1, 2, 3]]

&fun(1) # easy to mistake with fun(1) or &fun(&1)
&Mod.fun() # easy to confuse with Mod.fun(), &Mod.fun/0 wins IMO
&Mod.fun(a, b) # easy to confuse with Mod.fun(a, b)
hauleth

hauleth

name/num is perfectly valid and token and can be used for division. Which mean that in situation like:

f = &(a/2)

The compilation need to “deduce” whether a is a function or not.

Another reason can be the fact that &foo(1) and &foo(&1) can be easily confused one with another and could lead to strange bugs.

torimus

torimus OP

name/num is perfectly valid and token and can be used for division. Which mean that in situation like:

Yeah, I’ve meant standalone expression in function_name/arity meaning. I was not too clear, my bad.

f = &(a/2)
The compilation need to “deduce” whether a is a function or not.

Another reason can be the fact that &foo(1) and &foo(&1) can be easily confused one with another and could lead to strange bugs.

Right. Abuse of function argument reference &n for “deduction” purposes seems the true reason. Forcing existence of at least one reference signalizes function body else expression is considered as function/arity specification.

defmodule MyMod do
  def zero_arity_fn(), do: 42
end

# myfn = fn -> zero_arity_fn() / 2 end
# anon. function capture attempts:
myfn = &zero_arity_fn/2    # BadArityError
myfn = &(zero_arity_fn() / 2)    # BadArityError
myfn = &((zero_arity_fn()) / 2)    # BadArityError
# can't mix function specifier with body 
myfn = &((&zero_arity_fn/0) / 2)    # CompileError - nested captures not allowed

# Forced explicit declaration of argument reference allows parser cheat ...
myfn = &zero_arity_fn/&1    # "deduction"

#IO.inspect myfn.()
IO.inspect myfn.(2)    # 21.0

I don’t know guts of Elixir parser, not sure what solution would be possible while not introducing another inconsistency at the same time.

&<expression> or &(expression) - capture anonymous function body by default
(&expression/expression) - edge case of capturing function_name/arity
or
&:function_name/arity: - atom-like specifier to capture existing function, inspired a bit by Ruby’s Symbol#to_proc

peerreynders

peerreynders

https://groups.google.com/d/msg/elixir-lang-core/3HVYGqimS9o/8x9L6PNeHewJ


https://github.com/pragdave/elixir-fx

torimus

torimus OP

Thanks for the link to related discussion.
I can live with that, but it only leaves a bitter taste.

  • named functions can have zero or more arguments
  • anonymous functions can also have zero or more arguments
  • operator & does convert(capture) named function to anonymous Function instance, that function still can have zero arguments
  • operator & does also convert(capture) single expression to anonymous Function instance, that function now illogically can not have zero arguments
  • by mixing apples with oranges, & operator obviously introduced exception to the rule, but hey having cool-looking syntax is worth the hassle. Or not ? You won’t need zero-arity that much anyway. Or would ? Use full syntax for anon. functions then. But there is & macro … :zipper_mouth_face:
hauleth

hauleth

& operator when used as a sugar for generating lambda has more limitations, for example this is illegal:

fun = &(&2)

As you need to use all arguments within such lambda body. So no, there is no exception to the rule as &function/arity is something completely different from & &1 lambda as these will behave differently. First one will cause call to function/arity while second will expand to fn a -> a end which will expand even further to generate function with generated name, for example :'-lambda-line-1-arity-1'/0 which will be internally used by the compiler. So yes, there is huge difference between these two.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 92995 915
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
GES233
I’m posting this in response to Jose’s recent tweet (Cr. link) : People are sleeping on Elixir for a coding harness: Hot-code swappi...
New
_mfierro
Hello, I wrote Stop My Hand, a Scattergories-like web application using Phoenix/LiveView as my learning project for Elixir (after readin...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews