I have following piece of code:
let p = print_string("finished\n");;
let x0 = ref 0;;
class point =
object
val mutable x = incr x0; !x0
method get_x = x
method move d = x <- x + d
end
;;
print_int(new point#get_x);;
p;;
print_int(new point#get_x);;
p;;
Can't understand why the output is:
finished
12
My expectation is actually like:
1
finished
2
finished
Anyone can tell what's the correct order of executing this piece of code?
The main point of confusion is that your p isn't a function. It's just a value. In particular, it is the value () (known as unit). So when you evaluate p later in your code it has no effect. All the work was done when p was created.
If you want p to act like a function (which is what you seem to want), you should define it like this:
let p () = print_string "finished\n";;
And you should call it like this:
p ();;
Related
fun count_wcs p =
let
val count = 0
in
g (fn () => count + 1) (fn y => 1) p
end
I'm doing homework and we're not supposed to use mutations, this doesn't reassign the value to anything but it doesn't feel right. Please, don't say what is the right way to do this, because I'm supposed to figure this out.
datatype pattern = Wildcard
| Variable of string
| UnitP
| ConstP of int
| TupleP of pattern list
| ConstructorP of string * pattern
fun g f1 f2 p =
let
val r = g f1 f2
in
case p of
Wildcard => f1 ()
| Variable x => f2 x
| TupleP ps => List.foldl (fn (p,i) => (r p) + i) 0 ps
| ConstructorP(_,p) => r p
| _ => 0
end
This function g has to receive a type unit -> int function as the first argument. I checked the count after I called the function and got 0, so it is ok to write it like this, right? But still, it does feel sloppy.
Added the context (function g and the datatype used). The function count_wcs is supposed to count the number a Wildcard pattern appears in a pattern.
This does not count as a mutation, but it does resemble what you might do if you had them and is probably not going to work, depending on what it is you're doing. Mutations require references and they're made with ref and are de-referenced with !. So just stick away from those. :-)
You're doing something that will be of little benefit:
let
val count = 0
in
...
end
will bind count to 0, but will never cause count to have any other value; I presume that you want to eventually have that count increases. If it had been a reference, val count = ref 0, you could increment it by doing count := !count + 1, but since it's not, you have to make count a variable of some function for it to change.
For example:
fun count_4s ([], count) = count
| count_4s (x::xs, count) = count_4s (xs, if x = 4 then count + 1 else count)
In each call count is constant, but in each subsequent, recursive call it is possibly incremented.
This function g has to receive a type unit -> int function as first argument.
...
g (fn () => count + 1) (fn y => 1) p
...
[...] But still it does feel sloppy.
Assuming that g's first arguments have no side-effects and do not throw exceptions and do not loop forever, all they can do is return the same thing on every call. This makes them rather boring. Typically functions that either take as input or return () : unit do something else, like read or write from a source external to the program.
I wouldn't call it sloppy. Just a bit weird, without knowing the context.
It's very easy to identify mutation in standard ML - if you don't use ref variables and assign them new values with :=, it's not mutation.
And you don't, so you aren't mutating anything.
Also, your function can be simplified to
fun count_wildcards p = g (fn () => 1) (fn _ => 1) p
which makes it even clearer that nothing gets mutated.
(It's not at all clear what it's supposed to accomplish, so it's impossible to tell whether your solution is correct.)
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.
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.
The following OCaml code creates a universal type (not mine, from Jane Street's website):
module Univ : sig
type t
val embed: unit -> ('a -> t) * (t -> 'a option)
end = struct
type t = bool -> unit
let embed () =
let r = ref None in
let put x =
let sx = Some x in
fun b -> r := if b then sx else None
in
let get f =
f true;
let res = !r in
f false; res
in
put, get
end
creates a universal type. In it, a call to embed () creates a 2-tuple of functions. The first function in the tuple stores an arbitrary value in the closed-over ref cell; the second function retrieves it. If the wrong value of type t is given to the second function, it returns None instead. However, it appears to me that this would cause the ref cell to be cleared and thus further attempts to retrieve the value to fail, which does not happen. Also, I do not understand in general what happens when passed a wrong value to the projection function get.
When embed is called, a fresh reference r and two fresh closures for the functions put and get are allocated. When some put is called it returns a fresh function (let's call it the setter) that also has r in its closure.
If that setter is given to the corresponding get, the r captured in both closure is the same, hence when get calls f true, it modifies the r in get closure, and let res = !r read a Some value.
let get f =
f true; (* assign the shared reference r *)
let res = !r in (* read r *)
f false; (* clear r *)
res
If the setter is given to a non-corresponding get, the r captured by get and the setter is not the same. (let's call them r1 and r2)
let get f =
f true; (* assign r1 *)
let res = !r in (* read r2 *)
f false; (* clear r1 *)
res
Since the get takes care of always clearing r, we know that before calling
get, r2 is None. Hence get will return None.
I'm writing a program in ocaml containing some loops "for", my problem is that for each of these cycles you receive this message: "warning 10 : this expression should have type unit. "
Example :
let f q p rho=
let x = [] in
if q > p then
for i=0 to rho do
x= q :: x
done;
x;;
this every time I use a cycle "for" ,how can I solve this problem?
There are several problems with your code.
The error is because the for does not return anything, and so the inside of the loop to be purely for side-effect. So it should have unit type. Your use of = does not have unit type, because = is in fact the equality operator, comparing two values, and returning true or false.
So you are using the wrong operator. It appears that you are trying to "assign" to x. But in ML, you cannot assign to "variables", because they are bound to a value when they are defined and cannot change. One way to get mutability, is to use a mutable cell (called a "reference"): you use the ref function to create the mutable cell from an initial value; the ! operator to get its value out; and the := operator to change the value inside.
So for example:
let f q p rho=
let x = ref [] in
if q > p then
for i=0 to rho do
x := q :: !x
done;
!x;;
This kind of loop is probably best expressed using recursion:
let f q p rho=
let rec loop i =
if i > rho then
[]
else
q::(loop (i+1))
in
if q > p then
loop 0
else
[];;
Or we can make it tail recursive:
let f q p rho=
let rec loop i acc =
if i > rho then
acc
else
loop (i+1) (q::acc)
in
if q > p then
loop 0 []
else
[];;