I am trying to teach myself OCaml. I've been going nuts over this one syntax trap. I'm told that you can string expressions together in sequence using ";" ie, expr1 ; expr2 executes the first expr, then the second, as expected. For some reason, I cannot get the interpreter to agree with the following input
let x = 5 ; let y = 7;;
Bizarrely if ONLY the first expr is a let, it works. So
let x = 5 ; 7;;
Passes, and evaluates to 7.
Even worse, if I attempt to use parens to compose multiple sequences of statements where the let comes first, it still does not work. I.E.:
let x = 5 ; (let y = 7 ; 9);;
Is an error, even though it consists only of sequences where lets are the first expression. Can someone explain how to get this to work?
One way to look at the problem is that let x = 5 isn't an expression. It's a top-level declaration; i.e., it declares a name x with a value 5.
The ; operator works for combining expressions, but not for declarations.
You don't need to string declarations together with ;. You can just put one after the other:
# let x = 5 let y = 7;;
val x : int = 5
val y : int = 7
#
There is a completely different use of let in OCaml that is part of an expression. In that case it's followed by in:
# (let x = 4 in x + 1);;
- : int = 5
Since this is an expression, you can string several of them together with ;:
# (let x = 4 in x + 1); (let y = 6 in y + 1);;
Warning 10: this expression should have type unit.
- : int = 7
However, as the compiler is warning you, it's not idiomatic to string together arbitrary expressions. Normally you use ; with imperative code. With functional code it doesn't make sense. So the compiler expects all but the last expression to have type unit (which is used for imperative code that does something useful but doesn't return a useful value).
Related
F# makes it easy to unpack tuples. Unpacking lists is also feasible, but the compiler issues a warning:
let m = [1; 2; 3]
let [a; b; c] = m
// Incomplete pattern matches on this expression. For example, the value '[_;_;_;_]' may indicate a case not covered by the pattern(s)
Is there a way to avoid this warning?
You can disable warnings per file by using the #nowarn directive (in your case #nowarn "25") or you can disable warnings on the command line with --nowarn.
Check out the F# Compiler Directives for details.
There is currently no way to re-enable warnings again, when first disabled.
Your match may (unexpectedly) result in a runtime error if the number of elements cannot be unpacked to [a;b;c], so instead you can use a complete match that is explicit about the risc:
let m = [1;2;3]
let (a,b,c) =
match m with
| [a;b;c] -> (a,b,c)
| _ -> failwith "Expected exactly three items in m"
What would happen if your list m has 2 or 4 elements?
There is obviously a way, plain old pattern matching:
let a, b, c =
match m with
| [a;b;c] -> a,b,c
| _ -> ... // handle the length!=3 case
F# allows you to deconstruct the right-hand side objects that way when there's clear that you only have a single case you need to cover. This is the case with tuples, since there's only one tuple type that would match both the left and the right hand side. Something like this obviously would not compile, because the types won't match:
let m = 1, 2
let a, b, c = m
Yet in your case there's no guarantee that you're not in fact in this scenario:
let m = [ 1; 2 ]
let [1;2;3] = m
You're in fact asking the compiler to allow non-exhaustive pattern matching. You can disable the warning as noted in the other answer, but you're inviting runtime errors that way.
One obvious, but hardly elegant, way is:
let m = [1; 2; 3]
let a = List.item 0 m
let b = List.item 1 m
let c = List.item 2 m
You can write a helper function to make it neater:
let unpack3 x = (List.item 0 x, List.item 1 x, List.item 2 x)
let (a, b, c) = unpack3 m
Basically a list is not a great fit if you know you are always going to have a fixed number of items.
I want to calculate f(..f(x)) p times. The following is my code.
let rec function f x p = if p = 0 then x else function f (f x) p-1;;
I wonder how I should make it right.
This is very close, but your code has syntax errors that are going to make it hard to make progress. I think the main problem is that you're using function as an identifier, but it is a keyword in OCaml. If you change to myfun, things should start working quite a bit better.
You also need to watch your precedences. The following code:
f a b-1
is parsed like this:
(f a b) - 1
not like this:
f a (b - 1)
You need to write the parentheses explicitly to get this second parse.
You can define a recursive function ch to apply a function f many times (Church numeral??) as follows:
let rec ch f p x = if p = 0 then x else f (ch f (p-1) x);;
The problems in your original code are that:
need to name the function as something, such as ch here.
need to call the same function ch to get the recursion going as shown above. In your original code, there is no recursion.
Example
let p1 x = x + 1 ;;
ch p1 3 1 ;;
this will give you
- : int = 3
as intended.
I want to write something like
fun factorial 0 = 1
| factorial n = n * factorial(n-1);
but I don't get the "|" sign when i want to start the new line. I get something like:
fun factorial 0 = 1
= factorial n = n * factorial(n-1);
when I start the second line of code. If I hold shift and "\" I dont get the vertical bar, I get something else.
Since you say that the second line starts with an equal sign (=), it appear that you are writing your code directly into the interpreter?
In any case you have to write the pipe your self. The pipe is part of the SML syntax, and is used to "indicate" different function clauses, whereas the semicolon has a double meaning here. Doubling as being part of the SML syntax (though not strictly needed here) and as a special indicator to the interpreter (as explained below).
Most interpreters will keep reading data from stdin until it reads a semicolon, and first then will it start to interpret what you have written.
In the case of the SML/NJ interpreter, the first line is indicated by starting with a "-" and any subsequent lines starts with a "=". Note that the "-" and "=" signs are not interpreted as part of the final program.
An example of this can be seen below
- fun foo 0 y = 0
= | foo 1 y = y
= | foo x y = x*y;
val foo = fn : int -> int -> int
Here the last line is the output from the interpreter, when it reads the semicolon.
However we could also have declared two functions before writing the semicolon
- fun foo 0 y = 0
= | foo 1 y = y
= | foo x y = x * y
= fun fact 0 = 1
= | fact n = n * fact (n-1);
val foo = fn : int -> int -> int
val fact = fn : int -> int
Regarding the pipe, it depends on your keyboard layout, whether or not you will get it by typing shift+"\". However since your post contains multiple pipes, I suppose you already know how to write one.
I am new to OCaml. I am trying to use List.nth just like List.length but it keeps giving me a syntax error or complains about not matching the interface defined in another file. Everything seems to work fine if I comment out using List.nth
Thanks
It's hard to help unless you show the code that's not working. Here is a session that uses List.nth:
$ ocaml
OCaml version 4.00.0
# let x = [3;5;7;9];;
val x : int list = [3; 5; 7; 9]
# List.nth x 2;;
- : int = 7
#
Here's a session that defines a function that uses List.nth. (There's nothing special about this.)
# let name_of_day k =
List.nth ["Mon";"Tue";"Wed";"Thu";"Fri";"Sat";"Sun"] k;;
val name_of_day : int -> string = <fun>
# name_of_day 3;;
- : string = "Thu"
#
(As a side comment: using List.nth is often inappropriate. It takes time proportional to n to find the nth element of a list. People just starting with OCaml often think of it like accessing an array--i.e., constant time--but it's not.)
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:
The way you can assign variables;
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 = ()