Reason: More Intuitive Operators.

Created on 27 May 2016  路  9Comments  路  Source: reasonml/reason

If you watch new people program in the Reason syntax, you'll quickly see they trip up on some of the infix/prefix operators.
Now that we have a good framework in place (thanks to @yunxing) to swap operators, we can easily chose more intuitive operators. When upgrading OCaml code, it will automatically display the new operators, though they continue to be parsed into the AST as the old operators.

  • [x] ++ : String concatenation.
  • [x] ! : Boolean negation.
  • [x] ^ : Dereferencing of refs.
  • [ ] % Infix mod (see #40).

Boolean negation should be parsed with "prefix" precedence: ! x (y,z) should be parsed as ! (x (y, z)) instead of (!x) (y, z). This matches how unary - is parsed. We can copy whatever we're doing for unary negation and achieve the intuitive behavior.

% was suggested by @jberdine and there's "precedence" for this token in other languages. I don't have any opinion about what this token is because I always do x.contents to be noob friendly.

Most helpful comment

@spicyj I'm not sure how we'd solve this someInt * someOtherInt vs someFunc *dereferencedArg.

All 9 comments

Quick question, why change ^ to ++? Do we want to use ^ for something else?

Could unary * be used to dereference refs? Like a pointer. I guess the precedence might be a problem.

@spicyj I'm not sure how we'd solve this someInt * someOtherInt vs someFunc *dereferencedArg.

@bsansouci We have the same issue with someInt - someOtherInt vs someFunc -someOtherInt

The pattern is in the second case we require someFunc (-someOtherInt)

@yunxing I never liked that we have one symbol - which doubles as prefix and infix depending on context. I would rather have a ~ prefix negation operator, personally. But I recognize that that would be a tough sell, so if we decide to keep the nuanced dual mode - identifier, then we could have the same rules apply to the * identifier. We would teach people the difference between prefix precedence and infix precedence, and then say "oh by the way, these two identifiers can act as either infix or prefix".

Then again, ^ is freed up as a result of using ++. Perhaps it doesn't matter too much if we implement the "auto-dereferenced" local var (which simulates the local let binding that has proper lexical scoping, but is automatically dereferenced when referred to).

@jordwalke

"auto-dereferenced" local var

How would we know if this someFunc someRefVar is dereferencing someRefVar or passing it to the function?

@bsansouci

How would we know if this someFunc someRefVar is dereferencing someRefVar or passing it to the function?

The proposed convention would be that if a let binding was declared via var, then it is understood to be a mutable binding, that is automatically dereferenced any time it is referenced. That's the purpose of the var keyword. Then to express _not_ dereferencing you'd go out of your way (perhaps an &address operator?)

var x = "init val";
x = "next val";
print_string x;

Would automatically become:

let x = {contents: "init val"};
x.contents = "next val";
print_string x.contents;

This is not exactly trivial - knowing whether or not a variable x should _actually_ be automatically dereferenced involves more than mere lexical analysis.

@jordwalke I think the new syntax @let-def is working on addresses some of these. Is this okay to close?

closing, feel free to open a new issue if there are still questions

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shaneosullivan picture shaneosullivan  路  3Comments

kyldvs picture kyldvs  路  3Comments

TheSpyder picture TheSpyder  路  3Comments

modlfo picture modlfo  路  4Comments

braibant picture braibant  路  4Comments