Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between "let ()=" and "let _=" ;

Tags:

ocaml

let () = Random.self_init();;
let _ = Random.self_init ();;
│- : unit = ()

It seems "let ()" returns nothing ?

Sincerely!

like image 242
z_axis Avatar asked Jul 17 '12 02:07

z_axis


People also ask

What is different between LET and VAR?

let is block-scoped. var is function scoped. let does not allow to redeclare variables. var allows to redeclare variables.

What is the difference between let and let Rspec?

I understood the difference between let and let! with a very simple example. Let me read the doc sentence first, then show the output hands on. ... let is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked.

Is it better to use LET than VAR?

let can be updated but not re-declared. This is because both instances are treated as different variables since they have different scopes. This fact makes let a better choice than var . When using let , you don't have to bother if you have used a name for a variable before as a variable exists only within its scope.


1 Answers

let is the keyword used to define new variables, like in the following construct:

let pattern = expr

For instance

let a = 2

assigns the value 2 to the name a. (Note this is not a way to assign a value to an already existing variable, but this is another topic).

But the pattern to the left of the = sign can be more than just a name. For instance

let (a,b) = (42,"foo")

defines both a and b, to be respectively 42 and "foo". Of course, the types on both sides must match. Which is the case here: both sides are of type int * string.

The expressions to the right of the = sign can also be elaborated, for instance

let foo =
  let temp = String.make 10 'a' in
  temp.[2] <- 'b';
  temp

defines foo as the string "aabaaaaaaa". (As a side note, it also ensures that temp is local to this code snippet).

Now, let's use both: on the left, a pattern matching values of type unit, and on the right, an expression of type unit:

let () = Printf.printf "Hello world!\n"

Which explains the let () = construct. Now, about the let _, one simply needs to know that _ can be used in a pattern as a wildcard: it matches values of any type and does not bind any name. For instance

let (a,_) = (42,"foo")

defines a as 42, and discards the value "foo". _ means "I know there is something here and I explicitly say I will not use it, so I don't name it". Here _ was used to match values of type string, but it can match value of any type, like int * string:

let _ = (42,"foo")

which does not define any variable and is not very useful. Such constructs are useful when the right hand side has side effects, like this:

let _ = Printf.printf "Hello world!\n"

which explains the second part of the question.



Practical purposes

Both are used and it's rather a matter of taste whether to use one or the other.

let () = is slightly safer as it has the compiler check that the right hand side is of type unit. A value of any other type than unit is often a bug.

let _ = is slightly shorter (I've seen this argument). (Note that with an editor that automatically closes parenthesizes, the number of keystrokes is the same ;-)

like image 200
jrouquie Avatar answered Sep 20 '22 01:09

jrouquie