Consider this code
Open Cil
Cil.useLogicalOperators := true
let fct op =
match op with
LAnd|LOr -> true
| _ -> false
I'm trying to use LAnd and LOr from the type binop. These two can be used only if Cil.useLogicalOperators is true.
| LAnd (* logical and. Unlike other expressions this one does not always evaluate both operands. If you want to use these, you must set Cil.useLogicalOperators. *)
| LOr (* logical or. Unlike other expressions this one does not always evaluate both operands. If you want to use these, you must set Cil.useLogicalOperators. *)
So I must set Cil.useLogicalOperators.
val useLogicalOperators : bool ref
Is this code mentionned above is correct ?
Does it set Cil.useLogicalOperators to true ?
So you're asking how to set a global variable that is itself a reference.
In this case, no, a global assignment always start with let
In your case you need to write
let () = Cil.useLogicalOperators := true
In OCaml, files are compiled top to bottom and values are evaluated at once. Here, let () = ... is a value so it will be evaluated before the rest of the following code. You can check it with:
let () = Format.eprintf "%b#." !Cil.useLogicalOperators
let () = Cil.useLogicalOperators := true
let () = Format.eprintf "%b#." !Cil.useLogicalOperators
Related
I tried this in utop but since I am not familar with a dune project, it failed and report the error
This expression has type int list but an expression was expected of type unit.
This is for the line filter greaterthanfive list1
open Base
let rec filter p inputList = match inputList with
[] -> []
| x::xs -> if p x then x::filter p xs else filter p xs
;;
let greaterthanfive num =
if num>5 then true else false;;
let () =
let list1 = [1;6;8;3] in
filter greaterthanfive list1
;;
let () = <expr> means <expr> is expected to evaluate to ()
More generally, this construct has the form let <pattern> = <expr>, where <pattern> is anything you can put in the branch of a match expression. And () is a literal pattern that will only match this value, which is also the only value of the type unit.
In program code it is good practice to use let () = <expr> for the main part of the program to make sure it evaluates to () and indicates it will only have side-effects, such as printing to the terminal or writing to a file.
In utop however, you usually want the value of an expression to be sent to utop to be printed, and in that case let () = <expr> prevents that. Instead you should just evaluate the expression directly.
The following piece of code does not work as I thought it would :
let debug_flag = ref false
let dprintf = let open Printf in
match !debug_flag with
| true -> printf
| false -> ifprintf stdout
let test_dprintf () =
begin
debug_flag := true;
Printf.printf "print1\n";
dprintf "print2\n";
Printf.printf "print3\n";
debug_flag := false
end
I would expect it to output
print1
print2
print3
However it only prints
print1
print3
Assigning true to debug_flag in test_dprintf does not seem to have any impact at all.
Does anyone know why? And if so, do you know of a possible way to workaround?
I am using OCaml 4.09.0
Thanks for your answers
The definition of dprintf is not a function expression. It is an expression that will return a function, but the expression itself will be evaluated only when evaluating the definition of dprintf, not when the function it returns is called.
To solve this, you could just make the argument explicit:
let dprintf fmt = let open Printf in
match !debug_flag with
| true -> printf fmt
| false -> ifprintf stdout fmt
Now the body of dprintf will be evaluated when it's called.
Why is this Ocaml statement giving me a syntax error?
let a = 0;; if a = 0 then let b = 0;;
Do if then else statements always have to return a value?
EDIT: Here is the code I am struggling with. I want to apply this function over a list with the map function. The function is supposed to look at each word in the list wordlist and add to the stringmap. If it has already been added to the string map then add 1 to its password.
module StringMap = Map.Make(String)
let wordcount = StringMap.empty
let findword testword =
let wordcount = (if (StringMap.mem testword wordcount)
then (StringMap.add testword ((StringMap.find testword wordcount)+1) wordcount)
else (StringMap.add testword 1 wordcount))
List.map findword wordlist
You can only have an if then without else if the then expression evaluates to unit () Otherwise, the expression will not type check. An if without an else is equivalent to writing if x then y else () which can only type check if y is unit.
Check this out for a reference.
(Terminology note: there are no statements in OCaml because everything is an expression, so the term "if statement" doesn't quite apply. I still understood what you meant, but I thought this was worth noting)
Yes, if is an expression in OCaml, not a statement. The best way to look at it is that there are no statements in OCaml. Everything is an expression. (Admittedly there are expressions that return (), which are similar to statements.)
You can only have if b then e if the type of e is unit (i.e., if it returns ()).
Note also that you can't just say let v = e, except at the top level of a module. At the top level it defines a global name in the module. In other cases you need to say let v = e1 in e2; the let defines a local symbol v for use in the expression e2.
One answer to the let b = problem - it works like this:
let a = 0
let b = if a = 0 then 0 else 1
(* or whatever value you need in the else branch *)
And then the Map problem: the manual says Map is applicative - that means Stringmap.add returns a new map. You must use a ref to store your map - see this ocaml toplevel protocol:
# module StringMap = Map.Make(String);;
# let mymap = ref StringMap.empty ;;
val mymap : '_a StringMap.t ref = {contents = <abstr>}
# mymap := StringMap.add "high" 1 !mymap;;
- : unit = ()
# StringMap.mem "high" !mymap;;
- : bool = true
# StringMap.mem "nono" !mymap;;
- : bool = false
# StringMap.find "high" !mymap;;
- : int = 1
# StringMap.find "nono" !mymap;;
Exception: Not_found.
When using OCaml, I almost always use underscore wildcard in let _ = exp, especially when the result of exp is not important, but the computation inside it is. For example:
let _ = print_endline "abc" in
...
let _ = a := !a + 1 in
...
let _ = do_some_thing ... in
So, I just wonder if there is any side effect of extensively using let _ = ... ?
The side effect is annoying bugs to track in your software in the future. The problem with let _ = is that it will silently ignore partial applications you intended to be total. Suppose you write the following:
let f a b = ...
let _ = f 3 4
And that in the future you add an argument to f:
let f a b c = ...
The expression let _ = f 3 4 will still silently compile and your program will not invoke the function, leaving you wondering what is happening. It is much better to always let to () and use ignore when if you need to ignore a non unit result:
let () = ignore (f 3 4)
let () = print_endline "abc"
Using let _ = ... should be considered bad style.
No, there is absolutely no consequence to using let _ = extensively. The compiler does not add a name to the global environment since you didn't give one.
The purpose of let is to bind values to identifiers. If you doing side-effects only it's its better to wrap it in a begin .. end block. In your case:
begin
print_endline "abc";
a := !a + 1;
do_some_thing ();
end
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 = ()