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

**URL:** <https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507>\
**Category:** Learning\
**Created:** [October 6, 2019, 3:08pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507 "2019-10-06T15:08:08Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 6, 2019, 3:08pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/1 "2019-10-06T15:08:08Z")

</div>

I tried:

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

```

but is a syntax error. Why is that?

* * *

Note I know you can do

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

```

though thats not my question.

---

<div class="post-metadata">

**Author:** ![atavener](https://avatars.discourse-cdn.com/v4/letter/a/9f8e36/32.png) [@atavener](https://discuss.ocaml.org/u/atavener)\
**Post date:** [October 6, 2019, 4:22pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/2 "2019-10-06T16:22:47Z")

</div>

`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.

---

<div class="post-metadata">

**Author:** ![ancolie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ancolie/32/6189_2.png) [@ancolie](https://discuss.ocaml.org/u/ancolie)\
**Post date:** [October 6, 2019, 4:25pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/3 "2019-10-06T16:25:52Z")

</div>

Because it’s read as:

```ocaml
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:

```ocaml
let x =
  print_endline "hello";
  1

```

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 1:39am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/4 "2019-10-10T01:39:47Z")

</div>

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. 🙂

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 1:57am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/5 "2019-10-10T01:57:30Z")

</div>

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

```auto
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! ☹

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [October 10, 2019, 1:59am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/6 "2019-10-10T01:59:12Z")

</div>

I thought @ancolie’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](https://ocaml.org/learn/tutorials/structure_of_ocaml_programs.html#The-sequence-operator) , which explains it in further detail.

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 2:01am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/7 "2019-10-10T02:01:48Z")

</div>

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:

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

```

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 2:03am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/8 "2019-10-10T02:03:20Z")

</div>

> [@ancolie](#):
>
> let x = 1; (\* this should have type unit but only gives a warning \*) let y = 2 ;;

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

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

```

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [October 10, 2019, 2:08am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/9 "2019-10-10T02:08:21Z")

</div>

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:

```ocaml
expr1 ; expr2

```

… where `expr1 : unit` and `expr2 : 'b`.

---

<div class="post-metadata">

**Author:** ![mc10](https://avatars.discourse-cdn.com/v4/letter/m/ea5d25/32.png) [@mc10](https://discuss.ocaml.org/u/mc10)\
**Post date:** [October 10, 2019, 2:09am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/10 "2019-10-10T02:09:27Z")

</div>

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

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

```

results in

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

```

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 2:15am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/11 "2019-10-10T02:15:39Z")

</div>

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

```auto
# 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:

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

```

worked.

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 2:23am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/12 "2019-10-10T02:23:49Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 2:31am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/13 "2019-10-10T02:31:28Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [October 10, 2019, 3:30am UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/14 "2019-10-10T03:30:30Z")

</div>

Statements don’t ‘return’ a value. E.g. in a language like say Python:

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

```

This is a statement. It doesn’t ‘result in’ a final value. In OCaml:

```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.

---

<div class="post-metadata">

**Author:** ![ancolie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ancolie/32/6189_2.png) [@ancolie](https://discuss.ocaml.org/u/ancolie)\
**Post date:** [October 10, 2019, 2:17pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/15 "2019-10-10T14:17:37Z")

</div>

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.

```ocaml
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:

```ocaml
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;
  ()

```

---

<div class="post-metadata">

**Author:** ![cfcs](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cfcs/32/833_2.png) [@cfcs](https://discuss.ocaml.org/u/cfcs)\
**Post date:** [October 10, 2019, 2:59pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/16 "2019-10-10T14:59:39Z")

</div>

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

```ocaml
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:

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

```

and

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

```

is

```python
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`".

so revisiting your original:

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

```

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

```ocaml
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:

```ocaml
let ignore _whatever = ()

```

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

```ocaml
let x = ignore 1; let y = 2 in y
(* more readable formatting: *)
let x =
    ignore 1;
    let y = 2 in
    y

```

Hope that helps 🙂

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 6:18pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/17 "2019-10-10T18:18:27Z")

</div>

> [@yawaramin](#):
>
> e. Different parts of the syntax compose together because everything results in values after all. While other languages had to add special syntax for this

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?](https://discuss.ocaml.org/t/what-is-the-difference-between-statements-and-expressions-in-ocaml/4525)

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 6:28pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/18 "2019-10-10T18:28:29Z")

</div>

> [@yawaramin](#):
>
> if x == 1: print(“One”)

I don’t think this is right. Correct me if I’m wrong. Check this:

```auto
Python 3.7.3 (default, Mar 27 2019, 16:54:48)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 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.

---

<div class="post-metadata">

**Author:** ![bcc32](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bcc32/32/203_2.png) [@bcc32](https://discuss.ocaml.org/u/bcc32)\
**Post date:** [October 10, 2019, 6:30pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/19 "2019-10-10T18:30:06Z")

</div>

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

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

```

---

<div class="post-metadata">

**Author:** ![rene\_sax](https://avatars.discourse-cdn.com/v4/letter/r/0ea827/32.png) [@rene\_sax](https://discuss.ocaml.org/u/rene_sax)\
**Post date:** [October 10, 2019, 6:40pm UTC](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507/20 "2019-10-10T18:40:49Z")

</div>

> [@cfcs](#):
>
> (\* 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. \*)

I’m confused about this. I can easily do:

```auto
# let x = 3;;
val x : int = 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.

[Next page](https://discuss.ocaml.org/t/why-is-declaring-two-variables-with-the-sequence-operator-illegal/4507.md?page=2)
