[erlang-questions] Orthogonality and Principle of least surprise Was: chained functions

Fred Hebert mononcqc@REDACTED
Wed Feb 1 22:00:25 CET 2012


The following concepts are functions or things that can be interpreted as
functions:


   1. fun([Args]) -> ... end (declared in the shell / eval'd)
   2. fun([Args]) -> ... end (compiled)
   3. fun Name/Arity
   4. fun Mod:Name/Arity
   5. {Mod, Fun}(Args) (to be deprecated)
   6. ModAsVariable:FunAsVariable()
   7. FunAsVariable()
   8. apply(Fun, Args)
   9. apply(Mod, Fun, Args)


In the case of the two first ones, the scope of the function depends on
where it's coming from and so I can expect the call to be local.

For the 3rd and 4th ones, there is a very clear distinction between a local
call and a fully qualified call. The module name is obvious, and the arity
lets me know I'm pointing to a known function, and not just a name.

For the 5th and 6th ones, there is no doubt about whether I'm declaring
something to be a local or a fully qualified call. It's going to be the
latter.

For the 7th case, we have a funny possibility. It looks like what we're
doing is defining a local call, but the result is entirely depending on
whether I'm passing in {Mod,Fun}, a fun, fun Name/Arity, fun
Mod:Name/arity, etc. This is an entirely transparent way to make any kind
of call, as long as we know how many arguments we have.

The 8th case is the same as the 7th one, except the number of arguments is
unknown and variable.

The 9th case is obviously a fully qualified call, but the number of
arguments isn't known first hand.

With this being said, where does Mod:Fun as a syntax stand? I don't think
it would be semantically outrageous given it fits the use cases 7 and 8
quite well. I still don't think it could be the best thing to do, though.
Why? there are a two big issues I see with it:

I don't think it shows a clear gain in readability or maintainability. All
the cases above have different uses, different purposes. At most, Mod:Fun
is a shortcut to save typing time, without clear maintainability advantages
or even learning advantages. It doesn't do anything different than any of
the many forms that already exist. It's more syntax for a use case we
already have a solution for.

Secondly, it can't have a counterpart when it comes to local calls. I can't
just pass 'atom' and expect to be passing a local function reference --
otherwise we'd never know if what we're passing (whether it's an atom or a
function). This is the biggest problem to me.

We'd create a short form to avoid fun Mod:Name/N, but we have no equivalent
for fun Name/N. This is a gaping hole in what can be done with the language
and can be even more confusing, IMO. A good solution to simplify the syntax
should do it well, not in an incomplete way that creates more
inconsistencies in the language.

I think adding it would break more programmer expectations than not having
it.

On Wed, Feb 1, 2012 at 11:29 AM, Jakob Praher <jakob@REDACTED> wrote:

Am Mittwoch, 01. Februar 2012 15:04 CET, Alisdair Sullivan <
> alisdairsullivan@REDACTED> schrieb:
>
> > functions in erlang are identified by their name and their arity
> >
> > 'F = module:fun()' is ok because the arity, 0, is implied by the
> arguments
> >
> > 'F = module:fun' is not okay because it does not refer to a specific
> function. you need to tell the compiler which function you wish to call.
> hence the 'fun module:fun/n' syntax
>
>
> IMHO it depends what one is trying to achieve. From an operational point
> of view I am fine with having a "function reference" as something that can
> be called if applied with concrete arguments. Hence I do not require a
> funciton object in the sense that it represents the function itself.
>
> If one wants to make sure that the right function is targeted one could
> always write it like: "F = module:fun/N", which is not something I am
> thinking of.
>
> With the exception of currying, where the arity of the function arguments
> vs the actual arguments differs, it suffices to just apply the actual
> arguments to the matching function.
>
> E.g.
>
> map([],_) -> [];
> map([X|Rest], F) -> [F(X) | map(Rest, F)].
>
> > map([1,2,3], math:square).
> [1,4,9]
>
> This is a more lazy / symbolic usage of functions.
>
> Best,
> Jakob
>
> > _______________________________________________
> > erlang-questions mailing list
> > erlang-questions@REDACTED
> > http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20120201/f5debb68/attachment.htm>


More information about the erlang-questions mailing list