Varargs with different type parameters in scala - scala

I'm new to Scala...
Anyway, I want to do something like:
val bar = new Foo("a" -> List[Int](1), "b" -> List[String]("2"), ...)
bar("a") // gives List[Int] containing 1
bar("b") // gives List[String] containing "2"
The problem when I do:
class Foo(pairs: (String, List[_])*) {
def apply(name: String): List[_] = pairs.toMap(name)
}
pairs is gonna be Array[(String, List[Any]) (or something like that) and apply() is wrong anyway since List[_] is one type instead of "different types". Even if the varargs * returned a tuple I'm still not sure how I'd go about getting bar("a") to return a List[OriginalTypePassedIn]. So is there actually a way of doing this? Scala seems pretty flexible so it feels like there should be some advanced way of doing this.

No.
That's just the nature of static type systems: a method has a fixed return type. It cannot depend on the values of the method's parameters, because the parameters are not known at compile time. Suppose you have bar, which is an instance of Foo, and you don't know anything about how it was instantiated. You call bar("a"). You will get back an instance of the correct type, but since that type isn't determined until runtime, there's no way for a compiler to know it.
Scala does, however, give you a convenient syntax for subtyping Foo:
object bar extends Foo {
val a = List[Int](1)
val b = List[String]("2")
}

This can't be done. Consider this:
val key = readStringFromUser();
val value = bar(key);
what would be the type of value? It would depend on what the user has input. But types are static, they're determined and used at compile time.
So you'll either have to use a fixed number of arguments for which you know their types at compile time, or use a generic vararg and do type casts during runtime.

Related

How to use Type calculated in Scala Macro in a reify clause?

I've been working with Scala Macros and have the following code in the macro:
val fieldMemberType = fieldMember.typeSignatureIn(objectType) match {
case NullaryMethodType(tpe) => tpe
case _ => doesntCompile(s"$propertyName isn't a field, it must be another thing")
}
reify{
new TypeBuilder() {
type fieldType = fieldMemberType.type
}
}
As you can see, I've managed to get a c.universe.Type fieldMemberType. This represents the type of certain field in the object. Once I get that, I want to create a new TypeBuilder object in the reify. TypeBuilder is an abstract class with an abstract parameter. This abstract parameter is fieldType. I want this fieldType to be the type that I've found before.
Running the code shown here returns me a fieldMemberType not found. Is there any way that I can get the fieldMemberType to work inside the reify clause?
The problem is that the code you pass to reify is essentially going to be placed verbatim at the point where the macro is being expanded, and fieldMemberType isn't going to mean anything there.
In some cases you can use splice to sneak an expression that you have at macro-expansion time into the code you're reifying. For example, if we were trying to create an instance of this trait:
trait Foo { def i: Int }
And had this variable at macro-expansion time:
val myInt = 10
We could write the following:
reify { new Foo { def i = c.literal(myInt).splice } }
That's not going to work here, which means you're going to have to forget about nice little reify and write out the AST by hand. You'll find this happens a lot, unfortunately. My standard approach is to start a new REPL and type something like this:
import scala.reflect.runtime.universe._
trait TypeBuilder { type fieldType }
showRaw(reify(new TypeBuilder { type fieldType = String }))
This will spit out several lines of AST, which you can then cut and paste into your macro definition as a starting point. Then you fiddle with it, replacing things like this:
Ident(TypeBuilder)
With this:
Ident(newTypeName("TypeBuilder"))
And FINAL with Flag.FINAL, and so on. I wish the toString methods for the AST types corresponded more exactly to the code it takes to build them, but you'll pretty quickly get a sense of what you need to change. You'll end up with something like this:
c.Expr(
Block(
ClassDef(
Modifiers(Flag.FINAL),
anon,
Nil,
Template(
Ident(newTypeName("TypeBuilder")) :: Nil,
emptyValDef,
List(
constructor(c),
TypeDef(
Modifiers(),
newTypeName("fieldType"),
Nil,
TypeTree(fieldMemberType)
)
)
)
),
Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
)
)
Where anon is a type name you've created in advance for your anonymous class, and constructor is a convenience method I use to make this kind of thing a little less hideous (you can find its definition at the end of this complete working example).
Now if we wrap this expression up in something like this, we can write the following:
scala> TypeMemberExample.builderWithType[String]
res0: TypeBuilder{type fieldType = String} = $1$$1#fb3f1f3
So it works. We've taken a c.universe.Type (which I get here from the WeakTypeTag of the type parameter on builderWithType, but it will work in exactly the same way with any old Type) and used it to define the type member of our TypeBuilder trait.
There is a simpler approach than tree writing for your use case. Indeed I use it all the time to keep trees at bay, as it can be really difficult to program with trees. I prefer to compute types and use reify to generate the trees. This makes much more robust and "hygienic" macros and less compile time errors. IMO using trees must be a last resort, only for a few cases, such as tree transforms or generic programming for a family of types such as tuples.
The tip here is to define a function taking as type parameters, the types you want to use in the reify body, with a context bound on a WeakTypeTag. Then you call this function by passing explicitly the WeakTypeTags you can build from universe Types thanks to the context WeakTypeTag method.
So in your case, that would give the following.
val fieldMemberType: Type = fieldMember.typeSignatureIn(objectType) match {
case NullaryMethodType(tpe) => tpe
case _ => doesntCompile(s"$propertyName isn't a field, it must be another thing")
}
def genRes[T: WeakTypeTag] = reify{
new TypeBuilder() {
type fieldType = T
}
}
genRes(c.WeakTypeTag(fieldMemberType))

Scala - mapping a list of integers to a method that receives java.lang.Object

Working in Scala-IDE, I have a Java library, in which one of the methods receives java.lang.Object. And I want to map a list of Int values to it. The only solution that works is:
val listOfInts = groupOfObjects.map(_.getNeededInt)
for(int <- listOfInts) libraryObject.libraryMethod(int)
while the following one:
groupOfObjects.map(_.getNeededInt).map(libraryMethod(_)
and even
val listOfInts = groupOfObjects.map(_.getNeededInt)
val result = listOfInts.map(libraryObject.libraryMethod(_))
say
type mismatch; found : Int required: java.lang.Object Note: an
implicit exists from scala.Int => java.lang.Integer, but methods
inherited from Object are rendered ambiguous. This is to avoid a
blanket implicit which would convert any scala.Int to any AnyRef. You
may wish to use a type ascription: x: java.lang.Integer.
and something like
val result = listOfInts.map(libraryObject.libraryMethod(x => x.toInt))
or
val result = listOfInts.map(libraryObject.libraryMethod(_.toInt))
does not work also.
1) Why is it happening? As far as I know, the for and map routines do not differ that much!
2) Also: what means You may wish to use a type ascription: x: java.lang.Integer? How would I do that? I tried designating the type explicitly, like x: Int => x.toInt, but that is too erroneus. So what is the "type ascription"?
UPDATE:
The solution proposed by T.Grottker, adds to it. The error that I am getting with it is this:
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf[java.lang.Object])
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf{#null#}[java.lang.Object]{#null#}) {#null#}
and I'm like, OMG, it just grows! Who can explain what all these <null> things mean here? I just want to know the truth. (NOTE: I had to replace <> brakets with # because the SO engine cut out the whole thing then, so use your imagination to replace them back).
The type mismatch tells you exactly the problem: you can convert to java.lang.Integer but not to java.lang.Object. So tell it you want to ask for an Integer somewhere along the way. For example:
groupOfObjects.map(_.getNeededInt: java.lang.Integer).map(libraryObject.libraryMethod(_))
(The notation value: Type--when used outside of the declaration of a val or var or parameter method--means to view value as that type, if possible; value either needs to be a subclass of Type, or there needs to be an implicit conversion that can convert value into something of the appropriate type.)

What is the best way to create and pass around dictionaries containing multiple types in scala?

By dictionary I mean a lightweight map from names to values that can be used as the return value of a method.
Options that I'm aware of include making case classes, creating anon objects, and making maps from Strings -> Any.
Case classes require mental overhead to create (names), but are strongly typed.
Anon objects don't seem that well documented and it's unclear to me how to use them as arguments since there is no named type.
Maps from String -> Any require casting for retrieval.
Is there anything better?
Ideally these could be built from json and transformed back into it when appropriate.
I don't need static typing (though it would be nice, I can see how it would be impossible) - but I do want to avoid explicit casting.
Here's the fundamental problem with what you want:
def get(key: String): Option[T] = ...
val r = map.get("key")
The type of r will be defined from the return type of get -- so, what should that type be? From where could it be defined? If you make it a type parameter, then it's relatively easy:
import scala.collection.mutable.{Map => MMap}
val map: MMap[String, (Manifest[_], Any) = MMap.empty
def get[T : Manifest](key: String): Option[T] = map.get(key).filter(_._1 <:< manifest[T]).map(_._2.asInstanceOf[T])
def put[T : Manifest](key: String, obj: T) = map(key) = manifest[T] -> obj
Example:
scala> put("abc", 2)
scala> put("def", true)
scala> get[Boolean]("abc")
res2: Option[Boolean] = None
scala> get[Int]("abc")
res3: Option[Int] = Some(2)
The problem, of course, is that you have to tell the compiler what type you expect to be stored on the map under that key. Unfortunately, there is simply no way around that: the compiler cannot know what type will be stored under that key at compile time.
Any solution you take you'll end up with this same problem: somehow or other, you'll have to tell the compiler what type should be returned.
Now, this shouldn't be a burden in a Scala program. Take that r above... you'll then use that r for something, right? That something you are using it for will have methods appropriate to some type, and since you know what the methods are, then you must also know what the type of r must be.
If this isn't the case, then there's something fundamentally wrong with the code -- or, perhaps, you haven't progressed from wanting the map to knowing what you'll do with it.
So you want to parse json and turn it into objects that resemble the javascript objets described in the json input? If you want static typing, case classes are pretty much your only option and there are already libraries handling this, for example lift-json.
Another option is to use Scala 2.9's experimental support for dynamic typing. That will give you elegant syntax at the expense of type safety.
You can use approach I've seen in the casbah library, when you explicitly pass a type parameter into the get method and cast the actual value inside the get method. Here is a quick example:
case class MultiTypeDictionary(m: Map[String, Any]) {
def getAs[T <: Any](k: String)(implicit mf: Manifest[T]): T =
cast(m.get(k).getOrElse {throw new IllegalArgumentException})(mf)
private def cast[T <: Any : Manifest](a: Any): T =
a.asInstanceOf[T]
}
implicit def map2multiTypeDictionary(m: Map[String, Any]) =
MultiTypeDictionary(m)
val dict: MultiTypeDictionary = Map("1" -> 1, "2" -> 2.0, "3" -> "3")
val a: Int = dict.getAs("1")
val b: Int = dict.getAs("2") //ClassCastException
val b: Int = dict.getAs("4") //IllegalArgumetExcepton
You should note that there is no real compile-time checks, so you have to deal with all exceptions drawbacks.
UPD Working MultiTypeDictionary class
If you have only a limited number of types which can occur as values, you can use some kind of union type (a.k.a. disjoint type), having e.g. a Map[Foo, Bar | Baz | Buz | Blargh]. If you have only two possibilities, you can use Either[A,B], giving you a Map[Foo, Either[Bar, Baz]]. For three types you might cheat and use Map[Foo, Either[Bar, Either[Baz,Buz]]], but this syntax obviously doesn't scale well. If you have more types you can use things like...
http://cleverlytitled.blogspot.com/2009/03/disjoint-bounded-views-redux.html
http://svn.assembla.com/svn/metascala/src/metascala/OneOfs.scala
http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/

Scala type alias including companion object [beginner]

I'd like to write a type alias to shorten, nice and encapsulated Scala code.
Suppose I got some collection which has the property of being a list of maps, the value of which are tuples.
My type would write something like List[Map[Int, (String, String)]], or anything more generic as my application allows it. I could imagine having a supertype asking for a Seq[MapLike[Int, Any]] or whatever floats my boat, with concrete subclasses being more specific.
I'd then want to write an alias for this long type.
class ConcreteClass {
type DataType = List[Map[Int, (String, String)]]
...
}
I would then happily use ConcreteClass#DataType everywhere I can take one, and use it.
Now suppose I add a function
def foo(a : DataType) { ... }
And I want to call it from outside with an empty list.
I can call foo(List()), but when I want to change my underlying type to be another type of Seq, I'll have to come back and change this code too. Besides, it's not very explicit this empty list is intended as a DataType. And the companion object does not have the associated List methods, so I can't call DataType(), or DataType.empty. It's gonna be even more annoying when I need non-empty lists since I'll have to write out a significant part of this long type.
Is there any way I can ask Scala to understand my type as the same thing, including companion object with its creator methods, in the interest of shortening code and blackboxing it ?
Or, any reason why I should not be doing this in the first place ?
The answer was actually quite simple:
class ConcreteClass {
type DataType = List[String]
}
object ConcreteClass {
val DataType = List
}
val d = ConcreteClass.DataType.empty
This enables my code to call ConcreteClass.DataType to construct lists with all the methods in List and little effort.
Thanks a lot to Oleg for the insight. His answer is also best in case you want not to delegate to List any call to ConcreteClass.DataType, but control precisely what you want to allow callers to do.
What about this?
class ConcreteClass {
type DataType = List[String]
}
object DataType {
def apply(): ConcreteClass#DataType = Nil
}
//...
val a = DataType()

Spurious ambiguous reference error in Scala 2.7.7 compiler/interpreter?

Can anyone explain the compile error below? Interestingly, if I change the return type of the get() method to String, the code compiles just fine. Note that the thenReturn method has two overloads: a unary method and a varargs method that takes at least one argument. It seems to me that if the invocation is ambiguous here, then it would always be ambiguous.
More importantly, is there any way to resolve the ambiguity?
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
trait Thing {
def get(): java.lang.Object
}
new MockitoSugar {
val t = mock[Thing]
when(t.get()).thenReturn("a")
}
error: ambiguous reference to overloaded definition,
both method thenReturn in trait OngoingStubbing of type
java.lang.Object,java.lang.Object*)org.mockito.stubbing.OngoingStubbing[java.lang.Object]
and method thenReturn in trait OngoingStubbing of type
(java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object]
match argument types (java.lang.String)
when(t.get()).thenReturn("a")
Well, it is ambiguous. I suppose Java semantics allow for it, and it might merit a ticket asking for Java semantics to be applied in Scala.
The source of the ambiguitity is this: a vararg parameter may receive any number of arguments, including 0. So, when you write thenReturn("a"), do you mean to call the thenReturn which receives a single argument, or do you mean to call the thenReturn that receives one object plus a vararg, passing 0 arguments to the vararg?
Now, what this kind of thing happens, Scala tries to find which method is "more specific". Anyone interested in the details should look up that in Scala's specification, but here is the explanation of what happens in this particular case:
object t {
def f(x: AnyRef) = 1 // A
def f(x: AnyRef, xs: AnyRef*) = 2 // B
}
if you call f("foo"), both A and B
are applicable. Which one is more
specific?
it is possible to call B with parameters of type (AnyRef), so A is
as specific as B.
it is possible to call A with parameters of type (AnyRef,
Seq[AnyRef]) thanks to tuple
conversion, Tuple2[AnyRef,
Seq[AnyRef]] conforms to AnyRef. So
B is as specific as A. Since both are
as specific as the other, the
reference to f is ambiguous.
As to the "tuple conversion" thing, it is one of the most obscure syntactic sugars of Scala. If you make a call f(a, b), where a and b have types A and B, and there is no f accepting (A, B) but there is an f which accepts (Tuple2(A, B)), then the parameters (a, b) will be converted into a tuple.
For example:
scala> def f(t: Tuple2[Int, Int]) = t._1 + t._2
f: (t: (Int, Int))Int
scala> f(1,2)
res0: Int = 3
Now, there is no tuple conversion going on when thenReturn("a") is called. That is not the problem. The problem is that, given that tuple conversion is possible, neither version of thenReturn is more specific, because any parameter passed to one could be passed to the other as well.
In the specific case of Mockito, it's possible to use the alternate API methods designed for use with void methods:
doReturn("a").when(t).get()
Clunky, but it'll have to do, as Martin et al don't seem likely to compromise Scala in order to support Java's varargs.
Well, I figured out how to resolve the ambiguity (seems kind of obvious in retrospect):
when(t.get()).thenReturn("a", Array[Object](): _*)
As Andreas noted, if the ambiguous method requires a null reference rather than an empty array, you can use something like
v.overloadedMethod(arg0, null.asInstanceOf[Array[Object]]: _*)
to resolve the ambiguity.
If you look at the standard library APIs you'll see this issue handled like this:
def meth(t1: Thing): OtherThing = { ... }
def meth(t1: Thing, t2: Thing, ts: Thing*): OtherThing = { ... }
By doing this, no call (with at least one Thing parameter) is ambiguous without extra fluff like Array[Thing](): _*.
I had a similar problem using Oval (oval.sf.net) trying to call it's validate()-method.
Oval defines 2 validate() methods:
public List<ConstraintViolation> validate(final Object validatedObject)
public List<ConstraintViolation> validate(final Object validatedObject, final String... profiles)
Trying this from Scala:
validator.validate(value)
produces the following compiler-error:
both method validate in class Validator of type (x$1: Any,x$2: <repeated...>[java.lang.String])java.util.List[net.sf.oval.ConstraintViolation]
and method validate in class Validator of type (x$1: Any)java.util.List[net.sf.oval.ConstraintViolation]
match argument types (T)
var violations = validator.validate(entity);
Oval needs the varargs-parameter to be null, not an empty-array, so I finally got it to work with this:
validator.validate(value, null.asInstanceOf[Array[String]]: _*)