New EEP draft: Pinning operator ^ in patterns

Richard Carlsson carlsson.richard@REDACTED
Fri Jan 22 15:33:26 CET 2021


Den fre 22 jan. 2021 kl 12:57 skrev zxq9 <zxq9@REDACTED>:

> Why is using Elixir not good enough? It already exists.
>

Because there are companies with several million lines of Erlang code, and
hundreds of Erlang developers (most of whom are not on this list). The code
is not going to be rewritten in anything else. They need to keep their
current developers happy enough not to leave for other jobs with languages
that give them a better user experience, and they need to attract new
people when others leave or teams grow - new people who have to get up to
speed fairly quickly and not ragequit within a year. Fortran and C++ is no
longer the competition. Rust, Go, Swift and TypeScript is. Even Java and to
some extent Scala. Elixir has its own comfy niche in the Beam community
where it's doing great stuff, but has not yet proved itself for the
telecom-kind of large applications like at WhatsApp, Ericsson, Cisco and
Klarna.

On a side note, I don't even know enough Elixir to write a whole program in
it (not proud of that, just haven't had time - I still think of it as a
kind of Ruby), and I wouldn't have known about their ^-annotation unless
someone else had told me. To me it just seems like a pretty good solution.

I think Erlang needs to keep evolving, lest it becomes the Cobol of telecom
and the only people on this list 10 years from now are the same people as
today. We need to look honesly at where Erlang's ergonomics could be
improved, and not hold on to the survivorship bias of our own "works for me
and I've been doing it for decades" experience. The question we should be
asking is how many people went out the door again because they felt other
languages offered something better to them. Not change for change's sake,
but change to reduce friction, churn and confusion, and to enable better
tooling. Of course, safe, incremental change is the only way to do this.

It is clear that many people don't believe that ^-annotations are any good,
so that might not happen. I can live with that. I can even live without
warnings about already bound variables - I've done that for a long time.
And if we go for only the warnings and no annotations, many people will be
unhappy anyway because they may then be forced to use guards only (because
of company coding standards, or if the open source thing they contribute to
start enforcing the warnings for their code). It also becomes unlikely that
it would be possible to backtrack and add ^-annotations later on, because
by then everyone has turned their matches into guards already and won't go
through the code to change it again, so the opportunity for an easy
transition like the one I did on the OTP code base is lost.

Why not discuss eliminating shadowing entirely? Is there some reason
> this suggestion has not been addressed at all? It is a curious omission
> given that it has been brought up multiple times.
>

I think this has been at least briefly discussed in some other branch of
this thread - but it's a good point. We definitely know that there is some
confusion there, particularly with shadowing of variables in list
comprehensions (which work just like funs, for the generator patterns). For
example, some people would write

    get_all(Id, List) ->
        [X || {Id, X} <- List].

But Id is just as new as X in the pattern (you would get a warning for the
outer Id being shadowed and the inner Id being unused, though). Similar
mistakes can be made with funs, but people tend to have a better idea of
how they work.

What would happen if we'd allow already-bound variables in these patterns?
If someone uses shadowing today, it wil break their code, hard. I know it's
not common to do this and to disable the warnings for shadowed variables
but some people do it, and for them it would be a silent and breaking
change. Maybe we can sacrifice them, maybe not.

The other thing would be that you could no longer move around a fun or list
comprehension to a different location and expect it to keep working as
before - and I think that particularly for funs, this is a fundamental
assumption with most people, even if they don't use shadowing today. If you
innocently cut and paste a simple "fun (X) -> X+1 end" or "[f(X) || X <-
lists:seq(1,10)]" into another context, you have to be sure that X doesn't
exist in that context, or your fun/comprehension will quietly start to try
matching on that value instead. I think this would be too much for most
people. Adding the warning about already bound variables would tell you
this happened, at least, but you'd have to change the variable name just to
get it to work again in the new location. My instinct is that this is
something you don't want for funs.

    /Richard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20210122/b617e580/attachment.htm>


More information about the erlang-questions mailing list