Given an example closure, which in this case returns the number of words in a string (with an additional arbitrary operator).
val myfunc = (s: String) => Option(s).map(_.split(" ").size).filter(_ >= 2)
Is there a way I can hide some of the boilerplate such that I can write:
val myfunc = given[String].map(_.split(" ").size).filter(_ >= 2)
If you can live with two parentheses and an underscore extra, you don't need macros for that:
class Given[A] {
def apply[B](f: Option[A] => B): A => B = (a: A) => f(Option(a))
}
def given[A] = new Given[A]
In action:
scala> val myfunc = given[String](_.map(_.split(" ").size).filter(_ >= 2))
myfunc: String => Option[Int] = <function1>
scala> List("salmon cod herring","tuna").map(myfunc)
res4: List[Option[Int]] = List(Some(3), None)
I doubt. A macro replaces the function call it is in with something that type checks. So, what would you replace given[String] with in your example? If you replaced it with (s: String) => Option(s), you'd get this:
((s: String) => Option(s)).map(_.split(" ").size).filter(_ >= 2)
Which doesn't work like you want. You want the whole line to be changed, which is not going to happen.
Related
Suppose I have 2 methods:
def a(s: String) = s + "..."
def b(s: String) = s + ",,,"
And I want to create 3rd method which will call both methods:
def c (s: String) = a(b(s))
How I can do it in idiomatic Scala way?
I think it's better to aggregate this functions into some List and then sequentially apply them:
List(a_, b_)
I think it's better to aggregate this functions into some List and
then sequentially apply them.
You get some help by specifying an expected type:
scala> val fs: List[String => String] = List(a,b)
fs: List[String => String] = List(<function1>, <function1>)
scala> fs.foldLeft("something")((s,f) => f(s))
res0: String = something...,,,
Here is how you can combine a set of functions into one:
// a() and b() are as defined in the question
// the following is equivalent to newfunc(x) = b(a(x))
val newFunc: String => String = List( a _, b _).reduce( _ andThen _ )
You can even create a generic function to combine them:
def functionChaining[A]( functions: A => A *): A => A = functions.reduce( _ andThen _ )
or using foldLeft:
def functionChaining[A]( functions: A => A *): A => A = functions.foldLeft( (x:A) => x )( _ andThen _ )
Here is an example of how to use this on the REPL:
scala> val newFunc: String => String = functionChaining( (x:String) => x + "---", (x:String) => x * 4)
scala> newFunc("|")
res12: String = |---|---|---|---
Many answers use andThen, but that will be give you
b(a(s))
Given that you want
a(b(s))
compose is the way to go (well, that or reversing the list, but what's the point?)
def c(s: String) = List[String => String](a, b).reduce(_ compose _)(s)
// or alternatively
def c(s: String) = List(a _, b _).reduce(_ compose _)(s)
As a result
c("foo") // foo,,,...
Now, speaking of what's idiomatic, I believe that
a(b(s))
is more idiomatic and readable than
List(a _, b _).reduce(_ compose _)(s)
This clearly depends on the number of functions you're composing. If you were to have
a(b(c(d(e(f(g(h(s))))))))
then
List[String => String](a, b, c, d, e, f, g, h).reduce(_ compose _)(s)
is probably neater and more idiomatic as well.
If you really think you need to do this:
val c = a _ andThen b
// (The signature is:)
val c:(String)=>String = a _ andThen b
or, more obviously:
def d(s:String) = a _ andThen b
If chained application is preferred then the below works. Caveats - Implicit syntax is a bit ugly; This being a structural type uses reflection.
object string {
implicit def aPimp(s: String) = new {
def a = "(a- " + s + " -a)"
}
implicit def bPimp(s: String) = new {
def b = "(b- " + s + " -b)"
}
}
scala> import string._
scala> "xyz".a.b
res0: String = (b- (a- xyz -a) -b)
scala> "xyz".b.a
res1: String = (a- (b- xyz -b) -a)
In my opinion, if not for the ugly syntax, this would be idiomatic scala.
I'm pretty sure what I'd like to do is probably not possible and not a good idea anyway. Nonetheless, here it is.
I would like to find a generic way of transforming any method on any class into a function that takes as arguments an instance of the class and the parameters of the method and calls the method on the instance with the specified parameters (which is basically how method calls work at a low-level: the object instance is a hidden parameter pushed by the compiler on the stack frame)
Example:
Given
class A { def foo(param1: Type1): TypeN }
I would like to have something like:
def functor[X](methodName: String): (obj: X, methodParams: Types*) => TypeN
Such that:
// Type (obj: A, param1: Type1) => TypeN
val fooFn = functor[A]("foo")
val res: TypeN = fooFn(new A, new Type1)
Which would allow something like:
def flip[A, B, C](fn: A => B => C): B => A => C = (b: B) => (a: A) => fn(a)(b)
// Type (param1: Type1) => (obj: A) => TypeN
val fooFl = flip(fooFn.curried)
List(new A, new A).map(fooFl(new Type1) _)
One example where something like that could be useful follows:
Imagine you have:
val divide = (i: Int) => Try(2/i).toOption
List(1, 0).map(i => divide(i).getOrElse(0))
but you'd like an arguably cleaner:
import OptionUtils.getOrElse
List(1, 0).map(getOrElse(0) _ compose divide)
Now, I've defined that getOrElse manually as:
object OptionUtils {
def getOrElse[A](default: A)(option: Option[A]) = option.getOrElse(default)
}
But would like to be able to do automatically define such a methods for all (or any given selection) of methods in a specified class. Ideally I'd have something like:
val optionUtils: Utils[Option] = Utils(Option, List("getOrElse", "or"))
optionUtils.getOrElse(None, 1) // = 1
optionUtils.getOrElseFl(1)(None) // = 1
Any suggestions/comments?
You can use Java relection for this (here is scala code)
Or Scala reflection:
import scala.reflect._, runtime.universe._
def functor[X: TypeTag: ClassTag, R](methodName: String)(obj: X) = {
val m = runtimeMirror(getClass.getClassLoader)
val method = typeTag[X].tpe.declaration(newTermName(methodName)).asMethod
val call = m.reflect(obj).reflectMethod(method)
(call.apply _) andThen (_.asInstanceOf[R])
}
scala> functor[Option[Int], Int]("get") _
res19: Option[Int] => (Seq[Any] => Int) = <function1>
scala> res19(Some(5))(Nil)
res20: Int = 5
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
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)
I want to find in some Iterable some elements that both conform to some given type, and validates a predicate taking that type as an argument.
I wrote this method using imperative-style programming, which seems to conform to my expectations. Is there some way to write this in a more "scalaesque" way?
def findMatch[T](it: Iterable[_], clazz: Class[T], pred: T => Boolean): Option[T] = {
val itr = it.iterator
var res: Option[T] = None
while (res.isEmpty && itr.hasNext) {
val e = itr.next()
if (clazz.isInstance(e) && pred(clazz.cast(e))) {
res = Some(clazz.cast(e))
}
}
res
}
You can use collect if you want to find and then map.
scala> val it: Iterable[Any] = List(1,2,3,"4")
it: Iterable[Any] = List(1, 2, 3, 4)
scala> it.view.collect{case s: String => s}.headOption
res1: Option[String] = Some(4)
You can work with an existantial type X forSome{typeX} rather than using _ as type parameter. This then would enable you to write it with the mentioned find method and use the map method on the Option type:
def findMatch[T](it: Iterable[X forSome {type X}], clazz: Class[T], pred: T => Boolean): Option[T] = {
it.find{ e => clazz.isInstance(e) && pred(clazz.cast(e))}.map{clazz.cast(_)}
}
If you divide your problem into subproblems a more idiomatic version is easy to find.
You want to
find all instances of T in your Iterable[Any]
cast them to T to make the compiler happy
find the first matching element
For the first point you can easily use the filter Method on Iterator. So you have
it.iterator.filter(x => clazz.isInstance(x))
which returns you an Iterator[Any] that contains only Ts. Now let's convince the compiler:
it.iterator.filter(x => clazz.isInstance(x)).map(x => x.asInstanceOf[T])
Okay, now you have an Iterator[T] - so you just need to find the first element fulfilling your predicate:
def findMatch[T](it: Iterable[Any], clazz: Class[T], pred: T => Boolean): Option[T] =
it.iterator.filter(x => clazz.isInstance(x))
.map(x => x.asInstanceOf[T])
.find(pred)
You can use Iterable's find method and pattern matching with a guard:
scala> val it: Iterable[Any] = List(1,2,3,"4")
it: Iterable[Any] = List(1, 2, 3, 4)
scala> it.find { _ match {
case s: String if s == "4" => true
case _ => false
}}.asInstanceOf[Option[String]]
res0: Option[String] = Some(4)
For an introduction to pattern matching have a look at:
http://programming-scala.labs.oreilly.com/ch03.html