How to define a function inside match block - scala

Question
Is there a way to define the insert function inside the makeOrderedLeafList match block?
Problem
Since insert function is only used in makeOrderedLeafList, I would like to define it inside it. However, if placed at the bottom, an error "Unit required". Cannot place at the top as "case" is being expected.
def makeOrderedLeafList(freqs: List[(Char, Int)]): List[Leaf] = freqs match {
case List() => List()
case h :: t => insert(h, makeOrderedLeafList(t))
case _ => throw new IllegalStateException
}
//--------------------------------------------------------------------------------
// Insert Leaf in the sorted list of Leaf.
//--------------------------------------------------------------------------------
def insert(c: (Char, Int), list: List[Leaf]): List[Leaf] = list match {
case List() => List(new Leaf(c._1, c._2))
case h :: t => {
//--------------------------------------------------------------------------------
// If C:[char, counter] is smaller, prepend it to the List[Leaf].
// Otherwise, recurse call insert to find a position in the tail of the list.
//--------------------------------------------------------------------------------
if (c._2 <= h.weight) new Leaf(c._1, c._2) :: list
else h :: insert(c, t)
}
}

Just place it inside the case before calling it:
scala> "hello" match {
| case "hel" => 1
| case "hello" =>
| def f(i: Int): Int = {
| i * 2
| }
| f(3) // don't forget to call the function...
| }
res0: Int = 6
The right-hand side of a case expression can be any code block that returns the expected type. A code block can contain function definitions.

If you define you function inside the outer function call, it will create a new instance of inner function on every call of outer function.
val getInnerFuncHash = () => {
val func = (x: Int) => x + 1
func.hashCode().toString
}
println(getInnerFuncHash())
println(getInnerFuncHash())
println(getInnerFuncHash())
this will print the hashCodes for the inner functions, and will output something like,
1136974570
1030088901
2115208183
which means every call to outer function will create a new instanc eof inner function.
The same thing happens in case of defs
def getInnerFuncHash(): String = {
val func = (x: Int) => x + 1
func.hashCode().toString()
}
println(getInnerFuncHash())
println(getInnerFuncHash())
println(getInnerFuncHash())

Related

What is the difference between map{} and map() [duplicate]

This question already has answers here:
What is the formal difference in Scala between braces and parentheses, and when should they be used?
(9 answers)
Closed 6 years ago.
From this link showing some Scala examples: http://spark.apache.org/docs/latest/mllib-collaborative-filtering.html
what is the difference between map{} and map()?
val ratings = data.map(_.split(',') match { case Array(user, item, rate) =>
Rating(user.toInt, item.toInt, rate.toDouble)
})
val usersProducts = ratings.map { case Rating(user, product, rate) =>
(user, product)
}
map is a method which accepts a function as an argument. So map customarily is called just like methods get called: map(aFunction). However, Scala provides a lot of flexibility / shorthands in its syntax:
val list = List((1,2),(3,4))
//An ordinary method call. The braces just evaluate to an anonymous function
val a = list.map({ case (a, b) => a + b }) // List(3,7)
// Now lets define a non anonymous function of the same type as above:
def func(x: (Int,Int)) = x match {case (a,b) => a + b}
// Scala allows this readable "infix notation" for single parameter methods
val a = list map func // List(3,7)
//Now to the main point you asked, this syntax uses the same readable form as above
//but uses an anonymous function.
val a = list map {case (a,b) => a + b} // List(3,7)
val a = list.map(_.split(','))
// the above is a shorthand for
val a = list.map({ case i => i.split(',') })
// Now lets consider this
val a = list.map { case (a, b) => a + b }
// or this
val a = list map { case (a, b) => a + b }
// some people like the above ways of writing
// because they consider of less brackets as cleaner code.
// but the above two are another way to write
val a = list.map({ case (a, b) => a + b })
The thing to understand here is that in Scala you can use spaces instead of . to access instance methods.
So basically,
// lets say you have a class A
case class A(i: Int) {
def merged[B](b: B): String = i.toString + " :: " + b.toString
}
//Now, lets say you have an instance of A
val a = A(5)
// and an instance of String
val s: String = "abcd"
// Now, if you write
val merged = a merged s
// it is syntactic sugar for
val merged = a.merged(s)
Similarly, List[A] has a method map[B](f: A => B): List[B].
val list = List[Int](1, 2, 3)
// so when you write
val list2 = list map { case i => i + 1}
// its syntactic sugar for,
val list2 = list.map({ case i => i + 1 })
// There is a lot going on here
// if we were to do everything step by step
// first you are creating a partial function
val pf: PartialFunction[Int, Int] = { case i => i + 1 }
// Now, PartialFunction[Int, Int] is a subtype of Int => Int
// so we can refer to it as a Int => Int
val f: Int => Int = pf
// Now we pass it as an argument to map
val list2 = list.map(f)

Can we have an array of by-name-parameter functions?

In Scala we have a by-name-parameters where we can write
def foo[T](f: => T):T = {
f // invokes f
}
// use as:
foo(println("hello"))
I now want to do the same with an array of methods, that is I want to use them as:
def foo[T](f:Array[ => T]):T = { // does not work
f(0) // invokes f(0) // does not work
}
foo(println("hi"), println("hello")) // does not work
Is there any way to do what I want? The best I have come up with is:
def foo[T](f:() => T *):T = {
f(0)() // invokes f(0)
}
// use as:
foo(() => println("hi"), () => println("hello"))
or
def foo[T](f:Array[() => T]):T = {
f(0)() // invokes f(0)
}
// use as:
foo(Array(() => println("hi"), () => println("hello")))
EDIT: The proposed SIP-24 is not very useful as pointed out by Seth Tisue in a comment to this answer.
An example where this will be problematic is the following code of a utility function trycatch:
type unitToT[T] = ()=>T
def trycatch[T](list:unitToT[T] *):T = list.size match {
case i if i > 1 =>
try list.head()
catch { case t:Any => trycatch(list.tail: _*) }
case 1 => list(0)()
case _ => throw new Exception("call list must be non-empty")
}
Here trycatch takes a list of methods of type ()=>T and applies each element successively until it succeeds or the end is reached.
Now suppose I have two methods:
def getYahooRate(currencyA:String, currencyB:String):Double = ???
and
def getGoogleRate(currencyA:String, currencyB:String):Double = ???
that convert one unit of currencyA to currencyB and output Double.
I use trycatch as:
val usdEuroRate = trycatch(() => getYahooRate("USD", "EUR"),
() => getGoogleRate("USD", "EUR"))
I would have preferred:
val usdEuroRate = trycatch(getYahooRate("USD", "EUR"),
getGoogleRate("USD", "EUR")) // does not work
In the example above, I would like getGoogleRate("USD", "EUR") to be invoked only if getYahooRate("USD", "EUR") throws an exception. This is not the intended behavior of SIP-24.
Here is a solution, although with a few restrictions compared to direct call-by-name:
import scala.util.control.NonFatal
object Main extends App {
implicit class Attempt[+A](f: => A) {
def apply(): A = f
}
def tryCatch[T](attempts: Attempt[T]*): T = attempts.toList match {
case a :: b :: rest =>
try a()
catch {
case NonFatal(e) =>
tryCatch(b :: rest: _*)
}
case a :: Nil =>
a()
case Nil => throw new Exception("call list must be non-empty")
}
def a = println("Hi")
def b: Unit = sys.error("one")
def c = println("bye")
tryCatch(a, b, c)
def d: Int = sys.error("two")
def e = { println("here"); 45 }
def f = println("not here")
val result = tryCatch(d, e, f)
println("Result is " + result)
}
The restrictions are:
Using a block as an argument won't work; only the last expression of the block will be wrapped in an Attempt.
If the expression is of type Nothing (e.g., if b and d weren't annotated), the conversion to Attempt is not inserted since Nothing is a subtype of every type, including Attempt. Presumably the same would apply for an expression of type Null.
As of Scala 2.11.7, the answer is no. However, there is SIP-24, so in some future version your f: => T* version may be possible.

def macro inside case statement

I'd like to ask where def macros can be called and when they are expanded? I guess we cant just put an appropriate generated AST anywhere it fits?
For example, I want this:
(2,1) match {
case StandaloneMacros.permutations(1,2) => true ;
case (_,_) => false
}
become this after macro expansion
(2,1) match {
case (1,2) | (2,1) => true ;
case (_,_) => false
}
My macro permutations produces an Alternative of tuples. But when I run the first snippet, I get
macro method permutations is not a case class, nor does it have an unapply/unapplySeq member
I also tried defining a Permutations object with unapply macro method but got another error:
scala.reflect.internal.FatalError: unexpected tree: class scala.reflect.internal.Trees$Alternative
So: Is it possible to achieve at all?
I came up with a solution some time ago, and I thought I'd share it with you.
To achieve above task I've used a Transformer and transformCaseDefs
object Matcher {
def apply[A, B](expr: A)(patterns: PartialFunction[A, B]): B = macro apply_impl[A,B]
def apply_impl[A: c.WeakTypeTag, B: c.WeakTypeTag](c: Context)(expr: c.Expr[A])(patterns: c.Expr[PartialFunction[A, B]]): c.Expr[B] = {
import c.universe._
def allElemsAreLiterals(l: List[Tree]) = l forall {
case Literal(_) | Ident(_) => true
case _ => throw new Exception("this type of pattern is not supported")
}
val transformer = new Transformer {
override def transformCaseDefs(trees: List[CaseDef]) = trees.map {
case cas # CaseDef(pat # Apply(typTree, argList), guard, body) if allElemsAreLiterals(argList) =>
val permutations = argList.permutations.toList.map(t => q"(..$t)").map {
case Apply(_, args) => Apply(typTree, args)
}
val newPattern = Alternative(permutations)
CaseDef(newPattern, guard, body)
case x => x
}
}
c.Expr[B](q"${transformer.transform(patterns.tree)}($expr)")
}
}
It would be shorter, but somehow you need to provide the same TypeTree which was used in original (before transformation) case statement.
This way, it can be used like this
val x = (1,2,3)
Matcher(x) {
case (2,3,1) => true
case _ => false
}
which is then translated to something like
val x = (1,2,3)
x match {
case (1,2,3) | (1,3,2) | (2,1,3) | (2,3,1) | (3,1,2) | (3,2,1) => true
case _ => false
}

Scala: conditional yield with matching and side-effects?

What is the correct syntax for something like the following?
var foo = 0
someIterator.foreach{ x => x.property match {
case "a" => foo += 1
case "b" => yield "current foo" + foo
}}
I.e., I'm trying to iterate over someIterator. When it matches one thing, it should update a local variable via closure; when it encounters another, it should yield some derivation of the current state to the resulting iterator preserving the state for successive iterations.
You can use Option[String], unlift and collect.
unlift takes a function that returns an option and turns it into a partial function.
collect is like map, except it considers only the elements for which the partial function is defined.
The following example demonstrates the approach:
import Function.unlift
var foo = 0
someIterator.map(_.property).collect(unlift {
case "a" => foo += 1; None
case "b" => Some("current foo" + foo)
})
Live Demo
If you just want to have the final value of foo then you can use tail recursion and you won't have to use a mutable variable too.
#annotation.tailrec
def f(l: List[Char], foo: Int = 0):Int= {
if (l == Nil) foo
else {
l.head match {
case 'a' => f(l.tail, foo + 1)
case 'b' => f(l.tail, foo)
}
}
}
val l1 = List('a','b')
f(l1)
l1: List[Char] = List(a, b)
res0: Int = 1
You can use scanLeft's acumulator instead of variable:
someIterator.scanLeft((0, None: Option[String])){
case ((foo, _), "a") => (foo + 1, None)
case ((foo, _), "b") => (foo, Some(s"current foo $foo"))
}.map(_._2).flatten
Example:
val someIterator = List("a","a","a","a","b", "a", "a", "b").toIterator
scala> someIterator.scanLeft(...){...}.map(_._2).flatten
res16: Iterator[String] = non-empty iterator
scala> res16.toList
res17: List[String] = List(current foo 4, current foo 6)
So you still have an iterator as a result

implicit parameter definition in class

implicit val odkaz = head;
def vypis(implicit odkaz:Prvek):String = {
odkaz match{
case null => ""
case e => e.cislo + " " + e.pocet + "\n" + vypis(e.dalsi)
}
}
...
def main(args:Array[String]){
val q = new MyQueue() // insert some values
println(q.vypis)
}
This method(vypis) is a member of an queue-class so I'll always want to implicity start the recursion from the start of the queue, when calling the method from outside. Is there a way how to write it, that the method from outside calling, there's no paramter, but in inside, there's a parameter - for recursion...?
The compiler complains that the parameter is not defined when called from outside
Or is there are way how can specify the default value for a method's parameter?
Using a nested method
def sum(list: List[Int]) = {
#annotation.tailrec
def sum(ls: List[Int], s: Int): Int = ls match {
case x :: xs => sum(xs, x + s)
case _ => s
}
sum(list, 0)
}
Using a default parameter for the accumulator
#annotation.tailrec
def sum(list: List[Int], s: Int = 0): Int = list match {
case x :: xs => sum(xs, x + s)
case _ => s
}
The second approach (only possible with Scala 2.8) unneccesarily broadens the public API, so I would recommend the first.
In Scala 2.8, default method (and constructor) parameters are available:
def m1(i: Int = 23): Int = i * 2