Using lazy evaluation functions in varargs - scala

What is wrong is the following method?
def someMethod(funcs: => Option[String]*) = {
...
}

That actually "works" under 2.7.7 if you add parens:
scala> def someMethod(funcs: => (Option[String]*)) = funcs
someMethod: (=> Option[String]*)Option[String]*
except it doesn't actually work at runtime:
scala> someMethod(Some("Fish"),None)
scala.MatchError: Some(Fish)
at scala.runtime.ScalaRunTime$.boxArray(ScalaRunTime.scala:136)
at .someMethod(<console>:4)
at .<init>(<console>:6)
at .<clinit>(<console>) ...
In 2.8 it refuses to let you specify X* as the output of any function or by-name parameter, even though you can specify it as an input (this is r21230, post-Beta 1):
scala> var f: (Option[Int]*) => Int = _
f: (Option[Int]*) => Int = null
scala> var f: (Option[Int]*) => (Option[Int]*) = _
<console>:1: error: no * parameter type allowed here
var f: (Option[Int]*) => (Option[Int]*) = _
But if you try to convert from a method, it works:
scala> def m(oi: Option[Int]*) = oi
m: (oi: Option[Int]*)Option[Int]*
scala> var f = (m _)
f: (Option[Int]*) => Option[Int]* = <function1>
scala> f(Some(1),None)
res0: Option[Int]* = WrappedArray(Some(1), None)
So it's not entirely consistent.
In any case, you can possibly achieve what you want by passing in an Array and then sending that array to something that takes repeated arguments:
scala> def aMethod(os: Option[String]*) { os.foreach(println) }
aMethod: (os: Option[String]*)Unit
scala> def someMethod(funcs: => Array[Option[String]]) { aMethod(funcs:_*) }
someMethod: (funcs: => Array[Option[String]])Unit
scala> someMethod(Array(Some("Hello"),Some("there"),None))
Some(Hello)
Some(there)
None
If you really want to (easily) pass a bunch of lazily evaluated arguments, then you need a little bit of infrastructure that as far as I know doesn't nicely exist in the library (this is code for 2.8; view it as inspiration for a similar strategy in 2.7):
class Lazy[+T](t: () => T, lt: Lazy[T]) {
val params: List[() => T] = (if (lt eq null) Nil else t :: lt.params)
def ~[S >: T](s: => S) = new Lazy[S](s _,this)
}
object Lz extends Lazy[Nothing](null,null) {
implicit def lazy2params[T : Manifest](lz: Lazy[T]) = lz.params.reverse.toArray
}
Now you can easily create a bunch of parameters that are lazily evaluated:
scala> import Lz._ // To get implicit def
import Lz._
scala> def lazyAdder(ff: Array[()=>Int]) = {
| println("I'm adding now!");
| (0 /: ff){(n,f) => n+f()}
| }
lazyAdder: (ff: Array[() => Int])Int
scala> def yelp = { println("You evaluated me!"); 5 }
yelp: Int
scala> val a = 3
a: Int = 3
scala> var b = 7
b: Int = 7
scala> lazyAdder( Lz ~ yelp ~ (a+b) )
I'm adding now!
You evaluated me!
res0: Int = 15
scala> val plist = Lz ~ yelp ~ (a+b)
plist: Lazy[Int] = Lazy#1ee1775
scala> b = 1
b: Int = 1
scala> lazyAdder(plist)
I'm adding now!
You evaluated me!
res1: Int = 9

Evidently repeated arguments are not available for by-name parameters.

Related

Extract Value from nested options

What is the most concise way to get 10 out of Some(Some(Some(Some(10))))?
without resorting to some external library like Scalaz.
import scala.language.higherKinds
case class Flattener[W[_], WW, T](fn : WW => W[T])
implicit def optionRecFlattenFn[WW, T](
implicit f : Flattener[Option, WW, T] = Flattener((ww: WW) => Option(ww))
) = Flattener((ww : Option[WW]) => ww.flatMap(f.fn))
def optionRecursiveFlatten[WW, T](www : Option[WW])(
implicit f : Flattener[Option, Option[WW], T]
) = f.fn(www)
val nestedOption = Option(Option(Option(Option(10))))
// Some(Some(Some(Some(10))))
val flatOption = optionRecursiveFlatten(nestedOption)
// Some(10)
val evenMoreNestedOption = Option(Option(Option(Option(Option(Option(10))))))
// Some(Some(Some(Some(Some(Some(10))))))
val flatOption2 = optionRecursiveFlatten(evenMoreNestedOption)
// Some(10)
In case you don't know the nesting level in advance, this will work for any level:
def unwrapRec(o: Option[Any]) : Any = o match {
case Some(inner # Some(_)) => unwrapRec(inner)
case Some(x) => x
case _ => ???
}
However, please note that an Any is returned. You can change it to whatever type you like and adapt the pattern match accordingly but I think you will have to pass in an Option[Any]. So it's not typesafe at this point.
You can use flatten on nested Option[Option[A]] repeatedly:
scala> val a = Some(Some(Some(Some(10))))
a: Some[Some[Some[Some[Int]]]] = Some(Some(Some(Some(10))))
scala> a.flatten.flatten.flatten.get
res0: Int = 10
I do not think there is any generic and type-safe way to extract A from T[A] := Option[T[A]] | A.
Edit: This method can dynamically get the contents, returns either the innermost value, or None:
def unwrap(x: Any): Any = x match {
case Some(v) => unwrap(v)
case v => v
}
scala> unwrap(Some(Some(Some(Some(10)))))
res1: Any = 10
scala> unwrap(Some(None))
res2: Any = None
It has unfortunately too broad type: Any => Any.

Apply a list of parameters to a list of functions

I have a list of parameters like List(1,2,3,"abc","c") and a set of functions which validates the data present in the list like isNumberEven, isAValidString etc.
Currently, I take each value of the list and apply proper function which validates the data like isNumberEven(params(0)). This has led to big and messy code which is completely imperative in thinking.
I am expecting that it should be possible to do something like this in Scala -
List(1,2,3,"abc","c").zip(List(fuctions)).foreach{ x => x._2(x._1)}
However, this fails giving a runtime exception of type mismatch:
error: type mismatch;
found : x._1.type (with underlying type Any)
required: Int with String
I tried pattern matching on Function traits but it fails due to type erasure.
Any pointers will be appreciated as how can this be solved.
Very naive and non extensible implementation, I'm not very good with types, surely there's a better way:
val c = List(1,2,3,"abc","c")
def isEven(x: Int) = if(x % 2 == 0) true else false
def isUpperCase(x: String) = if(x.head.isUpper) true else false
c.map {
case x: Int => isEven(x)
case x: String => isUpperCase(x)
case _ => false
}
You could also define list of functions:
scala> val c = List(1,2,3,"abc","c")
c: List[Any] = List(1, 2, 3, abc, c)
scala> def isEven(x: Int) = if(x % 2 == 0) true else false
isEven: (x: Int)Boolean
scala> def isOdd(x: Int) = !isEven(x)
isOdd: (x: Int)Boolean
scala> def isUpperCase(x: String) = if(x.head.isUpper) true else false
isUpperCase: (x: String)Boolean
scala> def someString(x: String) = true
someString: (x: String)Boolean
scala> val ints = List(isEven(_), isOdd(_))
ints: List[Int => Boolean] = List(<function1>, <function1>)
scala> val strings = List(isUpperCase(_), someString(_))
strings: List[String => Boolean] = List(<function1>, <function1>)
scala> c.map {
| case x: Int => ints.map(f => f(x)).exists(f => f(x))
| case x: String => strings.map(f => f(x)).forall(f => f(x))
| case _ => false
| }
res2: List[Boolean] = List(true, true, true, false, false)
I just want to present a different approach without matching, although it is certainly sledgehammer-like.
First all functions are converted to functions of type Any => Boolean.
It iterates over the values in c. For each element it tries to find a function that is applicable and that results in true. If it doesn't find one, false is yielded.
def isEven(i: Int) = i % 2 == 0
def isGreaterThanTwo(i: Int) = i > 2
def hasB(s: String) = s.exists(_ == 'b')
def convert[T](func: T => Boolean) = (a: Any) => func(a.asInstanceOf[T])
val functions = List(isEven _, isGreaterThanTwo _, hasB _)
val c = List(1,2,3,"abc","c")
val result = {
val convertedFunctions = functions.map(convert)
c.map(elem => convertedFunctions.exists(func => Try(func(elem)) getOrElse false))
}
with the result List(false, true, true, true, false).
The upside is that you can have as many functions as you like and it is therefore extensible. The downside is that you rely on exceptions. (which is usually not a good practice)
I first tried a solution with converting to PartialFunction and modifying the isDefined methods so it can be called on Any but then checks for a certain type. Then a lot of type-erasure happened and I couldn't make it work. Maybe that could be worth a shot.
If that is possible the code could be changed to:
def convert[T](func: T => Boolean) = new PartialFunction[Any, Boolean] {
def isDefinedAt(x : Any) = ??? //check if x is an instance of T, type erasure problem
def apply(x : Any) = func(x.asInstanceOf[T])
}
val result = {
val convertedFunctions = functions.map(convert)
c.map(elem => convertedFunctions.exists(func =>
func.isDefinedAt(elem) && func(elem)))
}
which looks pretty nice.
I'm not entirely certain on how you're planning on using the data afterwards, because 'foreach' would not actually return anything. But maybe this pattern-matched solution can help you achieve what you want?
scala> val f1 = (x:Int) => false
f1: Int => Boolean = <function1>
scala> val f2 = (x:String) => true
f2: String => Boolean = <function1>
scala> List(1,2,3,"abc","c").map {
case x:String => f2(x)
case x:Int => f1(x)
}
res3: List[Boolean] = List(false, false, false, true, true)

Conditional application of one of two functions to one argument

I have two functions that take one argument, a String. I was to apply either one or the other based on some condition. This is what I attempted:
def foo(s: String) = { ... }
def bar(s: String) = { ... }
(if (condition) foo else bar)("baz")
But I get an error like this:
<console>:10: error: missing arguments for method foo;
follow this method with `_' if you want to treat it as a partially applied function
(if (true) foo else bar)("baz")
^
I tried writing foo_ but of course I got error: not found: value foo_. What's the correct way to express this idiom in Scala?
You need a space between the method name and the underscore. This works fine:
def foo(s: String) = s + "-FOO"
def bar(s: String) = s + "-BAR"
val condition = true
(if (condition) foo _ else bar _)("baz")
// res0: String = baz-FOO
The underscore after the method name tells Scala that you want to want to pass the method as a higher-level function. From what I understand, this is a way to disambiguate whether you want to pass a method as a function or pass the result of a method with no arguments. For example:
def f = 1
val x = Some(f)
What should the type of x be? Will it be Some[Int] or Some[()=>Int]? It should default to the former, but if you want the latter you can use the underscore notation:
val y = Some(f _)
You have to deal with all this underscore nonsense because Scala methods aren't functions. If you declare foo and bar as functions rather than methods then your original code works as-is:
val foo = (s: String) => s + "-FOO"
val bar = (s: String) => s + "-BAR"
val condition = false
(if (condition) foo else bar)("baz")
// res1: String = baz-BAR
There are several things I want to mention:
def foo(s: String) = { ... }
def bar(s: String) = { ... }
foo and bar are not functions, there are just normal method. Also, def f = 3 is also a method not function.
(if (condition) foo else bar)("baz") obviously, this statement need foo and bar to be a function because of ("baz") argument.
as #wendao mentioned to use _ to change method to function. I think the simplest solution is to define foo and bar as a function.
def foo: String => String = { value =>
"Hi " + value
}
def bar: String => String = { value =>
"farewell " + value
}
val x: Some[String => String] = Some(foo)
(if (true) foo else bar)("John") // Hi John
It doesn't know that what you actually want to return a function, you'd have to tell it that what you want is a by-name parameter:
def foo(x : String) = x //> foo: (x: String)String
def bar(x : String) = x //> bar: (x: String)String
val condition = true //> condition : Boolean = true
val result : String => String = if (condition) foo else bar
//> result : String => String = <function1>
result("something") //> res0: String = something
This is a little more absurd:
scala> var b = true
b: Boolean = true
scala> def f(s: String) = s"f+$s"
f: (s: String)String
scala> def g(s: String) = s"g+$s"
g: (s: String)String
scala> import Function._ ; import PartialFunction._
import Function._
import PartialFunction._
scala> unlift(condOpt(_: String) { case s if b => f(s) }) applyOrElse ("hi", g)
res0: String = f+hi
scala> b = false
b: Boolean = false
scala> unlift(condOpt(_: String) { case s if b => f(s) }) applyOrElse ("hi", g)
res1: String = g+hi

Chaining Scalaz validation functions: Function1[A,Validation[E,B]]

I'm trying to write some code to make it easy to chain functions that return Scalaz Validation types. One method I am trying to write is analogous to Validation.flatMap (Short circuit that validation) which I will call andPipe. The other is analogous to |#| on ApplicativeBuilder (accumulating errors) except it only returns the final Success type, which I will call andPass
Suppose I have functions:
def allDigits: (String) => ValidationNEL[String, String]
def maxSizeOfTen: (String) => ValidationNEL[String, String]
def toInt: (String) => ValidationNEL[String, Int]
As an example, I would like to first pass the input String to both allDigits and maxSizeOf10. If there are failures, it should short circuit by not calling the toInt function and return either or both failures that occurred. If Successful, I would like to pass the Success value to the toInt function. From there, it would either Succeed with the output value being an Int, or it would fail returning only the validation failure from toInt.
def intInput: (String) => ValidationNEL[String,Int] = (allDigits andPass maxSizeOfTen) andPipe toInt
Is there a way to do this without my add-on implementation below?
Here is my Implementation:
trait ValidationFuncPimp[E,A,B] {
val f: (A) => Validation[E, B]
/** If this validation passes, pass to f2, otherwise fail without accumulating. */
def andPipe[C](f2: (B) => Validation[E,C]): (A) => Validation[E,C] = (a: A) => {
f(a) match {
case Success(x) => f2(x)
case Failure(x) => Failure(x)
}
}
/** Run this validation and the other validation, Success only if both are successful. Fail accumulating errors. */
def andPass[D](f2: (A) => Validation[E,D])(implicit S: Semigroup[E]): (A) => Validation[E,D] = (a:A) => {
(f(a), f2(a)) match {
case (Success(x), Success(y)) => Success(y)
case (Failure(x), Success(y)) => Failure(x)
case (Success(x), Failure(y)) => Failure(y)
case (Failure(x), Failure(y)) => Failure(S.append(x, y))
}
}
}
implicit def toValidationFuncPimp[E,A,B](valFunc : (A) => Validation[E,B]): ValidationFuncPimp[E,A,B] = {
new ValidationFuncPimp[E,A,B] {
val f = valFunc
}
}
I'm not claiming that this answer is necessarily any better than drstevens's, but it takes a slightly different approach and wouldn't fit in a comment there.
First for our validation methods (note that I've changed the type of toInt a bit, for reasons I'll explain below):
import scalaz._, Scalaz._
def allDigits: (String) => ValidationNEL[String, String] =
s => if (s.forall(_.isDigit)) s.successNel else "Not all digits".failNel
def maxSizeOfTen: (String) => ValidationNEL[String, String] =
s => if (s.size <= 10) s.successNel else "Too big".failNel
def toInt(s: String) = try(s.toInt.right) catch {
case _: NumberFormatException => NonEmptyList("Still not an integer").left
}
I'll define a type alias for the sake of convenience:
type ErrorsOr[+A] = NonEmptyList[String] \/ A
Now we've just got a couple of Kleisli arrows:
val validator = Kleisli[ErrorsOr, String, String](
allDigits.flatMap(x => maxSizeOfTen.map(x *> _)) andThen (_.disjunction)
)
val integerizer = Kleisli[ErrorsOr, String, Int](toInt)
Which we can compose:
val together = validator >>> integerizer
And use like this:
scala> together("aaa")
res0: ErrorsOr[Int] = -\/(NonEmptyList(Not all digits))
scala> together("12345678900")
res1: ErrorsOr[Int] = -\/(NonEmptyList(Too big))
scala> together("12345678900a")
res2: ErrorsOr[Int] = -\/(NonEmptyList(Not all digits, Too big))
scala> together("123456789")
res3: ErrorsOr[Int] = \/-(123456789)
Using flatMap on something that isn't monadic makes me a little uncomfortable, and combining our two ValidationNEL methods into a Kleisli arrow in the \/ monad—which also serves as an appropriate model for our string-to-integer conversion—feels a little cleaner to me.
This is relatively concise with little "added code". It is still sort of wonky though because it ignores the successful result of applying allDigits.
scala> val validated = for {
| x <- allDigits
| y <- maxSizeOfTen
| } yield x *> y
validated: String => scalaz.Validation[scalaz.NonEmptyList[String],String] = <function1>
scala> val validatedToInt = (str: String) => validated(str) flatMap(toInt)
validatedToInt: String => scalaz.Validation[scalaz.NonEmptyList[String],Int] = <function1>
scala> validatedToInt("10")
res25: scalaz.Validation[scalaz.NonEmptyList[String],Int] = Success(10)
Alternatively you could keep both of the outputs of allDigits and maxSizeOfTen.
val validated2 = for {
x <- allDigits
y <- maxSizeOfTen
} yield x <|*|> y
I'm curious if someone else could come up with a better way to combine these. It's not really composition...
val validatedToInt = (str: String) => validated2(str) flatMap(_ => toInt(str))
Both validated and validated2 accumulate failures as shown below:
scala> def allDigits: (String) => ValidationNEL[String, String] = _ => failure(NonEmptyList("All Digits Fail"))
allDigits: String => scalaz.Scalaz.ValidationNEL[String,String]
scala> def maxSizeOfTen: (String) => ValidationNEL[String, String] = _ => failure(NonEmptyList("max > 10"))
maxSizeOfTen: String => scalaz.Scalaz.ValidationNEL[String,String]
scala> val validated = for {
| x <- allDigits
| y <- maxSizeOfTen
| } yield x *> y
validated: String => scalaz.Validation[scalaz.NonEmptyList[String],String] = <function1>
scala> val validated2 = for {
| x <- allDigits
| y <- maxSizeOfTen
| } yield x <|*|> y
validated2: String => scalaz.Validation[scalaz.NonEmptyList[String],(String, String)] = <function1>
scala> validated("ten")
res1: scalaz.Validation[scalaz.NonEmptyList[String],String] = Failure(NonEmptyList(All Digits Fail, max > 10))
scala> validated2("ten")
res3: scalaz.Validation[scalaz.NonEmptyList[String],(String, String)] = Failure(NonEmptyList(All Digits Fail, max > 10))
Use ApplicativeBuilder with the first two, so that the errors accumulate,
then flatMap toInt, so toInt only gets called if the first two succeed.
val validInt: String => ValidationNEL[String, Int] =
for {
validStr <- (allDigits |#| maxSizeOfTen)((x,_) => x);
i <- toInt
} yield(i)

Why put a generic type next to a function?

When I look at Scala libraries I see code like this. Why put test [A] .
def test[A](block : Int => Unit) : Unit = {
block(10)
}
test { u =>
println(u)
}
This is just as valid I suppose. It runs the same way.
def test(block : Int => Unit) : Unit = {
block(10)
}
I've just been curious what the reasoning(or design pattern) is behind it. Thanks.
The type parameter A makes no sense here because it is not used.
def test[A](block: Int => A): A = block(10)
Here A specifies the return type.
When there a generic type next to the function, it means that the function is a generic function.
The following is a very simple example:
// generic functions which returns type of `A`
def test1[A](x: A) = x
def test2[A](x: => A) = { println("Hello"); x }
val x1 = test1(1)
// x1: Int = 1
val x2 = test1("Hello World")
// x2: java.lang.String = Hello World
val x3 = test2(123.4)
// Hello
// x3: Double = 123.4
val x4 = test2("Test2")
// Hello
// x4: java.lang.String = Test2
As you can see, the return type of test1 and test2 are determined by the type of their arguments.
The following is another use case.
// We could implement `map` function ourself.
// We don't care about what type of List contains,
// so we make it a generic function.
def map[A, B](xs: List[A], f: A => B): List[B] = {
var result: List[B] = Nil
for (i <- xs) {
result ++= List(f(i))
}
result
}
// Now use can map any type of List to another List.
map(List("1", "2", "3"), (x: String) => x.toInt)
//res1: List[Int] = List(1, 2, 3)