Get anonymous/unnamed tuple-value by indirect index? - scala

Regard this
val oddOrEven = (odd, even)
oddOrEven._1 would give "odd", while oddOrEven._2 would give "even"
We basically get a tuple with "unnamed" members, if you will so.
But let's assume I wanted to get either odd or even, depending on some external data, like so:
val witness: Int = {numberOfPrevious % 2}
now, let's do this:
val one = oddOrEven._witness
This won't compile.
Is there some special syntax involved or is this simply not possible?
I got curious and wondered whether it was the compiler that could not deduce that the only possible values of witness would be 0 and 1 (but I thought that to be silly on my side, yet I had to try) and tried this:
val oddOrEven = (odd, even)
val witness: Int = {numberOfPrevs % 2}
val v = x match {
case 0 => oddOrEven._1
case 1 => oddOrEven._2
}
Yet again val one = oddOrEven._witness would not work
Then I dug deeper and found out that indeed the compiler would not check for exhaustion. Like:
val v = x match {
case 1 => oddOrEven._1
case 2 => oddOrEven._2
}
would still compile, although 2 was not possible and 0 was missing!
So, I know I am mixing things up here. I am aware that there are matches that are not what is called "exhausting" in my mothertongue, so the possible values are not deduced at compile-time, but at runtime (and indeed I would get a
scala.MatchError: 0 (of class java.lang.Integer)
at runtime.
But, what I'm really interested in: Can I get "unnamed" tuples by an "indirect index" like I mean to?

What about keep it simple, like this:
val oddOrEven = (odd, even)
val witness: Int = {numberOfPrevious % 2} // Or any other calculation of index
oddOrEven.productElement(witness)
You loose type safety while productElement returns Any, but when you know the type of members you can cast, like:
oddOrEven.productElement(witness).asInstanceOf[YourType]
I'm making assumption here that your odd and even values are of the same type, e.g:
sealed trait OddOrEven
case object odd extends OddOrEven
case object event extends OddOrEven
Then:
oddOrEven.productElement(witness).asInstanceOf[OddOrEven]
will give you correct type OddOrEven.
Btw. take a peek at ScalaDoc for Tuple2

You should probably not do that. If you need an index, think about a List or a Vector.
But if you really want this and all of your tuple items are of the same type (for example Int) you could do:
(even, odd).productIterator.collect { case x: Int => 2* x }.toList(0)

Well, you can do something like tuple.productIterator.toList(index-1), but if you want a list, it's probably a better idea to just use a list rather than converting a tuple to it.
And no, compiler doesn't try to figure out all possible ways your code can be executed in order to tell what possible values a variable could take.

Related

Why is a scala Set casted to a Vector instead of a List?

I wonder why a Set[A] is converted to a Vector[A] if I ask for a Seq[A] subclass? To illustrate this take the following example:
val A = Set("one", "two")
val B = Set("one", "two", "three")
def f(one: Seq[String], other : Seq[String]) = {
one.intersect(other) match {
case head :: tail => head
case _ => "unknown"
}
}
f(A.to, B.to)
This function will return "unknown" instead of one. The reason is that A.to will be casted to a Vector[String]. The cons operator (::) is not defined for Vectors but for Lists so the second case is applied and "unknown" is returned. To fix this problem I could use the +: operator which is defined for all Seqs or convert the Set to List (A.to[List]). So my (academic) question is:
Why does A.to returns a Vector. At least according to the scala docs the default implementation of Seq is LinearSeq and the default of this is List. What did I got wrong?
Because it can, you are depending on runtime class implementation details, instead of compile-time type information guarantees. The to or toSeq method is free to return anything that typechecks, it could even generate a random number and chose a concrete class in base of that number, so you may get a List something other times a Vector or whatever. It may even decide in base of the operating system. Of course, I am being pedantic here and hopefully, they do not do that, but my point is, we can't really explain, that is what the implementation does and it may change in the future.
Also, the "default implementation of Seq is a List", applies only in the constructor. And again, they may change that in any moment.
So, if you want a List ask for a List, not for a Seq.

Why does Scala sometimes ignore types that are clearly defined?

so here's the problem I keep running into various situations with Scala - it seemingly ignores the implied type, even when the situation is clear. Granted this could be my understanding I admit, but when it comes to underscore placeholders I keep running into trouble. For example below (this is fictional just to prove the point).The 2nd position of trait X has to be <:X[,] of some kind. There's no ambiguity here - so anywhere that scala sees this position, regardless of how weak it's coded - the contact is X and I should have access to functions like "doesX". Isn't that indisputable? No matter how poorly I deal with that position in the code, I must at least get X. Why does Scala constantly ignore this fact when you get deep into the type system? Any pointers would be appreciated, thank you!
object TestRun extends App {
trait X[T, Y<:X[_,_]] {
def doesX:Unit
def providesY:Y
}
class Test extends X[Int,Test]{
override def doesX: Unit = println("etc..")
def providesY:Test = new Test
}
val a:X[_,_] = new Test //yes I know I could define a better here, its just to demo. I shouldn't have to explicitly relabel the 2nd _ as _<:X[_,<:X[ etc..
val b = a.providesY //clearly this has to be at least a (something) WITH X, but scala claims this as "Any"
b.doesX //error won't compile!!
//trait
}
When you write:
val a: X[_, _] = new Test
^
// This is treated as if the type parameter is Any, for the most part
You are telling the compiler that a is an X, where you don't care what its type parameters are. That is, the unbounded wildcard _ is assumed to have an upper-bound of Any, and that's it.
providesY uses the second type parameter of X to determine its return type, but for a the compiler was told that to discard it. So b is just an Any. This is easier to see using the REPL:
scala> val a: X[_, _] = new Test
a: X[_, _] = Test#27abe2cd
scala> val b = a.providesY
b: Any = Test#f5f2bb7
Therefore, b.doesX fails to compile because the compiler now thinks it is Any. The simple solution is not to use wild cards for types (or any existential types in general, most of the time you do not want this).
scala> val a: X[Int, Test] = new Test
a: X[Int,Test] = Test#1134affc
scala> val b = a.providesY
b: Test = Test#6fc6f14e
scala> b.doesX
etc..
Or you could simply leave off the type annotation, and let the compiler infer the correct type.

Reference to anonymous value in Scala

I took up "99 Scala Problems", and I came across Problem 40 which is the Goldbach conjecture.
I came up with this solution which, actually, outputs all pairs of prime numbers whose sum is the given number:
def goldbach(n : Int) = {
val lprimes = listPrimesinRange(2 to n) // all primes less than n
lprimes.takeWhile(x=> x < (n-x)).filter(x=> lprimes.contains(n-x)).map(x=> (x,n-x))
}
Works perfectly, but is is not a one-liner. And this is because in the filter operation, we need to refer to the initial list of primes. Is there a way to write something like this:
def goldbach(n : Int) = {
listPrimesinRange(2 to n).takeWhile(x=> x < (n-x)).filter(x=> ???.contains(n-x)).map(x=> (x,n-x))
}
...where '???' will be replaced by an appropriate expression?
OK, I understand that asking for a 'name' for an anonymous value is self-contradicting. But, since I'm solving this problem just for fun, this is an opportunity to find out things about Scala internals; in this figurative one-liner approach, what was initially 'lPrimes' list will actually be internally represented. Do we have access to this internal representation? Or is it something we really should avoid?
No, I don't think this is possible. You could write your own extension method which would work like this:
implicit class RichAny[A](x: A) extends AnyVal {
def use(f: A => B) = f(x) // could have a better name
}
and use it as
listPrimesinRange(2 to n).takeWhile(x=> x < (n-x)).
use(primes => primes.filter(x => primes.contains(n-x))

A Map of Different Function Types in Scala

I have two functions with different type signatures, and I want to store them both in a Map:
val add = ((a: Int, b: Int) => a + b)
val odd = ((a: Int) => a % 2 == 0)
var funcs = Map[String, Any]("add" -> add, "odd" -> odd)
Then I want to access these functions at a later date, without having to know about their types. How would I do this? I can write:
funcs("add").asInstanceOf[(Int, Int) => Int](1, 2)
But that requires me to either
know ahead of time what the type of the function is
do some sort of pattern match that accounts for every possible type.
Is there some way I can find out the type of the object stored as Any and convert it to that type?
Although this certainly is not a good idea, if you really have to do it, you can do it using reflection.
Using PaulP's Invocation utility:
scala> val add: (Int, Int) => Int = _ + _
add: (Int, Int) => Int = <function2>
scala> val isOdd: Int => Boolean = _ % 2 != 0
isOdd: Int => Boolean = <function1>
scala> import Invocation._
import Invocation._
scala> val funcs = Map("add" -> add, "isOdd" -> isOdd)
funcs: scala.collection.immutable.Map[java.lang.String,ScalaObject] = Map(add -> <function2>, isOdd -> <function1>)
scala> funcs("add") o 'apply(3, 4)
res18: Any = 7
scala> funcs("isOdd") o 'apply(11)
res19: Any = true
Is there some way I can find out the type of the object stored as Any and convert it to that type?
This doesn't actually make sense. Lets suppose I could do it, and it looks like this:
val func = funcs(func_name).toAppropriateType
Now what?
func now holds a value of some unknown type. I can call it... but I don't know its signature, so what arguments do I pass it? And the type/signature is going to be different on every invocation (depending on what was pulled out of the map), so the code to call it is going to have to be different for every invocation; I need some way of having different code executed for each possibility of func... but that would be a pattern match! And it would have to account for every possible type, just as match on Any.
In fact, the magical toAppropriateType method, even if it could exist, gains me nothing on top of just using an Any. It's still the case that the only things I can do with func are things you can do with all values of every possible type (i.e. very little).
In general, when you take something out of a collection you have to handle it with code that is valid for anything that the type allows to be put into the collection. The only alternative is to use features such as asInstanceOf, which throws away the guarantees of the type system and puts the responsibility for ensuring that you don't use the wrong type on you; meaning you have to have some other way of knowing what type to expect, outside of the type system.
If you want to have a collection of functions with one of a pre-determined set of signatures then the best way is to construct a type that only allows those signatures, and allows you to tell the difference between them (such as Rex Kerr's suggestion of using Either). Switching to using Any as soon as you find you need to combine things of different types in a collection usually causes more problems than it solves.
You could store them in an Either:
val funcs = Map[String, Either[Int=>Boolean, (Int,Int)=>Int]](
"add" -> Right(add),
"odd" -> Left(odd)
)
Now you can pull them apart again, though pattern matching is finicky here (Right(f) will work, but don't try to put conditions on what f is). I suggest using fold, right, left (and isRight and isLeft if you really must), like so:
def doSomething(s: String) =
funcs(s).fold(
f => { f(4) }, // Left is Int=>Boolean
g => { g(3,5)==8 } // Right is (Int,Int)=>Int
)
Presumably you'd want some way to load appropriate arguments also instead of the dummy values I put in.
If you have many variants of functions, you can define your own either-like hierarchy except with more different cases, or you can nest Eithers.

Map from Class[T] to T without casting

I want to map from class tokens to instances along the lines of the following code:
trait Instances {
def put[T](key: Class[T], value: T)
def get[T](key: Class[T]): T
}
Can this be done without having to resolve to casts in the get method?
Update:
How could this be done for the more general case with some Foo[T] instead of Class[T]?
You can try retrieving the object from your map as an Any, then using your Class[T] to “cast reflectively”:
trait Instances {
private val map = collection.mutable.Map[Class[_], Any]()
def put[T](key: Class[T], value: T) { map += (key -> value) }
def get[T](key: Class[T]): T = key.cast(map(key))
}
With help of a friend of mine, we defined the map with keys as Manifest instead of Class which gives a better api when calling.
I didnt get your updated question about "general case with some Foo[T] instead of Class[T]". But this should work for the cases you specified.
object Instances {
private val map = collection.mutable.Map[Manifest[_], Any]()
def put[T: Manifest](value: T) = map += manifest[T] -> value
def get[T: Manifest]: T = map(manifest[T]).asInstanceOf[T]
def main (args: Array[String] ) {
put(1)
put("2")
println(get[Int])
println(get[String])
}
}
If you want to do this without any casting (even within get) then you will need to write a heterogeneous map. For reasons that should be obvious, this is tricky. :-) The easiest way would probably be to use a HList-like structure and build a find function. However, that's not trivial since you need to define some way of checking type equality for two arbitrary types.
I attempted to get a little tricky with tuples and existential types. However, Scala doesn't provide a unification mechanism (pattern matching doesn't work). Also, subtyping ties the whole thing in knots and basically eliminates any sort of safety it might have provided:
val xs: List[(Class[A], A) forSome { type A }] = List(
classOf[String] -> "foo", classOf[Int] -> 42)
val search = classOf[String]
val finalResult = xs collect { case (`search`, result) => result } headOption
In this example, finalResult will be of type Any. This is actually rightly so, since subtyping means that we don't really know anything about A. It's not why the compiler is choosing that type, but it is a correct choice. Take for example:
val xs: List[(Class[A], A) forSome { type A }] = List(classOf[Boolean] -> 'bippy)
This is totally legal! Subtyping means that A in this case will be chosen as Any. It's hardly what we want, but it is what you will get. Thus, in order to express this constraint without tracking all of the types individual (using a HMap), Scala would need to be able to express the constraint that a type is a specific type and nothing else. Unfortunately, Scala does not have this ability, and so we're basically stuck on the generic constraint front.
Update Actually, it's not legal. Just tried it and the compiler kicked it out. I think that only worked because Class is invariant in its type parameter. So, if Foo is a definite type that is invariant, you should be safe from this case. It still doesn't solve the unification problem, but at least it's sound. Unfortunately, type constructors are assumed to be in a magical super-position between co-, contra- and invariance, so if it's truly an arbitrary type Foo of kind * => *, then you're still sunk on the existential front.
In summary: it should be possible, but only if you fully encode Instances as a HMap. Personally, I would just cast inside get. Much simpler!