There are codes like
let () = print_string "something" in
fn
in some OCaml codes.
What does this mean? Is there special meaning on "()"? or Is it same meaning as
print_string "something";
fn
There's nothing special about () in this let expression, it's just a pattern. All let expressions look like let pattern = expression in other-expression. Here the pattern will always match, because print_string returns unit, and () is the only value of that type. In this way, it's just another way of combining two expressions into one when the first one is really more of a statement (returns unit).
So you're right, the construct has pretty much the same meaning as using the ; operator. The only real difference is in the precedence. If, for example, you write
if x < 3 then
print_string "something";
f x
you would find that f x is always called. The precedence of ; is too low to pull the second expression under the control of the if. That's the reason many people (including me) get into the habit of using let () = expression. If you write the above as
if x < 3 then
let () = print_string "something"
in f x
the f x is only called when x is less than 3, which is usually what I want. In essence, the precedence of let is much higher than ;.
Of course there are may other ways to get this effect, but the nice thing about using let is that you don't have to add anything later on in the code (like a closing parenthesis or an end). If you're adding the print_string as a debugging statement, this is a handy way of keeping the changes local to the one spot.
Jeffrey's answer is absolutely correct, but one more point:
if you write
fx "something";
fn
And you messed up the result type of fx "something" the compiler will emit a Warning, that might get lost during compilation. On the other hand if you write:
let () = fx "something" in
fn
The compiler will type check that the result of fx "something" can be matched against (), i.e. that it is really of type unit. Thus if you messed up an error is produced, which is usually more secure.
There also is the possibility to write
let _ = fx "something" in
fn
which will only get the precedence effect that Jeffrey mentioned, but not do any type checking, since _ can be matched against values of any type.
Related
Let's say I have a bunch of nested let...in statements. I noticed that if I have
(* a bunch of let... in above *)
let test = expr1 in
(* a bunch of let ... in below *)
I get this Error (warning 26): unused variable test, yet when I change it to let _ = expr1 in ... or let () = expr1 in ... there are no error messages.
I understand let _ = is pattern matching for anything and let () = is pattern matching for anything of type unit, but does this mean that my expr1 is just being executed anywhere? Is it being called once?
There's a very simple experiment you can do do test this:
let test = print_endline "named";;
let _ = print_endline "any pattern";;
let () = print_endline "unit";;
As you can see, whether you put this in a source file and compile it or run it in the toplevel, it will print each string exactly once.
OCaml is a strictly evaluated (more specifically, call by value) language with side-effects, which means it will evaluate expressions in order, and not optimize away code with potential side-effects.
I'm an OCaml beginner using OCaml 4.12.0 on MacOS. This let expression:
let gg x y = (x -. y) < 5.0
at the toplevel results in:
Error: This expression has type float but an expression was expected of type
int
Explicitly adding type information, etc., did not fix the problem. In frustration, I visited the online REPL TryOCaml, and the expression was accepted without error, returning the type signature of:
val f : float -> float -> bool = <fun>
as expected. But I'd like utop to work on the Mac - what am I missing?
Very possibly you're using a library that overrides the built-in meaning of < in OCaml. Some people (not me) think the polymorphic comparison operators are a problem.
One problem with this (IMHO) is that it causes confusing results like this.
For example, the Jane Street Base library is documented as overriding the polymorphic comparison operators: https://ocaml.janestreet.com/ocaml-core/latest/doc/base/index.html
When you use Base (or Core, or Core_kernel and other Janestreet standard libraries) the comparison operator and its friends (like various equality operators) work only on values of type int. For all other values you have to use specialized comparison operators provided by the module that implements that type, e.g., to compare two floats,
Float.(3.14 < 4.14)
to compare strings,
String.("hello" <> "world")
And, using your example,
let gg x y = Float.(x -. y < 5.0)
or even
let gg x y = Float.(x - y < 5.0)
Notice that we don't need to use the ugly -. operators anymore and can use - (and other arithmetic operators) as they are all defined specifically for float in module Float.
Besides, the notation Foo.(<expr>) is a short-hand for let open Foo in <expr> and is called local open.
Using the OUnit unit testing framework in OCaml, I would like to test that the result of evaluating a function is an instance of a specified type.
Defining such a test in Python's PyTest would be done as follows:
def test_foo():
assert isinstance(foo(2), int)
How can this logic be translated to OUnit? That is, how are assertions of type membership specified?
I'm aware that, assuming the function under test is annotated with the proper type signature, this testing might be unnecessary.
This is the job of a type checker, and it is made automatically during the compilation (at static time). The type checker (i.e., the compiler) guarantees that all values that are created by a function has the same type, and the type is defined statically at the compilation time. You will not be able to compile a function, that creates values of different types, as you will get a type error during the compilation. This is an essential property of all statically typed languages, e.g., Java, C and C++ also has the same property.
So, probably, you're using are confusing terminology. It might be the case, that what you're actually trying to test, is that the value belongs to a particular variant of a sum type. For example, if you have a sum type called numbers defined as:
type t =
| Float of float
| Int of int
and you would like to test that function truncate, defined as
let truncate = function
| Float x -> Int (truncate x)
| x -> x
always returns the Int variant, then you can do this as follows:
let is_float = function Float _ -> true | _ -> false
let is_int = function Int _ -> true | _ -> false
assert (is_int (truncate 3.14))
If I define a function in OCaml, for example let f x = x + 1;; and then I try to call it passing a negative number
f -1;; it gives to me the following error
Error: This expression has type int -> int
but an expression was expected of type int
Why this error occurs?
Basically, it comes from the precedence of the parser. The compiler believes that f -1 means you want to subtract f by 1. It has been complained about for ages now.
Typing in f (-1) or f ~-1 will solve your problem (the later using the "explicitly unary minus").
UPDATE:
As stated in the OCaml manual:
Unary negation. You can also write - e instead of ~- e.
Basically, - can be used both as a binary operator 4 - 1 and a unary operator -1. But, as in your case, there can be confusion: f - 1 is "f minus one" and not "f applied to minus one". So the ~- operator was added to have a non-confusing unary minus as well.
Note that the spaces are not significant here, and that won't change because a lot of already existing code may contain operations without space.
I'm playing with the difference between - as a unary operator and a binary operator in caml-light.
let a b =
print_int b;
print_newline();
;;
let c d e =
print_int d;
print_newline();
print_int e;
print_newline();
;;
a (3 - 4 ) ;
c (9 - 4 )
;;
I expect the code to either throw an error (because it gets confused about how many arguments a or c have) or to print:
-1
5
However, it compiles with no problems (compiler version below) and prints
-1
Can anyone tell me what happens with the last call?
Cobrakai$camlc -v
The Caml Light system, version 0.80
(standard library from /usr/local/lib/caml-light)
The Caml Light runtime system, version 0.80
The Caml Light compiler, version 0.80
The Caml Light linker, version 0.80
Cobrakai$
In ML, all functions take exactly one argument. A seemingly multi-parameter function is actually a function that takes one argument, and returns another function which takes the remaining arguments.
So let c d e = ... is actually syntactic sugar for let c = function d -> function e -> ...
And the type of c is int -> int -> unit, and -> is right-associative, so it is int -> (int -> unit). So you can see clearly that is a function which takes int and returns a function.
When you apply it to multiple arguments like c 1 2, function application is left-associative so it is actually (c 1) 2, so you can see that c 1 evaluates to a function which then is applied to 2.
So, when you give a function "too few arguments", the result is a function. This is a useful and common technique in ML called "partial application", which allows you a convenient way to "fix" the first few arguments of a function.
I am not sure how the Caml Light interpreter handles it when the expression you type evaluates to a function. But from what you're saying, it seems to not print anything.