cannot see difference between view bound and upper bound - scala

In the following example, I am using view bound and upper bound. The code is exactly the same except for the difference in signs of <% and <:. What is the difference between view bound and upper bound?
scala> class Person[T <% Ordered[T]](val fn:T, val ln:T) {
| def greater = if (fn > ln) fn else ln
| }
defined class Person
scala> val p1 = new Person("manu", "chadha")
p1: Person[String] = Person#31b91435
scala> val p2 = new Person("anita", "chadha")
p2: Person[String] = Person#61e0f9b9
scala> p1.greater
res3: String = manu
scala> p2.greater
res4: String = chadha
scala> class Person2[T <: Ordered[T]](val fn:T, val ln:T) {
| def greater = if (fn > ln) fn else ln
| }
defined class Person2
scala> val p3 = new Person("manu", "chadha")
p3: Person[String] = Person#7c50709a
scala> val p4 = new Person("anita", "chadha")
p4: Person[String] = Person#1d686622
scala> p3.greater
res5: String = manu
scala> p4.greater
res6: String = chadha
scala>

Related

Using an expression a(1) = 10 instead of a.set(1,10) in Scala

I can use apply in Scala to overload the () operator.
class A {
val arr = Array[Int](1,2,3,4,5)
def apply(i:Int) = {
arr(i)
}
}
object Main extends App {
val a = new A
println(a(0))
}
When I set the value, I can add the set method
def set(i:Int, value:Int) = {arr(i) = value}
...
arr.set(3, 10)
Does Scala allow better syntactic sugar such as arr(3) = 10 to get the same results?
You could define the update method:
scala> class A {
| val arr = Array[Int](1,2,3,4,5)
| def apply(i: Int) = {
| arr(i)
| }
| def update(i: Int, x: Int) {
| arr(i) = x
| }
| }
defined class A
scala> val a = new A
a: A = A#7d117aef
scala> a(0)
res0: Int = 1
scala> a(0) = 42
scala> a(0)
res2: Int = 42

Scala Double error when compiling in SPARK-REPL

I am learning Scala at the moment
<pre>
scala> val sample = similarities.filter(m => {
| val movies = m._1
| (movieNames(movies._1).contains("Star Wars (1977)"))
| })
</pre>
sample: org.apache.spark.rdd.RDD[((Int, Int), Double)] = FilteredRDD[25] at filter at :36
The sample compiled just fine
But when I tried to call sample again in the next command
<pre>
scala> val result = sample.map(v => {
| val m1 = v._1._1
| val m2 = v._1._2
| val correl = v._2._1
| //val rcorr = v._2._2
| // val cos = v._2._3
| //val j = v._2._4
| (movieNames(m1), movieNames(m2), correl)
| })
<console>:41: error: value _1 is not a member of Double
val correl = v._2._1
</pre>
Can someone please help me.Thanks in advance
Given the amount of indexing on the composed tuple, consider wrapping ((Int, Int), Double) onto a case class and defining an implicit on it as follows,
case class Movie(m1: Int, m2: Int, correl: Double)
implicit def RichMovie(v: ((Int,Int),Double) ) = Movie(v._1._1, v._1._2, v._2)
Thus, given an instance of a composed tuple
scala> val m = ( (1,2), 3.5)
m: ((Int, Int), Double) = ((1,2),3.5)
we can access its members as follows,
scala> m.m1
res0: Int = 1
scala> m.m2
res1: Int = 2
scala> m.correl
res2: Double = 3.5
val correl = v._2._1
should be just
val correl = v._2
because it is part of the second element in the tuple ((Int, Int), Double)

Simple destructuring extractor for command line args

The preferred approach would be to use something similar to the commented out line below.
def main(args: Array[String]) {
// val (dbPropsFile, tsvFile, dbTable) = args
val dbPropsFile = args(0)
val tsvFile = args(1)
val dbTable = args(2)
However I am having a little quarrel with the compiler over it:
Error:(13, 9) constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: Array[String]
val (dbPropsFile, tsvFile, dbTable) = args
^
So all told this should be an easy few points for someone out there.
Use
val Array(dbPropsFile, tsvFile, dbTable) = args
scala> val Array(a,b,c) = Array(1,2,3)
a: Int = 1
b: Int = 2
c: Int = 3
scala> a
res0: Int = 1

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.

Using lazy evaluation functions in varargs

What is wrong is the following method?
def someMethod(funcs: => Option[String]*) = {
...
}
That actually "works" under 2.7.7 if you add parens:
scala> def someMethod(funcs: => (Option[String]*)) = funcs
someMethod: (=> Option[String]*)Option[String]*
except it doesn't actually work at runtime:
scala> someMethod(Some("Fish"),None)
scala.MatchError: Some(Fish)
at scala.runtime.ScalaRunTime$.boxArray(ScalaRunTime.scala:136)
at .someMethod(<console>:4)
at .<init>(<console>:6)
at .<clinit>(<console>) ...
In 2.8 it refuses to let you specify X* as the output of any function or by-name parameter, even though you can specify it as an input (this is r21230, post-Beta 1):
scala> var f: (Option[Int]*) => Int = _
f: (Option[Int]*) => Int = null
scala> var f: (Option[Int]*) => (Option[Int]*) = _
<console>:1: error: no * parameter type allowed here
var f: (Option[Int]*) => (Option[Int]*) = _
But if you try to convert from a method, it works:
scala> def m(oi: Option[Int]*) = oi
m: (oi: Option[Int]*)Option[Int]*
scala> var f = (m _)
f: (Option[Int]*) => Option[Int]* = <function1>
scala> f(Some(1),None)
res0: Option[Int]* = WrappedArray(Some(1), None)
So it's not entirely consistent.
In any case, you can possibly achieve what you want by passing in an Array and then sending that array to something that takes repeated arguments:
scala> def aMethod(os: Option[String]*) { os.foreach(println) }
aMethod: (os: Option[String]*)Unit
scala> def someMethod(funcs: => Array[Option[String]]) { aMethod(funcs:_*) }
someMethod: (funcs: => Array[Option[String]])Unit
scala> someMethod(Array(Some("Hello"),Some("there"),None))
Some(Hello)
Some(there)
None
If you really want to (easily) pass a bunch of lazily evaluated arguments, then you need a little bit of infrastructure that as far as I know doesn't nicely exist in the library (this is code for 2.8; view it as inspiration for a similar strategy in 2.7):
class Lazy[+T](t: () => T, lt: Lazy[T]) {
val params: List[() => T] = (if (lt eq null) Nil else t :: lt.params)
def ~[S >: T](s: => S) = new Lazy[S](s _,this)
}
object Lz extends Lazy[Nothing](null,null) {
implicit def lazy2params[T : Manifest](lz: Lazy[T]) = lz.params.reverse.toArray
}
Now you can easily create a bunch of parameters that are lazily evaluated:
scala> import Lz._ // To get implicit def
import Lz._
scala> def lazyAdder(ff: Array[()=>Int]) = {
| println("I'm adding now!");
| (0 /: ff){(n,f) => n+f()}
| }
lazyAdder: (ff: Array[() => Int])Int
scala> def yelp = { println("You evaluated me!"); 5 }
yelp: Int
scala> val a = 3
a: Int = 3
scala> var b = 7
b: Int = 7
scala> lazyAdder( Lz ~ yelp ~ (a+b) )
I'm adding now!
You evaluated me!
res0: Int = 15
scala> val plist = Lz ~ yelp ~ (a+b)
plist: Lazy[Int] = Lazy#1ee1775
scala> b = 1
b: Int = 1
scala> lazyAdder(plist)
I'm adding now!
You evaluated me!
res1: Int = 9
Evidently repeated arguments are not available for by-name parameters.