What is the mechanism by which functions with multiple parameter lists can (sometimes) be used with less than the required number of parameters? - scala

Let me introduce this question by way of an example. This was taken from Lecture 2.3 of Martin Odersky's Functional Programming course.
I have a function to find fixed points iteratively like so
object fixed_points {
println("Welcome to Fixed Points")
val tolerance = 0.0001
def isCloseEnough(x: Double, y: Double) =
abs((x-y)/x) < tolerance
def fixedPoint(f: Double => Double)(firstGuess: Double) = {
def iterate(guess: Double): Double = {
println(guess)
val next = f(guess)
if (isCloseEnough(guess, next)) next
else iterate(next)
}
iterate(firstGuess)
}
I can adapt this function to finding square roots like so
def sqrt(x: Double) =
fixedPoint(y => x/y)(1.0)
However, this does not converge for certain arguments (like 4 for example). So I apply an average damping to it, essentially converting it to Newton-Raphson like so
def sqrt(x: Double) =
fixedPoint(y => (x/y+y)/2)(1.0)
which converges.
Now average damping is general enough to warrant its own function, so I refactor my code like so
def averageDamp(f: Double => Double)(x: Double) = (x+f(x))/2
and
def sqrtDamp(x: Double) =
fixedPoint(averageDamp(y=>x/y))(1.0) (*)
Whoa! What just happened?? I'm using averageDamp with only one parameter (when it was defined with two) and the compiler does not complain!
Now, I understand that I can use partial application like so
def a = averageDamp(x=>2*x)_
a(3) // returns 4.5
No problems there. But when I attempt to use averageDamp with less than the requisite number of parameters (as was done in sqrtDamp) like so
def a = averageDamp(x=>2*x) (**)
I get an error missing arguments for method averageDamp.
Questions:
How is what I have done in (**) different from (*) that the compiler complains in the former but not the latter?
So it looks like using less than the requisite parameters is allowed under certain circumstances. What are these circumstances and what is the name given to this mechanism? (I realize this would come under the topic of 'currying', but I'm after the specific name of this subset of currying, as it were)

This answer expands on the comment posted by #som-snytt.
The difference between (**) and (*) is that in the former, fixedPoint provides a type definition, whereas in the latter a does not. Essentially, whenever your code provides an explicit type declaration, the compiler is happy yo overlook the omission of the trailing underscore. This is a deliberate design decision, see Martin Odersky's explanation.
To illustrate this point, here is a small example.
object A {
def add(a: Int)(b:Int): Int = a + b
val x: Int => Int = add(5) // compiles fine
val y = add(5) // produces the following compiler error
}
/* missing arguments for method add in object A;
follow this method with `_' if you want to treat it as a partially applied function
val y = add(5)
^
*/

Related

What's the purpose of Currying given other alternatives to return a function in Scala?

I'm currently doing a Scala course and recently I was introduced to different techniques of returning functions.
For example, given this function and method:
val simpleAddFunction = (x: Int, y: Int) => x + y
def simpleAddMethod(x: Int, y: Int) = x + y
I can return another function just doing this:
val add7_v1 = (x: Int) => simpleAddFunction(x, 7)
val add7_v2 = simpleAddFunction(_: Int, 7)
val add7_v3 = (x: Int) => simpleAddMethod(x, 7)
val add7_v4 = simpleAddMethod(_: Int, 7)
All the values add7_x accomplish the same thing, so, whats the purpose of Currying then?
Why I have to write def simpleCurryMethod(x: Int)(y: Int) = x + y if all of the above functions do a similar functionality?
That's it! I'm a newbie in functional programming and I don't know many use cases of Currying apart from saving time by reducing the use of parameters repeatedly. So, if someone could explain me the advantages of currying over the previous examples or in Currying in general I would be very grateful.
That's it, have a nice day!
In Scala 2 there are only four pragmatic reasons for currying METHODS (as far as I can recall, if someone has another valid use case then please let me know).
(and probably the principal reason to use it) to drive type inference.
For example, when you want to accept a function or another kind of generic value whose generic type should be inferred from some plain data. For example:
def applyTwice[A](a: A)(f: A => A): A = f(f(a))
applyTwice(10)(_ + 1) // Here the compiler is able to infer that f is Int => Int
In the above example, if I wouldn't have curried the function then I would need to have done something like: applyTwice(10, (x: Int) => x + 1) to call the function.
Which is redundant and looks worse (IMHO).
Note: In Scala 3 type inference is improved thus this reason is not longer valid there.
(and probably the main reason now in Scala 3) for the UX of callers.
For example, if you expect an argument to be a function or a block it is usually better as a single argument in its own (and last) parameter list so it looks nice in usage. For example:
def iterN(n: Int)(body: => Unit): Unit =
if (n > 0) {
body
iterN(n - 1)(body)
}
iterN(3) {
println("Hello")
// more code
println("World")
}
Again, if I wouldn't have curried the previous method the usage would have been like this:
iterN(3, {
println("Hello")
// more code
println("World")
})
Which doesn't look that nice :)
(in my experience weird but valid) when you know that majority of users will call it partially to return a function.
Because val baz = foo(bar) _ looks better than val baz = foo(bar, _) and with the first one, you sometimes don't the the underscore like: data.map(foo(bar))
Note: Disclaimer, I personally think that if this is the case, is better to just return a function right away instead of currying.
Edit
Thanks to #jwvh for pointing out this fourth use case.
(useful when using path-dependant types) when you need to refer to previous parameters. For example:
trait Foo {
type I
def bar(i: I): Baz
}
def run(foo: Foo)(i: foo.I): Baz =
foo.bar(i)

How to write a currying Scala Function trait?

Issue
First approach
If would like to have
trait Distance extends ((SpacePoint, SpacePoint) => Double)
object EuclideanDistance extends Distance {
override def apply(sp1: SpacePoint, sp2: SpacePoint): Double = ???
}
trait Kernel extends (((Distance)(SpacePoint, SpacePoint)) => Double)
object GaussianKernel extends Kernel {
override def apply(distance: Distance)(sp1: SpacePoint, sp2: SpacePoint): Double = ???
}
However the apply of object GaussianKernel extends Kernel is not an excepted override to the apply of trait Kernel.
Second approach - EDIT: turns out this works afterall...
Alternatively I could write
trait Kernel extends ((Distance) => ( (SpacePoint, SpacePoint) => Double))
object GaussianKernel extends Kernel {
override def apply(distance: Distance): (SpacePoint, SpacePoint) => Double =
(sp1: SpacePoint, sp2: SpacePoint) =>
math.exp(-math.pow(distance(sp1, sp2), 2) / (2))
}
but am not sure this is currying...
EDIT: Turns out that I can use this second approach in a currying fashion. I think it is exactly what the typical currying is, only without the syntactic sugar.
Explanation of the idea
The idea is this: For my algorithm I need a Kernel. This kernel calculates a metric for two vectors in space - here SpacePoints. For that the Kernel requires a way to calculate the distance between the two SpacePoints. Both distance and kernel should be exchangeable (open-closed principle), thus I declare them as traits (in Java I had them declared as interfaces). Here I use the Euclidean Distance (not shown) and the Gaussian Kernel. Why the currying? Later when using those things, the distance is going to be more or less the same for all measurements, while the SpacePoints will change all the time. Again, trying to stay true to the open-closed principle. Thus, in a first step I would like the GaussianKernel to be pre-configured (if you will) with a distance and return a Function that can be feed later in the program with the SpacePoints (I am sure the code is wrong, just to give you an idea what I am aiming at):
val myFirstKernel = GaussianKernel(EuclideanDistance)
val mySecondKernel = GaussianKernel(FancyDistance)
val myThirdKernel = EpanechnikovKernel(EuclideanDistance)
// ... lots lof code ...
val firstOtherClass = new OtherClass(myFirstKernel)
val secondOtherClass = new OtherClass(mySecondKernel)
val thirdOtherClass = new OtherClass(myThirdKernel)
// ... meanwhile in "OtherClass" ...
class OtherClass(kernel: Kernel) {
val thisSpacePoint = ??? // ... fancy stuff going on ...
val thisSpacePoint = ??? // ... fancy stuff going on ...
val calculatedKernel = kernel(thisSpacePoint, thatSpacePoint)
}
Questions
How do I build my trait?
Since distance can be different for different GaussianKernels - should GaussianKernel be a class instead of an object?
Should I partially apply GaussianKernel instead of currying?
Is my approach bad and GaussianKernel should be a class that stores the distance in a field?
I would just use functions. All this extra stuff is just complexity and making things traits doesn't seem to add anything.
def euclideanDistance(p1: SpacePoint1, p1: SpacePoint1): Double = ???
class MyClass(kernel: (SpacePoint, SpacePoint) => Double) { ??? }
val myClass = new MyClass(euclideanDistance)
So just pass the kernel as a function that will computer your distance given two points.
I'm on my phone, so can't fully check, but this will give you an idea.
This will allow you to partially apply the functions if you have the need. Imagine you have a base calculate method...
def calc(settings: Settings)(p1: SpacePoint1, p1: SpacePoint1): Double = ???
val standardCalc = calc(defaultSettings)
val customCalc = calc(customSettings)
I would start with modeling everything as functions first, then roll up commonality into traits only if needed.
Answers
1. How do I build my trait?
The second approach is the way to go. You just can't use the syntactic sugar of currying as usual, but this is the same as currying:
GaussianKernel(ContinuousEuclideanDistance)(2, sp1, sp2)
GaussianKernel(ContinuousManhattanDistance)(2, sp1, sp2)
val eKern = GaussianKernel(ContinuousEuclideanDistance)
eKern(2, sp1, sp2)
eKern(2, sp1, sp3)
val mKern = GaussianKernel(ContinuousManhattanDistance)
mKern(2, sp1, sp2)
mKern(2, sp1, sp3)
Why the first approach does not work
Because currying is only possible for methods (duh...). The issue starts with the notion that a Function is very much like a method, only that the actual method is the apply method, which is invoked by calling the Function's "constructor".
First of all: If an object has an apply method, it already has this ability - no need to extend a Function. Extending a Function only forces the object to have an apply method. When I say "object" here I mean both, a singleton Scala object (with the identifier object) and a instantiated class. If the object is a instantiated class MyClass, then the call MyClass(...) refers to the constructor (thus a new before that is required) and the apply is masked. However, after the instantiation, I can use the resulting object in the way mentioned: val myClass = new MyClass(...), where myClass is an object (a class instance). Now I can write myClass(...), calling the apply method. If the object is a singleton object, then I already have an object and can directly write MyObject(...) to call the apply method. Of course an object (in both senses) does not have a constructor and thus the apply is not masked and can be used. When this is done, it just looks the same way as a constructor, but it isn't (that's Scala syntax for you - just because it looks similar, doesn't mean it's the same thing).
Second of all: Currying is syntactic sugar:
def mymethod(a: Int)(b: Double): String = ???
is syntactic sugar for
def mymethod(a: Int): ((Double) => String) = ???
which is syntactic sugar for
def mymethod(a: Int): Function1[Double, String] = ???
thus
def mymethod(a: Int): Function1[Double, String] = {
new Function1[Double, String] {
def apply(Double): String = ???
}
}
(If we extend a FunctionN[T1, T2, ..., Tn+1] it works like this: The last type Tn+1 is the output type of the apply method, the first N types are the input types.)
Now, we want the apply method here is supposed to be currying:
object GaussianKernel extends Kernel {
override def apply(distance: Distance)(sp1: SpacePoint, sp2: SpacePoint): Double = ???
}
which translates to
object GaussianKernel extends Kernel {
def apply(distance: Distance): Function2[SpacePoint, SpacePoint, Double] = {
new Function2[SpacePoint, SpacePoint, Double] {
def apply(SpacePoint, SpacePoint): Double
}
}
}
Now, so what should GaussianKernel extend (or what is GaussianKernel)? It should extend
Function1[Distance, Function2[SpacePoint, SpacePoint, Double]]
(which is the same as Distance => ((SpacePoint, SpacePoint) => Double)), the second approach).
Now the issue here is, that this cannot be written as currying, because it is a type description and not a method's signature. After discussing all this, this seems obvious, but before discussion all this, it might not have. The thing is, that the type description seemed to have a direct translation into the apply method's (the first, or only one, depending on how one takes the syntactic sugar apart) signature, but it doesn't. To be fair though, it is something that could have been implemented in the compiler: That the type description and the apply method's signature are recognized to be equal.
2. Since distance can be different for different GaussianKernels - should GaussianKernel be a class instead of an object?
Both are valid implementation. Using those later only differenciates only in the presence or absence of new.
If one does not like the new one can consider a companion object as a Factory pattern.
3. Should I partially apply GaussianKernel instead of currying?
In general this is preferred according to http://www.vasinov.com/blog/on-currying-and-partial-function-application/#toc-use-cases
An advantage of currying would be the nicer code without _: ??? for the missing parameters.
4. Is my approach bad and GaussianKernel should be a class that stores the distance in a field?
see 2.

Random as instance of scalaz.Monad

This is a follow-up to my previous question. I wrote a monad (for an exercise) that is actually a function generating random values. However it is not defined as an instance of type class scalaz.Monad.
Now I looked at Rng library and noticed that it defined Rng as scalaz.Monad:
implicit val RngMonad: Monad[Rng] =
new Monad[Rng] {
def bind[A, B](a: Rng[A])(f: A => Rng[B]) = a flatMap f
def point[A](a: => A) = insert(a)
}
So I wonder how exactly users benefit from that. How can we use the fact that Rng is an instance of type class scalaz.Monad ? Can you give any examples ?
Here's a simple example. Suppose I want to pick a random size for a range, and then pick a random index inside that range, and then return both the range and the index. The second computation of a random value clearly depends on the first—I need to know the size of the range in order to pick a value in the range.
This kind of thing is specifically what monadic binding is for—it allows you to write the following:
val rangeAndIndex: Rng[(Range, Int)] = for {
max <- Rng.positiveint
index <- Rng.chooseint(0, max)
} yield (0 to max, index)
This wouldn't be possible if we didn't have a Monad instance for Rng.
One of the benefit is that you will get a lot of useful methods defined in MonadOps.
For example, Rng.double.iterateUntil(_ < 0.1) will produce only the values that are less than 0.1 (while the values greater than 0.1 will be skipped).
iterateUntil can be used for generation of distribution samples using a rejection method.
E.g. this is the code that creates a beta distribution sample generator:
import com.nicta.rng.Rng
import java.lang.Math
import scalaz.syntax.monad._
object Main extends App {
def beta(alpha: Double, beta: Double): Rng[Double] = {
// Purely functional port of Numpy's beta generator: https://github.com/numpy/numpy/blob/31b94e85a99db998bd6156d2b800386973fef3e1/numpy/random/mtrand/distributions.c#L187
if (alpha <= 1.0 && beta <= 1.0) {
val rng: Rng[Double] = Rng.double
val xy: Rng[(Double, Double)] = for {
u <- rng
v <- rng
} yield (Math.pow(u, 1 / alpha), Math.pow(v, 1 / beta))
xy.iterateUntil { case (x, y) => x + y <= 1.0 }.map { case (x, y) => x / (x + y) }
} else ???
}
val rng: Rng[List[Double]] = beta(0.5, 0.5).fill(10)
println(rng.run.unsafePerformIO) // Prints 10 samples of the beta distribution
}
Like any interface, declaring an instance of Monad[Rng] does two things: it provides an implementation of the Monad methods under standard names, and it expresses an implicit contract that those method implementations conform to certain laws (in this case, the monad laws).
#Travis gave an example of one thing that's implemented with these interfaces, the Scalaz implementation of map and flatMap. You're right that you could implement these directly; they're "inherited" in Monad (actually a little more complex than that).
For an example of a method that you definitely have to implement some Scalaz interface for, how about sequence? This is a method that turns a List (or more generally a Traversable) of contexts into a single context for a List, e.g.:
val randomlyGeneratedNumbers: List[Rng[Int]] = ...
randomlyGeneratedNumbers.sequence: Rng[List[Int]]
But this actually only uses Applicative[Rng] (which is a superclass), not the full power of Monad. I can't actually think of anything that uses Monad directly (there are a few methods on MonadOps, e.g. untilM, but I've never used any of them in anger), but you might want a Bind for a "wrapper" case where you have an "inner" Monad "inside" your Rng things, in which case MonadTrans is useful:
val a: Rng[Reader[Config, Int]] = ...
def f: Int => Rng[Reader[Config, Float]] = ...
//would be a pain to manually implement something to combine a and f
val b: ReaderT[Rng, Config, Int] = ...
val g: Int => ReaderT[Rng, Config, Float] = ...
b >>= g
To be totally honest though, Applicative is probably good enough for most Monad use cases, at least the simpler ones.
Of course all of these methods are things you could implement yourself, but like any library the whole point of Scalaz is that they're already implemented, and under standard names, making it easier for other people to understand your code.

What's the difference between multiple parameters lists and multiple parameters per list in Scala?

In Scala one can write (curried?) functions like this
def curriedFunc(arg1: Int) (arg2: String) = { ... }
What is the difference between the above curriedFunc function definition with two parameters lists and functions with multiple parameters in a single parameter list:
def curriedFunc(arg1: Int, arg2: String) = { ... }
From a mathematical point of view this is (curriedFunc(x))(y) and curriedFunc(x,y) but I can write def sum(x) (y) = x + y and the same will be def sum2(x, y) = x + y
I know only one difference - this is partially applied functions. But both ways are equivalent for me.
Are there any other differences?
Strictly speaking, this is not a curried function, but a method with multiple argument lists, although admittedly it looks like a function.
As you said, the multiple arguments lists allow the method to be used in the place of a partially applied function. (Sorry for the generally silly examples I use)
object NonCurr {
def tabulate[A](n: Int, fun: Int => A) = IndexedSeq.tabulate(n)(fun)
}
NonCurr.tabulate[Double](10, _) // not possible
val x = IndexedSeq.tabulate[Double](10) _ // possible. x is Function1 now
x(math.exp(_)) // complete the application
Another benefit is that you can use curly braces instead of parenthesis which looks nice if the second argument list consists of a single function, or thunk. E.g.
NonCurr.tabulate(10, { i => val j = util.Random.nextInt(i + 1); i - i % 2 })
versus
IndexedSeq.tabulate(10) { i =>
val j = util.Random.nextInt(i + 1)
i - i % 2
}
Or for the thunk:
IndexedSeq.fill(10) {
println("debug: operating the random number generator")
util.Random.nextInt(99)
}
Another advantage is, you can refer to arguments of a previous argument list for defining default argument values (although you could also say it's a disadvantage that you cannot do that in single list :)
// again I'm not very creative with the example, so forgive me
def doSomething(f: java.io.File)(modDate: Long = f.lastModified) = ???
Finally, there are three other application in an answer to related post Why does Scala provide both multiple parameters lists and multiple parameters per list? . I will just copy them here, but the credit goes to Knut Arne Vedaa, Kevin Wright, and extempore.
First: you can have multiple var args:
def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
...which would not be possible in a single argument list.
Second, it aids the type inference:
def foo[T](a: T, b: T)(op: (T,T) => T) = op(a, b)
foo(1, 2){_ + _} // compiler can infer the type of the op function
def foo2[T](a: T, b: T, op: (T,T) => T) = op(a, b)
foo2(1, 2, _ + _) // compiler too stupid, unfortunately
And last, this is the only way you can have implicit and non implicit args, as implicit is a modifier for a whole argument list:
def gaga [A](x: A)(implicit mf: Manifest[A]) = ??? // ok
def gaga2[A](x: A, implicit mf: Manifest[A]) = ??? // not possible
There's another difference that was not covered by 0__'s excellent answer: default parameters. A parameter from one parameter list can be used when computing the default in another parameter list, but not in the same one.
For example:
def f(x: Int, y: Int = x * 2) = x + y // not valid
def g(x: Int)(y: Int = x * 2) = x + y // valid
That's the whole point, is that the curried and uncurried forms are equivalent! As others have pointed out, one or the other form can be syntactically more convenient to work with depending on the situation, and that is the only reason to prefer one over the other.
It's important to understand that even if Scala didn't have special syntax for declaring curried functions, you could still construct them; this is just a mathematical inevitability once you have the ability to create functions which return functions.
To demonstrate this, imagine that the def foo(a)(b)(c) = {...} syntax didn't exist. Then you could still achieve the exact same thing like so: def foo(a) = (b) => (c) => {...}.
Like many features in Scala, this is just a syntactic convenience for doing something that would be possible anyway, but with slightly more verbosity.
The two forms are isomorphic. The main difference is that curried functions are easier to apply partially, while non-curried functions have slightly nicer syntax, at least in Scala.

Clojure's 'let' equivalent in Scala

Often I face following situation: suppose I have these three functions
def firstFn: Int = ...
def secondFn(b: Int): Long = ...
def thirdFn(x: Int, y: Long, z: Long): Long = ...
and I also have calculate function. My first approach can look like this:
def calculate(a: Long) = thirdFn(firstFn, secondFn(firstFn), secondFn(firstFn) + a)
It looks beautiful and without any curly brackets - just one expression. But it's not optimal, so I end up with this code:
def calculate(a: Long) = {
val first = firstFn
val second = secondFn(first)
thirdFn(first, second, second + a)
}
Now it's several expressions surrounded with curly brackets. At such moments I envy Clojure a little bit. With let function I can define this function in one expression.
So my goal here is to define calculate function with one expression. I come up with 2 solutions.
1 - With scalaz I can define it like this (are there better ways to do this with scalaz?):
def calculate(a: Long) =
firstFn |> {first => secondFn(first) |> {second => thirdFn(first, second, second + a)}}
What I don't like about this solution is that it's nested. The more vals I have the deeper this nesting is.
2 - With for comprehension I can achieve something similar:
def calculate(a: Long) =
for (first <- Option(firstFn); second <- Option(secondFn(first))) yield thirdFn(first, second, second + a)
From one hand this solution has flat structure, just like let in Clojure, but from the other hand I need to wrap functions' results in Option and receive Option as result from calculate (it's good it I'm dealing with nulls, but I don't... and don't want to).
Are there better ways to achieve my goal? What is the idiomatic way for dealing with such situations (may be I should stay with vals... but let way of doing it looks so elegant)?
From other hand it's connected to Referential transparency. All three functions are referentially transparent (in my example firstFn calculates some constant like Pi), so theoretically they can be replaced with calculation results. I know this, but compiler does not, so it can't optimize my first attempt. And here is my second question:
Can I somehow (may be with annotation) give hint to compiler, that my function is referentially transparent, so that it can optimize this function for me (put some kind of caching there, for example)?
Edit
Thanks everybody for the great answers! It's just impossible to select one best answer (may be because they all so good) so I will accept answer with the most up-votes, I think it's fair enough.
in the non-recursive case, let is a restructuring of lambda.
def firstFn : Int = 42
def secondFn(b : Int) : Long = 42
def thirdFn(x : Int, y : Long, z : Long) : Long = x + y + z
def let[A, B](x : A)(f : A => B) : B = f(x)
def calculate(a: Long) = let(firstFn){first => let(secondFn(first)){second => thirdFn(first, second, second + a)}}
Of course, that's still nested. Can't avoid that. But you said you like the monadic form. So here's the identity monad
case class Identity[A](x : A) {
def map[B](f : A => B) = Identity(f(x))
def flatMap[B](f : A => Identity[B]) = f(x)
}
And here's your monadic calculate. Unwrap the result by calling .x
def calculateMonad(a : Long) = for {
first <- Identity(firstFn)
second <- Identity(secondFn(first))
} yield thirdFn(first, second, second + a)
But at this point it sure looks like the original val version.
The Identity monad exists in Scalaz with more sophistication
http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Identity.scala.html
Stick with the original form:
def calculate(a: Long) = {
val first = firstFn
val second = secondFn(first)
thirdFn(first, second, second + a)
}
It's concise and clear, even to Java developers. It's roughly equivalent to let, just without limiting the scope of the names.
Here's an option you may have overlooked.
def calculate(a: Long)(i: Int = firstFn)(j: Long = secondFn(i)) = thirdFn(i,j,j+a)
If you actually want to create a method, this is the way I'd do it.
Alternatively, you could create a method (one might name it let) that avoids nesting:
class Usable[A](a: A) {
def use[B](f: A=>B) = f(a)
def reuse[B,C](f: A=>B)(g: (A,B)=>C) = g(a,f(a))
// Could add more
}
implicit def use_anything[A](a: A) = new Usable(a)
def calculate(a: Long) =
firstFn.reuse(secondFn)((first, second) => thirdFn(first,second,second+a))
But now you might need to name the same things multiple times.
If you feel the first form is cleaner/more elegant/more readable, then why not just stick with it?
First, read this recent commit message to the Scala compiler from none other than Martin Odersky and take it to heart...
Perhaps the real issue here is instantly jumping the gun on claiming it's sub-optimal. The JVM is pretty hot at optimising this sort of thing. At times, it's just plain amazing!
Assuming you have a genuine performance issue in an application that's in genuine need of a speed up, you should start with a profiler report proving that this is a significant bottleneck, on a suitably configured and warmed up JVM.
Then, and only then, should you look at ways to make it faster that may end up sacrificing code clarity.
Why not use pattern matching here:
def calculate(a: Long) = firstFn match { case f => secondFn(f) match { case s => thirdFn(f,s,s + a) } }
How about using currying to record the function return values (parameters from preceding parameter groups are available in suceeding groups).
A bit odd looking but fairly concise and no repeated invocations:
def calculate(a: Long)(f: Int = firstFn)(s: Long = secondFn(f)) = thirdFn(f, s, s + a)
println(calculate(1L)()())