Why does this helper function give me an unbound value error? - ocaml

I have a helper funtion which is as follows:
let rec helper2 nfa l symb res =
match l with
| [] -> res
| h::t -> res#(transitions nfa.trans symb h) in
helper2 nfa t symb res
Now when I try compiling it it gives me an unbound value error at the last line saying nfa is unbound value. I am just trying to use the recursive function with the same nfa so I dont know why I keep getting this error. I have encountered this error multiple times in different parts of my code as well.
Any help is appreciated!

What #octachron is telling you is that there's no expression in OCaml that looks like this:
a in b
But that's what your code seems to be asking for:
res#(transitions nfa.trans symb h) in
helper2 nfa t symb res
It's difficult for us to help any more than this because it's not completely clear what your code is supposed to do. Let's assume that the recursive call to helper2 is supposed to return a new value for res and that you want to use this new value where your current code has res. Then something like this might work:
let res' = helper2 nfa t symb res in
res' # transitions nfa.trans symb h
There is no expression of the form expr1 in expr2 but there is an expression of the form let var = expr1 in expr2 as here.
In OCaml (and functional languages in general) you need to think of defining new variables rather than of modifying existing variables. Modification isn't possible for a variable like res; it's immutably bound to one specific value. But you can compute a new value and use the new value instead.

Your formatting is lying to you. The right formatting for your function is:
let rec helper2 nfa l symb res =
match l with
| [] -> res
| h::t -> res#(transitions nfa.trans symb h)
in
helper2 nfa t symb res
which is probably not what you wanted.
It may be useful to setup an auto-formatting (or indenting) tool in your workflow.

Related

OCaml initializing list in loop for

I am a beginner with OCaml. I would like to skip the first element of my list.
Here is my list:
let l = [1;2;3;4;5;6;7;2;1];;
I want to use this in my FOR:
let l = List.tl l;
here is my full code:
let l = [1;2;3;4;5;6;7;2;1];;
let n = 1;;
let counter = ref 0;;
for i = 0 to (List.length l) do
if List.hd l = n then counter := !counter + 1;
print_int(!counter);
print_string("\n");
let l = List.tl l
done;;
But I have errors in the DONE and it says syntax error.
Can anyone help me please?
Your problem is that let always requires a matching in. The full expression looks like this:
let var = expr1 in expr2
Since you're missing the in part, you get a syntax error.
However, the deeper problem is that you're trying to modify the value of l. The way you have defined l, it's immutable. You can't change its value. If you want to be able to change its value you can define it as a reference, as you have done for counter.
(There is another form of let used at the top level of a module. This form doesn't have a matching in. But your code isn't defining a top-level name, so this is not relevant.)

trimming a list of pairs with OCaml

I am trying to filter a list of pairs and return a new list containing only the first element of each pair. The input/output should go like this:
input = [('A', 3); ('B', 2); ('D', 1)]
output = ['A'; 'B'; 'D']
The code i have so far is this:
let rec trimList l = function
| [] -> []
| head::tail -> let l' = [fst head] # trimList List.tl l;;
but i get the following error:
Line 3, characters 59-61:
3 | | head::tail -> let l' = [fst (head)] # trimList List.tl l;;
^^
Error: Syntax error
I don't know why this isn't working. I know this is very simple, but i am new to OCaml.
Any help would be appreciated, thank you.
Your syntax problem is caused by the fact that you have let with no corresponding in.
A let expression looks like this:
let v = expr1 in expr2
In essence this establishes a local variable v with value expr1 and has the value of expr2 (which will probably contain instances of the variable v).
You are missing the in part of the let expression.
As another comment, if you define a function like this:
let f l = function ...
You are defining a function of two parameters. There is an implicit parameter defined by the function keyword; the parameter is matched against the following patterns.
Most likely you want to remove the l from you function definition.
There are a few other problems with your code, but I hope this helps to make progress.

Why do i get syntax error at end problem with pattern matching

I have to make a function that takes list a list and returns list of pairs of first and last element,2nd and 2nd last and so forth It doesn't matter if the list has even or odd number of elements because if its odd i will just ignore the middle element.The idea i have is that make a new rec fun that takes old list and its revers as input i think i finished the code but i get Syntax error for ;;
let lip l =
if [] then []
else let l1=l l2=List.rev l in
let rec lp l1 l2 = match l1,l2 with
| [],[] ->[]
| [],h2::t2->[]
| h1::_,h2::_ ->
if (List.length l -2) >= 0 then [(h1,h2)]# lp(List.tl l1) t2
else [] ;;
There are quite a few errors in your code.
I think the specific error you're seeing is caused by the fact that there is no in after let rec lp ....
Every let that's not at the top level of a module needs to be followed by in. One way to think of it is that it's a way of declaring a local variable for use in the expression that appears after in. But you need to have the in expr.
Another way to look at it is that you're defining a function named lp but you're not calling it anywhere.
As #lambda.xy.x points out, you can't say if [] then ... because [] isn't of type bool. And you can't say let x = e1 y = e2 in .... The correct form for this is let x = e1 in let y = e2 in ...
(Or you can write let x, y = e1, e2 in ..., which looks nicer for defining two similar variables to two similar values.)
The following code should at least compile:
let lip list1 =
if list1 = [] then []
else
let list2=List.rev list1 in
let rec lp l1 l2 = match l1,l2 with
| [], [] ->[]
| [], _::_->[]
| h1::_::_, h2::t2 -> (* l1 length >= 2*)
(h1,h2) :: lp(List.tl l1) t2
| h1::_,h2::t2 -> (* l1 length = 1 *)
[]
in
[]
I have made the following changes:
renamed the arguments of lip to make clear they are different from the arguments of lp
removed the alias let l1 = l
changed the if condition to a term of type boolean -- there's not much to compare, so I assume you are checking list1
replaced the list length condition by a pattern match against two heads
the else path is the second match - it might be better to rewrite that one to | [h1, _] -> ...
the definition of lp needs to be followed with the actual body of lip - to make it compile, we just return [] at the moment but you probably would like something else there
As #Jeffrey Scofield already mentioned, you are not using lp in your code. It could help if you added a comment that explains what you'd like to achieve and what the intended role of lp is.

Pairwise swap of adjacent elements in OCaml

So far I have
let flipeven(listname)=
let newlist= [] in
let first=0 in
let second=1 in
let stop= List.length(listname)-1 in
let rec flipevenhelper (x,y)=
if (second<= stop) then
insert((List.nth(listname) x), newList) in
insert((List.nth(listname) y), newList) in
let second=second+2 in
let first=first+2 in
flipevenhelper (first, second)
else
newList;;
But just receive a syntax error at the else statement. What exactly am i doing wrong?
edit:
Here is the insert function
let rec insert (x,y) = match (x, y) with
| (x,[ ]) -> x::[]
| (x,y::ys) -> if (x>y) then (y:: insert(x, ys))
else (x::y::ys);;
The in keyword is always paired with a let keyword. It's not a general way of joining two expressions, which is what you seem to want.
The ; operator in OCaml does join two expressions into a single expression. The first expression is evaluated but then ignored (it should have unit type). The second expression is evaluated, and its value is the value of the combined expression.
Note that ; has lower precedence than if/then/else (in some sense). So you should parenthesize the expression after then if you use the ; operator.
Here's a small example:
# if 3 > 2 then Printf.printf "yes\n"; 4 else 5;;
Error: Syntax error
# if 3 > 2 then (Printf.printf "yes\n"; 4) else 5;;
yes
- : int = 4
After fixing the syntax, you still have many things to fix. In particular, you should realize that variables and lists in OCaml are immutable. You can't insert into your list newList just by calling insert.

Is it possible to match with decomposed sequences in F#?

I seem to remember an older version of F# allowing structural decomposition when matching sequences just like lists. Is there a way to use the list syntax while keeping the sequence lazy? I'm hoping to avoid a lot of calls to Seq.head and Seq.skip 1.
I'm hoping for something like:
let decomposable (xs:seq<'a>) =
match xs with
| h :: t -> true
| _ -> false
seq{ 1..100 } |> decomposable
But this only handles lists and gives a type error when using sequences. When using List.of_seq, it seems to evaluate all the elements in the sequence, even if it is infinite.
If you use the LazyList type in the PowerPack, it has Active Patterns called LazyList.Nil and LazyList.Cons that are great for this.
The seq/IEnumerable type is not particulaly amenable to pattern matching; I'd highly recommend LazyList for this. (See also Why is using a sequence so much slower than using a list in this example.)
let s = seq { 1..100 }
let ll = LazyList.ofSeq s
match ll with
| LazyList.Nil -> printfn "empty"
| LazyList.Cons(h,t) -> printfn "head: %d" h
Seq works fine in active patterns! Unless I'm doing something horrible here...
let (|SeqEmpty|SeqCons|) (xs: 'a seq) =
if Seq.isEmpty xs then SeqEmpty
else SeqCons(Seq.head xs, Seq.skip 1 xs)
// Stupid example usage
let a = [1; 2; 3]
let f = function
| SeqEmpty -> 0
| SeqCons(x, rest) -> x
let result = f a
Remember seq has map reduce functions as well, so you might often be able to get away with only those. In the example, your function is equivalent to "Seq.isEmpty". You might try to launch fsi and just run through the tab completion options (enter "Seq." and hit tab a lot); it might have what you want.