[Proposal] Control block with annotations and no commas

103 views
Skip to first unread message

niahoo osef

unread,
Jul 23, 2017, 4:06:04 PM7/23/17
to elixir-lang-core
Hi, 

I would like yo know your opinion about cunstructs like this one. I guess this is not a priority for Elixir, and I know I can add it to Hex.pm. I'm just unhappy with the `with` block and I want to know what you think.

I made a simple implementation here : https://github.com/niahoo/ctrl with detailed information of the annotation feature.

Basically it's a `with` block but with standard block syntax and match selection with tags :


ctrl
do
 
{:ok, state} <- init()                              # Classic `with` clause
 
%{id: id, opts: opts} = state                       # Any expression
 
:ok <- register(id)
 
:f_repo | {:ok, repo} <- Keyword.fetch(opts, :repo) # Tagged match
 
:f_user | {:ok, user} <- Keyword.fetch(opts, :user) # Different tagged match
 
{:ok, do_something(id, repo, user)}
else
 
{:error, _} = err -> err                            # Errors with info
 
:f_repo | :error -> {:error, :no_repo_option}       # Errors on :repo only
 
:f_user | :error -> {:error, :user_not_set}         # Errors on :user only
end



Thanks for reading :)
Message has been deleted

Burdock

unread,
Jul 23, 2017, 6:51:40 PM7/23/17
to elixir-lang-core
I feel like adding a new macro this similar to with would just bloat the Elixir spec. That being said, adding shorthand for tagged matches would be nice as long as it doesn't pollute the spec. 
Personally, I don't like the idea of adding new syntax to describe this.

That being said, if in Elixir 2.0's with used newlines instead of commas to delineate sections, unwrapped keyword list syntax would be usable. 

with all: {:ok, users} <- all: cashed_users()
     best
: {:ok, user} <- best: get_best_user(users)
do   state
else all: {:error, msg} -> dostuff
     best
: {:error, msg} -> dostuff


This is existing syntax and is instantly recognizable by someone familiar with Elixir.

Personally, I think this is the best option. But as far as I am aware there is no way to avoid the commas without moving everything after the do

Paul Schoenfelder

unread,
Jul 23, 2017, 7:04:41 PM7/23/17
to elixir-l...@googlegroups.com
I'm not clear on the benefit here, why not just wrap the with expressions in a tuple for tagging? It's basically the same amount of code, doesn't require any new syntax, and accomplishes the same goal.

In my opinion with is already the most complex syntactic construct in the language, adding even more complexity for basically no additional benefit is something to avoid as much as possible.

Paul

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/3c8eca18-fc6c-4317-a81b-5b83f4978279%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

niahoo osef

unread,
Jul 24, 2017, 4:09:32 AM7/24/17
to elixir-lang-core
"Why not just wrap the expressions in a tuple ?" Well because you have to wrap both sides and mess with those commas, which is annoying for editing code and adds noise for the reader. Tags, on the other side, are clearly identified as tags, a branching mechanism that is separated from the expressions you want to match.

The `with` block is not that complicated, we could even think about adding support for left arrow notation, the `with` block beeing just a specific case

"I feel like adding a new macro this similar to with would just bloat the Elixir spec." Well I was more thinking about extending with (allowing this syntax when used in the do block) instead of adding a new block.

Using keyword notation wraps everything in lists, I think it's way less clear.

Thank you both for comments :)

Paul Schoenfelder

unread,
Jul 24, 2017, 7:48:43 AM7/24/17
to elixir-l...@googlegroups.com
The `with` block is not that complicated, we could even think about adding support for left arrow notation, the `with` block beeing just a specific case

It's not complicated for those of us who have the benefit of already knowing the language inside and out, but it is absolutely a complicated construct for new users of the language - it combines several new and old concepts, a unique arrow notation (like `for`, but different), pattern matching in the else block (like `try`, but new to anyone coming from other languages or unaware that they can use else there), the semantics of how it handles failed matches is also unique (and of course the reason why it exists at all), you have to know that expressions are comma separated, not broken up by newlines, and there are other small details one has to learn. It's one of the most powerful constructs in the language, and important to learn, but adding yet another layer to it makes it feel overloaded to me, it will be confusing to beginners trying to read code using it (and they'll likely already be confused when they see it initially). Once you are familiar with it, it's no problem, but it's very important to consider that aspect. Constructs should compose so that as you learn the basics, more complex constructs can be seen as building on what you've learned to provide more expressive power - they slowly reveal themselves as you learn the basics so that by the time you get to it, you already have a grasp of what it probably does and what problem it solves (or at least that's the ideal in my mind)

My main beef with this is that the tags concept would only be used here - I can't see any other place where it could be applied, and everything else about `with` is present in at least one other area of the language. In my opinion that's what makes this proposal seem out of place. Additionally the syntax is used in typespecs to represent alternations. That alone isn't a huge deal, but will lend to confusion around what the syntax is trying to express. If anything I'd think `pattern :: tag` would be a better fit for the syntax, since it's annotating something, much like we do with the bit syntax and in typespecs. Even with that change though, I don't think it really fixes the issues I've raised.

I agree that tagged tuples are not as succinct,  but they are easy to understand, and they aren't *that* verbose. Is it really worth making an already complex construct even more so for relatively little gain?

I think it's an interesting idea anyway, and at the very least made me wonder how I'd want to solve it, and that's always a fun exercise :)

Paul

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

niahoo osef

unread,
Jul 24, 2017, 9:24:38 AM7/24/17
to elixir-lang-core
Tags are not very important, I agree with you for them being overkill and having them just in one particular place is not satisfying. That being said, it's an advanced feature that a newcomer can just ignore. It does not make the current features worse. The other issues you raise about the with block are there because this block is specific. It can be rewritten to a block with standard syntax (and add tags later or forget them).

My main point is that the `with` contruct allows for very erlangish error handling and promotes good practices, but its current syntax feels a bit arcane, as you've said, so it should be changed to be more accessible.

I'm glad if I gave you some fun :)

OvermindDL1

unread,
Jul 24, 2017, 12:26:25 PM7/24/17
to elixir-lang-core
It sounds like you want happy:  https://hex.pm/packages/happy

Tallak Tveide

unread,
Jul 24, 2017, 6:21:41 PM7/24/17
to elixir-lang-core
I dont like it. Its too flexible. I believe the code becomes unwieldy as you can mix s lot of different stuff into the ctrl block.

I believe this construct may promote complex code.

Why do we need this? Elixir has excellent patten matching support that is lightyears ahead of the C class of languages. Better than a more flexible with statement is to split the code into smaller chunks.

Sorry, my humble opinion. To be fair, I did not go into great depths to learn how the code works, and might have missed something.

niahoo osef

unread,
Jul 25, 2017, 3:57:35 AM7/25/17
to elixir-lang-core
Hi Tallak, 

The functionality is the same as the `with` block where you can also mix very different stuff. The only difference is the do/block/commas layout and I added a shorthand to tag tuples easily.

Thank you for your comment

Tallak Tveide

unread,
Jul 25, 2017, 5:09:55 AM7/25/17
to elixir-lang-core
Ok. Now I understand more.

I believe the use of '|' is new?

Tallak

niahoo osef

unread,
Jul 25, 2017, 8:26:13 AM7/25/17
to elixir-lang-core
Yes, it was a proposal for the tagging, but as it has been said, it may not be a good symbol choice.
Reply all
Reply to author
Forward
0 new messages