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
Related
I'm reading some Scala problems and I see this:
def last[A](l: List[A]): A = l match {
case h :: Nil => h
case _ :: tail => last(tail)
case _ => throw new NoSuchElementException
}
I understand the basics of the cons operator. But where does the h come from?
In that top case h, I can see how we're saying in the event that there is Nil at the end of the list, return h, which would be the last element of the list. But where is h even defined?
The h is defined right there in the case statement.
Scala's pattern matching has pretty concise syntax that can take a beat to get used to. It mixes some stuff that look very similar:
If you include a literal value, the object you're matching on must be equal to that value. Example: case 1 :: tail => ... matches only lists that start with 1.
If you include an _, that matches anything. Example: case _ :: tail => ...
If you include a new variable name, that matches anything, and assigns what it matched to that variable within the scope of the corresponding body. Example: case h :: tail => ... which matches the exact same inputs as the previous example but also assigns the first element to h within the "..." section.
h is an identifier that represents a single element of type A and is defined in the case clause itself: the letter "h" is sensible in this context because it clearly means "head." However, you can use whatever legal Scala identifier you want:
def last[A](l: List[A]): A = l match {
case baconWrappedShrimp :: Nil => baconWrappedShrimp
case _ :: tail => last(tail)
case _ => throw new NoSuchElementException
}
Scala pattern matching allows you to write temp variables in the cases.
The first case covers the case where l is a the following list {h, Nil}. Pay attention that the '::' operator is used to concatanate a single element with a list. Unlike the ':::' operator which concatanates two lists.
So I read about right-associative operators like the cons operator in Scala. I'm wondering why they work in case statements. It seems like you can pattern match using the cons statement here?
def findKth1[A](k:Int, l:List[A]):A = (k, l) match {
case (0, h::_) => h
case(k, _::tail) if k > 0 => findKth1(k - 1, tail)
case _ => throw new NoSuchElementException
}
findKth1(2, List(3,4,5,6))
res1: Int = 5
What is the placeholder doing here? I've only seen placeholders used in functions like this: <SomeList>.map(_.doThing). Is it the same concept?
The only difference with :: and ::: is that ::: is used for 2 Lists right?
tl;dr It isn't pattern matching the operator, it's pattern matching a case class called ::
There are a couple of things happening at the same time. First of all, there may be a bit of confusion, because :: is a method on List:
val x: List[Int] = 1 :: 2 :: 3 :: Nil
But there is also a case class :: that, according to the docs is:
A non empty list characterized by a head and a tail.
More info here
Scala's case classes automatically come with extractor methods(unapply), which allow pattern matching, as in case User(name, age) => ....
You are also allowed to use the case class name in an infix position (although you shouldn't do so, except when the case class is used like an operator, such as in this case). So case head :: tail => ... is the same as case ::(head, tail) => .... More info here
When pattern matching, you can use _ to mean that there will be a value there, but you don't care about it, so you aren't providing it a name.
So the three cases you provided are roughly:
A tuple where the first value is 0, and the second value is a list with a head to be called h, and a tail which we will ignore.
A tuple with some integer to be called k, and a list with a head that we don't care about, and a tail, which we will call tail. Also, k must be greater than 0
Anything else, then throw a NoSuchElementException
object Test1 extends App {
val list: List[Int] => Int = {
case x :: y :: _ => y //what is ::? method or case class?
}
println(list(List(1, 2, 3))) //result is 2.
}
I set "syntax coloring" in scala IDE, foreground color of method I set Red. code snapshot:
And I can't open declaration of black ::, so I don't know what it is.
If black :: is method, it should be called by this way:
... {case _.::(y).::(x) => y} //compile failed!
So, What is black ::? method or case class?
Thanks a lot!
I think it's a method as described here. For history's sake, in case that page goes away, here's the blurb:
About pattern matching on Lists
If you review the possible forms of patterns explained in Chapter 15,
you might find that neither List(...) nor :: looks like it fits one of
the kinds of patterns defined there. In fact, List(...) is an instance
of a library-defined extractor pattern. Such patterns will be treated
in Chapter 24. The "cons" pattern x :: xs is a special case of an
infix operation pattern. You know already that, when seen as an
expression, an infix operation is equivalent to a method call. For
patterns, the rules are different: When seen as a pattern, an infix
operation such as p op q is equivalent to op(p, q). That is, the infix
operator op is treated as a constructor pattern. In particular, a cons
pattern such as x :: xs is treated as ::(x, xs). This hints that there
should be a class named :: that corresponds to the pattern
constructor. Indeed there is such as class. It is named scala.:: and
is exactly the class that builds non-empty lists. So :: exists twice
in Scala, once as a name of a class in package scala, and again as a
method in class List. The effect of the method :: is to produce an
instance of the class scala.::. You'll find out more details about how
the List class is implemented in Chapter 22.
So it's scala.::(a,b)
Here Sequence pattern is applied.
case x :: y :: _ => y
means, the passed sequence first value is mapped to x and second value is mapped to y and all remaining values are applied with wildcard pattern (_).
Here finally the case returns y means second value.
another ex: case x :: y :: z :: _ => z
this case returns third element from the sequence.
another ex: case _ :: _ :: z :: _ => z
in this example first and second element are used underscore as we don't need THESE elements hence replaced with _.
Also it throws Exception if the passing list size is less than what it expects, for Example the below throws exception:
val third: List[Int] => Int = {case _ :: _ :: z :: _ => z}
third(List(1, 2))
If I have a function List[A] => List[List[A]] and need to return an "empty" value, is there a theoretical preference between the following
a) Nil
b) List(Nil)
... or does it depend on the function?
For a concrete example, I could implement a function to split a list into sublists of length n or less as follows:
def sublists[A](xs: List[A], n: Int): List[List[A]] = {
val (ys, zs) = xs.splitAt(n)
if (zs.isEmpty) ys :: Nil
else ys :: sublists(zs, n)
}
If xs is empty this returns List(Nil). Do I need to include a check on whether xs is empty, returning Nil, for this function to be correct?
Without doubt, the correct empty value for a List is the empty List, no matter what the type of the List elements is.
The same is true for more elaborated types. A set containing the empty set is very different from an empty set, and so forth.
Think of it like this: A list result allows you to ask: how many results do we have? If you use a list with an empty List as empty value, then the answer would be incorrectly 1.
I would stick with Nil, aka List(). For example,
sublists(1 :: 2 :: 3 :: 4 :: Nil), 2)
returns
List(1 :: 2 :: Nil, 3 :: 4 :: Nil)
and not
List(1 :: 2 :: Nil, 3 :: 4 :: Nil, Nil)
The terminal Nil is usually chopped off. So for consistency I would keep sublists(Nil) -> List().
I don't know the context, so I don't feel comfortable being definitive. In general, I think the answer is context-dependent. In the abstract, I'd definitely prefer Nil as a client-code writer - in writing a closure over the results, I don't think I'd be expecting an empty sublist.
Rearranging to put the null-check before the splitAt will do the trick.
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