I need to define val tuple in my scala case classe as value parameter
case class (v1:(a:String, b:String), v2:String)
but it gives me a compilation error..can someone point me how to that?
You can't name the tuple elements in the class parameters, but you can in the class body.
scala> case class CC(v1:(String, String), v2:String) {
| val (a,b) = v1
| }
defined class CC
scala> val cc = CC(("X", "Y"), "Z")
cc: CC = CC((X,Y),Z)
scala> cc.a
res11: String = X
scala> cc.b
res12: String = Y
Using the REPL, note the inferred type for a given value; for instance
scala> val t = ("a","b")
t: (String, String) = (a,b)
Hence
scala> val t2: (String,String) = ("a","b")
t2: (String, String) = (a,b)
case class v1(t: (String, String), v2: String)
Related
I know isInstanceOf can be used to find value type, but how do I find the type of 'str'?
What type is it?
scala> val str = ("Scala", "Elixir","Spark")
str: (String, String, String) = (Scala, Elixir, Spark)
The following throws an error (exclude Any/AnyRef etc for now):
scala> str.isInstanceOf[List]
<console>:13: error: type List takes type parameters
str.isInstanceOf[List]
scala> str.isInstanceOf[String]
<console>:13: warning: fruitless type test: a value of type (String, String, String) cannot also be a String (the underlying of String)
str.isInstanceOf[String]
^
res9: Boolean = false
I can check it this way but is there a name for this?
scala> str.isInstanceOf[(String, String, String)]
res12: Boolean = true
Use :type in scala repl to find type
Actual type is Tuple3[String, String, String]
str.isInstanceOf[Tuple3[String, String, String]]
Scala REPL
scala> val str = ("Scala", "Elixir","Spark")
str: (String, String, String) = (Scala,Elixir,Spark)
scala> :type str
(String, String, String)
scala> str.isInstanceOf[Tuple3[String, String, String]]
res2: Boolean = true
scala> str.getClass
res3: Class[_ <: (String, String, String)] = class scala.Tuple3
How to determine val type programmatically?
For instance, you want to know the type of the value is some specific type?
// assign x value
val x: Any = "this is string"
// custom function evaluate type
def f[T](v: T) = v match {
case _: Int => println("Int")
case _: String => println("String")
case _ => println("Unknown")
}
// determine val type
f(x)
Yet another way to determine a type programmatically is using Manifest:
scala> def getType[T: Manifest](t: T): Manifest[T] = manifest[T]
getType: [T](t: T)(implicit evidence$1: Manifest[T])Manifest[T]
scala> val str = ("Scala", "Elixir","Spark")
str: (String, String, String) = (Scala,Elixir,Spark)
scala> getType(str)
res0: Manifest[(String, String, String)] = scala.Tuple3[java.lang.String, java.lang.String, java.lang.String]
The modern (meaning Scala 2.10 or later), Scala way of programmatically getting the compile time type of something is using a TypeTag.
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> def getType[T: TypeTag](value: T) = typeOf[T]
getType: [T](value: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type
scala> val str = ("Scala", "Elixir","Spark")
str: (String, String, String) = (Scala,Elixir,Spark)
scala> println(getType(str))
(java.lang.String, java.lang.String, java.lang.String)
scala> getType(str) <:< typeOf[(String,String,String)]
res1: Boolean = true
scala> getType((1,2,3)) <:< typeOf[(String,String,String)]
res2: Boolean = false
getClass will give your the erased runtime class. isInstanceOf[T] will test whether the erased runtime class is the same as or a subclass of the erased runtime class of T.
And "erased" means that the following evaluates to true.
(1,2,3).isInstanceOf[(String,String,String)]
"runtime" and "compile time" mean that this is true:
val a: Any = (1,2,3)
a.isInstanceOf[(_,_,_)]
while this is false:
val a: Any = (1,2,3)
getType(a) <:< typeOf[(Int,Int,Int)]
This method can help you get the type of any val/var at runtime, it's also works in compiled code.
import scala.reflect.runtime.universe._
def printType[T](x: T)(implicit tag: TypeTag[T]): Unit = println(tag.tpe.toString)
printType(List[Int](1,2,3)) // output: List[Int]
printType(("xxx", 123, 0.1)) // output: (String, Int, Double)
printType(2) // output: Int
I'm using a ConcurrentHashMap in Scala and I would like to use the computeIfAbsent() method but can't figure out the syntax for the second argument. Can someone show me what would be the proper syntax?
When running the following code
val data = new ConcurrentHashMap[String, LongAdder]
data.computeIfAbsent("bob", k: String => new LongAdder()).increment()
I'm getting the following error
Type mismatch, expected: Function[_ >: String, _ <: LongAdder], actual: (String) => Any
Thanking you in advance
Francis
The problem is that you're using java.util.concurrent.ConcurrentHashMap, which accepts java.util.function.Function as a parameter for computeIfAbsent() instead of scala.Function1 which you pass to it.
Since scala doesn't support lambda conversion for functional interfaces as Java does (at least not without the -Xexperimental flag), you can solve this by implementing a java.util.function.Function explicitly:
val data = new ConcurrentHashMap[String, LongAdder]
val adderSupplier = new java.util.function.Function[String, LongAdder]() {
override def apply(t: String): LongAdder = new LongAdder()
}
data.computeIfAbsent("bob", adderSupplier).increment()
Alternatively, if you need this more often, you may write a utility conversion function or even an implicit conversion:
object FunctionConverter {
implicit def scalaFunctionToJava[From, To](function: (From) => To): java.util.function.Function[From, To] = {
new java.util.function.Function[From, To] {
override def apply(input: From): To = function(input)
}
}
}
import FunctionConverter._
val data = new ConcurrentHashMap[String, LongAdder]()
data.computeIfAbsent("bob", (k: String) => new LongAdder()) // <- implicit conversion applied here
If you enable -Xexperimental flag you can use scala anonymous function notation for this:
scala> val data = new java.util.concurrent.ConcurrentHashMap[String, Int]
data: java.util.concurrent.ConcurrentHashMap[String,Int] = {}
scala> data.computeIfAbsent("bob", _.size)
res0: Int = 3
Note that you still can't pass regular scala Function
scala> val f: String => Int = _.size
f: String => Int = <function1>
scala> data.computeIfAbsent("bob", f)
<console>:13: error: type mismatch;
found : String => Int
required: java.util.function.Function[_ >: String, _ <: Int]
data.computeIfAbsent("bob", f)
^
But eta-expansion will work
scala> def a(s: String): Int = s.size
a: (s: String)Int
scala> data.computeIfAbsent("bob", a)
res3: Int = 3
I want to map a pair of options of String like the following
val pair: (Option[String], Option[String]) = (Some("a"), None)
val mapped: (String, String) = pair map {case (a:Option[String],b:Option[String]) => (a.getOrElse(""),b.getOrElse(""))}
but the output signature is different from what I expected
(Option[String],(String,String))
It seems that I'm missing something here... maybe scalaz or shapeless allows for such functionality of mapping tuples?
Simple change from map to match you'll get expected types.
scala> val pair: (Option[String], Option[String]) = (Some("a"), None)
pair: (Option[String], Option[String]) = (Some(a),None)
scala>
scala> val mapped: (String, String) = pair match {case (a:Option[String],b:Option[String]) => (a.getOrElse(""),b.getOrElse(""))}
mapped: (String, String) = (a,"")
scala>
scala> mapped
res8: (String, String) = (a,"")
In case if you specifically want to do things like that with shapeless, you should make some preparations.
First tell your compiler what you want to use in case of None:
class Default[T](val value: T)
implicit object defaultString extends Default[String]("")
Now create your function to map:
import shapeless._
object extract extends Poly1 {
implicit def withDefault[T](implicit default: Default[T]) =
at[Option[T]](_ getOrElse default.value)
}
Now use shapeless extension for tuples:
import syntax.std.tuple._
pair.map(extract) // res0: (String, String) = (a,)
Given a (data structure that operates like a) Map. Is there a type level way of inserting to it? That is:
val myMap: Map[Int, String] = Map(1 -> "a", 2 -> "b")
val x: Int = 5
val y: Int = 99
val myMap2 = myMap + (x -> "e")
What I'm hoping for is that myMap2 will have some type wherein I can safely do something like myMap2.retrieve(x) and have it compile and return "e". But myMap2.retrieve(y) should not even compile.
It's possible with Shapeless if your keys have different types:
import shapeless._
object _1
object _2
object _3
object _4
//-------------Map definition starts here----------------
class StaticMap1[K, V]
trait StaticMap1Like {
type M[T] <: StaticMap1[T, String]
private def add[T]: M[T] = (new StaticMap1[T, String] {}).asInstanceOf[M[T]]
implicit val __1 = add[_1.type] //add key to StaticMap1
implicit val __2 = add[_2.type] //add key to StaticMap1
}
object StaticMap1 extends StaticMap1Like
val hm = HMap[StaticMap1](_1 -> "a", _2 -> "b") //add values
//-------------Map definition ends here-----------------
scala> hm.get(_1)
res0: Option[String] = Some(a)
scala> hm.get(_2)
res1: Option[String] = Some(b)
scala> hm.get(_3) //compile-time error
<console>:18: error: could not find implicit value for parameter ev: BiMapIS[shapeless.nat._3,V]
hm.get(_3)
^
And key insertion:
//----Adding element _3 -> "c" starts here--------------
class StaticMap2[K, V] extends StaticMap1[K, V]
trait StaticMap2Like extends StaticMap1Like {
type M[T] <: StaticMap2[T, String]
private def add[T] = new StaticMap2[T, String] {}.asInstanceOf[M[T]]
implicit val __3 = add[_3.type] //add key to StaticMap2
}
object StaticMap2 extends StaticMap2Like
val hm2 = hm.asInstanceOf[HMap[StaticMap2]] + (_3 -> "c")
//----Adding element ends here---------------------------
scala> hm2.get(_3)
res6: Option[String] = Some(c)
scala> hm2.get(_2)
res7: Option[String] = Some(b)
scala> hm2.get(_1)
res8: Option[String] = Some(a)
scala> hm2.get(_4)
<console>:21: error: could not find implicit value for parameter ev: StaticMap2[_4.type,V]
hm2.get(_4)
^
scala> hm.get(_3) //old `hm` still working
<console>:17: error: could not find implicit value for parameter ev: StaticMap1[_3.type,V]
hm.get(_3)
^
But:
don't use Shapeless native nat here - it won't work as it can't distinguish nat._1 from nat._2 (at least for my version of Shapeless)
adding element to а Map also wouldn't be so convinient, as user is gonna have to add an implicit for every new key
Each time you use myMap2.get(y) you will get an Option of String for any y if it is an Int.
In case you try to use any other type, you will have a compilation exception.
e.g.: myMap2.get("y") will throw a type mismatch.
So you can't compile if the key type is not the right one.
Is it possible to get the type of a type field after creating an object ?
I would like to do something like this:
scala> class A { type T = String }
defined class A
scala> val a = new A
a: A = A#591171
scala> a.T
<console>:13: error: value T is not a member of A
a.T
^
The last
What do you want to do with the type? You can use a type projection in various ways with the class's type (without an instance):
scala> class A { type T = String }
defined class A
scala> val x: A#T = "test"
x: java.lang.String = test
scala> def f(b: A#T) = b
f: (a: java.lang.String)java.lang.String
Or if you enable -Ydependent-method-types, you can get the type member from the instance:
scala> val a = new A
a: A = A#6a3de2df
scala> val x: a.T = "test"
x: a.T = test
scala> def f(b: a.T) = b
f: (b: a.T)a.T
Scala's reflection API prior to 2.10 doesn't really model types in any clean way, so if you want to "get the type" in some other sense, you're probably out of luck.
One way is with reflection (since 2.10M4):
// with static types
scala> class A { type T = String }
defined class A
scala> import reflect.runtime.{universe => u}
import reflect.runtime.{universe=>u}
scala> val t = u.typeOf[A]
t: reflect.runtime.universe.Type = A
scala> val types = t.declarations.filter(_.isType)
types: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(type T)
scala> types.toList.head.typeSignature
res9: reflect.runtime.universe.Type = String
// with instances
scala> val a = new A
a: A = A#68d7c870
scala> import reflect.runtime.{currentMirror => m}
import reflect.runtime.{currentMirror=>m}
scala> m.reflect(a).symbol.asType // same type as t
res20: reflect.runtime.universe.Type = A