scala quasiquotes string variable lifting in multiple steps - scala

this is what i want:
scala> var x:Int = 10
x: Int = 10
scala> var y:Int = 20
y: Int = 20
scala> val ret = q"return $x>$y"
ret: universe.Return = return 10.$greater(20)
scala> val result1 = toolbox.compile(ret)()
result1: Any = false
But the problem is that I will be getting the expression $x>$y in a string var, like
scala> m
res20: String = $x>$y
And then I want to perform the operation as,
var ret = q"return $m"
but this return:
scala> var ret = q"return $m"
ret: universe.Return = return "$x>$y"
which is not serving the purpose. How can I get the value of x and y in the last step instead $x and $y.

You can mix quasiquotes and ToolBox.parse to achieve results mostly like what you are looking for:
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._
val toolbox = scala.reflect.runtime.currentMirror.mkToolBox()
val s = "10>20"
val ret = q"return ${toolbox.parse(s)}"
// reflect.runtime.universe.Return = return 10.$greater(20)
toolbox.eval(ret)
// Any = false
Making use of your values as variables:
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._
val toolbox = scala.reflect.runtime.currentMirror.mkToolBox()
val x = 10
val y = 20
val m = "x>y"
val ret = q"return ${toolbox.parse(m)}"
// reflect.runtime.universe.Return = return x.$greater(y)
If you evaluate q"return ${toolbox.parse(m)}" you will see the error because x and y are not in scope.
scala> toolbox.eval(q"return ${toolbox.parse(m)}")
scala.tools.reflect.ToolBoxError: reflective compilation has failed:
object > is not a member of package x ...
To fix that:
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._
val toolbox = scala.reflect.runtime.currentMirror.mkToolBox()
val q1 = q"val x = 10; val y = 20; "
val m = "x>y"
val ret = q"""
| ..$q1
| return ${toolbox.parse(m)}
| """
toolbox.eval(ret)
// Any = false

Related

Split key value in map scala

I don't know if it is possible, but I'd like in my mapPartitions to split in two lists the variable "a". Like here to have a list l that stores all numbers and an other list let's say b that stores all words. with something like a.mapPartitions((p,v) =>{ val l = p.toList; val b = v.toList; ....}
With for example in my for loop l(i)=1 and b(i) ="score"
import scala.io.Source
import org.apache.spark.rdd.RDD
import scala.collection.mutable.ListBuffer
val a = sc.parallelize(List(("score",1),("chicken",2),("magnacarta",2)) )
a.mapPartitions(p =>{val l = p.toList;
val ret = new ListBuffer[Int]
val words = new ListBuffer[String]
for(i<-0 to l.length-1){
words+= b(i)
ret += l(i)
}
ret.toList.iterator
}
)
Spark is a distributed computing engine. you can perform operation on partitioned data across nodes of the cluster. Then you need a Reduce() method that performs a summary operation.
Please see this code that should do what you want:
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
object SimpleApp {
class MyResponseObj(var numbers: List[Int] = List[Int](), var words: List[String] = List[String]()) extends java.io.Serializable{
def +=(str: String, int: Int) = {
numbers = numbers :+ int
words = words :+ str
this
}
def +=(other: MyResponseObj) = {
numbers = numbers ++ other.numbers
words = words ++ other.words
this
}
}
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("Simple Application").setMaster("local[2]")
val sc = new SparkContext(conf)
val a = sc.parallelize(List(("score", 1), ("chicken", 2), ("magnacarta", 2)))
val myResponseObj = a.mapPartitions[MyResponseObj](it => {
var myResponseObj = new MyResponseObj()
it.foreach {
case (str :String, int :Int) => myResponseObj += (str, int)
case _ => println("unexpected data")
}
Iterator(myResponseObj)
}).reduce( (myResponseObj1, myResponseObj2) => myResponseObj1 += myResponseObj2 )
println(myResponseObj.words)
println(myResponseObj.numbers)
}
}

scala case class var val

Can anyone explain this strange behavior with my case class?
case class Dai(var g :Int) {
def getG() = g
}
val dai: Dai = Dai(20)
dai.g = 30
// why v2 difference with getGet
val v2 = dai.getG // 30
var getGet = dai.getG // 20
Intellij Worksheet has this problem
But not from the REPL
Must have something to do with how Intellij is running the worksheet?
It doesn't happen on my system running 2.11.2. Most probably a bug that can be fixed by upgrading your distribution.
scala> case class Dai(var g :Int) {
| def getG() = g
| }
defined class Dai
scala>
scala> val dai: Dai = Dai(20)
dai: Dai = Dai(20)
scala>
scala> dai.g = 30
dai.g: Int = 30
scala> // why v2 difference with getGet
scala> val v2 = dai.getG // 30
v2: Int = 30
scala> var getGet = dai.getG // 20
getGet: Int = 30

Calling methods of object in Scala dynamically with scala.reflect.runtime.universe?

I'd like to dynamically execute the methods that start with removeAt of the object X at runtime.
How can I do that with the scala.reflect.runtime.universe API described in REFLECTION Environment, Universes, and Mirrors
Here is solution for your problem:
object X {
def aa = 1
def ab = 2
def removeAtX = 3
def bb = 4
def removeAtY = 5
}
val ru = scala.reflect.runtime.universe
val m = ru.runtimeMirror(getClass.getClassLoader)
val im = m.reflect(X)
val l = X.getClass.getMethods.map(_.getName).filter(_ startsWith "removeAt")
val r = l.map(y => ru.typeOf[X.type].declaration(ru.newTermName(y)).asMethod).map(im.reflectMethod(_).apply())
Result:
r: scala.collection.mutable.ArraySeq[Any] = ArraySeq(3, 5)

Skip initialization of hash of hash (of hash) in scala?

How do I avoid the initialization (lines 5 and 6) here?
import scala.collection._
def newHash = mutable.Map[String,String]()
def newHoH = mutable.Map[String,mutable.Map[String,String]]()
var foo = mutable.Map[String,mutable.Map[String,mutable.Map[String,String]]]()
foo("bar") = newHoH //line 5
foo("bar")("baz") = newHash //line 6
foo("bar")("baz")("whee") = "duh"
I tried withDefaultValue with a simpler example but obviously I did it wrong:
/***
scala> var foo = mutable.Map[String,mutable.Map[String,String]]().withDefaultValue(mutable.Map(""->""))
foo: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]] = Map()
scala> foo("bar")("baz") = "duh"
scala> foo("b")("baz") = "der"
scala> foo("bar")("baz")
res7: String = der
*/
The withDefault method won't work here. A Map created this way returns a new map everytime there is no key, so calling mymap("foo")("bar") = "ok" will assign "ok" into a temporarily created map, but the next time you call mymap("foo")("bar"), a non-existent "foo" key on mymap will result in creating a new map, which will not contain the mapping "foo" -> "bar".
Instead, consider creating an anonymous map. I show a solution with only 1 nestings:
‡ scala-version 2.10.1
Welcome to Scala version 2.10.1 (Java HotSpot(TM) Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import collection._
import collection._
scala> :paste
// Entering paste mode (ctrl-D to finish)
def newHash = mutable.Map[String,String]().withDefault(_ => "")
def newHoH = new mutable.Map[String,mutable.Map[String,String]]() {
val m = mutable.Map[String, mutable.Map[String, String]]()
def +=(kv: (String, mutable.Map[String, String])) = { m += kv; this }
def -=(k: String) = { m -= k; this }
def get(k: String) = m.get(k) match {
case opt # Some(v) => opt
case None =>
val v = newHash
m(k) = v
Some(v)
}
def iterator = m.iterator
}
// Exiting paste mode, now interpreting.
newHash: scala.collection.mutable.Map[String,String]
newHoH: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]{val m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]}
scala> val m = newHoH
m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]{val m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]} = Map()
scala> m("foo")("bar") = "ok"
scala> m("foo")("bar")
res1: String = ok

Can't get inherited vals with Scala reflection

I'm using Scala 2.10.1 and I'm trying the define a method which will retrieve all the vals (including the inherited ones) from an object.
I have the following:
import scala.reflect.runtime.{universe => ru}
object Reflection {
val mirror = ru.runtimeMirror(this.getClass.getClassLoader)
def findVals(x: Any): Iterable[String] = {
val theType = mirror.classSymbol(x.getClass).toType
theType.members.collect({case x if x.isTerm => x.asTerm}).filter(_.isVal).map(_.name.toString)
}
}
I am testing on these two classes:
class Base {
val x = 10
}
class Child extends Base {
val y = 20
}
When calling the following code:
val x = new Child
val vs = Reflection.findVals(x)
println(vs)
The result is List(y)
For some reason, the isVal method returns false for the term corresponding to the x field from the Base class.
Can someone tell me what's the problem here? Am I doing something wrong?
Per Why don't Scala case class fields reflect as public? you should use isAccessor instead of isVal.
I'm actually using isGetter and setter to properly filter vars per your comment:
def findVals(x: Any): Iterable[String] = {
val theType = mirror.classSymbol(x.getClass).toType
val xtm = theType.members.collect({case x if x.isTerm => x.asTerm})
xtm.filter(m => m.isGetter && !xtm.exists(m.setter == _)).map(_.name.toString)
}
Results:
scala> class Base {
| var x = 10
| val xx = 2
| }
defined class Base
scala> class Child extends Base {
| val y = 3
| }
defined class Child
scala> val x = new Child
x: Child = Child#1c0026e
scala> val vs = Reflection.findVals(x)
vs: Iterable[String] = List(y, xx)
scala> println(vs)
List(y, xx)
Using SMirror:
scala> implicit val mirror = scala.reflect.runtime.currentMirror
mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.tool…
scala> import net.fwbrasil.smirror._
import net.fwbrasil.smirror._
scala> class Base {
val x = 10
}
defined class Base
scala> class Child extends Base {
val y = 20
}
defined class Child
scala> val x = new Child
x: Child = Child#448593d0
scala> x.reflect.vals
res5: List[net.fwbrasil.smirror.SInstanceVal[Child]] = List(val x: scala.Int (bound to Child#448593d0), val y: scala.Int (bound to Child#448593d0))
scala> x.reflect.vals.head.get
res7: Any = 10
So, this is terribly inelegant, but it seems to work:
import scala.reflect.runtime.{universe => ru}
object Reflection {
val mirror = ru.runtimeMirror(this.getClass.getClassLoader)
val ObjectClass = classOf[java.lang.Object];
def findVals(x: Any) : Iterable[String] = findVals( x.getClass, List.empty );
def findVals(clz: Class[_], accum : Iterable[String]): Iterable[String] = {
clz match {
case ObjectClass => accum;
case _ => {
val theType = mirror.classSymbol(clz).toType
val newVals = theType.members.collect({case x if x.isTerm => x.asTerm}).filter(_.isVal).map(_.name.toString)
findVals( clz.getSuperclass, accum ++ newVals )
}
}
}
}
Then...
scala> class Base {
| val x = 10
| var z = 20
| }
defined class Base
scala> class Child extends Base {
| val y = 20
| var a = 9
| }
defined class Child
scala> val x = new Child
x: Child = Child#3093266d
scala> val vs = Reflection.findVals(x)
vs: Iterable[String] = List("y ", "x ")
scala> println(vs)
List(y , x )
It seems that, at least for now, Scala reflection looks at the Java field to determine the presence of a val, so I guess you just have to climb the class hierarchy... I'm guessing it looks for the presence of a setter to distinguish val from var. Again, not so lovely, but functional.