
Erlangers, Use Labels - kumaranvpl
http://zxq9.com/archives/1337
======
athenot
> Which versions force your eyes to do less jumping around?

Maybe I'm weird but the author's first examples are easier to read. Having
labels is good when there is a non-trivial nested mess, but nothing comes for
free. When the idiom is well-understood, being overly explicit ends up with
more noise. In the first examples, I'm looking at 1 paragraph of code and
understand what's going on. In the supposedly improved examples, labels force
a mental dereferencing and a jump to different code paragraphs. Sometimes I
don't want to scroll throughout the file (or lookup references) to understand
something that's logically part of the same unit of processing.

Of course if the lamdas end up doing a lot of work then the overall structure
gets lost and a label would be the right thing to do. But code is no exception
to the rule "write for your audience". In this case, the audience is the
compiler and humans which are versed in the idioms and style of that
environment.

~~~
ams6110
Agree entirely. My eyes are jumping around most on his last, "preferred"
version.

------
chriswarbo
This kind of thing is always a balancing act.

There's the argument that implementation details should be hidden, therefore
separate named functions should be defined and their behaviour should be clear
from the name. In my experience, those who go too far in this direction may
not be used to first class functions; for example, I worked on a PHP project
which dated way before the addition of closures, and even their JS had no
lambdas: all functions, even trivial one-liners which were only used once,
were given top-level, globally-scoped names, defined all together in a
separate file.

There's the argument that each expression shouldn't do too much, hence pulling
a lambda out into a (locally scoped) name.

There's the argument that variables which are only used once should be written
inline to avoid the mental cost of indirection.

There's the argument that values should have the tightest possible scope.

There's the argument that common 'utility functions' should be pulled out to a
separate place.

In situations like this, I usually favour doing the 'real work' in a locally
scoped function, and writing the argument-plumbing inline. That lies somewhere
in between the author's "labelled_lambda" (tightly scoped definitions, but
conflates processing with argument juggling) and "isolated_functions"
(separates processing from argument juggling, but has a wider scope).

PS: Having only dabbled in Erlang, to me the real problem exposed by those
examples is the lack of a combined lambda/case, e.g. as (eventually) found in
Haskell [https://unknownparallel.wordpress.com/2012/07/09/the-long-
an...](https://unknownparallel.wordpress.com/2012/07/09/the-long-and-epic-
journey-of-lambdacase-2/)

~~~
geocar
> PS: Having only dabbled in Erlang, to me the real problem exposed by those
> examples is the lack of a combined lambda/case,

All lambda in Erlang is case:

    
    
        do_whatever(Keys, SomeParameter) ->
          Lookups = lists:map(fun external_lookup/1, Keys),
          lists:foreach(fun
            ({ok, V}) -> do_side_effecty_thing(V, SomeParameter);
            ({error, R}) -> report_some_failure(R)
          end, Lookups).

~~~
strmpnk
I came away with a similar reaction, but there is no need to map separately
first:
[https://news.ycombinator.com/item?id=13136056](https://news.ycombinator.com/item?id=13136056)

Sometimes I do wish Erlang had something like F#'s active patterns because
it'd make this sort of thing trivial to add to standard pattern expressions.
Maybe someday I'll figure out how to add it myself.

------
kwhitefoot
I agree with the sentiment but a better example should have been chosen. The
first example given is very easy to read and not at all confusing while the
last is much more verbose and hence harder to parse for non-experts.

I see that for serious Erlangers it would make a lot of sense but for people
like me who only dabble in it the first is probably as easy or even easier to
read than the rest. And the ones using list comprehension are the worst
whether they use named functions or not.

------
spdionis
Why not

    
    
      do_whatever(Keys, SomeParameter) ->
        lists:foreach(fun(Key) -> maybe_do_stuff(Key, SomeParameter) end, Keys).
      //...
    

Still simple, wins a line, removes the ugly ExecIfFound name

------
strmpnk
There might be a good alternative. Sometimes it's that one function right in
the case expression that prevents lifting the matching to the function head
(which is considered good style in Erlang).

To do this you could try wrapping the list:foreach itself rather than worry
about the inner function, leading to something which seems more concise and in
one piece, leaving the more generic iteration to a well named function:

    
    
        -spec do_whatever(Keys, SomeParameter) -> ok when
            Keys :: [some_kind_of_key()],
            SomeParameter :: term().
        do_whatever(Keys, SomeParameter) ->
            lookup_each(fun
                ({ok, Value}) -> do_side_effecty_thing(Value, SomeParameter);
                ({error, Reason}) -> report_some_failure(Reason)
            end, Keys).
    
        lookup_each(Fn, Keys) ->
            lists:foreach(fun (Key) -> Fn(external_lookup(Key)) end, Keys).

------
andybak
Would I be correct in thinking this is a similar argument those put forward by
GvR against the desirability of multi-line lambdas in Python? i.e. once you
need multiple lines then you probably should be naming them.

~~~
noselasd
Yes. There's no pride in jamming the most amount of code into one line unless
you're entering a contest.

~~~
chriswarbo
Surely it's the current one-line* restriction which forces "jamming the most
amount of code into one line".

Allowing multiple lines, by definition, allows breaking up those lines.

* It's not actually one-line, it's one expression; Python's just picky about where you're allowed to break up an expression over multiple lines. For example see [http://softwareengineering.stackexchange.com/questions/99243...](http://softwareengineering.stackexchange.com/questions/99243/why-doesnt-python-allow-multi-line-lambdas/252546#252546)

~~~
randallsquared
I don't think GP meant one editor line, but one "line of code".

------
nicoster
for the list comprehension, why not

``` do_whatever(Keys, SomeParameter) -> [case external_lookup(Key) of {ok, V}
-> do_side_effecty_thing(V, SomeParameter); {error, R} ->
report_some_failure(R) end || Key <\- Keys], ok. ```

or

``` [begin some_func(Key), other_func(Key) end || Key <\- Keys]. ```

if only the value of other_func() needs to be in the result list.

~~~
masklinn
FWIW HN does not do markdown[0], let alone markdown extensions like triple-
backtick code blocks.

[0] it implements a very small subset of markdown badly: emphasis (with no
escape so it tends to break when you try to use multiplication signs in your
comments) and indented "code" blocks

~~~
dragonwriter
HN works fine with multiplication signs ("×"), it's asterisks that are
problematic.

