I want to print a list inside a help function, for debugging purpose. And for some reason it's not printing anything. Does anyone know what's wrong?
Here is some of my code:
local
....
and xx(LparenToken) = "LparenToken"
| xx(RparenToken) = "RparenToken"
| xx(QuoteToken) = "QuoteToken"
| xx(DotToken) = "DotToken"
| xx(VectorToken) = "VectorToken"
| xx(IntToken(a)) = "IntToken"
| xx(CharToken(a)) = "CharToken"
| xx(StringToken(a)) = "StringToken"
| xx(SymbolToken(a)) = "SymbolToken"
| xx(BoolToken(a)) = "BoolToken"
and readList(nil) = []
| readList(lst:SchemeToken list) = (map(print)((map(xx)(lst))); read(getFirstSexpr(lst))::readList(getRestSexpr(lst)))
...
in
some functions..
end
i have tried this also:
and readList(nil) = []
| readList(lst:SchemeToken list) = (print "x"; read(getFirstSexpr(lst))::readList(getRestSexpr(lst)))
it is not printing. i get just the answer:
- Reader.stringToSexpr "#(a b (1 2 3) c)";
val it =
Vector
[Symbol "a",Symbol "b",Pair (Number 1,Pair (Number 2,Number 3)),
Symbol "c"] : Sexpr
I suspect the problem is not with your list printing code - that's going to work fine, provided it is called with some data.
For reference, there's a nicer way to evaluate for effects with lists: List.app : ('a -> unit) -> 'a list -> unit. It's like List.map, but it doesn't construct a list as a return value. Another one you might like is String.concatWith, which often makes printing code easier, e.g.:
print (String.concatWith "\n" (map xx lst))
And as a final note, you've used lots of unnecessary parentheses there in your example code. You rarely need to parenthesise expressions - especially not if there is no function application involves (i.e., writing (lst) or (xx) is always just going to mean lst or xx, and does not resolve any ambiguity (because there is none). Similarly in your patterns, they could just as easily be written (IntToken a) without changing the meaning (and possibly adding to readability).
Related
I want to find all the possible partitions of a string into a list of non-empty strings.
For example if i give as input "sun",
i want to create this output : [["s","u","n"], ["s","un"], ["su","n"], ["sun"]].
I have created a simple function with recursion but it prints this overflow error i can't fix it please i need help:
partition :: String->[[String]]
partition w = [[(head w)]:fix | fix <- partition (tail w)]
++[((head w):fix):fixfix | (fix:fixfix)<-partition (tail w)]
The essential problem is that you're missing the base case for the recursion, so you have an infinite loop.
The simple thing is just to replace the head/tail mess with pattern matching, which will solve that problem as a side effect.
partition [] = [[]]
partition (w:ws) =
[[w]:fix | fix <- partition ws] ++
[(w:fix):fixfix | (fix:fixfix)<-partition ws]
This turns out to work okay, somewhat to my surprise. Why was I surprised? I figured that, with optimization, GHC would use common subexpression elimination to rewrite it to
partition [] = [[]]
partition (w:ws) =
[[w]:fix | fix <- partitionws] ++
[(w:fix):fixfix | (fix:fixfix)<-partitionws]
where partitionws = partition ws
That would be bad: it would save the entire partition ws calculation across the ++, using lots of memory. But it seems GHC is clever enough these days not to do that.
To be more confident, you can avoid the common subexpression, by accumulating a "continuation" explaining how you'll process each element you produce.
part :: ([[a]] -> [b]) -> [a] -> [b]
part f [] = f []
part f (w:ws) =
part (\fix -> f ([w]:fix)) ws ++
part (\q -> case q of
[] -> []
fix:fixfix -> f ((w:fix):fixfix)) ws
partition = part (:[])
For reasons I don't know, this version is a couple times faster than the simple one.
If you don't care about the order in which the elements are produced, you can avoid the space leak risk much more simply (and perhaps even faster) by doing something like this:
partition [] = [[]]
partition (w:ws) =
[ q
| m <- partition ws
, q <- ([w]:m) : [(w:fix):fixfix | fix:fixfix <- [m]]]
This is almost as simple as the simplest solution.
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.
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.
I am currently working on a ML small project and learning how to work with it, but here are some problems that I'm facing but cannot find any source online.
I want to have a function to return the last number of the list, which is a real number list. I wrote a code to return a single element real list, but i will it to be a real number but not a list. here is my code:
fun last [] = nil
| last(head::nil) = [head]
| last(head::list) = last(list)
I thought
last(head::nil)=head
would help get the real number but it just give me an error that:
operator domain: 'Z list list
operand: real list
Thank you!
As melpomene says, nil isn't a value of type real, so it can't be the return type for the empty list. In fact, no value can be returned, because the list is empty! This makes the function last partial. You want to avoid partial functions, because they may crash at runtime. You can define an alternative function, lastOpt:
fun lastOpt [] = NONE
| lastOpt [x] = SOME x
| lastOpt (_::xs) = lastOpt xs
For example,
- lastOpt [1,2,3];
> val it = SOME 3 : int option
- lastOpt [];
> val it = NONE : 'a option
This passes responsibility for handling empty lists explicitly to the caller of lastOpt.
The built-in function List.last was made unsafely with exceptions:
fun last [] = raise Empty
| last [x] = x
| last (_::xs) = last xs
I wouldn't recommend using this.
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.