Conversation
|
Quick comments:
|
c84a45e to
216c3f2
Compare
Examples of
That's fair, I'm personally in the team of
I'm just hoping that we could have this without too much discussion. But ... as @Octachron pointed out, it's not simple and there is some problems, I will edit the original post with more problems. |
|
Yeah right, a new syntax without too much discussion :-) |
parsing/lexer.mll
Outdated
| ['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~'] | ||
| let dotsymbolchar = | ||
| ['!' '$' '%' '&' '*' '+' '-' '/' ':' '=' '>' '?' '@' '^' '|'] | ||
| let letopsymbolchar = dotsymbolchar | ['.' '\\' 'a'-'z' 'A'-'Z' '_' '0'-'9'] |
There was a problem hiding this comment.
The character \ is only used for escape sequence, it seems more coherent to not include it here.
|
I agree that the syntax looks fine, we could also be more conservative and allow just the |
|
Personally I like the idea of being able to combine operator symbols and alphabetic names, eg. Even if we don't start parsing |
|
My point was indeed that requiring a let+.List.app1 x = ininterpreted as |
|
Ah, so maybe your idea is to allow |
|
@EduardoRFS Since the merge windows for OCaml 5.1 is open, what are your thoughts on starting by restricting the syntax first to |
4006bbc to
3c02fd8
Compare
|
Did the suggested changes, also removed But I wonder if allowing for |
3c02fd8 to
2b27ff7
Compare
|
A potential issue with Moreover, since the |
parsing/lexer.mll
Outdated
| | '#' symbolchar_or_hash + as op | ||
| { HASHOP op } | ||
| | "let" kwdopchar dotsymbolchar * as op | ||
| | "let" kwdopchar? '.' letdotopsymbolchar * as op |
There was a problem hiding this comment.
For my conservative option, I had in mind something more akin to:
| "let" kwdopchar? '.' lowercase identchar* as op
There was a problem hiding this comment.
Why not extending letdotopsymbolchar to include uppercase and saying only the first one must be a initial one? Yours approach would not allow for let.some.map for example.
But the current one allow for some weird stuff such as let.some.....
| "let" kwdopchar? '.' lowercase letdotopsymbolchar* as op
There was a problem hiding this comment.
The token . is generally used for projection or paths, typically I would expect let.some.map and let.some.bind to be somehow related to a let.some but that is not the case here.
It seems fine to me to be conservative and first limit ourselves to the syntax that we really want like let.option, let.some_map, let.ok, let.error_map, or let.app_list and leave some rooms for future options. After all, it is far easier to relax the syntax constraint in the future compared to trying to deprecate an existing but nearly totally unused syntax.
There was a problem hiding this comment.
In case additional opinions can help: I agree that I prefer to allow let*.some but rule out let.some* for now (so: keeping operator symbols adjacent to the keyword, not in other places), but I would be fine with allowing let.some.map as well. It is probably wise to disallow Uidents for now, to leave room for a proper qualification semantics in the future, and generally to try to under-approximate rather than over-approximate the allowed utterances, to keep freedom for future extensions.
There was a problem hiding this comment.
I made the changes as they do make sense and I will make the discussion worse.
The usage of . is probably bad, as . commonly has the notion of accessing something.
I know that the analogy here is that let.some means access the Some and do some stuff inside of it. But for that meaning as a language designer I would much rather allow only let*.some. And in the future I would do the breaking change and not add the ., so let*some, maybe add a lexer warning?
But I know that we're being victim's of the Wadler's Law, and as an OCaml developer, I think let.some is way better than let*.some, even thought it is a single token. It just reads naturally.
Worst case scenario we will need a typer hack to workaround another bit of syntax that is half broken and that at some point will need a deprecation policy.
There was a problem hiding this comment.
Is let.some intended to be the map or the bind for the option type? I'm not sure.
There was a problem hiding this comment.
That's a convention up to the user, in the same way that * | + are conventions, I personally don't ever add map so let.some is always bind.
My usage is a pairing of let.some for bind and some for return.
There was a problem hiding this comment.
let.some x = 1 in some (x + 2)
2b27ff7 to
d6cba6d
Compare
d6cba6d to
31630d4
Compare
Octachron
left a comment
There was a problem hiding this comment.
I am approving for the record the current version of this PR: this is a minimal extension to the let binding operator that covers the extension that the people involved in the discussion really want.
Moreover this version has no incompatibility with existing code since the new lexer rules for LETOP are currently lexed to LET DOT LIDENT or LETOP DOT LIDENT which are not valid in the grammar. In fact, the change could be lifted from the lexer to the parser to make this point more self-evident.
Since this is a syntax change, I will leave one week reaction time for possible objections.
|
If I read the lexer change correctly, currently |
|
i had the impression that the syntax change would benefit from a wider discussion, so I created #12015 to summarize and discuss some feedback on this PR that I had received. My understanding from the discussion so far is that there isn't a strong consensus yet in favor of the language change, and we probably want to wait a bit to see how the discussion evolves.... sorry. |
What
ReasonML syntax in the past provide an additional feature to the current let syntax, where you could use alphanumeric.
This is a very useful feature if you're dealing with many monads at any point in time or just to have them available globally on a local stdlib. At work we use this under some bindings like
let.{some,ok,await}but as we wanted to migrate to OCaml syntax we end up developing a ppx to workaround this.Problems
As pointed out by @Octachron this is actually a breaking change as
let+x = 1is currently parsed aslet+ x = 1But it was also pointed out that this is not a breaking change without precedents, as that also happened for custom indexing operators.< m: 'a.?x:int -> ... >. I would argue thatlet+xworking nowadays seems more like an artifact of the implementation than something desirableThe
.on the other hand is a new character, so not a breaking changes and it fits kind of well with the remaining of the language as it gives this notion ofaccessingthe content of the monad.So this PR limits the patch to
let<symbol>(. <lident>)andlet.<lident>is allowed.Examples