Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am new to scala, I have a use case where I want to define a partial function to add three numbers in which one number is constant and two
numbers can be passed as inputs and define another method which can take the partial
function as input and gives its cube as result.
Well... That depends on where is your constant coming from?
Choice 1 - Your function forms a closure with a constant present in scope.
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
pf((5, 10))
Choice 2 - Your function has a local constant.
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + 10
}
pf((5, 10))
Also, as many others pointed out - this does not look like a use case of partial function. Are you sure that you want a Partial Function and not a partially applied function ?
if you were looking for a partially applied function then,
// first you need a curried function
// Curries function are function which can take parameters in steps to build intermidatary functions.
def normalDef(c: Int)(x: Int, y: Int): Int = c + y + x
// normalDef: normalDef[](val c: Int)(val x: Int,val y: Int) => Int
// now you can "partially apply" this "curried" function to your partially applied function
val addTo10PartiallyApplied = normalDef(10) _
// addTo10PartiallyApplied: (Int, Int) => Int = $Lambda$1240/1924827254#46202553
val total = addTo10PartiallyApplied(1, 2)
// total: Int = 13
The following partial function adds 12345 to each number in the tuple passed to it
scala> val addConstantTo: PartialFunction[(Int, Int), Int] = {
| case (a, b) => a + b + 12345
| }
addConstantTo: PartialFunction[(Int, Int),Int] = <function1>
scala> addConstantTo((12, 34))
res4: Int = 12391
This expands on the concept, by programmatically defining a partial function which adds any number to the elements of a tuple:
scala> def addTo(c: Int): PartialFunction[(Int, Int), Int] = {
| case (a, b) => a + b + c
| }
addTo: (c: Int)PartialFunction[(Int, Int),Int]
scala> val pf = addTo(3)
pf: PartialFunction[(Int, Int),Int] = <function1>
scala> pf((1, 2))
res5: Int = 6
Let that sink in for a bit :)
Related
how do I pass different parameters for my function inside a higher order function. my code below.
val sum = (a: Int, b:Int) => a + b
val x = 7
val y = 9
def sq (x: Int, y: Int, f: (Int, Int)=> Int): Int = {
x + y * f(a,b)
}
println(sq(x,y,sum(2,3)))
This doesn't work and throws an error that 'a' is not defined.
The parameter list for sq looks ok.
The call to sq isn’t right, the function would get evaluated before it gets passed in. Assuming it got by the compiler, which of course it doesn’t.
Passing in a function does not mean its arguments come along for the ride. Passing in a function means the caller may not know what arguments to use or even if the function should be called. The sq function has to supply arguments when it calls it. a and b mean nothing outside the definition of sum. sq could supply x and y as arguments to sum.
Just as an addition to #Nathan answer. This example would make sense:
val sum = (a: Int, b:Int) => a + b
def sq (x: Int, y: Int, f: (Int, Int)=> Int): Int = {
x + y * f(x, y)
}
val x = 7
val y = 9
println(sq(x,y,sum))
This would be evaluated in your sgfunction like:
7 + 9 * sum(7, 8)
I hope this makes sense.
In addition to the #Nathan Hughes answer, if you want to pass the different argument to the sum function on each call you need to change your sq method like
def sq (x: Int, y: Int, f: (Int, Int)=> Int): (Int, Int)=> Int = {
x + y * f(_: Int, _:Int)
}
Insted of expecting the int from the sq method return partially applied function of type (Int, Int) => Int from `sq' then pass other argument to that function like,
sq(10, 20, sum)(1, 2) // 1st approach
//2nd approach would be
//You can hold the function in another variable and call that function with other arguments
val partialSum = sq(10,20, sum)
partialSum(1, 2)
and you will get your result.
Or if you still want that sq method should return Int, you can define your sq method like
def sq (x: Int, y: Int, f: (Int, Int)=> Int)(a:Int, b:Int):Int = {
x + y * f(a, b)
}
scala> sq(10,20, sum)(1,2)
res2: Int = 70
In order to use infix notation, I have the following example of scala code.
implicit class myclass(n:Int ){
private def mapCombineReduce(map : Int => Double, combine: (Double,Double) => Double, zero: Double )(a:Int, b:Double): Double =
if( a > b) zero else combine ( map(a), mapCombineReduce(map,combine,zero)(a+1,b) )
var default_value_of_z : Int = 0
def sum( z : Int = default_value_of_z) = mapReduce( x=>x , (x,y) => x+y+z, 0)(1,n)
def ! = mapCombineReduce( x=> x, (x,y) => x*y, 1)(1,n)
}
4 !
4 sum 1 //sum the elements from 1 to 7 and each time combine the result, add 1 to the result.
4 sum
Is there any way in scala 2.12 to run 4 sum without have a double declaration of the sum method inside myclass ?
No, because default arguments are only used if argument list is provided
def f(x: Int = 1) = x
f // interpreted as trying to do eta-expansion
In fact starting Scala 3 it will indeed eta-expand
scala> def f(x: Int = 1) = x
def f(x: Int): Int
scala> f
val res1: Int => Int = Lambda$7473/1229666909#61a1990e
so in your case you will have to write 4.sum() with argument list present.
Whilst I understand what a partially applied/curried function is, I still don't fully understand why I would use such a function vs simply overloading a function. I.e. given:
def add(a: Int, b: Int): Int = a + b
val addV = (a: Int, b: Int) => a + b
What is the practical difference between
def addOne(b: Int): Int = add(1, b)
and
def addOnePA = add(1, _:Int)
// or currying
val addOneC = addV.curried(1)
Please note I am NOT asking about currying vs partially applied functions as this has been asked before and I have read the answers. I am asking about currying/partially applied functions VS overloaded functions
The difference in your example is that overloaded function will have hardcoded value 1 for the first argument to add, i.e. set at compile time, while partially applied or curried functions are meant to capture their arguments dynamically, i.e. at run time. Otherwise, in your particular example, because you are hardcoding 1 in both cases it's pretty much the same thing.
You would use partially applied/curried function when you pass it through different contexts, and it captures/fills-in arguments dynamically until it's completely ready to be evaluated. In FP this is important because many times you don't pass values, but rather pass functions around. It allows for higher composability and code reusability.
There's a couple reasons why you might prefer partially applied functions. The most obvious and perhaps superficial one is that you don't have to write out intermediate functions such as addOnePA.
List(1, 2, 3, 4) map (_ + 3) // List(4, 5, 6, 7)
is nicer than
def add3(x: Int): Int = x + 3
List(1, 2, 3, 4) map add3
Even the anonymous function approach (that the underscore ends up expanding out to by the compiler) feels a tiny bit clunky in comparison.
List(1, 2, 3, 4) map (x => x + 3)
Less superficially, partial application comes in handy when you're truly passing around functions as first-class values.
val fs = List[(Int, Int) => Int](_ + _, _ * _, _ / _)
val on3 = fs map (f => f(_, 3)) // partial application
val allTogether = on3.foldLeft{identity[Int] _}{_ compose _}
allTogether(6) // (6 / 3) * 3 + 3 = 9
Imagine if I hadn't told you what the functions in fs were. The trick of coming up with named function equivalents instead of partial application becomes harder to use.
As for currying, currying functions often lets you naturally express transformations of functions that produce other functions (rather than a higher order function that simply produces a non-function value at the end) which might otherwise be less clear.
For example,
def integrate(f: Double => Double, delta: Double = 0.01)(x: Double): Double = {
val domain = Range.Double(0.0, x, delta)
domain.foldLeft(0.0){case (acc, a) => delta * f(a) + acc
}
can be thought of and used in the way that you actually learned integration in calculus, namely as a transformation of a function that produces another function.
def square(x: Double): Double = x * x
// Ignoring issues of numerical stability for the moment...
// The underscore is really just a wart that Scala requires to bind it to a val
val cubic = integrate(square) _
val quartic = integrate(cubic) _
val quintic = integrate(quartic) _
// Not *utterly* horrible for a two line numerical integration function
cubic(1) // 0.32835000000000014
quartic(1) // 0.0800415
quintic(1) // 0.015449626499999999
Currying also alleviates a few of the problems around fixed function arity.
implicit class LiftedApply[A, B](fOpt: Option[A => B]){
def ap(xOpt: Option[A]): Option[B] = for {
f <- fOpt
x <- xOpt
} yield f(x)
}
def not(x: Boolean): Boolean = !x
def and(x: Boolean)(y: Boolean): Boolean = x && y
def and3(x: Boolean)(y: Boolean)(z: Boolean): Boolean = x && y && z
Some(not _) ap Some(false) // true
Some(and _) ap Some(true) ap Some(true) // true
Some(and3 _) ap Some(true) ap Some(true) ap Some(true) // true
By having curried functions, we've been able to "lift" a function to work on Option for as many arguments as we need. If our logic functions had not been curried, then we would have had to have separate functions to lift A => B to Option[A] => Option[B], (A, B) => C to (Option[A], Option[B]) => Option[C], (A, B, C) => D to (Option[A], Option[B], Option[C]) => Option[D] and so on for all the arities we cared about.
Currying also has some other miscellaneous benefits when it comes to type inference and is required if you have both implicit and non-implicit arguments for a method.
Finally, the answers to this question list out some more times you might want currying.
I am taking the Functional Programming in Scala course on Coursera and I am having a hard time understanding this code snippet -
def sqrtStream(x: Double): Stream[Double] = {
def improve(guess: Double): Double = (guess+ x/ guess) / 2
lazy val guesses: Stream[Double] = 1 #:: (guesses map improve)
guesses
}
This method would find 10 approximate square root of 4 in increasing order of accuracy when I would do sqrtSteam(4).take(10).toList.
Can someone explain the evaluation strategy of guesses here? My doubt is what value of guesses in substituted when the second value of guesses is picked up?
Let's start from simplified example:
scala> lazy val a: Int = a + 5
a: Int = <lazy>
scala> a
stack overflow here, because of infinite recursion
So a is recalculating til it gets some stable value, like here:
scala> def f(f:() => Any) = 0 //takes function with captured a - returns constant 0
f: (f: () => Any)Int
scala> lazy val a: Int = f(() => a) + 5
a: Int = <lazy>
scala> a
res4: Int = 5 // 0 + 5
You may replace def f(f:() => Any) = 0 with def f(f: => Any) = 0, so a definition will look like it's really passed to the f: lazy val a: Int = f(a) + 5.
Streams use same mechanism - guesses map improve will be passed as parameter called by name (and lambda linked to the lazy a will be saved inside Stream, but not calculated until tail is requested), so it's like lazy val guesses = #::(1, () => guesses map improve). When you call guessess.head - tail will not be evaluated; guesses.tail will lazily return Stream (improve(1), ?), guesses.tail.tail will be Stream(improve(improve(1)), ?) and so on.
The value of guesses is not substituted. A stream is like a list, but its elements are evaluated only when they are needed and then they stored, so next time you access them the evaluation will not be necessary. The reference to the stream itself does not change.
On top of the example Αλεχει wrote, there is a nice explanation in Scala API:
http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream
You can easily find out what's going on by modifying the map function, as described in the scaladoc example:
scala> def sqrtStream(x: Double): Stream[Double] = {
| def improve(guess: Double): Double = (guess + x / guess) / 2
| lazy val guesses: Stream[Double] = 1 #:: (guesses map {n =>
| println(n, improve(n))
| improve(n)
| })
| guesses
| }
sqrtStream: (x: Double)Stream[Double]
The output is:
scala> sqrtStream(4).take(10).toList
(1.0,2.5)
(2.5,2.05)
(2.05,2.000609756097561)
(2.000609756097561,2.0000000929222947)
(2.0000000929222947,2.000000000000002)
(2.000000000000002,2.0)
(2.0,2.0)
(2.0,2.0)
(2.0,2.0)
res0: List[Double] = List(1.0, 2.5, 2.05, 2.000609756097561, 2.0000000929222947, 2.000000000000002, 2.0, 2.0, 2.0, 2.0)
In this function "f" :
def f(x: => Int) : Int = x * x * x //> f: (x: => Int)Int
var y = 0 //> y : Int = 0
f {
y += 1
println("invoked")
y
} //> invoked
//| invoked
//| invoked
//| res0: Int = 6
"f" is invoked same amount of times as "x" parameter is multiplied.
But why is function invoked multiple times ?
Should "f" not expand to 1 * 1 * 1 not 1 * 2 * 3 ?
Your x is not a function, it is a by-name parameter, and its type is a parameterless method type.
Parameterless method type means the same as def x, something that is evaluated every time you reference it. By reference, we mean x and not x.apply() or x().
The expression you're passing to your function f is evaluated every time x is referenced in f. That expression is the whole thing in braces, a block expression. A block is a sequence of statements followed by the result expression at the end.
Here's another explanation: https://stackoverflow.com/a/13337382/1296806
But let's not call it a function, even if it behaves like one under the covers.
Here is the language used in the spec:
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#by-name-parameters
It's not a value type because you can't write val i: => Int.
It was a big deal when they changed the implementation so you could pass a by-name arg to another method without evaluating it first. There was never a question that you can pass function values around like that. For example:
scala> def k(y: => Int) = 8
k: (y: => Int)Int
scala> def f(x: => Int) = k(x) // this used to evaluate x
f: (x: => Int)Int
scala> f { println("hi") ; 42 }
res8: Int = 8
An exception was made to "preserve the by-name behavior" of the incoming x.
This mattered to people because of eta expansion:
scala> def k(y: => Int)(z: Int) = y + y + z
k: (y: => Int)(z: Int)Int
scala> def f(x: => Int) = k(x)(_) // normally, evaluate what you can now
f: (x: => Int)Int => Int
scala> val g = f { println("hi") ; 42 }
g: Int => Int = <function1>
scala> g(6)
hi
hi
res11: Int = 90
The question is how many greetings do you expect?
More quirks:
scala> def f(x: => Int) = (1 to 5) foreach (_ => x)
f: (x: => Int)Unit
scala> def g(x: () => Int) = (1 to 5) foreach (_ => x())
g: (x: () => Int)Unit
scala> var y = 0
y: Int = 0
scala> y = 0 ; f { y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
scala> y = 0 ; g { y += 1 ; println("hi") ; () => y }
hi
y: Int = 1
scala> y = 0 ; g { () => y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
Functions don't cause this problem:
scala> object X { def f(i: Int) = i ; def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
res12: Int = 0
scala> trait Y { def f(i: Int) = i }
defined trait Y
scala> object X extends Y { def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
<console>:11: error: ambiguous reference to overloaded definition,
both method f in object X of type (i: => Int)Int
and method f in trait Y of type (i: Int)Int
match argument types (Int)
X.f(0)
^
Compare method types:
http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#method-types
This is not a pedantic distinction; irrespective of the current implementation, it can be confusing to think of a by-name parameter as "really" a function.
Another way of saying what has already been said is that inside f you invoke the function x three times. The first time it increments the y var and returns 1. The second time it again increments y returning 2 and the third time it again increments y and returns 3.
If you want it invoked only once then you may want to do something like this:
def f(x: => Int) : Int = x * x * x
var y = 0
lazy val xx = {
y += 1
println("invoked")
y
}
f {xx}
This will print 'invoked' only once and result in a returned value of 1.
x: T means need a T value.
x: => T means need a T value, but it is call by name.
x: () => T This means need a function given nothing to T
However, this question is not related to the difference between function and method.
The reason is call by name is invoked every time you try to use it.
change to call by value def f(x: Int) : Int, it will only invoke once.
Because you increment y by 1 every time the argument is used inside f
The result which your function f() returns is changing, because there is a global variable that is incremented with every subsequent call to that function.
the x in f(x: => Int) is interpreted as "some function that returns Int". So it has to be called 3 times to evaluate the x*x*x expression. With every call, you increment the global variable and return the result, which is how you arrive at three subsequent natural numbers (because the global variable is initialized to 0). Hence 1*2*3.