Here’s where you are going wrong I think. cd(temp)
and exec(...)
are expressions, not statements.
Let me just write it like this so it’s clear:
let someValue = {
expression1
expression2
expression3
}
In that let-binding, there is a scope delimited with {}
. In that scope there is a sequence of three expressions, expression1
, expression2
, and expression3
. And in a sequence of expressions, they are evaluated in order and the value of the final expression is returned (docs, in OCaml, but there if you need it). Note that the expression sequencing is implicit, meaning that you don’t use an expression separator to separate them as in OCaml, so you need the brackets to define the scope of the expression as a whole.
In ReScript there are certain rules you have to follow when sequencing multiple expressions like that. Any expression on the left hand side of a sequence must evaluate to unit
. That means in the above example, expression1
, and expression2
must have a value of unit
, whereas expression3
can be any value. Note that the value of the expression sequence is the last expression in the sequence (thus that mention in the docs about the value of the last expression is implicitly returned in a block/scope).
I actually don’t think it’s a silly trip up on your part…unless you’re coming from OCaml, I don’t think it’s obvious those rules about sequencing. And unless you dig through ReScript compiler github issues, even if you know how expression sequencing works in OCaml, you may not realize that ReScript is more strict with what it allows.
I also couldn’t find this in the docs anywhere, but here are some quotes/links from ReScript compiler github issues:
In general the typing rules are more strict expr1; expr2
, the expr1 is expected to have type unit
(link)
in recent releases we already do a strict check over sequences of expressions: e0 ; e1
, it will assume e0
to have type unit
(link)
In OCaml, if the value of an expression on the left-hand side of a sequence is not unit
, it will be a warning (warning 10), and as far as I can tell, this was the case in older versions of Bucklescript too (see here). However, now in ReScript, it is always an error (link).
So back to your example.
You have a let binding for a functional value:
In that let-binding there is a sequence of two expressions, cd(temp)
and exec(...)
. We now from the ReScript rules shown above that left-hand side expressions in a sequence must return unit
. However, the cd
function returns string
. Thus the error: Somewhere wanted: unit
.