wren-lang / wren

The Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.
http://wren.io
MIT License
6.93k stars 555 forks source link

Functional operators #1154

Open mhermier opened 1 year ago

mhermier commented 1 year ago

An attempt at #1144 and more:

This is a lot of syntaxic sugar, but it should help readability of cascaded function calls.

mhermier commented 1 year ago

A small note: while working, precedence of operators has only been tested between themselves and will probably need tuning based on feedback and usage.

PureFox48 commented 1 year ago

I see that you have also reserved @ on its own for future use as a token.

Any plans on what to use that for?

mhermier commented 1 year ago

To put it simply, I thought it was the way to to make an error here, but it's a mistake.

That said, I think it would be a nice user defined operator. If my memory is correct, squeak/pharo use it to define coordinates/points. It can be a nice addition, but for now I don't really plan to implement it unless there is more user interest.

clsource commented 1 year ago

Thanks for sharing. I quite do not understand the usecase for reverse pipeline, but it's ok I guess for completeness?. Using @> seems odd choice to me. Maybe ||>? I dont know why such operator is needed and why must be different from the traditional pipe though.

I think that maybe reusing + operator for pipelines would do, since it's creating a new function by aggregating other functions?.

mhermier commented 1 year ago

|< and @< are made for completeness. While investigating for composition operator, I hitted rosetta code function composition with some example of language with builtin support. And base on some comment, I discovered that the meaning behind the |> was to indicate the direction of the chain of evaluation. While it usually may not have much importance, it impact order of evaluation, so I think we need both in case order of evaluation matters in some context. In addition, not everyone understand that concept first try the same way.

@> was chosen as a mix match of the |> operator and the @ operator used for composition in some language. While I'm happy with it, we can discuss the color of the operator when other issues are sorted out (probably mostly precedence ones).

That operator is required to prepare and pass pipeline parts using variables. That mean, they can be passed as arguments and returned from functions/methods. This allow pipelines calls to be programmatically tuned while using a fixed chain of calls.

No, we can't reuse any of the already defined ones basically because of functor objects (that you encounter usually when trying to functions of different arity, eg when emulating function with default values). It has the consequence that theses operator must be built-ins.

PureFox48 commented 1 year ago

Now that I've had more time to think about this, I'd just like to add my two cents to what I think is basically a good proposal.

  1. I don't think that completeness is a good enough reason to include the |< and @< operators. I agree with @clsource that there isn't really a use case for these and I think their existence might actually confuse people as to which to use.

  2. I can see the sense in having the @> operator as we're talking here about composing functions themselves (a pain at present) rather than composing a pipeline of function calls.

  3. As there's no obvious choice for a function composition operator, I think @> is as good as any. I don't really like ||> as I think it would be too easily confused with |>. It incorporates a symbol @ which we don't currently use in Wren and that opens the door to perhaps using that symbol in its own right either for some particular purpose (swapping variables maybe?) and/or as a sort of 'wildcard' overloadable operator for DSLs where you don't want to use the existing operators for some reason.

  4. I think that |> and @> should be operators which cannot be overloaded - they would just be there to serve a specific purpose in the language - and so having a precedence no lower than 13 in the table would be about right for them. I agree with @mhermier that we cannot use existing operators for these purposes.

mhermier commented 1 year ago

@PureFox48 Can you describe operator precedence in terms of between operators? Expressing in terms of numbers is not really clear, and might change with possible additions.

PureFox48 commented 1 year ago

Sorry, I was referring to the table here in the docs.

I can't make up my mind whether they should be inserted in the table at 13 and 14 between == and != and && which I think is where you have them just now or whether they should go right at the end (17 and 18) after =. I'm inclining towards the latter.

PureFox48 commented 1 year ago

On reflection, I don't think it would be a good idea to place them after = because, if they appeared on the RHS of an assignment statement, you'd then need to parenthesize any expression they appeared in.

You could put them just before = though. Don't know, it's a difficult one!

mhermier commented 1 year ago

I also always struggle with these questions. I updated the priority to be in par with the JS pipeline. My main question was about the ?:, and it appears that it was a solved problem in their paper.

PureFox48 commented 1 year ago

In practice, I suspect that many people (myself included) put parentheses around stuff either just for clarity or because they can't remember what the operator precedence rules actually are. No doubt this will also apply to these operators if they're adopted but we do, of course, still have to come up with a definite priority for them.

I see that you've updated the proposal to put them just ahead of ?: as JS are suggesting and I've no quarrel with that.