I am new to OCaml and functional programming as a whole. I am working on a part of an assignment where I must simply return the first n elements of a list. I am not allowed to use List.Length.
I feel that what I have written is probably overly complicated for what I'm trying to accomplish. What my code attempts to do is concatenate the front of the list to the end until n is decremented to 1. At which point the head moves a further n-1 spots to that the tail of the list and then return the tail. Again, I realize that there is probably a much simpler way to do this, but I am stumped and probably showing my inability to grasp functional programming.
let rec take n l =
let stopNum = 0 - (n - 1) in
let rec subList n lst =
match lst with
| hd::tl -> if n = stopNum then (tl)
else if (0 - n) = 0 then (subList (n - 1 ) tl )
else subList (n - 1) (tl @ [hd])
| [] -> [] ;;
My compiler tells me that I have a syntax error on the last line. I get the same result regardless of whether "| [] -> []" is the last line or the one above it. The syntax error does not exist when I take out the nested subList let. Clearly there is something about nested lets that I am just not understanding.
Thanks.
Since you're just starting with FP, I suggest you look for the simplest and most elegant solution. What you're looking for is a way to solve the problem for n by building it up from a solution for a smaller problem.
So the key question is: how could you produce the first n elements of your list if you already had a function that could produce the first (n - 1) elements of a list?
Then you need to solve the "base" cases, the cases that are so simple that the answer is obvious. For this problem I'd say there are two base cases: when n is 0, the answer is obvious; when the list is empty, the answer is obvious.
If you work this through you get a fairly elegant definition.
let rec firstk k xs = match xs with
| [] -> failwith "firstk"
| x::xs -> if k=1 then [x] else x::firstk (k-1) xs;;
You might have been looking for this one.
What you have to do here, is to iterate on your initial list l
and then add elements of this list in an accumulator until n is 0.
let take n l =
let rec sub_list n accu l =
match l with
| [] -> accu (* here the list is now empty, return the partial result *)
| hd :: tl ->
if n = 0 then accu (* if you reach your limit, return your result *)
else (* make the call to the recursive sub_list function:
- decrement n,
- add hd to the accumulator,
- call with the rest of the list (tl)*)
in
sub_list n [] l
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.