Implementing multiple if statements in OCaml - if-statement

So I am a little new to OCaml and I am trying to figure out a way for my function to check multiple conditions and modify a variable if any of those conditions are true
rough pseudo code would be
var list = []
if cond1 then 1::list
if cond2 then 2::list
etc
but from what I am able to tell once you enter an if statement you stay in it until it returns a value to the function. Is there a way around this limitation? Thanks for your time, tips or hints are greatly appreciated as I would love to understand the language

OCaml variables are immutable, you can't change their values. So you need to think of this a different way. One reasonable thing would be to have a function whose value is equal to a supplied list with something added to the front:
let f list =
if cond1 then 1 :: list
else if cond2 then 2 :: list
else 3 :: list
Note that if in OCaml is an expression, i.e., it has a value. It's similar to the ?: ternary operator in languages influenced by C.
Here is an OCaml session that shows a function like this. It's just an example, this isn't a useful function:
$ ocaml
OCaml version 4.01.0
# let f list =
if List.length list > 3 then 1 :: list
else if List.length list > 1 then 2 :: list
else 3 :: list ;;
val f : int list -> int list = <fun>
# f [];;
- : int list = [3]
# f [1;2];;
- : int list = [2; 1; 2]
Update
If you want to apply the ifs all the time the code looks like this:
let f list =
let list' = if cond1 then 1 :: list else list in
let list'' = if cond2 then 2 :: list' else list' in
let list''' = if cond3 then 3 :: list'' else list'' in
list'''
You can capture the repeated pattern in its own function:
let f list =
let cpfx cond pfx l = if cond then pfx :: l else l in
cpfx cond3 3 (cpfx cond2 2 (cpfx cond1 1 list))

If you want to have a sequence of if statements, each if must return unit. You can use a reference to your list to make it mutable, put semicolons after each if statement and return the referenced list at the end:
let f list =
let list = ref list in
if cond1 then list := 1 :: !list;
if cond2 then list := 2 :: !list;
[...]
!list
;;
The given list will not be modified, there is just a new variable called list that shadows the original one within the function definition.

Related

Determine if a matrix is square OCaml

I'm working on a problem where they ask us to write a function to determine if a matrix is square (n by n, for any n >= 0) with OCaml
I have a type matrix already defined
type matrix = float list list
Also I previously have a function that works to determine the length of a list
let rec length (l : 'a list): int =
match l with
| [] -> 0
| _ :: xs' -> 1 + length xs'
Right now I'm thinking about writing a helper function which checks if the length of all rows are equal
let rec check_row_equal (m : matrix): bool =
match m with
| [] -> true
| h1 :: h2 :: t ->
if length h1 <> length h2 then false
else check_row_equal (h2 :: t)
But when I ran this function in utop, it says Match_failure ("//toplevel//", 2, 2). If I have this helper function running correctly, my thought for my next function would be
let rec is_square (m : matrix): bool =
let l = length m in
if check_row_equal m == false then false
else if (l != the length of one of the rows) then false
else true
I haven't figured out how to calculate the length of the row, maybe another helper function like
let row_length (m : matrix): int =
match m with
| [] -> 0
| h :: t -> length h
But again, I need help with the check_row_equal function, please help me to fix that, thank u!
let rec check_row_equal (m : matrix): bool =
match m with
| [] -> true
| h1 :: h2 :: t ->
if length h1 <> length h2 then false
else check_row_equal (h2 :: t)
You're getting a match error because you have a case for an empty list, and a list with two or more elements, but not a list with one element. Presumably if there is only one row, this should return true.
Incorporating this and simplifying the code a bit.
let rec check_row_equal (m : matrix): bool =
match m with
| [] | [_] -> true
| h1 :: (h2 :: _ as tl) ->
length h1 = length h2 && check_row_equal tl
You don't say what it means specifically to check whether a matrix is square. I'll assume you want to check the lengths of all the contained lists to make sure they're the same, and this should also be the same as the length of the outer list.
Here are a couple of comments:
Your length function works correctly in the abstract, but it doesn't work for the normal kind of OCaml list. In OCaml, the empty list (the final tail of every list) looks like [] and Cons (a, b) looks like a :: b. Maybe your code is supposed to work with a custom list type, but then it's confusing to name it list, like the normal OCaml list.
You already have a function length that visits every element of a list and calculates an answer. You need a function just like this except that each element of the list is another list, and you want to determine whether the lengths of these are all the same. Just as your length function gets a new result by adding 1 to the returned result, you can figure out an operation that tracks whether the lists have all been the same length so far and, if so, what that length was.
I hope this helps. I don't want to write code for you because this is an assignment.

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.

Add elements to list in a loop in OCAML

Hi i'm a beginner in OCAML and i would like to create a function to add elements a the end of a list and return this list. Here is my code :
let test () : int list =
let mylist = [] in
for i = 1 to 3 do
mylist#[i];
done;
mylist;;
It says that mylist#[i] should have type unit. When I call this function it returns an empty list. Can anyone help me ? Thanks
Ocaml lists are immutable, i.e., they cannot be changed. The expression
mylist#[i]
creates a new list. However, since you do nothing with the result, it is just thrown away. If you want to build a list like that, you need to store it in a reference.
let l = ref [] in
for i = 0 to 3 do
l := !l # [i]
done;
List.iter (fun item -> print_int item; print_newline ()) !l
I would, however, recommend to do this differently. Appending two lists is a rather expensive operation, because a new list is created and all elements are copied every time. A much more efficient way to do what you want is to create the list in reverse order and use List.cons (the :: operator), which adds new elements to the beginning of the list.
let l = ref [] in
for i = 3 downto 0 do
l := i :: !l
done;
List.iter (fun item -> print_int item; print_newline ()) !l
The cons operation runs in constant time, because it can reuse the already existing list.
Alternatively, you can also create the list using recursion.
let rec l i =
if i <= 3 then i :: l (i+1) else [] in
List.iter (fun item -> print_int item; print_newline ()) (l 0)
This variant also does not need to copy the list, but it is not tail-recursive, i.e., it uses as much stack space as elements in the list.
let rec l acc i =
if i >= 0 then l (i :: acc) (i-1) else acc in
List.iter (fun item -> print_int item; print_newline ()) (l [] 3)
This variant is efficient, tail-recursive, but harder to read (IMHO).
As a final remark, you might want to check out the Queue module or the DynArray module in ExtLib or
in Batteries.
Lists are immutable in OCaml. In particular, the line
mylist#[i];
is equivalent to
mylist#[i]; ()
Or in other words, first append the list [i] at the end of mylist then discard the result of this computation. This is why the compiler is warning you that mylist # [i] should have type unit: unit is the result type used for functions that only perform side-effects and do not return a value.
If you want to create a range function, the idiomatic way is to define a recursive function
let rec range start stop =
if start > stop then
...
else
... range (start+1) stop ...

Function for infinite list excluding multiples of three

This question is related to my previous question Removing items from a list if a predicate holds .
I am struggling with outputting an infinite list which does not contain any multiple of three.
For that I have these few functions till now:
delete :: Eq a => a -> [a] -> [a]
delete deleted xs = [ x | x <- xs, x /= deleted ]
removeif ::(a -> Bool)->[a]->[a]
removeif func [] = []
removeif func (h:t)= if func h then delete h (h:t) else removeif func t
nothreefolds :: [Integer]
nothreefolds = removeif (x `mod` 3 == 0) [1..]
But the problem is that I am missing some syntax knowledge and I want to tell removeif to remove the elements from natural numbers if they are multiple of 3.
If you can please help me to the right direction, I will be thoroughly grateful.
removeif wants a function as first argument. But x `mod` 3 == 0 is not a function. It's an expression that references a non-existing name x.
You want to use a lambda abstraction: \x -> x `mod` 3 == 0.
The \x -> part says that this is a function with one parameter called x.
The result is given by the following expression.
Alternatively you could simply use sections and function composition: (== 0) . (`mod` 3).
Using composition :
removeThreeMultiple = filter ( (/= 0) . (`mod` 3))
Example:
Prelude> removeThreeMultiple [1,2,3,4,9,0]
[1,2,4]
Make it simple, try to write correctly the intermediate function that checks if a number is a mutliple of three or not. Then use it to clean your list.

OCaml - Add a new tuple, containing a list of tuples, to that list

I'm writing an interactive calculator in OCaml with some simple commands. Users should be able, among other things, to define their own simple functions (mathematical functions), for instance
let f(x) = x
let g(x) = 2*f(x)
Now, the functions should be handled like in functional languages, that means they should remember their time-of-creation environment. That means, that with a function I have to keep a closure of its environment, which is functions and variables.
I keep currently defined functions in a list of tuples formed like (functions_present_at_the_time_of_creation, variables_present_at_the_time_of_creation, function_name, function_argument_names, function_formula). When I try to add a new function to the list of functions (let's assume, that it's not currently defined and I don't have to overwrite anything), I recurrently iterate to the end of the list of functions and there would like to add a new tuple.
The problem is, assuming my current functions list is of type (a*b*c*d*e) list when i try to add a tuple with itself to the end of it, it changes its type to ((a*b*c*d*e) list*f*g*h*i) list. What can I do to be able to perform such addition of a list to itself, encapsulated in a tuple?
Here's some simple SSCCE I wrote while trying to find a workaround to this issue.
let rec add_to_end list list_copy dummy = match list with
| [] -> [(list_copy, dummy)]
| h::t -> h::(add_to_end t list_copy dummy)
let add list dummy = add_to_end list list dummy
This one tries to do it with a copy of the list. The following one is written without using of a copy (both of these examples don't work, of course):
let rec add_to_end list dummy = match list with
| [] -> [(list, dummy)]
| h::t -> h::(add_to_end t dummy)
The first example doesn't work when trying to use the function add, but when doing it for instance this way (in the interpreter):
let l = [];;
let l = add_to_end l l 1;;
let l = add_to_end l l 2;;
let l = add_to_end l l 3;;
Then it works fine. I'd appreciate any help, I may think about changing the design also, any proposals are very welcome.
Edit: Here's the output of the above commands:
# let l = [];;
val l : 'a list = []
# let l = add_to_end l l 1;;
val l : ('a list * int) list = [([], 1)]
# let l = add_to_end l l 2;;
val l : (('a list * int) list * int) list = [([], 1); ([([], 1)], 2)]
# let l = add_to_end l l 3;;
val l : ((('a list * int) list * int) list * int) list =
[([], 1); ([([], 1)], 2); ([([], 1); ([([], 1)], 2)], 3)]
It's hard to tell whether you're aware that OCaml lists are immutable. You can't add a value to the end of an existing list. An existing list can never be changed. You can create a new list with a value added to the end. If you do this, I don't see why you would want to add a pair to the end consisting of the list and the new value. I suspect you're thinking about it wrong. Here's a function that takes a list and an integer and adds the integer to the end of the list.
# let rec addi i list =
match list with
| [] -> [i]
| h :: t -> h :: addi i t
;;
val addi : 'a -> 'a list -> 'a list = <fun>
# let x = [1;2;3];;
val x : int list = [1; 2; 3]
# addi 4 x;;
- : int list = [1; 2; 3; 4]
# x;;
- : int list = [1; 2; 3]
#
The function returns a new list with the value added to the end. The original list isn't changed.
As a side comment, it's much more idiomatic to add values to the front of a list. Repeatedly adding to the end of the list is slow--it gives quadratic behavior. If you want the other order, the usual thing to do is add everything to the front and then reverse the list--this is still linear.
Edit
Apparently you really want a function that looks something like this:
let f a list = list # [(list, a)]
This is not realistically possible, the types don't work out right. A list can contain things of only one type. So you can conclude that the type of the list t is the same as the type (t, v) list, where v is the type of a. This is a recursive type, not something you would really want to be working with (IMHO).
You can actually get this type in OCaml using -rectypes:
$ ocaml -rectypes
OCaml version 4.00.0
# let f a list = list # [(list, a)];;
val f : 'a -> (('b * 'a as 'c) list as 'b) -> 'c list = <fun>
#
But (as I say) it's something I would avoid.
Edit 2
Now that I look at it, your first code sample avoids requiring a recursive type because you
specify two different copies of the list. Until you call the function with the same list, these are potentially different types. So the function type is not recursive. When you call with two copies of the same list, you create a new value with a type that's different than the type of the list. It only works because you're using the same name l for different values (with different types). It won't work in a real program, where you'd need a single type representing your list.
As another side comment: the beauty of adding values to the beginning of a list is that the old value of the list is still there. It's the tail of the new list. This seems lot closer to what you might actually want to do.