I am trying to create a very simple recursive function to delete all element that have a particular value that the user decides on from a list.
In haskell I would use guards and do:
deleteAll_rec _ [] = []
deleteAll_rec del (x:xs) | del==x = deleteAll_rec del xs
| otherwise = x:deleteAll_rec del xs
I am trying to code up an Erlang equivalent, however, I am not sure how to handle the otherwise case:
deleteAll_rec(_, []) -> [];
deleteAll_rec(DEL, [X|XS]) when DEL =:= X -> deleteAll_rec(DEL, XS).
I was wondering if someone can demonstrate how this can be done?
Many thanks in advance!
The otherwise becomes a separate clause in Erlang:
delete_all_rec(_, []) -> [];
delete_all_rec(Del, [Del|Xs]) ->
delete_all_rec(Del, Xs);
delete_all_rec(Del, [X|Xs]) ->
[X|delete_all_rec(Del, Xs)].
An alternative is to use an if like:
delete_all_rec(_, []) -> [];
delete_all_rec(Del, [X|Xs]) ->
if Del =:= X ->
delete_all_rec(Del, Xs);
true ->
[X|delete_all_rec(Del, Xs)]
end.
The resultant code is the same but I think the first version looks better. Whether you put the terminating case first or last is irrelevant in this example, I prefer putting it last.
Related
Is there anyway to contruct a list in reverse order without having to reverse it
Here is an example, I read all lines from stdin
#!/usr/bin/env dotnet fsi
open System
let rec readLines1 () =
let rec helper acc =
match Console.ReadLine() with
| null -> acc
| line ->
helper (line :: acc)
helper [] |> List.rev
readLines1 () |> List.iter (printfn "%s")
Before return from readLines1 I have to List.rev it so that is in right order. Since the result is a slightly linked list it will have to read all trough it and create the reversed version. Is there any way of creating the list in right order?
You can use a sequence instead of accumulating the lines in a list:
open System
let readLines1 () =
let rec helper () =
seq {
match Console.ReadLine() with
| null -> ()
| line ->
yield line
yield! helper ()
}
helper () |> Seq.toList
readLines1 () |> List.iter (printfn "%s")
You cannot create list in reverse order, because that would require mutation. If you read inputs one by one, and want to turn them into a list immediately, the only thing you can do is to create new list, linking to the previous one.
In practice, reversing the list is perfectly fine and that's probably the best way of solving this.
Out of curiosity, you could try defininig a mutable list that has the same structure as immutable F# list:
open System
type MutableList<'T> =
{ mutable List : MutableListBody<'T> }
and MutableListBody<'T> =
| Empty
| Cons of 'T * MutableList<'T>
Now you can implement your function by mutating the list:
let rec readLines () =
let res = { List = Empty }
let rec helper acc =
match Console.ReadLine() with
| null -> res
| line ->
let next = { List = Empty }
acc.List <- Cons(line, next)
helper next
helper res
This may be educational, but it's not very useful and, if you really wanted mutation in F#, you should probably use ResizeArray.
Yet another trick is to work with functions that take the tail of the list:
let rec readLines () =
let rec helper acc =
match Console.ReadLine() with
| null -> acc []
| line -> helper (fun tail -> acc (line :: tail))
helper id
In the line case, this returns a function that takes tail adds line before the tail and then calls whatever function was constructed before to add more things to the front.
This actually creates the list in the right order, but it's probably less efficient than creating a list and reversing it. It may look nice, but you are allocating a new function for each iteration, which is not better than allocating an extra copy of the list. (But it is a nice trick, nevertheless!)
Alternative solution without implementing recursive functions
let lines =
Seq.initInfinite (fun _ -> Console.ReadLine())
|> Seq.takeWhile (not << isNull)
|> Seq.toList
I would like to know if its possible to use lists:duplicate in this case:
decompress_1([])->
[];
decompress_1(L)->
MyNum = lists:map(fun(T)-> element(1,T) end,L),
Res = lists:map(fun(T)-> element(2,T) end,L).
to get :
decompress_1([{3,1},{3,2},{1,5},{1,4},{1,1},{1,0},{1,1}]) == [1,1,1,2,2,2,5,4,1,0,1]
I just manage to retrieve the first and second elements of the tuple.
There is a solution with list comprehension but I would know to do it without.
decompress([]) ->
[];
decompress(L) ->
[Y || {X, Y} <- L, _ <- lists:seq(1, X)].
Without using a list comprehension, we can use lists:duplicate/2 to create the result, but we have to flatten it to get the desired final answer:
decompress([]) ->
[];
decompress(L) ->
lists:flatten(lists:map(fun({X,Y}) ->
lists:duplicate(X,Y)
end, L)).
Without the flatten we'd get the first result shown below, instead of the second correct result:
1> decompress_no_flatten([{3,1},{3,2},{1,5},{1,4},{1,1},{1,0},{1,1}]).
[[1,1,1],[2,2,2],[5],[4],[1],[0],[1]]
2> decompress([{3,1},{3,2},{1,5},{1,4},{1,1},{1,0},{1,1}]).
[1,1,1,2,2,2,5,4,1,0,1]
By the way, you can use lists:duplicate/2 in the original list comprehension approach as well:
decompress([]) ->
[];
decompress(L) ->
[Y || {X,Y} <- L, _ <- lists:duplicate(X,Y)].
This works because here we don't use the values produced by lists:seq/2 or lists:duplicate/2, but rather we use only the number of items they produce.
Suppose I have a DU like so:
type DU = Number of int | Word of string
And suppose I create a list of them:
[Number(1); Word("abc"); Number(2)]
How can I write a function that would return true for a list of DUs where all the elements are the same case. For the above list it should return false.
The general approach I'd use here would be to map the union values into tags identifying the cases, and then check if the resulting set of tags has at most one element.
let allTheSameCase (tagger: 'a -> int) (coll: #seq<'a>) =
let cases =
coll
|> Seq.map tagger
|> Set.ofSeq
Set.count cases <= 1
For the tagger function, you can assign the tags by hand:
allTheSameCase (function Number _ -> 0 | Word _ -> 1) lst
or use reflection (note that you might need to set binding flags as necessary):
open Microsoft.FSharp.Reflection
let reflectionTagger (case: obj) =
let typ = case.GetType()
if FSharpType.IsUnion(typ)
then
let info, _ = FSharpValue.GetUnionFields(case, typ)
info.Tag
else -1 // or fail, depending what makes sense in the context.
In case you wanted to check that the elements of a list are of a specific union case, it's straightforward to provide a predicate function.
let isNumbers = List.forall (function Number _ -> true | _ -> false)
If you do not care which union case, as long as they are all the same, you need to spell them all out explicitly. Barring reflection magic to get a property not exposed inside F#, you also need to assign some value to each case. To avoid having to think up arbitrary values, we can employ an active pattern which maps to a different DU behind the scenes.
let (|IsNumber|IsWord|) = function
| Number _ -> IsNumber
| Word _ -> IsWord
let isSameCase src =
src |> Seq.groupBy (|IsNumber|IsWord|) |> Seq.length <= 1
I had the exact same use case recently and the solution can be done much simpler than complicated reflections or explicit pattern matching, GetType does all the magic:
let AreAllElementsOfTheSameType seq = // seq<'a> -> bool
if Seq.isEmpty seq then true else
let t = (Seq.head seq).GetType ()
seq |> Seq.forall (fun e -> (e.GetType ()) = t)
Using Erlang, I have the following expression:
{add,{var,a},{mul,{num,2},{var,b}}}
and I am using lists:keymember to see whether the letter b is within the expression as such:
lists:keymember(b,2,[expr])
However, it doesn't look within the third tuple '{mul,{num,2},{var,b}' as that is a separate tuple. Is there a function that will search through the whole tuple and tuples within?
Thanks
As far I as I know there are no such functions. Probably you will have to implement some custom solution using recursion. Here is my example:
-module(test).
-compile(export_all).
find(_, []) -> false;
find(E, T) when is_tuple(T) ->
find(E, tuple_to_list(T));
find(E, [H|T]) ->
case find(E, H) of
false -> find(E, T);
true -> true
end;
find(V, E) -> V == E.
And usage:
1> test:find(b, {add,{var,a},{mul,{num,2},{var,b}}}).
true
2> test:find(b, {add,{var,a},{mul,{num,2},{var,c}}}).
false
Please review your code.
Line1: this is a tree, not a list.
Line2: expr is not a variable.
What you want to do is a visitor function, and you'll have to write it yourself.
A very good start would be to read this.
I am trying to write a code to remove stopwords like "the", "this" in a string list etc.
I wrote this code:
let rec public stopword (a : string list, b :string list) =
match [a.Head] with
|["the"]|["this"] -> stopword (a.Tail, b)
|[] -> b
|_ -> stopword (a.Tail, b#[a.Head])
I ran this in the interactive:
stopword (["this";"is";"the"], []);;
I got this error:
This expression was expected to have type string list but here has type 'a * 'b
Match expressions in F# are very powerful, although the syntax is confusing at first
You need to match the list like so:
let rec stopword a =
match a with
|"the"::t |"this"::t -> stopword t
|h::t ->h::(stopword t)
|[] -> []
The actual error is due to the function expecting a tuple argument. You would have to call the function with:
let result = stopword (["this";"is";"the"], [])
Edit: since the original question was changed, the above answer is not valid anymore; the logical error in the actual function is that you end up with a single element list of which the tail is taken, resulting in an empty list. On the next recursive call the function chokes on trying to get the head of this empty list
The function in itself is not correctly implemented though and much more complicated than necessary.
let isNoStopword (word:string) =
match word with
| "the"|"this" -> false
| _ -> true
let removeStopword (a : string list) =
a |> List.filter(isNoStopword)
let test = removeStopword ["this";"is";"the"]
Others have mentioned the power of pattern matching in this case. In practice, you usually have a set of stopwords you want to remove. And the when guard allows us to pattern match quite naturally:
let rec removeStopwords (stopwords: Set<string>) = function
| x::xs when Set.contains x stopwords -> removeStopwords stopwords xs
| x::xs -> x::(removeStopwords stopwords xs)
| [] -> []
The problem with this function and #John's answer is that they are not tail-recursive. They run out of stack on a long list consisting of a few stopwords. It's a good idea to use high-order functions in List module which are tail-recursive:
let removeStopwords (stopwords: Set<string>) xs =
xs |> List.filter (stopwords.Contains >> not)