I have something that looks like this:
def a(b:String)(implicit c:String = "") = {println(b); b}
a("1")(a("2")(a("3")))
which prints
3
2
1
How can I get scala to print out this instead?
1
2
3
Laziness is always the way to go to invoke code not before it is used. In your example, though, you are not using c at all, which would mean that when it is lazy it would never be invoked at all.
Changing this a little bit would result in:
scala> def a(b: String)(c: => String = "") = {println(b); c; b}
a: (b: String)(c: => String)String
scala> a("1")(a("2")(a("3")()))
1
2
3
res15: String = 1
Here, c is declared as call-by-name, which results in the lazy behavior. However implicit parameters can't be call-by-name, thus we have to use a more heavyweight approach:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> def a(b: String)(implicit c: () => String = () => "") = {println(b); c(); b}
a: (b: String)(implicit c: () => String)String
scala> implicit def conv(s: => String) = () => s
conv: (s: => String)() => String
scala> a("1")(a("2")(a("3")))
1
2
3
res0: String = 1
Now, the laziness is even more explicit but we need an implicit conversion to allow your original syntax.
In summary you can't just toggle the evaluating order of your function arguments, you have to understand laziness to benefit from it. Nevertheless laziness comes with syntactic overhead (at least in Scala, in Haskell for example it would already be built-in into the language), therefore it leads to a different design of your code.
Related
I am new to Scala (Functional Programming). I am reading the book 'Functional Programming in Scala'. It was an exercise in which we need to define a partially applied function
def partial1 [A, B, C] (a: A, f: (A, B) => C): B => C = {
(b: B) => f(a, b)
}
I was wondering what is a real world use of this function? I tried to read different blogs to find an example, but couldn't find a useful example.
(Relevant to your question before you edited it) Let's start with terminology. PartialFunction is trait in scala that says that your function might not process all possible variations of the input:
val partialFunction: PartialFunction[Int, Int] = {
case 1 => 1
case 2 => 2
}
scala> partialFunction(1)
res43: Int = 1
scala> partialFunction(3)
scala.MatchError: 3 (of class java.lang.Integer)
It's completely unrelated to your example, which is a partial application - the article provided basically shows real-world example with email filtering.
About partial application.
Sometimes you might have a function with several parameters, let's say:
def sendMail(recipient: String, subject: String, body: String) = println(s"To: $recipient\n Subj: $subject\n Body: $body")
This function might be a part of the API, so you might not be able to change it. Now, let's say you need to send a same email to many different recipients:
object Spam{
val subject = "Hello!"
val body = "World!"
def spam(recipient: String) = sendMail(recipient, subject, body)
}
scala> Spam.spam("aaa#aa")
To: aaa#aa
Subj: Hello!
Body: World!
Another way to do that is to generate a function per subject/body, so to make it customizable:
def spammer(subject: String, body: String): String => Unit = (recipient: String) => {
sendMail(recipient, subject, body)
}
val spam1 = spammer("Hello", "World!")
spam1("emai#email.com")
It's roughly equivalent to OOP's:
class Spammer(subject: String, body: String){
def apply(recipient: String) = sendMail(recipient, subject, body)
}
val spam1 = new Spammer("Hello", "World!")
spam1("emai#email.com")
The difference is that partial application is able to deal more easily with complex cases and also has additional syntax sugar:
val spam1 = sendMail(_, "Hello", "World!")
spam1("emai#email.com")
So in simple cases you don't even need to define your own wrapper.
Returning to your more sophisticated example, you could use it this way:
scala> val incrementInt = partial1[Int, Int, Int](1, _ + _)
incrementInt: Int => Int = $$Lambda$1258/21635151#18ca65ea
scala> incrementInt(2)
res47: Int = 3
scala> val incrementList = partial1[List[Int], List[Int], List[Int]](List(0), _ ++ _)
incrementList: List[Int] => List[Int] = $$Lambda$1258/21635151#79f8af90
scala> incrementList(List(0))
res49: List[Int] = List(0, 0)
scala> incrementList(List(0, 0))
res50: List[Int] = List(0, 0, 0)
Basically abstract over addition (A, B) = C of some fixed abstract element A to unknown element B. In the example above it's addition over integers, and addition over lists of zeros. You can imagine more practical example like merging two json's with some fixed pattern and so on.
You might think of partail1 as providing a unified interface to all those cases.
I have a function in a context, (in a Maybe / Option) and I want to pass it a value and get back the return value, directly out of the context.
Let's take an example in Scala :
scala> Some((x:Int) => x * x)
res0: Some[Int => Int] = Some(<function1>)
Of course, I can do
res0.map(_(5))
to execute the function, but the result is wrapped in the context.
Ok, I could do :
res0.map(_(5)).getOrElse(...)
but I'm copy/pasting this everywhere in my code (I have a lot of functions wrapped in Option, or worst, in Either...).
I need a better form, something like :
res0.applyOrElse(5, ...)
Does this concept of 'applying a function in a concept to a value and immediatly returning the result out of the context' exists in FP with a specific name (I'm lost in all those Functor, Monad and Applicatives...) ?
You can use andThen to move the default from the place where you call the function to the place where you define it:
val foo: String => Option[Int] = s => Some(s.size)
val bar: String => Int = foo.andThen(_.getOrElse(100))
This only works for Function1, but if you want a more generic version, Scalaz provides functor instances for FunctionN:
import scalaz._, Scalaz._
val foo: (String, Int) => Option[Int] = (s, i) => Some(s.size + i)
val bar: (String, Int) => Int = foo.map(_.getOrElse(100))
This also works for Function1—just replace andThen above with map.
More generally, as I mention above, this looks a little like unliftId on Kleisli, which takes a wrapped function A => F[B] and collapses the F using a comonad instance for F. If you wanted something that worked generically for Option, Either[E, ?], etc., you could write something similar that would take a Optional instance for F and a default value.
You could write something like applyOrElse using Option.fold.
fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B
val squared = Some((x:Int) => x * x)
squared.fold {
// or else = ifEmpty
math.pow(5, 2).toInt
}{
// execute function
_(5)
}
Using Travis Browns recent answer on another question, I was able to puzzle together the following applyOrElse function. It depends on Shapeless and you need to pass the arguments as an HList so it might not be exactly what you want.
def applyOrElse[F, I <: HList, O](
optionFun: Option[F],
input: I,
orElse: => O
)(implicit
ftp: FnToProduct.Aux[F, I => O]
): O = optionFun.fold(orElse)(f => ftp(f)(input))
Which can be used as :
val squared = Some((x:Int) => x * x)
applyOrElse(squared, 2 :: HNil, 10)
// res0: Int = 4
applyOrElse(None, 2 :: HNil, 10)
// res1: Int = 10
val concat = Some((a: String, b: String) => s"$a $b")
applyOrElse(concat, "hello" :: "world" :: HNil, "not" + "executed")
// res2: String = hello world
The getOrElse is most logical way to do it. In regards to copy/pasting it all over the place - you might not be dividing your logic up on the best way. Generally, you want to defer resolving your Options (or Futures/etc) in your code until the point you need to have it unwrapped. In this case, it seems more sensible that your function takes in an an Int and returns an Int, and you map your option where you need the result of that function.
I have a case class Foo which has a field baz: Option[List[Bar]].
Also, I have a function - def f(baz: List[Bar])
I need to pass the List[Bar] to f().
What would be the best way to do this?
Option is great because it forces you to come to grips when there is no item. In the case of a List, Option may be overkill as there already exists a corresponding empty, i.e. they are both Monads:
f(myOptList getOrElse Nil)
wherein I'd say you should probably only have a List ever. Otherwise you deal with a trinary case: Something that is empty, something that has items and empty.
case class Baz(b: Int)
case class Foo(bazs: Option[List[Baz]])
val foo = Foo(Option(List(Baz(1), Baz(2))))
foo.bazs.map(list => f(list))
Option is a monad, if it's a Some the map will we applied to it, else if it's a None nothing will happen, from the REPL:
scala> def f(b: List[Baz]) = b.foreach(println)
f: (b: List[Baz])Unit
scala> foo.bazs.map(list => f(list))
Baz(1)
Baz(2)
res1: Option[Unit] = Some(())
scala> val foo = Foo(None)
foo: Foo = Foo(None)
scala> foo.bazs.map(list => f(list))
res2: Option[Unit] = None
I've got a class with a collections of Foos we'll call Bar. Foo has a number of number-returning methods that we want to aggregate at the Bar level, like so:
def attribute1(inputs: Map[Int, Double]) =
foos.foldLeft(0d)((sum, foo) => sum + foo.attribute1(inputs(foo.id)))
To aggregate these various attributes, I can have n functions of the form
def attributeN(inputs: Map[Int, Double]) =
foos.foldLeft(0d)((sum, foo) => sum + foo.attributeN(inputs(foo.id)))
However, that's ugly - I hate the fact that the iteration and summation are repeated. I want to abstract that, so I can do something like:
def attribute1(inputs: Map[Int, Double]) = aggregate(Foo.attribute1, inputs)
private def aggregate(f: Double => Double) = foos.foldLeft(0d)((sum, foo) => sum + foo.f(inputs(foo.id)
Of course, that does not work as one cannot reference Foo.attribute1 as a function - . is not a function instance.
I've basically stumbled through various solution, but every one results in code for each aggregation method at least as verbose or complex as what we have with no helper, and I'm left with the duplication of the iteration.
I may be just hoping for too much here, but I am virtually certain there is an elegant way to do this is Scala that is escaping me. So, any of the Scala gurus here who answers - thanks in advance!
I'm not sure I get what you're trying to do, but in scala a number-returning method like this:
def attribute1 = 5
IS a function. Well, sort of... It can be seen as a function with type () => Int (takes no argument, returns an Integer). You just need to use the omnipresent _ to tell scala to turn attribute1 into a function.
See if this helps as a starting point:
scala> class Foo {
| def attribute1=5
| def attribute2=2
| }
defined class Foo
scala> val foo=new Foo
foo: Foo = Foo#4cbba0bd
// test takes a function of type () => Int and just applies it (note
// the f() followed by () in the right-hand side to say we want to apply f
scala> def test(f: () => Int) = f()
test: (f: () => Int)Int
// the _ after foo.attribute1 tells scala that we want to use
// res2.attribute as a function, not take its value
scala> test(foo.attribute1 _)
res0: Int = 5
So basically what you're asking for is a way to address a specific method on multiple instances, right? If so, it's easily solvable:
trait Foo {
def id : Int
def attribute1( x : Double ) : Double
}
def aggregate( f : (Foo, Double) => Double, inputs : Map[Int, Double] ) =
foos.foldLeft(0d)( (sum, foo) => sum + f(foo, inputs(foo.id)) )
def aggregateAttribute1(inputs: Map[Int, Double]) =
aggregate(_.attribute1(_), inputs)
The key to this solution is _.attribute1(_) which is a sugarred way of writing
(foo, input) => foo.attribute1(input)
Building on #Nikita's answer, if you want to remove a bit more redundancy from your boring methods, you can curry the aggregate method:
def aggregate(f: (Foo, Double) => Double)(inputs: Map[Int, Double]): Double =
foos.foldLeft(0d)((sum, foo) => sum + f(foo, inputs(foo.id)))
def aggregateAttribute1: Map[Int, Double] => Double =
aggregate(_.attribute1(_))
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.