In Scala we have a by-name-parameters where we can write
def foo[T](f: => T):T = {
f // invokes f
}
// use as:
foo(println("hello"))
I now want to do the same with an array of methods, that is I want to use them as:
def foo[T](f:Array[ => T]):T = { // does not work
f(0) // invokes f(0) // does not work
}
foo(println("hi"), println("hello")) // does not work
Is there any way to do what I want? The best I have come up with is:
def foo[T](f:() => T *):T = {
f(0)() // invokes f(0)
}
// use as:
foo(() => println("hi"), () => println("hello"))
or
def foo[T](f:Array[() => T]):T = {
f(0)() // invokes f(0)
}
// use as:
foo(Array(() => println("hi"), () => println("hello")))
EDIT: The proposed SIP-24 is not very useful as pointed out by Seth Tisue in a comment to this answer.
An example where this will be problematic is the following code of a utility function trycatch:
type unitToT[T] = ()=>T
def trycatch[T](list:unitToT[T] *):T = list.size match {
case i if i > 1 =>
try list.head()
catch { case t:Any => trycatch(list.tail: _*) }
case 1 => list(0)()
case _ => throw new Exception("call list must be non-empty")
}
Here trycatch takes a list of methods of type ()=>T and applies each element successively until it succeeds or the end is reached.
Now suppose I have two methods:
def getYahooRate(currencyA:String, currencyB:String):Double = ???
and
def getGoogleRate(currencyA:String, currencyB:String):Double = ???
that convert one unit of currencyA to currencyB and output Double.
I use trycatch as:
val usdEuroRate = trycatch(() => getYahooRate("USD", "EUR"),
() => getGoogleRate("USD", "EUR"))
I would have preferred:
val usdEuroRate = trycatch(getYahooRate("USD", "EUR"),
getGoogleRate("USD", "EUR")) // does not work
In the example above, I would like getGoogleRate("USD", "EUR") to be invoked only if getYahooRate("USD", "EUR") throws an exception. This is not the intended behavior of SIP-24.
Here is a solution, although with a few restrictions compared to direct call-by-name:
import scala.util.control.NonFatal
object Main extends App {
implicit class Attempt[+A](f: => A) {
def apply(): A = f
}
def tryCatch[T](attempts: Attempt[T]*): T = attempts.toList match {
case a :: b :: rest =>
try a()
catch {
case NonFatal(e) =>
tryCatch(b :: rest: _*)
}
case a :: Nil =>
a()
case Nil => throw new Exception("call list must be non-empty")
}
def a = println("Hi")
def b: Unit = sys.error("one")
def c = println("bye")
tryCatch(a, b, c)
def d: Int = sys.error("two")
def e = { println("here"); 45 }
def f = println("not here")
val result = tryCatch(d, e, f)
println("Result is " + result)
}
The restrictions are:
Using a block as an argument won't work; only the last expression of the block will be wrapped in an Attempt.
If the expression is of type Nothing (e.g., if b and d weren't annotated), the conversion to Attempt is not inserted since Nothing is a subtype of every type, including Attempt. Presumably the same would apply for an expression of type Null.
As of Scala 2.11.7, the answer is no. However, there is SIP-24, so in some future version your f: => T* version may be possible.
Related
I'm new to Scala, and I'm running into this strange situation.
def bar[A, B](implicit foo: A => B): B = {
// do something
foo
}
And then I got error like
require B but found A => B
How should I get B form A => B
Here's the reason why I did this, I have two functions:
def funcA: String = {
def getStrA: String = "A"
// then there's the same operation in both functions
Try{ } match {
case Success(_) => getStrA
case Failure(_) => // exactlly same error handler in both function
}
}
def funcB: Int = {
def doSomething(x: Int): Int = {
// do something
x / 1
}
val x = 1
Try{ } match {
case Success(_) => doSomething(1)
case Failure(_) => // exactlly same error handler in both function
}
}
Here's what I want to achieve
def funcA: String = {
implicit def getStrA: String = "A"
bar
}
def funcB: Int = {
val x = 1
implicit def doSomething(x: Int): Int = {
// do something
x / 1
}
bar
}
def bar[A, B](implicit foo: A => B): B = {
Try{ } match {
case Success(_) => foo
case Failure(_) => // exactlly same error handler in both function
}
}
You have a conversion from A to B. You need to return B. The only way to do this is to pass A into the function. This signature has an implied assumption that you have some valid A value (most likely hardcoded) that you will always use here.
def bar[A, B](implicit foo: A => B): B = {
val a: A = ... // hmm...
foo(a)
}
Considering, that A is parametric, then you are either missing some information, or this A is impossible to create (it cannot be null because not all types can take null as a value), so you might need to throw exception in such case. Probably you are either missing some A provider or you should always fail this operation.
UPDATE:
There is no need for using implicits at all in your code:
def bar[B](f: onSuccess: A => B) =
Try{ some operations } match {
case Success(value) => onSuccess(value)
case Failure(_) => // error handler
}
def funcA = bar(_ => "A")
def funcB = bar(_ => 1)
I have an array of objects of type Either[A, B]. If I know for a particular element whether it is an A or a B, how do I call a method on it that only exists on one of the 2 types. For example:
import scala.util.Random
object EitherTest extends App {
def newObj(x: Int): Either[A,B] = {
if (x == 0)
Left(new A())
else
Right(new B())
}
val random = new Random()
val randomArray = (0 until 10).map(_ => random.nextInt(2))
val eitherArray = randomArray.map(newObj)
(0 until 10).foreach(x => randomArray(x) match {
case 0 => eitherArray(x).aMethod()
case 1 => eitherArray(x).bMethod()
case _ => println("Error!")
})
}
class A {
def aMethod() = println("A")
}
class B {
def bMethod() = println("B")
}
When I compile this code, the lines
case 0 => eitherArray(x).aMethod()
case 1 => eitherArray(x).bMethod()
both have the error "value aMethod is not a member of Either[A,B]". How can I solve this?
I don't know why fold doesn't get the respect it deserves. It can be so useful.
eitherArray.foreach(_.fold(_.aMethod(), _.bMethod()))
Well, you can do it if you exctract the logic to another method, and do some pattern matching over the value Either, then check if it is Right or Left, and that's it!
object HelloWorld {
import scala.util.Random
def main(args: Array[String]) {
val random = new Random()
val randomArray = (0 until 10).map(_ => random.nextInt(2))
val eitherArray = randomArray.map(EitherTest.newObj)
(0 until 10).foreach(x => randomArray(x) match {
case 0 => EitherTest.callmethod(eitherArray(x))
case 1 => EitherTest.callmethod(eitherArray(x))
case _ => println("Error!")
})
println("Hello, world!")
}
}
class EitherTest
object EitherTest {
def callmethod(ei : Either[A,B]) = {
ei match {
case Left(a) => a.aMethod()
case Right(b) => b.bMethod()
}
}
def newObj(x: Int): Either[A,B] = {
if (x == 0)
Left(new A())
else
Right(new B())
}
}
class A {
def aMethod() = println("A")
}
class B {
def bMethod() = println("B")
}
Will print for you, for one random example:
A
B
A
B
A
A
A
B
B
B
Hello, world!
Basically, the way you do with Either is projections: Either.left gives you the projection of the left type, and Either.right gives you that of the right.
The projections are somewhat similar to options, in that they can be empty (if your Either is a Right, then the left projection is empty and vice versa), and you can use the usual monadic transformations with them, like map, flatMap, foreach, getOrElse etc.
Your example, could look like this:
randomArray.foreach { either =>
either.left.foreach(_.aMethod)
either.right.foreach(_.bMethod)
}
You could also use pattern-matching instead, that's less general, but, perhaps looks a bit clearer in this case:
randomArray.foreach {
case Left(a) => a.aMethod
case Right(b) => b.bMethod
}
I want to get value from function that passed as parameter and returns Option[Int], after that if I have None throw an exception and in any other case return value
I tried to do like this:
def foo[T](f: T => Option[Int]) = {
def helper(x: T) = f(x)
val res = helper _
res match {
case None => throw new Exception()
case Some(z) => z
}
I call it like this:
val test = foo[String](myFunction(_))
test("Some string")
I have compilation error with mismatched types in match section (Some[A] passed - [T] => Option[Int] required)
As I understood res variable is reference to the function and I cannot match it with optional either call get\gerOrElse methods.
Moreover I probably just dont get how the underscore works and doing something really wrong, I'm using it here to pass a something as parameter to function f, can you explain me where I made a mistake?
helper is a method taking a T and returning an Option[Int].
res is a function T => Option[Int].
Difference between method and function in Scala
You can't match a function T => Option[Int] with None or Some(z).
You should have an Option[Int] (for example the function applied to some T) to make such matching.
Probably you would like to have
def foo[T](f: T => Option[Int]) = {
def helper(x: T) = f(x)
val res = helper _
(t: T) => res(t) match {
case None => throw new Exception()
case Some(z) => z
}
}
or just
def foo[T](f: T => Option[Int]): T => Int = {
t => f(t) match {
case None => throw new Exception()
case Some(z) => z
}
}
or
def foo[T](f: T => Option[Int]): T => Int =
t => f(t).getOrElse(throw new Exception())
I have this code that I use in a spray handler
get {
def callService = {
val p = Promise[Option[DocumentRef]]
val fut = p.future
archiveService.getByHash(ZeroHash, {
result => p success result
})
fut
}
onComplete(OnCompleteFutureMagnet(callService)){
case Success(docRef) => {
val doc = docRef map {
x => x.title
} getOrElse "nothing"
complete("Done with " + doc)
}
case Failure(ex) => complete("error ${ex.getMessage}")
}
}
so I had the bright idea of writing the following function to encapsulate the work done to create a future out of a promise:
def callback2Future[T](funToCall: (T => Unit) => Any): Future[T] = {
val p = Promise[T]
val resultFuture = p future
def callbacklistener(arg: T): Unit = {
arg: T => p success arg
}
funToCall(callbacklistener)
resultFuture
}
And restructure the onComplete as:
onComplete(OnCompleteFutureMagnet(callback2Future(archiveService.getByHash(ZeroHash, _: Option[DocumentRef] => Unit)))) {
case Success(docRef) => {
...
}
In the original implementation with callservice, it works great (with great throughput too), with the callback2Future implementation I get a forever wait and it eventually times out. They seem the same to me, can anyone spot the error?
I believe that your problem is due to the infamous auto-Unit feature of Scala. Your function:
def callbacklistener(arg: T): Unit = {
arg: T => p success arg
}
will probably be interpreted as:
def callbacklistener(arg: T): Unit = {
{ arg: T => p success arg }
()
}
What you really want is probably:
def callbacklistener(arg: T): Unit = p success arg
To be clear, in your implementation you are defining a function callbackListener with return type Unit; in the body of this function you have an expression, { arg: T => p success arg }, whose value is of type T => Unit and is discarded; the Scala compiler will then put a free () in your code as the return type of the callbackListener is supposed to be Unit.
Is there a shorter/better way to do the following :
mySeq.map { elmt =>
// do stuff
}
if (mySeq.isEmpty) {
// some other stuff
}
Ps : I'm using PlayFramework and this is meant to be used in templates, so if there are any "helpers" there I missed, I would be glad to discover those ;)
How about this?
mySeq.headOption.map { _ =>
mySeq.map { elmt =>
// do stuff
}
}.getOrElse {
// some other stuff
}
You can use match:
l match {
case l if !l.isEmpty => l.map{ // do stuff }
case _ => // some other stuff
}
For List:
l match {
case h :: t => l.map{ // do stuff }
case _ => // some other stuff
}
Alternatively you can define your own method:
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
class FoldEmpty[T, S[T] <: TraversableLike[T, S[T]]](l: S[T]){
def foldEmpty[B, That](notEmpty: T => B, empty: => That)(implicit cbf: CanBuildFrom[S[T], B, That]): That =
l match {
case t if !t.isEmpty => l map notEmpty
case _ => empty
}
}
implicit def seqToFoldEmpty[T, S[T] <: TraversableLike[T, S[T]]](l: S[T]) = new FoldEmpty(l)
Usage:
scala> IndexedSeq(1, 2, 3).foldEmpty( _ + 1 , IndexedSeq(-1))
res0: IndexedSeq[Int] = Vector(2, 3, 4)
scala> IndexedSeq[Int]().foldEmpty( _ + 1 , Seq(-1))
res1: Seq[Int] = List(-1)
I recently gisted a helper that generates some HTML only if the given sequence is non-empty. Put this slight variation in a file, e.g. Helpers.scala:
package views.html.helper
import play.api.templates.Html
object nonEmptyOrElse {
def apply[T <: Seq[_]](t: T)(nonEmptyBlock: (T) => Html)(emptyBlock: => Html) = {
if (t.nonEmpty) nonEmptyBlock(t) else emptyBlock
}
}
And use it like this in your template:
#nonEmptyOrElse(mySeq) { seq =>
//doSomething with entire seq
} {
// do something else
}
Edit: And here is the version the maps each element:
object mapOrElse {
def apply[T](t: Seq[T])(nonEmptyBlock: (T) => Html)(emptyBlock: => Html) = {
if (t.nonEmpty) t.map(nonEmptyBlock(_)) else emptyBlock
}
}
Having the following simple extension in scope:
(for Scala 2.10):
implicit class AnyExtensions[A] ( val x : A ) extends AnyVal {
def asSatisfying(p: A => Boolean): Option[A] =
if (p(x)) Some(x) else None
}
(for Scala 2.9):
implicit def anyExtensions[A] (x : A) = new {
def asSatisfying(p: A => Boolean): Option[A] =
if (p(x)) Some(x) else None
}
you'll be able to rewrite your code as follows:
mySeq
.asSatisfying{_.nonEmpty}
.map{
_.map{elmt =>
// do stuff
}
}
.getOrElse{
// some other stuff
}
In my practice this extension turned out to be applicable in a lot of cases and very useful. It excels in situations when you realize you need an if statement in a middle of an expression, which without this extension would have required you to introduce a temporary variable. Here's an example:
List(1, 2, 3).mkString(", ").asSatisfying{_.nonEmpty}.getOrElse("Empty list")
It will result in a String 1, 2, 3 and would have resulted in a String Empty list if the list was empty.
Here's a useful value class converts Seq[A] to None if the Seq.isEmpty, otherwise wraps it in a Some[Seq[A]].
for Scala 2.10:
/**
* A value type class to add some useful utility methods to Seq
*
* #param underlying The Seq to augment.
*/
implicit class SeqExt[+A](private val underlying: Seq[A]) extends AnyVal {
/** If this Seq is empty, returns None, otherwise builds a new collection by
* applying a function to all elements of this immutable sequence, and wraps
* the Seq in an Option.
*
* #tparam B The element type of the returned collection.
* #param f The function to apply to each element.
* #return If this Seq is empty, returns None, otherwise builds a new collection by
* applying a function to all elements of this immutable sequence, and wraps
* the Seq in an Option.
*/
def mapOption[B](f: (A) ⇒ B): Option[Seq[B]] = {
if(underlying.isEmpty) None else Some(underlying.map(f))
}
}
Usage (as in your example):
mySeq
.mapOption { elmt =>
// do stuff to each element if mySeq.nonEmpty
}
.getOrElse {
// some other stuff if mySeq.isEmpty
}