How to reassign value to def in scala - scala

I am writing a parser in which I have the following function:
def lastop:(Either[RDD[(Int,Array[Float])], Float], Either[RDD[(Int,Array[Float])], Float]) => RDD[(Int,Array[Float])] = add
In which "add" is a function to perform addition. Then I want to use it in my program like the following line:
terms.foreach(t =>
t match { case nums ~ op => lastop = op; stack = reduce(stack ++ nums, op)}
I am getting the following error:
[error] /home/mahsa/calculator/temp/ScalaParser.scala:183: reassignment to val
[error] t match { case nums ~ op => lastop = op; stack = reduce(stack ++ nums, op)}
[error] ^
Can't figure how to solve this error!

You want to store a changing reference to the function you want to invoke. If you are storing and reassigning something, that implies you need a var, not a val or a def. Try declaring lastop like:
var lastop:(Either[RDD[(Int,Array[Float])], Float], Either[RDD[(Int,Array[Float])], Float]) => RDD[(Int,Array[Float])] = add
Note that you will still need to invoke lastop like a function, since retrieving the var's value will return a function. It's a subtle but significant difference.

Related

Scala Try[String] found instead of String

I am trying to understand how Try works in scala (not try/catch) but Try. As an example, here I wish to check if the file exists, and if yes, I will use the data in the file later in the code, but it doesn't work:
val texte = Try(Source.fromFile(chemin_texte).getLines().filter(_!="").foldLeft(""){_+_})
texte match {
case Success(x) => x
case Failure(e) => println("An error occured with the text file"); println("Error: " + e.getMessage)
}
/*phrases du texte*/
val phrases_txt = split_phrases(texte).map(phrase => phrase)
At val phrases_txt I wish to use the output of texte if the file exists, if not the program should halt at Failure(e).
The error that I get is type mismatch; found: scala.util.Try[String] required: String .
Any help? Thanks.
Think of Try as just a container for a computation that can fail. It is not comparable with a try and catch block because they just "throw" the exceptions, which are expected to be handled later on in the program. Scala Try forces you to ensure that a possible error is handled at all times from that point onwards in your program.
You can do something like this:
val texte = Try(Source.fromFile(chemin_texte).getLines().filter(_!="").foldLeft(""){_+_})
val phrases: Try[List[String]] = texte.map(split_phrases)
I don't see the point of .map(phrases => phrases) because it will return the same object. The map function has a type of T[A] => T[B], so that means that for a container with values of type A, the map will run a given function f on the contents of the container and produce a container of type B where function f is responsible for converting an object of type A to type B.
If you wish to further use your phrases object in your program with other values that produce Try values, you can use the flatMap function or for expressions that make life easier. For example:
val morePhrases: Try[List[String]] = ???
def mergePhrases(phrases1: List[String], phrases2: List[String]): Phrases = phrases1 ++ phrases2
val mergedPhrases: Try[List[String]] = for {
p1 <- phrases
p2 <- morePhrases
} yield mergePhrases(p1, p2) // Only for demonstration, you could also do yield p1 ++ p2
The mergedPhrases value in the code above is just a Try container containing the result of application of mergePhrases function on contents of phrases and morePhrases.
Note that the Try block may not always be the best way to capture error at the end of your program you'll what the first error occurred, but you won't know what exactly the error was. That's why we have things like Either.

Found Unit, required Int

I have the following Scala code:
object Solution {
def getBestSolution(sumList: List[Int]): Int = {
return 0
}
def main(args: Array[String]) {
val t = readInt()
(0 until t).foreach({
val n = readInt()
val a = readLine().split(" ").map(_.toInt).toList
val sumList = a.scanLeft(0)(_ + _).tail.toList
//println(classOf[sumList])
println(sumList)
println(getBestSolution(sumList))
})
}
}
For it, I am getting this error:
file.scala:16: error: type mismatch;
found : Unit
required: Int => ?
println(getBestSolution(sumList))
^
one error found
Any idea what is causing this?
The argument you are passing to foreach is the result of executing the code block (which is a Unit), not a function.
Remove the outer parentheses (they do not really hurt anything, but are unnecessary and look ugly), and add _ => in the beginning:
(0 to t).foreach { _ =>
...
println(getBestSolution(sumList))
}
This is the proper syntax for creating an unnamed function. The stuff before => is the parameter list that the function accepts. In your case, you can just put an underscore there, because you do not need the value of the parameter. Or you could give it a name if you needed to do something with it, e.g.: (0 to t).foreach { x => println(x*x) }
you could have done it with simple for comprehension too instead of foreach
for(x <- 0 to t){
val n = readInt()
val a = readLine().split(" ").map(_.toInt).toList
val sumList = a.scanLeft(0)(_ + _).tail.toList
//println(classOf[sumList])
println(sumList)
println(getBestSolution(sumList))
}
To sum up, Programming in Scala book has pointed that Scala provides the for comprehension, which provides syntactically pleasing nesting of map, flatMap, and filter ... The for comprehension is not a looping construct, but is a syntactic construct the compiler reduces to map, flatMap, and filter.

Scala partial application via underscore when composing function literals

I am composing function literals, though unlike most examples I've seen I'm starting with a multi-argument function that is then curried.
I have:
//types
case class Thing1(v: Double)
case class Thing2(v: Double)
case class Thing3(v: Double)
type Multiplier = Double
//functions
val f1 = (t: Thing1, m: Multiplier) => Thing2(m * t.v)
val f2 = (t: Thing2) => Thing3(t.v)
I want to compose f1 and f2 to get a combined function
Thing1 => (Multiplier => Thing3)
As expected, the following doesn't compile:
val fcomposed1 = f1.curried.andThen(f2) // does not compile
By experimentation, I was able to work out that the following does compile and has the right signature for fcomposed:
val fcomposed2 = f1.curried(_:Thing1).andThen(f2)
I've read various sources like What are all the uses of an underscore in Scala? and possibly relevant Why does Scala apply thunks automatically, sometimes? but unfortunately I still cannot work out exactly step-by-step what is happening here and why it works.
Furthermore, I would expect the above separated into two expressions to work identically to fcomposed2, however instead the second does not compile:
val f1partial = f1.curried(_:Thing1)
val fcomposed3 = f1partial.andThen(f2) // does not compile - same error as fcomposed1
Looks like f1partial returns the same signature as f1.curried, which makes me wonder further how the earlier fcomposed2 works.
Could someone please explain both behaviours step by step?
Here, the _ is acting as syntactical sugar for a lambda expression, but at a level you might not expect.
f1.curried has type Thing1 => Multiplier => Thing2
f1.curried(_:Thing1) is the same as { x: Thing1 => f1.curried(x) }. Since the result of f1.curried(x) has type Multiplier => Thing2, the final type of the whole expression is still Thing1 => Multiplier => Thing2. So it is not valid to call andThen(f2) on the result (f1partial) because the input type of function f2 (Thing2) is not the same as the output of the previous function (Multiplier => Thing2).
By contrast, f1.curried(_:Thing1).andThen(f2) expands to { x: Thing1 => f1.curried(x).andThen(f2) }. f1.curried(x) evaluates to type Multiplier => Thing2, like stated earlier, so you can call andThen(f2) on that, resulting in a Multiplier => Thing3. So then the entire expression evaluates to a Thing1 => Multiplier => Thing3
Perhaps it's more clear if you think about the differences between these two expressions:
val fcomposed1 = { x: Thing1 => f1.curried(x).andThen(f2) } // valid
val fcomposed2 = { x: Thing1 => f1.curried(x) }.andThen(f2) // error

Scala implicit for Option containing Map

I am trying to write the following implicit:
implicit class ExtractOrElse[K, V](o: Option[Map[K, V]]) {
def extractOrElse(key: K)(f: => V): V = { if (o.isDefined) o.get(key) else f }
}
Which I want to use in this way:
normalizationContexts.extractOrElse(shardId)(defaultNormalizationContext)
to avoid a clunkier syntax (normalizationContexts is an Option[Map[String, NormzalitionContext]]).
Also, let me add that it is intentional that there is only one default value: it will be used if the Option isEmpty, but if the Option isDefined, then the behavior of the Map is not changed, and it will throw an exception if the key is not found - so the default value won't be used in that case, and this is all intentional.
However, I get an error when passing in None in unit tests:
assertEquals(None.extractOrElse('a')(0), 0)
results in:
Error:(165, 37) type mismatch;
found : Char('a')
required: K
assertEquals(None.extractOrElse('a')(0), 0)
I realize that None is not parametric, as it is defined as:
case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
What is the best way to make this work?
Instead of None.extractOrElse(...), try Option.empty[Map[Char, Int]].extractOrElse(...).
If you always use the same types for your test cases, you could also create a type alias in the specs class in order to reduce the clutter:
type OpMap = Option[Map[Char, Int]]
// ...
assertEquals(Option.empty[OpMap].extractOrElse('a')(0), 0)
Just in case, you can use flatMap and getOrElse to achieve the same thing without writing a new method:
val n = Option.empty[Map[String, Int]]
val s = Some(Map("x" → 1, "y" → 2))
n.flatMap(_.get("x")).getOrElse(3) // 3
s.flatMap(_.get("x")).getOrElse(3) // 1
s.flatMap(_.get("z")).getOrElse(3) // 3
The type system doesn't have enough information about the types K and V. There is no way to know what the type of A would be in the case where your None was Some[A].
When I create an example with explicit types, the code works as expected:
// Like this
val e = new ExtractOrElse(Option.empty[Map[Char, Int]])
e.extractOrElse('a')(0) // Equals 0
// Or like this
val e = new ExtractOrElse[Char, Int](None)
println(e.extractOrElse('a')(0))
// Or like this
val m: Option[Map[Char, Int]] = None
val e = new ExtractOrElse(m)
println(e.extractOrElse('a')(0))

Scala functional composition

I'm trying to get a function currying working correctly. What I have is the following:
def method(x: ByteArrayInputStream)
(y: ByteArrayOutputStream)
(z: GZIPOutputStream)
(func: (ByteArrayInputStream, GZIPOutputStream) => Unit) = {
.....
.....
}
Now when I call it, I call it like this:
method(new ByteArrayInputStream("".getBytes("UTF-8")))
(new ByteArrayOutputStream())
(new GZIPOutputStream(_))
(myFunc(_, _))
My understanding is that in the third parameter i.e., to the GZIPOutputStream, when I say _, it will pick the value from the second parameter. But it complains saying that
Type mismatch, expected: GZIPOutputstream, actual: (OutputStream) => GZIPOutputStream
Any hints?
The problem is at
(new GZIPOutputStream(_))
As your error says, your method wants a a GZIPOutputstream, but you are passing it a function from OutputStream to GZIPOutputStream
The underscore is a little confusing at first, but it is the way to tell scala that you are intentionally not passing an argument to GZIPOutputStream so that it won't complain about missing arguments. In other words, you are passing the function itself instead of the result of the function.
How to fix it depends on what you're actually trying to do. If you actually want to pass a GZIPOutputStream, you'll need to replace that _ with an OutputStream.
If your intent is to have method create a GZIPOutputStream given a factory function like the one you are passing, you'd want to change the declared type for z. Eg,
(z: (OutputStream) => GZIPOutputStream)
and then in the method body you could say something like z(y) to get a GZIPOutputStream. (Or replace y with some other output stream.)
I'm not exactly sure how to do this... but here is one solution that mimics what you are looking for
def add(j: Int)(i: Option[Int] = None): Int = j + i.getOrElse(j)
add(5)()
The add(5)() returns 10 and uses the j value
I have managed to skin that a bit and here is what I have been to:
val bytePayload = method(new ByteArrayInputStream(s.getBytes("UTF-8")))(new ByteArrayOutputStream())(writeBytes(_,_))
def method(bin: ByteArrayInputStream)
(bos: ByteArrayOutputStream)
(func: (ByteArrayInputStream, GZIPOutputStream) => Unit): Either[String, Array[Byte]] = {
val gzip = new GZIPOutputStream(bos)
try {
func(bin, gzip)
gzip.finish
} catch {
case e: Exception => Left(e.getMessage)
} finally {
bin.close()
bos.close()
gzip.close()
}
Right(bos.toByteArray)
}
Though I still handle Exceptions, I'm to some extent convinced that I don't throw them around.