# Why is declaring two variables with the sequence operator ; illegal?

I tried:

``````let x = 1; let y = 2;;
``````

but is a syntax error. Why is that?

Note I know you can do

``````let x = 1 let y = 3;;
``````

though thats not my question.

`let` is for expressions ā something which will resolve to a result. Sequencing is for statements, with no used value but generally having some side-effect (eg. screen output, or modifying a memory cell).

If `let x = 1;` was accepted, it wouldnāt do anything. The scope of `x` only exists within that statement.

What you want instead is `let x = 1 and y = 2 in` ā¦ followed by use of `x` and `y`. Or `let x = 1 in let y = 2 in` ā¦

Think of building an expression rather than a sequence of statements.

2 Likes

``````let x =
1; (* this should have type unit but only gives a warning *)
let y = 2
;;
``````

Your expression doesnāt have any value.

Because sometimes you want to write things like:

``````let x =
print_endline "hello";
1
``````
2 Likes

I guess I still donāt get it and I donāt know what it is. I will try to ask something to perhaps figure out whats confusing me. I guess I donāt understand what the difference is between statements and expressions in OCAML. I am also confused when `;` vs `;;` is usedā¦thnx for the help.

I think this sequencing, statements and expression things is still not clear to me at all. Perhaps going through this example would help?

``````let result =
let test x = ( p 650; fun y -> ( p x ) + ( p y ) ) in test ( p 4 ) ( test ( p 5 ) ( p 6 ) );;
``````

what on earth is going on there!

I thought @zapashcanonās answer was pretty good, but given your confusion, maybe have a look at https://ocaml.org/learn/tutorials/structure_of_ocaml_programs.html#The-sequence-operator , which explains it in further detail.

oh, Iāve read that before of course! Though, perhaps I can clarify what confuses me about that document. What does this mean:

The semi-colon `;` may be seen as having type `unit -> 'b -> 'b` ā it takes two values and simply returns the second one, the first expression is guaranteed to be evaluated before the second.

What confuses me a lot is that `;` ātakes the unit typeā. I thought to take the unit type one has to pass itā¦ like:

``````let f () = 2;;
f ();; (* returns 2 afaik*)
``````

what do you mean it only gives a warning? To me it gives me a syntax error:

``````# let x =
1; (* this should have type unit but only gives a warning *)
let y = 2
;;
Error: Syntax error
``````

The `()` value is the only literal value of type `unit`, but itās not the only expression of type `unit` For example, the function `ignore` takes a value and returns a result of type `unit`: `ignore 5 (* has type unit *)`

Its implementation is: `let ignore _anything = ()`

As you can imagine, many different functions can return `()` and therefore so can many different expressions. So saying that the semicolon āoperatorā takes two expressions, one of type `unit`, and the other of polymorphic type `'b`, means that it looks like this:

``````expr1 ; expr2
``````

ā¦ where `expr1 : unit` and `expr2 : 'b`.

The exampleās incomplete; you need to complete it with an expression; e.g.

``````let x =
1;
let y = 2 in y + 3
;;
``````

results in

``````Line 2, characters 2-3:
Warning 10: this expression should have type unit.
val x : int = 5
``````
1 Like

I guess your explanation makes sense, after, to my surprise the following code gave me a warning:

``````# let do_this x = ( add2 5; fun y -> y + 4 );;
Warning 10: this expression should have type unit.
val do_this : 'a -> int -> int = <fun>
``````

although, I guess the code DID work since:

``````# do_this 2 4;;
- : int = 8
``````

worked.

This are making a lot more sense. But I still donāt understand the difference between expressions and statements.

what [quote=āatavener, post:2, topic:4507ā]
Think of building an expression rather than a sequence of statements.
[/quote]

what is the difference between a statement and an expression?

Statements donāt āreturnā a value. E.g. in a language like say Python:

``````if x == 1: print("One")
``````

This is a statement. It doesnāt āresult inā a final value. In OCaml:

``````if x = 1 then print_endline "One"
``````

This is an expression. It āresults inā a value. In this case `()` of type `unit`. OCaml is designed so that almost all syntax is an expression. The standard `if ... else ...`, the `try ... with ...`, even `for ... in ... do`. This is useful because itās more expressive. Different parts of the syntax compose together because everything results in values after all. While other languages had to add special syntax for this (e.g. Pythonās `X if COND else Y` and C/C++/etc.'s ternary syntax), ML (and Lisp) languages get it from day one.

IMO, a good way to start is to stop using the top level, to write all your code in a file and to wrap all your code in a single āmainā function (`let _ = ...`). Then, you can stop completely using `;;` youāre only left with `let ... in` and statements.

``````let _ =
let rec fib x =
if x < 0 then failwith "fib";
if x < 2 then x else fib (x - 1) + fib (x - 2)
in
let print_res x =
Printf.printf "fib %d = %d" x (fib x)
in
let x1 = 5 in
print_res x1;
let x2 = 6 in
print_res x2;
()
``````

Once youāre at ease with this, itāll be easier to understand. You would just rewrite it like that:

``````let rec fib x =
if x < 0 then failwith "fib";
if x < 2 then x else fib (x - 1) + fib (x - 2)

let print_res x =
Printf.printf "fib %d = %d" x (fib x)

let _ =
let x1 = 5 in
print_res x1;
let x2 = 6 in
print_res x2;
()
``````

Not sure if you are familiar with Python, but I will try translating your questions to that.

``````let x = 1 ; let y = 2
(* this fails because let .. = .. must be followed by `in`.

In the top level / outer scope of a module (such as your file.ml)
you don't need the "in," but for all the nested let .. you do.
*)
``````

is essentially equivalent to:

``````x = ( 1; y = 2
``````

and

``````let x = 1 let y = 3;;
(* with less misleading formatting: *)
let x = 1
let y = 3
;;
``````

is

``````x = 1 ; y = 2
# aka
x = 1
y = 2
``````

basically `;` in ocaml is a very strong binding operator, as opposed to being a statement/expression separator in most other languages.
When you see a `;` in OCaml you should read it at "put () around the previous expression, and this one, and make sure that the previous expression returned type `unit`".

``````let x = 1; let y = 2
;;
``````

first we need to close the `let ..` scope:

``````let x = 1; let y = 2 in y
;;
(* with the implicit grouping/binding order spelled out: *)
let x = ( 1; (let y = 2 in y) )

(* x is now 2 *)
``````

OCaml will still complain, because the type of `1` is `int`, and youāre using `;` to denote you want a side-effect and donāt care about the value of the expression (since nothing is recording it).

Thereās a function in the standard library called `ignore` which has signature `'a -> unit`, it is basically implemented like this:

``````let ignore _whatever = ()
``````

We can use it like this to satisfy the type checker:

``````let x = ignore 1; let y = 2 in y
let x =
ignore 1;
let y = 2 in
y
``````

Hope that helps

What does this mean? I think Iām starting to understand better that everything in OCAML results in a value (even though the distinction between expressions and statements is still not clear to me). I guess what I am confused is that I ONLY know python really. So Iām having a hard time understand what OCAML does. I thought python always returned values too. The way I thought about python is I have a bunch of statements (pretty much one per line usually) and they get executed and return a value. So for me everything is a statement in the programming I am used to. So what I am trying to understand is how do things work in OCAML. It seems once the distinction btw statements and expressions is clear everything would make sense to me.

me asking for clarification on the precise difference between statements and expressions: What is the difference between statements and expressions in OCAML?

I donāt think this is right. Correct me if Iām wrong. Check this:

``````Python 3.7.3 (default, Mar 27 2019, 16:54:48)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
>>> print("One")
One
>>> x = print("One")
One
>>> x
>>> print(x)
None
>>> y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
``````

it seems that x DOES have a value. The print statement is a function and it returns None afaik. I tried printing y to emphasize that x had to be assigned.

`print("One")` is an expression. `if x == 1: print("One")` doesnāt.

``````>>> x = 1
>>> y = (if x == 1: print("One"))
File "<stdin>", line 1
y = (if x == 1: print("One"))
^
SyntaxError: invalid syntax

``````
2 Likes

``````# let x = 3;;
not only in top level but in my `.ml` file to. I can define a variable and then use it later if I need to. My question makes me feel there is something fundamental about OCAML or perhaps fp programming I donāt understand.