I have Future[MyType] and I need to pass the value of MyType to a method which returns Seq[Future[MyType]], so basic signature of problem is:
val a: Seq[Future[MyType]] = ...
getValue(t: MyType): Seq[Future[MyType]] = {...}
I want to pass value of a to getValue. I tried something like:
val b:Seq[Future[MyType]] = a.map{v => getValue(v)}
I want b to be of Seq[Future[MyType]] type
but, it obviously didn't worked as v is of type Future[MyType] and getValue needs only MyType as parameter. What could be a possible solution??
You can do:
val b = a.map(_.map(getValue(_)))
This will give you a Seq[Future[Seq[Future[MyType]]]]. That's pretty ugly. There are three tools that can make that better.
Future.sequence takes a Seq[Future[A]] and gives you a Future[Seq[A]]. The output future will wait for all input futures to complete before giving a result. This might not always be what you want.
fut.flatMap takes a function computing a Future as a result but does not return a nested Future, as would happen with .map.
You can call .flatten on a Seq[Seq[A]] to get a Seq[A]
Putting this all together, you could do something like:
val b: Seq[Future[Seq[MyType]] = a.map(_.flatMap(x => Future.sequence(getValue(x))))
val c: Future[Seq[MyType]] = Future.sequence(b).map(_.flatten)
More generally, when dealing with "container" types, you'll use some combination of map and flatMap to get at the inner types and pass them around. And common containers often have ways to flatten or swap orders, e.g. A[A[X]] => A[X] or A[B[X]] => B[A[X]].
Related
I am trying to define a higher order function f which accepts a variable number of parameters args of type Wrapper[T]* and a function parameter g in Scala.
The function f should decapsulate each object passed in args and then call g with the decapsulated parameters. Therefore, g has to accept exactly the same number of parameters of type T as args contains.
The closest thing I could achieve was to pass a Seq[T] to g and to use pattern matching inside of g. Like the following:
f("This", "Is", "An", "Example")(x => x match {
case Seq(a:String, b:String, c:String): //Do something.
})
With f defined like:
def f[V](args: Wrapper[T]*)
(g: (Seq[T]) => (V)) : V = {
val params = args.map(x => x.unwrap())
g(params)
}
How is it possible to accomplish a thing like this without pattern
matching?
It is possible to omit the types in the signature of g
by using type inference, but only if the number of parameters is
fixed. How could this be done in this case?
It is possible to pass
different types of parameters into varargs, if a type wildcard is
used args: Wrapper[_]*. Additionally, casting the result of
x.unwrap to AnyRef and using pattern matching in g is
necessary. This, however, completely breaks type inference and type
safety. Is there a better way to make mixing types in the varargs
possible in this special case?
I am also considering the use of scala makros to accomplish these tasks.
Did I get you right? I replaced your Wrapper with some known type, but that doesn't seem to be essential.
def f[T, V](args: T*)(g: PartialFunction[Seq[T], V]): V = g(args)
So later you can do this:
f(1,2,3) { case Seq(a,b,c) => c } // Int = 3
Okay, I've made my own Wrapper to be totally clear:
case class Wrapper[T](val x:T) {
def unwrap = x
}
def f[V](args: Wrapper[_]*)(g: PartialFunction[Seq[_], V]): V =
g(args.map(_.unwrap))
f(Wrapper("1"), Wrapper(1), Wrapper(BigInt(1))) {
case Seq(s: String, i: Int, b: BigInt) => (s, i, b)
} // res3: (String, Int, BigInt) = (1,1,1)
Regarding your concerns about type safety and conversions: as you can see, there aren't any explicit conversions in the code above, and since you are going to pattern-match with explicitly defined types, you may not to worry about these things - if some items of an undefined origin are going to show in your input, scala.MatchError will be thrown.
My code heavily uses Akka and untyped actors.
An example of typical logic is as follows:
val myFuture: Future[Any] = akka.pattern.AskSupport.ask(myActorRef, myMessage)
val completedLogic: Future[Unit] = myFuture.map(myFunction)
myFunction then contains a strongly typed signature as follows:
def myFunction(): (Option[MyStronglyTypedClass]) => Unit = {
(myOption: Option[MyStronglyTypedClass]) => myOption foreach (myObject => // do some logic
}
I know that myFuture will always contain an instance of MyStronglyTypedClass or null for this particular actor. I will also know this for other actor/future/function combinations.
My problem comes when I look to create an implicit conversion from the Future[Any] to the Option[MyStronglyTypedClass] or Option[MyOtherStronglyTypedClass]
The implicit conversion will just do a null check and one other piece of logic before creating the Option
How do I go about performing this implicit conversion from Any to a subtype, or is it even possible?
You should, instead, convert to Future[Option[MyStronglyTypedClass]]:
def asMyStronglyTypedClass(x: Any): Option[MyStronglyTypedClass] = x match {
case null => None
case ...
}
// this will fail if myFuture fails or asMyStronglyTypedClass throws
val typedFuture = myFuture.map(asMyStronglyTypedClass)
and do what you want with this future. E.g.
typedFuture.onSuccess(myFunction)
EDIT: I missed you already have a map. In this case the issue is that you don't need to convert Future[Any] to Option, but its result (i.e. Any). You can write e.g. myFuture.map(asMyStronglyTypedClass).map(myFunction) or myFuture.map(x => myFunction(asMyStronglyTypedClass(x))). You could also make asMyStronglyTypedClass implicit and write myFuture.map(x => myFunction(x)). I still think it isn't a good idea, as it could get applied somewhere you don't expect.
If you really want to write myFuture.map(myFunction), you'll need a different implicit conversion to make the compiler understand:
implicit def contraMap(f: Option[MyStronglyTypedClass] => Unit): Any => Unit =
x => f(asMyStronglyTypedClass(x))
Of course, these can be made generic over your types, as mentioned in the comments.
Impliciy converting from Any to something else is something that you should never do because it effectively switches off Scala's type system. Converting the type of a future in a safe fashion can be done using
myFuture.mapTo[Option[MyStronglyTypedClass]]
I have a series of validation functions that returns an Option[Problem], if any, or None if no validation problems are found.
I would like to write a simple function that calls each validation function, stop and return the first not-None result.
Naturally I can write this method in the "java-style", but I would like to know if a better approach exists.
EDIT
This was the original Java solution:
validate01(arg);
validate02(arg);
validate03(arg);
...
Each method throws an exception in case of problem. I would stay away from the exceptions while I'm writing Scala.
As an example, let's say we want to validate a String. Our validation function takes a String and a list of validators, which are functions from String to Option[Problem]. We can implement it in a functional manner like this:
def firstProblem(validators: List[String => Option[Problem]], s:String) =
validators.view.flatMap(_(s)).headOption
This creates a new list by applying each validation function to the string and keeping the result only if it is a Some. We then take the first element of this List. Because of the call to view, the list will be computed only as needed. So as soon as the first Problem is found, no further validators will be called.
If you have finite and known at compile time number of validations you may use .orElse on Options:
def foo(x: Int): Option[Problem] = ...
def bar(x: Int): Option[Problem] = ...
...
def baz(x: Int): Option[Problem] = ...
foo(1) orElse bar(2) orElse .. baz(n)
Maybe you want--assuming the validation functions take no arguments
def firstProblem(fs: (() => Option[Problem])*) = {
fs.iterator.map(f => f()).find(_.isDefined).flatten
}
You'll get an existing Option[Problem] if there are any, or None if they all succeed. If you need to pass arguments to the functions, then you need to explain what those arguments are. For example, you could
def firstProblem[A](a: A)(fs: (A => Option[Problem])*) = /* TODO */
if you can pass the same argument to all of them. You would use it like this:
firstProblem(myData)(
validatorA,
validatorB,
validatorC,
validatorD
)
How to pass a tuple argument the best way ?
Example:
def foo(...): (Int, Int) = ...
def bar(a: Int, b: Int) = ...
Now I would like to pass the output of foo to bar. This can be achieved with:
val fooResult = foo(...)
bar(fooResult._1, fooResult._2)
This approach looks a bit ugly, especially when we deal with a n-tuple with n > 2. Also we have to store the result of foo in an extra value, because otherwise foo has to be executed more than once using bar(foo._1, foo._2).
Is there a better way to pass through the tuple as argument ?
There is a special tupled method available for every function:
val bar2 = (bar _).tupled // or Function.tupled(bar _)
bar2 takes a tuple of (Int, Int) (same as bar arguments). Now you can say:
bar2(foo())
If your methods were actually functions (notice the val keyword) the syntax is much more pleasant:
val bar = (a: Int, b: Int) => //...
bar.tupled(foo())
See also
How to apply a function to a tuple?
It is worth also knowing about
foo(...) match { case (a,b) => bar(a,b) }
as an alternative that doesn't require you to explicitly create a temporary fooResult. It's a good compromise when speed and lack of clutter are both important. You can create a function with bar _ and then convert it to take a single tuple argument with .tupled, but this creates a two new function objects each time you call the pair; you could store the result, but that could clutter your code unnecessarily.
For everyday use (i.e. this is not the performance-limiting part of your code), you can just
(bar _).tupled(foo(...))
in line. Sure, you create two extra function objects, but you most likely just created the tuple also, so you don't care that much, right?
Using tupled, as #Tomasz mentions, is a good approach.
You could also extract the tuple returned from foo during assignment:
val (x, y) = foo(5)
bar(x, y)
This has the benefit of cleaner code (no _1 and _2), and lets you assign descriptive names for x and y, making your code easier to read.
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/