简体   繁体   中英

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

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

It seems "let ()" returns nothing ?

Sincerely!

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 ;-)

I'm not an OCaml expert, although let me share something :)

The let in OCaml can represent two things:

  1. The way you can assign variables;
  2. The way you can declare functions or assign functions to names;

Using examples, you can see clearly how it works: Assigning variables:

# let ten = 10;;
val ten : int = 10

# let hello_world_string = "Hello World";;
val hello_world_string : string = "Hello World"

Declaring functions:

# let sum a b = a+b;;
val sum : int -> int -> int = <fun>
# sum 2 3;;
- : int = 5

So, answering the question the difference between let ()= and let _= is:

At first example, you are declaring a function that doesn't have name, parameters nor instructions that should output an unit. The second example, you aren't assigning to _, that is OCaml's wildcard, any value.

As we can see below, we can define a function, that will be executed immediatly because we won't be able to call it anymore:

# let () = print_string "Hello";;
Hello

Or assign to OCaml's wildcard a type and value, or a function:

# let _ = 10;;
- : int = 10
# let _ = print_string "Maybe I answered your question :) ";;
Maybe I answered your question :) - : unit = ()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM