How much space is required in my SML code? - sml

I have SML code like below.
fun fact(n) =
let fun f(n,g) = if n=0 then g(1)
else f(n-1, fn x=>g(x)*n)
in f(n, fn x=> x) end;
I want to know how much space is required in my code for computing fact(n).
Is it right it requires O(n)? I don't know exactly.

Yes, the function you wrote creates n closures before evaluating them at the end.
Here is a more space-efficient version:
fun fact n =
let fun fact' 0 result = result
| fact' n result = fact' (n-1) (n*result)
in fact' n 1 end
It resolves n*result before making a recursive call, rather than delaying it, making it tail-recursive.

Related

Minimum of a list

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.

Tail Recursive ocaml function that outputs a List with numbers from n to 0;

This is what function should do:
to0from 5 = [5;4;3;2;1;0]
I'm trying to do this tail recursive but I can't find a way. This is what I've got:
if n = 0 then
0
else
let rec loop r = function
| 0 -> r
| _ -> loop (List.append r [n]) (n-1)
in loop [] n;;
Any clues? Thank you.
Well, #glennsl is right that you don't seem to be asking a specific question. So it's difficult to know how to help. But here are some comments.
Your code doesn't define a function at all. It just computes a value based on a global variable named n. You should flesh out your code into a definition of a function named to0from (from what you seem to be saying).
In the case that n is 0, your code returns an integer value of 0. In other cases it returns a list. This can't be right, and it could possibly be what you mean when you say you can't get your code to work.
Is the recursive call to loop in tail position? If so, I'd say that your code was tail recursive.
I can give you a hint on how I would approach this...
let to0from d =
let rec to0from_aux s acc =
(* add code here to build list *) in
to0from_aux 0 []

OCaml Factorial Function with Restrictions

I'm trying to learn OCaml on my own, and I've reached imperative programming. I found this little exercise that I'm just completely stuck on how to even approach. It seems so simple, but I think my understanding is just lacking.
The problem asks me to write the function for factorial without using the rec keyword, and without loops. It's supposed to teach me the environment model, but that's also confusing to me.
My first thought was to try something like this:
let factorial =
let f = ref (fun n -> 0) in
let temp_factorial n =
if n = 0
then 1
else
begin
f := n * !f*(n-1)
!f
end
But I'm not sure if this works. Any help would be greatly appreciated :)
Your code is a little strange and wrong, but the basic idea is workable. Once you have a reference f to a function of type int -> int, you can use !f freely in later code. In fact you can assign f so it refers to a function that uses !f. This is equivalent to recursion, but it uses the imperative part of OCaml.
let f = ref (fun n -> n + 1)
f :=
(fun n ->
if n < 2 then 1
else (* ... left as an exercise ... *)
)
let factoral n = !f n
The key is that the part left as an exercise can use !f.

Standard ML recursive function error

So i just got in ML programming and I found this excercise in a book. The excercise says to build a recursive function that takes an integer and a list. If L=[a1,a2,a3] then the desired result is [ai+1,ai+2,...,an,a1,a2,...,ai]. So I wrote a function and after a lot of hours I narrowed the errors down to one which I can't understand. Here is my function:
fun cycle L i =
if i = 0 then L
else (cycle tl(L) (i-1)) # [hd(L)];
I will upload an image with the error that i get so someone can explain to me what the interpreter is trying to say to me.
The numbers next to the "a" just show the order of these elements in the list.So for L=[1,2,3,4,5] and for i = 2, the desire result is the List L=[3,4,5,1,2]. I don't think that the type of list is essential in this problem. Hope this further explanation helped
It's a syntactic problem with the recursive call cycle tl(L) (i-1).
In SML, the syntax for function application is juxtaposition, not parentheses. In your case tl(L) indeed calls the function tl with argument L, but that's equivalent to just tl L. The parentheses are redundant and, as such, ignored.
Now, if you replace the minimal version within your original call, you'll get this: cycle tl L (i-1). It's calling cycle with three arguments, instead of just two.
The correct way of writing it would be: cycle (tl L) (i-1).
Ionuț already gave a sufficient answer to the syntax problem; here are some further suggestions:
Use pattern matching rather than hd and tl.
Consider the base cases; what are the simplest sub-problems you can think of? E.g. cycling the empty list will always give the empty list regardless of n, and cycling L 0 times will always give L back. Having both base cases as patterns helps.
Consider the recursive case; the top element (assuming it exists) is cycled and i is reduced by one, until eventually i is 0 or L is empty. Because the second base case catches the empty list, we can freely assume that L is non-empty here, in which case it will match the pattern x::xs.
fun cycle 0 xs = xs
| cycle i [] = []
| cycle i (x::xs) = cycle (i-1) (xs # [x])
Depending on whether 0 <= i and i <= length xs are preconditions for the function or not, you may want to handle these once before activating the main recursion, e.g. by wrapping the function above:
fun cycle i ys =
let fun fun cycle' 0 xs = xs
| cycle' i [] = []
| cycle' i (x::xs) = cycle' (i-1) (xs # [x])
in
if 0 <= i andalso i <= length xs
then cycle' i ys
else raise Domain
end
The main operation, namely xs # [x] is terribly inefficient, since its running time is proportional to the length of xs and is activated n times. So the running time of cycle becomes O(n • |L|) when something like O(min(n,|L|)) should be achievable.
You could probably make a much faster version if you store the cycled elements in a separate list, without using #, and combine the remaining elements with this list after the elements have been cycled. Depending on what you felt about 0 <= i and i <= length xs, you may run into problems with the following test case:
val cycle_test_1 = (cycle 5 [1,2,3,4] = [2,3,4,1])

Is this a reasonable implementation of the quadratic Bézier function in OCaml?

A friend came across a quadratic Bézier curve function in his codebase that used a gigantic rats nest of a switch table to perform the computation. He challenged me to find a single, short expression that would allow him to replace the gigantic block of code.
In attempting to satisfy two different curiosities, I thought I'd try implementing the function in OCaml. I'm a very novice OCaml programmer and I'm also unfamiliar with the function and this specific implementation is hard to come by via Google.
Critiques on both the function's performance/correctness as well as its implementation are very much appreciated.
Implementation of Quadratic Bézier Curve:
let rec b2 n =
let p1 = -10. in
let p2 = 10. in
let q = n*.n in
let rec b2i n i hd =
if i > n then
List.rev hd
else
let t = i /. n in
b2i n (i+.1.) ((((1.-.t)**2.)*.p1+.(2.*.t*.(1.-.t)*.q)+.(t**2.)*.p2) :: hd)
in
b2i n 0. []
;;
let floatprint lst =
List.iter (fun f -> Printf.printf "%f; " f) lst ;;
floatprint (b2 8.);;
b2 isn't recursive, so no need for [let rec b2 n =]. Since n never changes, no need to have it as argument to b2i, just use n from the enclosing scope. Your inner function should depend on p0, p1 and p2, but I see it depending on -10., n**2 and 10. The function also has the form of a map from [ 0.0; 1.0; 2.0; ...; n.0] to the final values. Could you write it:
let b i =
let t = i /. n in
let tminus = (1.-.t) in
(tminus *. tminus *. p0) +. (2. *. t *. tminus *. p1) +. (t *. t * p2)
in
List.map b ([generate list 1.0; 2.0; ... n.0])
A function to generate the list 1.0...n.0 could be: (for small n)
let rec count m n = if m > n then [] else m :: (count (m+.1.) n)
I have two suggestions:
You should call List.rev after b2i returns so ocaml can exploit it's tail-recursion optimizations. I am not sure how well OCaml will deal with the current implementation, List.rev is tail-recursive though. You'll notice that in this post it is done like that.
Also, you can make the resolution of the iteration be an optional argument like ?(epsilon=0.1).
As an ocaml programmer I don't see much wrong here aside from that --as long as P1 and P2 are in fact constants. Compile it down and see what the difference in assembly is between moving List.rev inside or out of the tail-recursion.