blue-sky
blue-sky

Reputation: 53786

Explain some scala code - beginner

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
} 

Upvotes: 0

Views: 1996

Answers (2)

adelbertc
adelbertc

Reputation: 7320

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:

  1. 3 :: Nil is evaluated first, creating the equivalent of a List(3) which has head 3 and empty tail.
  2. 2 is prepended to the above list, creative a new list with head 2 and tail List(3).
  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:

  1. Take the l List parameter and see if it can be decomposed into a head and tail.
  2. 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)
  3. If it cannot be decomposed, the function returns 0.

Upvotes: 16

santiagobasulto
santiagobasulto

Reputation: 11686

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

Upvotes: 1

Related Questions