other annotations

zxq9 zxq9@REDACTED
Fri Jan 29 00:10:54 CET 2021


On 2021/01/28 22:17, Raimo Niskanen wrote:
> On Thu, Jan 28, 2021 at 01:43:00PM +0100, Loïc Hoguin wrote:
>> On 28/01/2021 13:11, Richard Carlsson wrote:
>>> Den tors 28 jan. 2021 kl 11:23 skrev Loïc Hoguin <essen@REDACTED
>>> <mailto:essen@REDACTED>>:
>>>
>>>      By the way, if annotations are going to be a thing, it might be a good
>>>      idea to make them more general so we can annotate other things, such as
>>>      "pure function" / "side effect function" or "local send" / "remote
>>>      send". I would personally love to easily identify message sends to
>>>      remote nodes.
>>>
>>>
>>> These are also interesting things - maybe not inline but perhaps as
>>> keywords on function definitions; we had some ideas about marking
>>> functions as pure (for guards) back in the HiPE project, for example.
>>> Like any kind of strict typing, you then get into the question about
>>> such functions in other modules: If they can only be used locally, the
>>> feature is perhaps too limited to be worth it. To put them in other
>>> modules, you'd probably need to do name mangling like e.g. when linking
>>> C++, to ensure both caller and callee are following the conventions, and
>>> that might get too messy. I don't know anyone who has prototyped that,
>>> though, so it's not clear how it would look and feel.
>>
>> Considering the small number of already bound variables used in a match,
>> it might be more appropriate to make this a keyword as well. Or have a
>> longer form, for example "^match Var". Then you can have "^pure
>> function() -> todo.", "^remote Pid ! Msg" and so on. With the annotation
>> being added as metadata and usable by the compiler, parse transforms or
>> other tools (allowing custom annotations the compiler doesn't otherwise
>> understand).
>>
>> Other options could be "match^Var", "pure^function()" "remote^Pid !
>> ...", or "match::Var", ":match: Var"...
>>
>> The added advantage is that you're explicitly writing that this is a
>> match rather than relying on people's understanding of what ^ means.
> 
> That is an interesting idea.
> 
> {ok, ^Var} = foo(),
> {ok, match^Var} = foo(),
> 
> More verbose, but not terribly.  Still next to the variable. and no
> intermediate variable is needed.  Maybe even clearer.
> Opens up for other annotations.
> 
> Then ^ would be the annotation binary operator.

This is way more clear. And also makes it something new users could 
*search* for.

As for pure functions VS side effecty functions... My idea on that is to 
make them typespec annotations that Dialyzer can check:

-spec side_effecty_fun() -> ok.

-pure pure_fun(integer()) -> {ok, float()}.

or similar.

Note that allowing Dialyzer to actually handle this would require 
adjusting every pure function in the standard library. Not a hard task, 
but certainly a large one.

As for remote VS local send... need to think about that one a bit.

While the above would resolve some of my arguments against the "pinning" 
issue, I can't shake the feeling that the real solution would be to move 
forward with the direction we *already* have moved in Erlang (as regards 
shadowing, specifically): Eliminate shadowing entirely and make the only 
thing possible a match.

One Scope To Rule Them All is much more Erlangish than needing to add an 
annotation and we already have a warning about shadowing as it is nearly 
always an accident. We don't require an annotation for a match/assertion 
anywhere else in the body of a function, so why only in a lambda *head* 
only or an iterative assignment in a list comprehension?

Since we already have a warning, I believe it would be cleaner to enable 
a compiler mode that removes shadowing and eventually make that the 
default (and leave open the option to use a compiler mode that still 
only warns).

Principles matter, and while I could groan and go along with a new 
concept of variable annotations, I believe this will eventually take us 
down a stupid road and warn against it. Any new thing will get abused by 
people hypnotized by the Good Idea Fairy. Language design is hard. All 
additions to a language increase its complexity. New users who find 
Prolog syntax a bit icky will *definitely* find putting what looks like 
the pow operator between a keyword that by the language's core 
definition should be redundant and a variable name ultra icky (if 
anything `shadow^VarName` should be the special case rather than 
`match^VarName`).

Anyway, interesting idea. Much more interesting than "let's just throw 
an unused ASCII char at it!"

-Craig


More information about the erlang-questions mailing list