What is the significance of trailing underscore?

Used with a labeled argument labeled argument

Used with a function name

This is just a way to bypass a fact that you can’t use a reserved keyword like to as an identifier.

3 Likes

I like the pattern in other fp where this means “and cast to unit”, fwiw

I don’t see “to” or “then” in the list of reserved keywords

They are reserved keywords in OCaml, so that enables using these bindings in OCaml syntax. Actually, to is also a keyword in ReScript, e.g.

let () = for i in 1 to 5 {
  print_int(i)
}

So it looks like you caught a missing keyword there.

Indeed “then” is a keyword of OCaml… well that’s awkward.

Instead of

Js.Promise.then_

how about

Js.Promise.next

The list is missing “to” as a keyword. Will add that in a bit.

EDIT: Actually, to is not a keyword either. Here is a perfectly valid program:

let to = () => {
  ""
}

let hello = (~to=1, ()) => {
  to + 1
}

module Button = {
  @react.component
  let make = (~to: string) => {
    <div> {React.string(to)} </div>
  }
}


let foo = <Button to="test"/>

Playground Link

“then” is not a keyword in ReScript. The current Promise bindings are outdated… see rescript-promise as a proper Promise substitution

So I guess we will remove that inconsistency (to_) as soon as we migrated our stdlib source code to ReScript.

2 Likes

And please don’t refer to the OCaml keyword list since it is not a source of truth for ReScript keywords.

(Just realized you did that because the stdlib is currently in ml syntax)

1 Like

Ok I think I understand, rescript seems more OK with OCaml keywords but it seems a little more complicated.

in rescript

let to = (x, y) => x + y;

unsurprisingly generates

function to(x, y) {
  return x + y | 0;
}

but

let then = (x, y) => x + y;

generates

function $$then(x, y) {
  return x + y | 0;
}

and on the Reason side both of these are errros

let to = (x, y) => x + y;
let then = (x, y) => x + y;

but unexpectly this

let match = (x, y) => x + y;

generates

function match_(x, y) {
  return x + y | 0;
}

Then is mangled since in js then is a keyword.
Name mangling in reason syntax is complicated, that’s part of the motivation we deprecated reason syntax

to is a keyword in ReScript too, as per the example I gave above. But it looks like somehow ReScript also allows it as an identifier name. Either that’s awesome, or a bug. I’m not sure :slight_smile:

to is not a keyword since it is a handwritten parser, you dont need to make it a keyword to parse the grammar

Yes, I’ve run into it the situation where to in .re becomes to_ in .res, and, to make things weirder, to_ becomes to__. It makes sense, because a .re module could have both to and to_, but it’s still mildly confusing :sweat_smile:

but then is not a keyword in JS

1 Like

That’s interesting. What is to called in the ReScript grammar when used in for i in 1 to 5 { ... }?

to is a regular identifier starting with a lowercase character. It isn’t a keyword, just like in JavaScript

I understand but it depends on context right? Clearly, when used like let to = 1, it’s an identifier. But when used in for i in 1 to 5, clearly it’s not an identifier?

2 Likes

There’s no difference between to in let to = 1 and to in a for expression in scanning phase. It’s an ident from lexical point of view.
but when parsing a for expression, parser expects an ident with value of to or downto so in my imaginary syntax notation it would be something like this:

forExpr ::=
  forKeyword anyIdent inKeyword intLiteral (Ident("to") | Ident("downto")) intLiteral leftBrace ...

instead of

forExpr ::=
  forKeyword anyIdent inKeyword intLiteral (toKeyword | downtoKeyword) intLiteral leftBrace ...

That’s what I understood, I may be wrong. Maxim can correct me.

1 Like

Fascinating. So this is totally valid, I just checked:

let to = 5

let () = for i in to to to {
  print_int(i)
}

EDIT: so is the below :grin:

let to = 5

let () = for to in to to to {
  print_int(to)
}
4 Likes

That’s good to know. I thought it was, can you file an issue on the repo