syntax explanation for pattern matching a list in scala - scala

I was reading this blog post and i was not able to understand a part of the code.
object O {
def maximum(x: List[Int]): Int = x match {
case Nil => error("maximum undefined for empty list")
case x :: y :: ys => maximum((if(x > y) x else y) :: ys)
case x :: _ => x
}
}
Please explain the code maximum((if(x > y) x else y) :: ys)
How the if condition can be a part of the method maximum ?
I understand that if condition is not exactly a parameter.

In Scala, if is an expression, not a statement.
Try this in the REPL:
scala> val x=1; val y=0
x: Int = 1
y: Int = 0
scala> val test=if(x > y) x else y
test: Int = 1
if evaluates to 1 and 1 is assigned to test. In Java if could be expressed with the conditional operator (x > y) ? x : y
Now, you have a function called maximum that takes a List[Int] as a parameter.
maximum((if(x > y) x else y) :: ys) calls maximum (recursively) with a list obtained prepending one between x and y (depending on what the if evaluates to) to ys.

Related

Adding elements to a list in a for loop

var locations: List[Location] = List[Location]()
for (x <- 0 to 10; y <- 0 to 10) {
println("x: " + x + " y: " + y)
locations ::: List(Location(x, y))
println(locations)
}
The code above is supposed to concatenate some lists. But the result is an empty list. Why?
Your mistake is on the line locations ::: List(Location(x, y)). This is concatenating the lists, but the doing nothing with the result. If you replace it with locations = locations ::: List(Location(x, y)) you would have your desired result.
However there are more idiomatic ways to solve this problem in Scala. In Scala, writing immutable code is the preferred style (i.e. use val rather than var where possible).
Here's a couple of ways to do it:
Using yield:
val location = for (x <- 0 to 10; y <- 0 to 10) yield Location(x, y)
Using tabulate:
val location = List.tabulate(11, 11) { case (x, y) => Location(x, y) }
Even shorter:
val location = List.tabulate(11, 11)(Location)
Edit: just noticed you had 0 to 10 which is inclusive-inclusive. 0 until 10 is inclusive-exclusive. I've changed the args to tabulate to 11.

Haskell to Scala

Im new to Scala but I know something about functional programing thanks to Haskell and I'm looking for some examples, can you tell me how this would be in Scala?
scalarProduct :: [Int] -> [Int] -> Int
scalarProduct [] _ = 0
scalarProduct _ [] = 0
scalarProduct (x:xs) (y:ys) = if length(xs) == length (ys) then x*y + scalarProduct xs ys else 0
lessThan :: [Float] -> Float -> Int
lessThan [] _ = 0
lessThan (x:xs) n = if x < n then 1 + lessThan xs n else lessThan xs n
removeLast :: [a] -> [a]
removeLast [] = []
removeLast (x:xs) = if length(xs) == 0 then [] else [x] ++ removeLast xs
funcion :: Int -> Float
funcion x | x >= 6 = fromIntegral(product[9..x*2])
| x > 0 = fromIntegral(x) ** (1/4)
| x <= 0 = fromIntegral(product[1..(-x)]) * 5.0**fromIntegral(x)
If you want literal transformations, I think the below is as close as you will get. Bear in mind you have to put this inside an object/class/trait for this to compile (or just past it into the REPL).
def scalarProduct(list1: List[Int], list2: List[Int]): Int = (list1,list2) match {
case (Nil,_) => 0
case (_,Nil) => 0
case (x :: xs, y :: ys) => if (xs.length == ys.length) x*y + scalarProduct(xs,ys) else 0
}
def lessThan(floats: List[Float], bound: Float): Int = floats match {
case Nil => 0
case x :: xs => if (x < bound) 1 + lessThan(xs,n) else lessThan(xs,n)
}
def removeLast[A](list: List[A]): List[A] = list match {
case Nil => Nil
case x :: xs => if (xs.length == 0) Nil else List(x) ++ removeLast(xs)
}
def funcion(x: Int): Double = {
if (x >= 6)
(9 to x*2).product
else if (x > 0)
Math.pow(x,0.25)
else
(1 to -x).product.toDouble * Math.pow(5.0,x)
}
This code is pretty un-Scala-like. For example, the Scala way of doing the first three would probably be with an implicit conversion class RichList[A]. Also, these can all be done much more simply using library functions - but I don't think that's what you are looking for (else you would've used the corresponding library functions for the Haskell code).

Scala - error: type not found

I am a newbie in Scala and I have an error that i cannot understand. Here is my array of int : (numbers from 1 to 100)
val rdd = sc.parallelize(1 to 100)
Next I wrote a function, which is returning the MAX value of my array:
rdd.reduce((x, y) => x > y ? x : y)
But I always get this error:
<console>:30: error: not found: type y
rdd.reduce((x, y) => x > y ? x : y)
^
I don't really know what the error means so i can't find a solution. But if i use my function like this, it works:
rdd.reduce((x, y) => if(x > y) x else y)
Thank you for your answers !
There is no ? : operator in Scala, use if instead:
rdd.reduce((x, y) => if (x > y) x else y)
Or use max instead of building it on your own:
rdd.reduce((x, y) => x max y)
Or with _ syntax for anonymous function:
rdd.reduce(_ max _)
Or avoid building collection max on your own:
rdd.max

Implementing map for an intensionally-defined set in Scala

type Set = Int => Boolean
/**
* Returns whether all bounded integers within `s` satisfy `p`.
*/
def forall(s: Set, p: Int => Boolean): Boolean = {
def iter(a: Int): Boolean = {
if (a > bound) true
else if (contains(s, a) && !p(a)) false
else iter(a + 1)
}
iter(-bound)
}
/**
* Returns whether there exists a bounded integer within `s`
* that satisfies `p`.
*/
def exists(s: Set, p: Int => Boolean): Boolean = !forall(s, (x => !p(x)))
/**
* Returns a set transformed by applying `f` to each element of `s`.
*/
def map(s: Set, f: Int => Int): Set = (x => exists(s, (y: Int) => f(y) ==
x))
so for this piece of code. I don't understand function map.
I see its input are 2 arguments, which are set and method f. But the "body" part, I tried so hard but still don't get it. And what is that "y", and why using f(y) == x makes it apply method f to set elemtns?
need some explanation for me.
thank you!
To be succinct:
If you say: val set2 = map(set1, f),
then set2(x) will returns true if and only if there exits y in set1 such as f(y) == x
That's exactly what exists(set1, y => f(y) == x) is checking.
To put it an other way, an integer is in set2 only if you can obtain it by applying f to an element of set1.
We can try to understand this piece of code by applying it backwards.
The map method here would return true for every given x and function f, if x is a result of the function f applied to the elements of the original set.
It is done by checking that if we go over the original map and apply f to every element of this map, at least one of them will be equal to x (that is what the part (x => exists(s, (y: Int) => f(y) == x)) does).
Regarding exists itself, it is a statement that if we go over all elements of the set (using forall method) with a given predicate p, for at least one of the elements this predicate will not be false (this is the part !forall(s, (x => !p(x)))).
And what is that "y"
exists takes a function Int => Boolean as its second argument. This function is (y: Int) => f(y) == x, and y is simply the name we give to its argument, same as x in x => !p(x).
and why using f(y) == x makes it apply method f to set elemtns?
This definition says "x is a member of map(s, f) when exists(s, y => f(y) == x). Now consider a simple case: s is the set {1, 2} represented by a function x => (x == 1) || (x == 2), and f = z => z + 1 over it. Then we have
s2 = map(s, z => z + 1) = x => exists(s, y => y + 1 == x)
by inlining f into definition of map. You can check that:
2 is a member of s2, i.e. s2(2) is exists(s, y => y + 1 == 2) is exists(s, y => y == 1) is true.
0 is not a member of s2, i.e. s2(2) is exists(s, y => y + 1 == 0) is exists(s, y => y == -1) is false.
Thinking a bit more, you should be able to list all members of s2, and then to generalize to any s and f.

How to understand function reduceLeft?

Why can (1 :: xs) be inserted?
One is cons'd onto beginning of list xs.
So List(3,2,1) becomes List(1,3,2,1) but what is significance of (1 :: xs)?
I'm having trouble understanding how this works :
def product(xs : List[Int]) = (1 :: xs) reduceLeft((x , y) => x * y)
In method signature a prefix operand (in this case (1 :: xs)) is not described? :
def reduceLeft[B >: A](f: (B, A) => B): B =
(1 :: xs) is not a prefix operand.
You are actually adding 1 before your list xs.
So product(List(3,2,1)) becomes List(1,3,2,1) reduceLeft((x,y) => x * y).
The reduceLeft function will take the 2 elements on the left and replace by the result of your function (x,y) => x * y.
In your case
List(1,3,2,1) => takes (1,3) and replaces by 1* 3 = 3 new List: List(3,2,1)
List(3,2,1) => takes (3,2) and replaces by 3 *2 = 6 new List: (6,1)
Finally takes (6,1) and get the final result 6.
As multiplying by one has no effect in the product, we add the number 1 before the List to avoid an error if the List is Empty.
Remove that and try product(List()) and you will see. If the List had at least on element (1::xs) will have no effect in your function
I believe you understand cons just fine. (1 :: xs) is simply another way to express List(1,3,2,1), on which you then invoke reduceLeft.
As for a better understanding of reduceLeft, I recently blogged this exact topic.
That's not a prefix operand--it's a method invocation on a List instance. The method reduceLeft is being called on the List (1 :: xs).
(1 :: xs) reduceLeft((x , y) => x * y)
can also be written as
(1 :: xs).reduceLeft((x , y) => x * y)
Or, even more explicitly:
val myList = (1 :: xs)
myList.reduceLeft((x , y) => x * y)