Problem:
It's a bad experience for users every time they encounter a syntax error. It breaks they flow and concentrating cycle.
Solution:
Make the syntax more forgiving: we can have multiple ways to represent the same semantics. Then in the formatter, we format them to the same "suggested" syntax.
Example:
We can support both
switch x {
| A => 1
| B => 2
};
and
switch x {
| A -> 1
| B -> 2
};
But in the formatter, we format both of them to
switch x {
| A => 1
| B => 2
};
I believe there are more cases where we can do this trick.
Mmmmh I'd be more inclined to make the parser a bit smarter to have better errors messages. We could successfully parse -> and error saying it's => that people meant :)
@bsansouci Yes, that's one approach that I was doing before:

But I somehow realize it is a much better experience (at least for me) to have a gentle hand that helps me correct my mistakes every time I save my file (which invokes refmt automatically in emacs) instead of being presented an error saying I'm wrong.
But there are an infinite number of ways to imagine syntax (similar to NLP). Based on my experience in other languages I prefer rigid syntax but forgiveness in types (like Haskell's deferred type errors).
@texastoland My hope is that this can cover some mostly common mistakes (like mistakenly wrote "->" for "=>").
Haven't really used deferred type errors before. I think they are more for debugging purpose so one can have an easier run-debug-change cycle without fixing all type errors first. A forgiving syntax gives people an easier editing cycle by implicitly fixing user's errors.
I think I originally got this experience from Go's formatter -- trailing semicolon is automatically removed instead of being reported as an error.
As an example, try click the "format" button here: https://play.golang.org/p/k0mVyIKiFO
@yunxing I really don't enjoy optional semicolons... I don't think it's helpful to have optional things / multiple syntaxes for the same thing because you're putting the burden of choice on the user. Here the burden of having to fix syntax errors is greatly reduced because of the tooling anyway. Accepting -> and transforming it to => seems too loose. It also doesn't necessarily help you learn that you should just use =>.
Perhaps we could make some exceptions, at least in areas where common mistakes are made. I'm actually more interested in how we are going to figure out these mistakes or if we are going to base everything on a hunch.
@bsansouci Good point on multiple syntaxes. I agree that multiple syntaxes for the same thing are bad because users will have the burden of choice. However I somehow feel in a language with first-class formatter support this won't be a problem. In this special case, instead of providing negative feedback and asking users to remember: "->" is for pattern machining in ocaml and "=>" is for pattern matching in reason, we can tell users (implicitly) that "just keep writing your program, either -> or => is fine, we will correct it to the right syntax for you whenever you save".
Users will learn to use the right syntax eventually because: 1. All the tutorials and examples and even their own codebase will have the right syntax (since the code are formatted) 2. Whenever people run refmt, presumably when they save their file, there will be a visual change on the screen that helps user to notice and remember.
I think this can be uncontroversial if the "forgiven" syntax isn't considered part of the official grammar, and we keep a clear separation between forgiven syntax, and the official syntax. For example, when compiling, we'd _want_ to have an error for -> arrows, but inside the IDE we can tell refmt/merlin to parse forgivingly, and we can tell the user to hit a certain command to automatically fix them. It's a really good teaching/learning opportunity. We just have to find a way to keep the two grammars separate (because, for example, we would always reserve the right to remove any of the forgiving parsings if they end up making the parsing too complicated/conflict-prone ).
We probably should not tell people "you can continue to use this alternative syntax", because we very well may want to use that syntactic pattern for something else in the future, or some other pattern that conflicts with it - we want to manage user expectations that we might not always catch this common mistake, but we'll try for now. Conflict-free syntactic real estate is a limited resource and we can lend it out to allow some errors to be automatically correctable, but we should be able to take it back if needed.
@jordwalke Yes, if we ever do this, we need to be careful to not let user grow the habit of using the alternative syntax. The whole purpose of here is to educate user to user the in a gentle way instead of a way that would break their flow. So hopefully this can indeed educate users.
@bsansouci I hear what you are saying. From my personal experience syntax error is actually an effective way to learn: I remembered to use "=>" after spent x minutes staring at my screen before figuring out "->" is not the right way to do pattern matching in reason. The downside is that I was quite annoyed then and started questioning the syntax.
@SanderSpies Good point. I think in this case it is more from my personal experience and mistakes people around me have made.
Honestly don't know which approach is better. Maybe we can try this trick for one version or two, and see what users think about it?
I think I can be convinced that the formatter should transform -> into => but the parser/compiler should error. That would be nice, but it might make people never really learn and heavily rely on it... The same way I totally rely on my Mac's autocorrect because I got used to it being very good and predictable.
Alright, people have accustomed to => now I think, so I'll close this.
But we should have this spirit for other new syntax we introduce!
Most helpful comment
Mmmmh I'd be more inclined to make the parser a bit smarter to have better errors messages. We could successfully parse
->and error saying it's=>that people meant :)