Roslyn: new 'reverse arrow' operator to making arrow expressions more powerful

Created on 6 Nov 2016  路  11Comments  路  Source: dotnet/roslyn

With new operator <= the code like

// very popular idea - send your custom action to the reusable wrapper and context provider 'handle';
handle(dbContext=>
                {
                    dbContext.Remove(entity);
                });

would be possible to wrote without hunting the last ) parentheses:
handle <= dbContext=> dbContext.Remove(entity);

Additionally:
more complex use case, wrapper constructed from two steps:

routine( errorParserFactory =>
errorParserFactory(entityModelDescription).handle(dbContext => 
{ 
   dbContext.Update(entity)
});
)

can be encoded:

routine <= errorParserFactory => errorParserFactory(entityModelDescription) =>handle <= dbContext => dbContext.Update(entity)

Alternatively "reverse row" operator can be expressed with characters =< or even with colon :

E.g. code like

            routine.Handle(
                (state, dbContextHandler) => {
                    dbContextHandler(dbContext => {

                        });
                });

Can be expressed as:

             routine.Handle : (state, dbContextHandler) =>  dbContextHandler : dbContext => {

            };

Note how we eliminate those ugly double }); at the end

Actually, what I want you think about: why we have samples with arrow function chains like par1=>par2=>par3 in C# guidebooks, we appreciate them for a possibility to "precisely wrap functions" , "curing" but mostly never use them in real code? With that proposal I want to give to the "arrow chains sintax" a little bit more power.

Area-Language Design Discussion

Most helpful comment

can be encoded:
routine <= errorParserFactory => errorParserFactory(entityModelDescription) =>handle <= dbContext => dbContext.Update(entity)

a) Even as someone who appreciates the "hunting the last parenthesis" angle, this is making me sea sick because it's not at all immediately clear "what happens where", and my first instinct is to... add parentheses to it :grimacing:. The original case may be longer, but it is easier to break apart and make sense of.

b) <= is already the "less than or equal to" operator, so this would very probably change the meaning of some code or introduce ambiguity.

All 11 comments

``` c#
public class Wrapper
{
private Action action;

    public static Wrapper operator |(Wrapper left, Action<DbContext> action)
    {
        left.action += action;
        return left;
    }

}
public static class Test
{
    public static Wrapper WrapperTest()
    {
        var context = new Wrapper();
        return context | (dbContext =>
        {
            dbContext.Entry(new object());
        });

    }
}

```

Thank you, aluanhaddad.
That is very nice, but still with what I call "hunting last parentheses ) " and because of nested parentheses I would write it exactly how you have wrote: in several lines.
When I would prefer to write the same code in one line:

context | dbContext => dbContext.Entry(new object());

What is of course impossible.

I think someone already requested Scala-like syntax to simplify this a bit:

handle(_.Remove(entity));

If you still insist on having less parentheses, I would suggest F# or other ML-like languages. But honestly, I am not sure what is there to hunt. With modern IDE's this is not a problem. Maybe even old stuff like Vim/Emacs can do this.

@rpokrovskij,

Since your code example can be written as:

handle(dbContext => dbContext.Remove(entity));

I'm unclear as to how introducing <= to replace the outer () really makes much difference. I suspect I'm missing something.

5445 could help the parentheses issue:

c# dbContext => dbContext.Remove(entity) |> handle;

The title hurts.

@DavidArno

Of course I have in mind more complex use cases of brief syntax. E.g. wrapper constructed from two steps:

routine( errorParserFactory =>
errorParserFactory(entityModelDescription).handle(dbContext => 
{ 
   dbContext.Update(entity)
});
)

can be encoded:

routine <= errorParserFactory => errorParserFactory(entityModelDescription) =>handle <= dbContext => dbContext.Update(entity)

can be encoded:
routine <= errorParserFactory => errorParserFactory(entityModelDescription) =>handle <= dbContext => dbContext.Update(entity)

a) Even as someone who appreciates the "hunting the last parenthesis" angle, this is making me sea sick because it's not at all immediately clear "what happens where", and my first instinct is to... add parentheses to it :grimacing:. The original case may be longer, but it is easier to break apart and make sense of.

b) <= is already the "less than or equal to" operator, so this would very probably change the meaning of some code or introduce ambiguity.

@JesperTreetop
1) Instincts, feelings, sea mirages... Actually the proposed "arrow chains syntax" is very easy to read from left to right (X provides Y, Y returns Z, Z provides dbContext ) when from right to left you need to understand only "ok I have there dbContext". Again we have a "tube" and "custome code" (dbContext.Update(entity)) at the end. It is not complex at all. No more complex then original C#.

2) There you are right. But what about =<

routine =< errorParserFactory => errorParserFactory(entityModelDescription) => handle =< dbContext => dbContext.Update(entity)

or even colon?

routine : errorParserFactory => errorParserFactory(entityModelDescription) => handle : dbContext => dbContext.Update(entity)

Actually I do not think that it is ideal C# improvement. But what I want you think about: why we have samples with arrow function chains like par1=>par2=>par3 in C# guidebooks, we appreciate them for a possibility to "precisely wrap functions" (curing) but mostly never use them in real code? I just want to give to the "arrow chains sintax" a little bit more power.

@rpokrovskij
I make no claims to be providing the absolute truth, just my own opinions, which anyone is free to disagree with. What is "very easy to read" apparently differs between the two of us, and it's one of many factors to consider for a language feature. How people feel about the syntax may be nebulous and subjective, but it's highly relevant for a syntactical sugar feature.

I think I'm getting lost mainly because the punctuation that has provided bracketing and grouping has evaporated in your example. That's what's making it hard for me to parse. It's hard for me to look at that expression and in a short amount of time arrive at which code is the "innermost" and then work my way out to understanding all of it. With parentheses and other punctuation, even though the expression itself may be complex, this task is straightforward. As someone who did not propose this, I don't really know where to start - thus my "sea sickness". (If I had to read this in my own project, =< may indeed be a suitable ASCII smiley... ;)) So in this way, I do contend that the task of understanding the code is more complex.

<= operator is already used as comparison operator in Boolean expressions.
It would be re-use of already existing operator.

Was this page helpful?
0 / 5 - 0 ratings