I am just curious about these two functions in Lazy.
Lazy.from_fun
From the doc:
val from_fun : (unit -> 'a) -> 'a t
from_fun f is the same as lazy (f()) but slightly more efficient.
I then had a look at the source
let from_fun (f : unit -> 'arg) =
let x = Obj.new_block Obj.lazy_tag 1 in
Obj.set_field x 0 (Obj.repr f);
(Obj.obj x : 'arg t)
I guess Obj is used to directly allocate memories for from_fun. But why exactly does it boost the efficiency? or what is the difference between Lazy.from_fun and lazy (f())?
Lazy.from_val
val from_val : 'a -> 'a t
from_val v returns an already-forced suspension of v.
This is for special purposes only and should not be confused with lazy (v).
I really do not understand these. To me, Lazy.from_val 5 and lazy(5) both returns int lazy.t which has a concrete value of 5. Why is Lazy.from_val is for special purposes? and what kind of special purposes?
It's just my guess: let's compare the following:
let z1 = lazy (print_newline ())
let z2 = Lazy.from_fun print_newline
using ocamlc -dlambda:
(setglobal Lz!
(let
(z1/1008 =
(makemutable 246
(function param/1012 (apply (field 31 (global Pervasives!)) 0a)))
z2/1009 =
(apply (field 2 (global Lazy!)) (field 31 (global Pervasives!))))
(makeblock 0 z1/1008 z2/1009)))
z1 is a lazy value created from a function of the code function param/1012 -> Pervasives.print_newline (), while z2 is created directly from Pervasives.print_newline. z1 can be slightly inefficient because of the extra lambda abstraction.
Just as the documentation says, Lazy.from_val simply creates a lazy value from an already computed value without any suspension. You can check it by trying Lazy.from_val (print_string "hello") and lazy (print_string "hello"). The former immediately prints hello, but the latter does not.
Related
I want to create a non-recursive function for my minimum
but I have some troubles with it
Can you help me please.
`let min_list lst=
let n=list.length lst ;;
let a=list.nth lst ;;
for i = 1 to n-1 ;;
let b=list.nth lst i;;
if a >b then a=b lst done ;;`
Honesly,It's difficult with non recursive fonction.So this is just for learning.I still have erreur in ligne 6
let min_list lst=
let a=List.hd lst in
let n=List.length lst in
for j =1 to n-1 do
let b=List.nth lst j in
if a > b then (let a=b) done ;;
Thank you it's useful It help me a lot .I have one other question what the difference between this
let min_array a =
let min =ref (List.hd a) in
for i = 1 to List.length a -1 do
if List.nth a i < !min then min := List.nth a i
done;
!min;;
print_int (min_array [ 10 ; 5 ; 7 ; 8 ; 12 ]);;
and
let min_array a =
let min =ref (List.hd a) in
for i = 1 to List.length a -1 do
if ref (List.nth a i) < min then min := List.nth a i
done;
!min;;
print_int (min_array [ 10 ; 5 ; 7 ; 8 ; 12 ]);;
It's the same ?I think
Why don't you want to use a recursive function ?
Liste are made to be crossed by recursive function. Everytime you use List.nth l n Ocaml has to cross n values until he found the nth element.
In Ocaml you can't change variable value as you do in other languages. You want a to be a ref.
Also your function won't return anything you'll have to put a !a between the done and the ;;. There will be a ! Because a will be a ref.
But if you want to practice use arrays instead because what you do here is in complexity O(n²) instead of O(n).
As said in the answer from Butanium, this kind of non-recursive function might be more relevant with arrays. And to work with mutable values, you need to use a reference.
A solution might then be something like (without dealing with case of an empty array):
let min_array a =
let min = ref a.(0) in
for i = 1 to Array.length a -1 do
if a.(i) < !min then min := a.(i)
done;
!min
The last line is important here, because it gets the value to be returned by the function.
Can then be used like that:
# min_array [| 10 ; 5 ; 7 ; 8 ; 12 |];;
- : int = 5
If you really do want to use lists instead of arrays, just use List.nth a i instead of a.(i) and List.length instead of Array.length.
Edit after question update
As Shawn and Jeffrey Scofield said in their respective comment, you should try to understand a bit better OCaml's syntax. And please don't use ;; in your programs, just keep it for the REPL.
As described in the documentation,
ref returns a fresh reference containing the given value.
Which means that when you write ref (List.nth a i) < min,
you create a fresh reference containing the i-th value the list, then compare it to min (which is also a reference). Luckily, mutable structures are compared by contents, which means that OCaml will access to your fresh reference's value, then access to min's value, and compare them. Thus, it will produce the same result as the direct comparison List.nth a i < !min, with a bit of useless memory allocation/access.
You can do this quite concisely by taking advantage of some features of the OCaml stdlib:
(* 'a list -> 'a option *)
let min_list l =
if List.length l > 0 then
Some (List.fold_left min (List.hd l) l)
else
None
Thanks to the min built-in, this works for lists of any type.
e.g. in a utop shell we can see:
min_list [99; 33; -1];;
- : int option = Some (-1)
min_list [99.1; 33.2; -1.3];;
- : float option = Some (-1.3)
min_list ["z"; "b"; "k"];;
- : string option = Some "b"
Explanation
First we recognise that the list may be empty, in which case we cannot return a meaningful value. This implies the function should return an option type, so either Some <value> or None.
Next we can use List.fold_left to iterate through the list.
Unfortunately the docs for List.fold_left are almost completely unhelpful:
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
fold_left f init [b1; ...; bn] is f (... (f (f init b1) b2) ...) bn.
It's as if they assume that if you're using OCaml you're already an elite master of functional programming, who naturally knows what a "fold left" does.
I'm not an elite master of functional programming, but I've been around long enough to know that fold_left is basically the same as the reduce function in Python.
It's a function that iterates through a list, applies a function to each value as it goes, and returns a single value.
So we can start to make sense of the signature of fold_left...
It takes three arguments:
The first arg, f, is a function which itself takes two args - the first or 'left' arg is the 'accumulated' value, and the second arg is the current value from the list as we iterate through. Whatever value you return from this function will be passed back into it as the left 'accumulated' value on the next iteration. When the list is exhausted the accumulated value will be returned from fold_left.
The second arg, init is an initial value. It is passed to f as the left 'accumulated' arg in the first step, when nothing has been otherwise accumulated yet.
Third arg is our list of values
So when we return:
Some (List.fold_left min (List.hd l) l)
...we are passing the min function as f and (List.hd l) as init.
List.hd l just returns the first element of the list l. We could use any element from the list as an initial value, but List.hd exists and gives us the first.
So fold_left is going to iterate through the list and f will return min <accumulated> <current>. So at each iteration step the accumulated value passed forward is the lowest value seen so far.
Non-recursive?
I did wonder if perhaps the fold_left method does not count as non-recursive somehow, since no one else had suggested it. Even though we have not used let rec anywhere, maybe somewhere internally it is secretly recursive?
For fun I decided to try writing the reduce/fold function from scratch:
let reduce f init l =
let acc = ref init in
List.iter (fun el -> acc := f !acc el) l;
!acc
(* we can directly substitute `reduce` for `List.fold_left` *)
let min_list l =
if List.length l > 0 then
Some (reduce min (List.hd l) l)
else
None
...again, no let rec needed so I guess it counts as non-recursive.
Batteries.LazyList allows one to define lazy lists. I would like to define a lazy list consisting of x, f x, f (f x), f (f (f x)), etc.
Based on comments in the module documentation, it appears that from_loop is the function I want:
"from_loop data next creates a (possibly infinite) lazy list from the successive results of applying next to data, then to the result, etc."
This description suggests that if I wanted a lazy list of non-negative integers, for example, I could define it like this:
let nat_nums = from_loop 0 (fun n -> n + 1)
However, this fails because the signature of from_loop is
'b -> ('b -> 'a * 'b) -> 'a LazyList.t
so the next function has signature ('b -> 'a * 'b). In utop, the error message underlines n + 1 and says
Error: This expression has type int but an expression was expected of type 'a * int
I don't understand what 'a is supposed to be. Why is the next function supposed to return a pair? Why is the type of the list supposed to be a 'a LazyList.t? Shouldn't the type of the elements be the same as the type of the argument to the next function? The description of the function doesn't make the answers clear to me.
In case it's helpful, my conception of what I'm trying to do comes from Clojure's iterate. In Clojure I could create the above definition like this:
(def nat-nums (iterate (fn [n] (+ n 1)) 0))
The function passed to from_loop has to return a pair. The first element of the pair is the value you want to return. The second element of the pair is the state required to calculate the next element later on.
Your code:
(fun n -> n + 1)
Just calculates the next element of the lazy list, it doesn't return the state required for the next call. Something like this is what is wanted:
(fun n -> (n, n + 1))
(This will return a list starting with 0, which I think is what you want.)
This formulation is more flexible than your clojure example, because it allows you to maintain arbitrary state distinct from the values returned. The state is of type 'b in the type you give for from_loop.
I don't have Batteries right now, so I can't try this out. But I think it's correct based on the types.
It turns out that the function that I really wanted was LazyList.seq, not from_loop. While from_loop has its uses, seq is simpler and does what I wanted. The only trick is that you have to provide a third argument which is a termination test that returns false when the list should end. I wanted an infinite list. One can create that using use a termination function that always returns true:
let nat_nums = seq 0 (fun n -> n + 1) (fun _ -> true);;
LazyList.to_list (LazyList.take 8 nat_nums);;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7]
In OCaml, the [#tailcall] annotation lets you assert that a particular function-call is a tail call (and so hopefully your whole function is tail recursive). The question is: Where do I place the annotation exactly?
Obvious, easy example:
let rec f = function
| 0 -> 0
| x -> (f [#tailcall]) (x - 1) (* works like a charm *)
But I don't see how I can do it in "less obvious" places:
let rec f = function
| 0 -> 0
| x -> (|>) (x - 1) f (* uh? *)
I can see from the assembly code that the latter example is recognized as tail recursive by the compiler. So until someone implements [#tailrec]: Where exactly do I place my [#tailcall] annotations? (if it's possible at all in the 2nd example)
The docs say in subsection 18.1 that
“ocaml.tailcall” or “tailcall” can be applied to function application in order to check that the call is tailcall optimized. If it it not the case, a warning (51) is emitted.
Since your second example does not apply f, the attribute is not applicable in this context.
did you try :
let rec f = function
| 0 -> 0
| x -> (|>) (x - 1) (f[#tailcall])
I need to convert a list into a function. I've managed to make the list into a list of tuples. So I have something like this now:
[Expr, (Expr, [[T"("; N Expr; T")"]; [N Num]; [N Expr; N Binop; N Expr]; [N Lvalue]; [N Incrop; N Lvalue]; [N Lvalue; N Incrop]]
Lvalue, [[T"$"; N Expr]])]
I want the final result to look something like:
(Expr,
function
| Expr ->
[[N Term; N Binop; N Expr];
[N Term]]
| Lvalue ->
[[T"$"; N Expr]])
I'm mostly stuck on how I can implement the OR symbols (|). Any advice would be greatly appreciated. Thanks!
You're describing things as if you want to generate the source of your function. That doesn't make a lot of sense unless you're writing some kind of preprocessing tool.
Assuming you're not working on a preprocessor, you should think about what you want the function to do, rather than the textual form it should have. You can easily get the functionality you seem to want--it basically works like the List.assoc function. But you can't do it by creating a certain textual form for the function at runtime.
Here's a function that translates a list of pairs into a lookup function:
# let makeLookup pairs = fun x -> List.assoc x pairs;;
val makeLookup : ('a * 'b) list -> 'a -> 'b = <fun>
# let f = makeLookup [(1, "yes"); (2, "no")];;
val f : int -> string = <fun>
# f 1;;
- : string = "yes"
# f 2;;
- : string = "no"
#
(In fact makeLookup is the same as List.assoc with its parameters reversed.)
The doc of Lazy.lazy_from_val states that this function is for special cases:
val lazy_from_val : 'a -> 'a t
lazy_from_val v returns an already-forced suspension of v This is for special purposes only and should not be confused with lazy (v).
Which cases are they talking about?
If I create a pair of suspended computation from a value like:
let l1 = lazy 123
let l2 = Lazy.lazy_from_val 123
What is the difference between these two? Because Lazy.lazy_is_val l1 and Lazy.lazy_is_val l2 both return true saying that the value is already forced!
The special purpose would be if you need a lazy value but you sometimes have an already computed (non-lazy) value. You can use lazy_from_val to turn an already computed value into a (forced) lazy version of your value.
let f lazyint =
Lazy.force lazyint + 42
let li = lazy 4;;
# f li;;
- : int = 46
# f 14;;
^^
Error: This expression has type int but an expression was expected of type
int Lazy.t = int lazy_t
# f (Lazy.lazy_from_val 14);;
- : int = 56
In this (contrived) example, you might wish to call f with an ordinary integer value (14, in this example). You can do it, but you need to use Lazy.lazy_from_val to make it work.
The key difference is that lazy takes an expression of type 'a and creates a suspended computation (in essence, a closure) of type 'a lazy_t. Lazy.lazy_from_val takes a pre-computed value of type 'a and converts it to a (pre-forced) value of type 'a lazy_t. If the expression has side-effects, the difference between the two can be seen.
# let p () = print_string "here\n"; 3 ;;
val p : unit -> int = <fun>
# let l1 = lazy (p ());;
val l1 : int lazy_t = <lazy>
# let l2 = Lazy.lazy_from_val (p ());;
here
val l2 : int Lazy.t = lazy 3
# f l1;;
here
- : int = 45
# f l2;;
- : int = 45
#
You could implement lazy operations directly using explicit closures and references. As Matthias Benkard points out, OCaml's lazy mechanism uses special syntax to make it less cumbersome to work with. I.e., lazy is an OCaml keyword, not a function.
lazy_from_val is a function rather than syntax. Thus,
# let id = fun x -> x;;
val id : 'a -> 'a = <fun>
# Lazy.lazy_is_val (lazy (id 123));;
- : bool = false
# Lazy.lazy_is_val (Lazy.lazy_from_val (id 123));;
- : bool = true