I am reading the book programming in Scala from Martin O. and there is one example there to remove duplicates totally confused me:
def removeDuplicates[A](xs: List[A]): List[A] = {
if (xs.isEmpty) xs
else
xs.head :: removeDuplicates(
xs.tail filter (x => x != xs.head)
)
}
println(removeDuplicates[String](List("a", "a", "b", "a", "c")))
gives me:
List(a,b,c)
I know that .head will give you the very first element of the List while .tail give you the rest of the List. And I can understand that xs.tail filter (x => x != xs.head) will return a list containing the elements which don't equal to the head.
My Google search leads me to this cons operator however, I am still having a hard time mapping Martin's words to this example. And anyone help me understand how this :: works in this function?
A peculiarity in Scala is that operators ending in : (colon) are right-associative, and they are dispatched to the object on the right, with the parameter being on the left. For example: a :: list (infix notation) is equivalent to list.::(a) (method notation).
Have a look at the documentation for :: (cons). It constructs a linked list from an element and another list. Note that a :: b :: c :: Nil is equivalent to List(a, b, c), but note that the construction is happening from right to left, as Nil.::(c).::(b).::(a).
The example you gave uses recursion, which is based on a base case and an inductive case. The base case says that an empty list has no duplicates. The inductive case says that, assuming you have a removeDuplicates method which can remove all duplicates from a list, you can construct a new (sometimes larger) duplicate-free list by adding a value to the beginning, as long as you've remove that value from the remainder of the list first.
This is a very common pattern in functional programming.
Realize that removeDuplicates evaluates to a list, which the cons operator takes on its right side. The end result is a list where it's tail doesn't contain its head.
Every recurse, we add the head of the remaining list to the new list that we're constructing using the cons operator. We see if the current head exists in the rest of the list, and filter them out.
Look up what a the map method is. If you get how it works, this should click. They aren't exactly the same, but it involves building a list using the cons operator.
Related
From the Book programming in Scala I got the following line of code:
val second: List[ Int] => Int = { case x :: y :: _ => y }
//warning: match may not be exhaustive.
It states that this function will return the second element of a list of integers if the list is not empty or nil. Stil this part is a bit awkward to me:
case x :: y :: _
How does this ecxactly work? Does this mathches any list with at least 2 Elements and than return the second? If so can somebody still explain the syntax? I understood that :: is invoked on the right operand. So it could be written as
(_.::(y)).::(X)
Still I than don't get why this would return 2
val second: List[ Int] => Int = { case x :: y :: _ => y }
var x = List(1,2)
second(x) //returns 2
In the REPL, you can type:
scala> val list = "a" :: "b" :: Nil
list: List[String] = List(a, b)
which is to be read from right to left, and means take the end of a List (Nil), prepend String "b" and to this List ("b" :: Nil) prepend String a, a :: ("b" :: Nil) but you don't need the parens, so it can be written "a" :: "b" :: Nil.
In pattern matching you will more often see:
... list match {
case Nil => // ...
case x :: xs => // ...
}
to distinguish between empty list, and nonempty, where xs might be a rest of list, but matches Nil too, if the whole list is ("b" :: Nil) for example, then x="b" and xs=Nil.
But if list= "a" :: "b" :: Nil, then x="a" and xs=(b :: Nil).
In your example, the deconstruction is just one more step, and instead of a name like xs, the joker sign _ is used, indicating, that the name is probably not used and doesn't play a role.
The value second is of function type, it takes List[Int] and returns Int.
If the list has first element ("x"), and a second element ("y"), and whatever comes next (we don't care about it), we simply return the element "y" (which is the second element of the list).
In any other case, the function is not defined. You can check that:
scala> val second: PartialFunction[List[Int], Int] = {
| case x :: y :: _ => y
| }
second: PartialFunction[List[Int],Int] = <function1>
scala> second.isDefinedAt(List(1,2,3))
res18: Boolean = true
scala> second.isDefinedAt(List(1,2))
res19: Boolean = true
scala> second.isDefinedAt(List(0))
res20: Boolean = false
First of all. When you think about pattern matching you should think about matching a structure.
The first part of the case statement describes a structure. This structure may describe one or more things (variables) which are useful to deriving your result.
In your example, you are interested in deriving the second element of a list. A shorthand to build a list in Scala is to use :: method (also called cons). :: can also be used to describe a structure in case statement. At this time, you shouldn't think about evaluation of the :: method in first part of case. May be that's why you are saying about evaluation of _.::(y).::(x). The :: cons operator help us describe the structure of the list in terms of its elements. In this case, the first element (x) , the second element (y) and the rest of it (_ wildcard). We are interested in a structure that is a list with at least 2 elements and the third can be anything - a Nil to indicate end of list or another element - hence the wildcard.
The second part of the case statement, uses the second element to derive the result (y).
More on List and Consing
List in Scala is similar to a LinkedList. You know about the first element called head and start of the rest of the list. When traversing the linked list you stop if the rest of the list is Nil. This :: cons operator helps us visualise the structure of the linked list. Although Scala compile would actually be calling :: methods evaluating from right to left as you described _.::(y).::(x)
As an aside, you might have already noticed that the Scala compiler might be complain that your match isn't exhaustive. This means that this second method would work for list of any size. Because there isn't any case statement to describe list with zero or one element. Also, as mentioned in comments of previous answers, if you aren't interested in first element you can describe it as a wildcard _.
case _ :: y :: _ => y
I hope this helped.
If you see the structure of list in scala its head::tail, first element is treated as head and all remaining ones as tail(Nil will be the last element of tail). whenever you do x::y::_, x will match the head of the list and remaining will be tail and again y will match the head of the next list(tail of first list)
eg:
val l = List(1,2,3,4,5)
you can see this list in differnt ways:
1::2::3::4::5::Nil
1::List(2,3,4,5)
1::2::List(2,3,4,5)
and so on
So try matching the pattern. In your question y will give the second element
One of my exercises requires me to write a recursive method in which a list is given, and it returns the same list with only every other element on it.
for example : List {"a", "b", "c"} would return
List{"a","c"}
I am writing in scala, and I understand that it has built in library but I am not supposed to use those. I can only use if/else, helper methods,and patterns.
How could I parse thru a list using head and tail only?
so far I have this:
def removeLetter(list:List[String]):List[String]=list match{
case Nil => Nil
case n::rest=>
if (n == rest){ // I understand that this doesn't quite work.
tail
}
else
head::removeLetter(tail)
}
}
I am looking for the logic and not code.
Using pattern matching, you can also deconstruct a list on it's first two elements in the same way you're doing with your n::rest construction. Just remember to also take lists with uneven length into account.
You correctly stated one base-case to the recursion: In case of an empty list, the result is again the empty list. case Nil => Nil
There is a second base-case: A list containing a single element is again the list itself. case x :: Nil => x :: Nil
You can formulate the recursive step as follows: Given a list with at least two elements, the result is a list containing the first element, followed by every other element of the list after the second element. case x :: y :: z => x :: removeLetter(z) (Note that here, x and y are both of type String while z is of type List[String])
Remark: If you wanted to, you could also combine both base-cases, as in both cases, the input to the function is its output.
I am currently facing the following issue.
I have code that essentially has the following cases:
val toList = this.toString.match {
case "" => List[MyType]()
case _ => this.val :: this.prev.toList
}
Obviously not exact but its the general gist. It works fine but I want the values appended to the list in the reverse order. Is there any good way to do this? Intellij throws errors if I try to reverse the order and do
this.prev.toList :: this.val
and also if I try to use operations like ++. Is what I'm trying to do impossible based on the structure of my class?
The specific errors I get involve "cannot resolve ::" or whatever symbol I use when I try to put this.prev.toList before this.val.
And yes the "this" aren't necessary- I included it to hopefully make my problem easier to understand.
:: adds an element at the beginning of this list
scala> 1 :: List(2,3)
List(1, 2, 3)
+: is the equivalent of ::
scala> 1 +: List(2,3)
List(1, 2, 3)
:+ append element at the end of the list
scala> List(1,2) :+ 3
List(1, 2, 3)
However the cost of prepending on List is O(1) but the appending one is O(n)!
For "numerous" collections you could consider other datastructure like Vector:
Vector provides very fast append and prepend
http://www.scala-lang.org/api/2.11.7/index.html#scala.collection.immutable.Vector
You can append with this method :+:
this.prev.toList :+ this.val // is `val` really then name?
But keep in mind that appending to a List can be very inefficient for long lists.
Given a list L I want to keep an element L(i) if it exists at least one value j > i such that L(j) is a multiple of L(i), otherwise L(i) should be discarded.
It is quite simple to do that by means of imperative programming paradigms, but I would like to do that using functional programming.
Is that possible to use the filter method? If so, how to write the condition (i.e. the parameter of the filter function) ? Otherwise, what can I do?
For example:
val l = (1 to 100)
l.tails.collect { case (head +: tail) if tail.exists(_ % head == 0) => head } .toList
tail produces an iterator that returns in each step the input minus one element, e.g.
(1 to 10).tails.foreach(println)
gives
Vector(1, 2, 3, 4)
Vector(2, 3, 4)
Vector(3, 4)
Vector(4)
Vector()
You can view these 'tails' as a head element to which you want to apply a filter and a tail in itself that is used to find out whether to keep the head.
The collect method is useful here, because it takes a partial function, so you only need to specify the cases where you actually retain a value—like filter—, while at the same time it acts like a map by letting you specify how the filtered value is to be collected.
So we can match on tails that have at least one head element and a tail of any size, and then see if in that tail there exists an element that is a multiple of the head. I use a guard here for the match case, so the match is a double filter. First, the tail must be non-empty, second there must be multiple. A multiple means that the modulus is zero. If the case matches, just return the verified head element.
Finally, since without specific type annotations the collect will just return another iterator, we turn the result into a list with toList.
A more "explicit" one - you accumulate elements in a case if tail has a multiple of head:
(1 to 10).tails.foldLeft(List[Int]())((acc, tl) => tl match {
case h +: t if (t.exists(_ % h == 0)) => h :: acc
case _ => acc
}).reverse
I've encountered this scala code and I'm trying to work out what its doing except the fact it returns an int. I'm unsure of these three lines :
l match {
case h :: t =>
case _ => 0
Function :
def iterate(l: List[Int]): Int =
l match {
case h :: t =>
if (h > n) 0
case _ => 0
}
First, you define a function called iterate and you specified the return type as Int. It has arity 1, parameter l of type List[Int].
The List type is prominent throughout functional programming, and it's main characteristics being that it has efficient prepend and that it is easy to decompose any List into a head and tail. The head would be the first element of the list (if non-empty) and the tail would be the rest of the List(which itself is a List) - this becomes useful for recursive functions that operate on List.
The match is called pattern matching.. it's essentially a switch statement in the C-ish languages, but much more powerful - the switch restricts you to constants (at least in C it does), but there is no such restriction with match.
Now, your first case you have h :: t - the :: is called a "cons", another term from functional programming. When you create a new List from another List via a prepend, you can use the :: operator to do it.
Example:
val oldList = List(1, 2, 3)
val newList = 0 :: oldList // newList == List(0, 1, 2, 3)
In Scala, operators that end with a : are really a method of the right hand side, so 0 :: oldList is the equivalent of oldList.::(0) - the 0 :: oldList is syntactic sugar that makes it easier to read.
We could've defined oldList like
val oldList = 1 :: 2 :: 3 :: Nil
where Nil represents an empty List. Breaking this down into steps:
3 :: Nil is evaluated first, creating the equivalent of a List(3) which has head 3 and empty tail.
2 is prepended to the above list, creative a new list with head 2 and tail List(3).
1 is prepended, creating a new list with head 1 and tail List(2, 3).
The resulting List of List(1, 2, 3) is assigned to the val oldList.
Now when you use :: to pattern match you essentially decompose a List into a head and tail, like the reverse of how we created the List above. Here when you do
l match {
case h :: t => ...
}
you are saying decompose l into a head and tail if possible. If you decompose successfully, you can then use these h and t variables to do whatever you want.. typically you would do something like act on h and call the recursive function on t.
One thing to note here is that your code will not compile.. you do an if (h > n) 0 but there is no explicit else so what happens is your code looks like this to the compiler:
if (h > n) 0
else { }
which has type AnyVal (the common supertype of 0 and "nothing"), a violation of your Int guarentee - you're going to have to add an else branch with some failure value or something.
The second case _ => is like a default in the switch, it catches anything that failed the head/tail decomposition in your first case.
Your code essentially does this:
Take the l List parameter and see if it can be decomposed into a head and tail.
If it can be, compare the head against (what I assume to be) a variable in the outer scope called n. If it is greater than n, the function returns 0. (You need to add what happens if it's not greater)
If it cannot be decomposed, the function returns 0.
This is called pattern matching. It's like a switch statement, but more powerful.
Some useful resources:
http://www.scala-lang.org/node/120
http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4