This maybe a very basic question. I am new to Scala. In Scala, I have a function with a default parameter value for its second parameter:
def fun(number : Int, defaultNumber : Int = 0): Int = {number + defaultNumber}
I want to have a higherOrder function to which I can pass a lowerOrder function such as the function above whose second argument has a default value. First attempt is as follows:
def higherOrder(lowerOrder : (Int, Int) => Int, number: Int) =
{lowerOrder(number)}
This obviously gives an error:
error: not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2.
Unspecified value parameter v2.
A way around this is to get the default value in the higherOrder function:
def higherOrder(lowerOrder : (Int, Int) => Int, number: Int, defaultNumber: Int = 0) =
{lowerOrder(number, defaultNumber)}
But I don't want to do that because I may want to pass different lowerOrder functions that have different default values for their second parameter and I may not know what that default value is to pass the default value to the higherOrder function. Is there any solution for this?
Define the trait for your lower Order function.
trait Fun {
def apply(number : Int, defaultNumber : Int = 0): Int
}
Create lambda function for your lower Order function. Now you can use the function literal notation to define a Fun (note that you'll need to have started the REPL with -Xexperimental for this step to work)
val fun: Fun = { (number : Int, defaultNumber : Int) => number + defaultNumber }
Now, you can use this lambda function in your higher order function.
def higherOrder(lowerOrder : Fun, number: Int) =
{lowerOrder(number)}
Call the higher order function now.
higherOrder(fun, 10)
> result: Int = 10
Related
When learning Scala, I get an example for HIGHER-ORDER FUNCTIONS, from here
https://docs.scala-lang.org/tour/higher-order-functions.html
def apply(f : Int => String, v : Int) = f(v)
def layout[A](x : A) : String = x.toString
println(apply(layout, 1000))
My question is if layout has more than 1 parameters, like this :
def layout[A](x : A, y : A) : String = x.toString + y.toString
for Intuitive understanding, I define apply as follows
def apply(f : Int, Int => String, v : Int, w : Int) = f(v, w)
Of course, this is can not compiled.
I think I have a deviation from the understanding of the type of function in Scala.
How to solve this problem with the right posture, and Solve this problem with the right posture, and more in-depth understanding of the definition of scala function types is good.
Just put a bracket around the arguments
def apply(f : (Int, Int) => String, v1 : Int, v2: Int) = f(v1, v2)
Read about Function traits in scala , there are 22 Function traits are there(Function0, Function1, .....Function2), for your case :
http://www.scala-lang.org/api/2.12.3/scala/Function2.html
Also learn about functional interface in Java8 and then try to compare with Scala Function traits.
Let me help you with an example
package scalaLearning
object higherOrderFunctions {
def main(args: Array[String]): Unit = {
def add(a: Int , b:Int):Int =a+b //Function to add integers which two int values and return and int value
def mul(a:Int, b:Int ) :Float=a*b //Function which takes two int values and return float value
def sub(a:Int,b:Int):Int=a-b //function which takes two int values and return int value
def div(a:Int,b:Int):Float =a/b//Function which takes two int value and return float value
def operation(function:(Int,Int)=>AnyVal,firstParam:Int,secondParam:Int):AnyVal=function(firstParam,secondParam) //Higher order function
println(operation(add,2,4))
println(operation(mul,2,4))
println(operation(sub,2,4))
println(operation(div,2,4))
}
}
Here while creating higher order function which takes input as function,
first you need to understand what type of of inputs your parameter functions
takes and what it returns,
In my case it takes two int values and return either float or int so you can
mention function_:(Int,Int) => AnyVal
and to pass the parameters to this function you specify
firstParam:Int(Thiscould also be firstParam:AnyVal) for the first parameter and specify
secondParam:Int(This could also be secondParam:AnyVal) for second paramter .
def operation(function(Int,Int)=>AnyVal,firstParam:Int,secondParam:Int):AnyVal=function(firstParam,secondParam) //Higher order function
I was going through the test code for spark. While I understand the logic behind the function given below
What does it means and What is the benefit of defining in the below syntax ?
Test Code
def withStreamingContext[R](ssc: StreamingContext)(block: StreamingContext => R): R = {
try {
block(ssc)
} finally {
try {
ssc.stop(stopSparkContext = true)
} catch {
case e: Exception =>
logError("Error stopping StreamingContext", e)
}
}
}
why does it has to be defined this way ? why can't it be
def withStreamingContext[R](ssc: StreamingContext,block: StreamingContext => R): R =
Well, it can. Separating arguments into two or more parameter lists is called currying. This way a two-parameter function can be turned into a function that takes one argument and returns a function that takes one argument and returns the result. This is what happened in the code you posted. Every n-parameter function can be seen as n 1-parameter functions (in fact, in Haskell all functions are treated like this).
Note that Scala also has a concept of partially applied functions, which boils down to the same thing. Both PAF and currying allow you to only pass a subset of parameters, thus receiving a function that takes the rest.
For example,
def sum(x: Int, y: Int) = x + y
can be curried and then you could say, for example:
def sum(x: Int)(y: Int) = x + y
def addTwo = sum(2) _ // type of addTwo is Int => Int
which gives you the same function, but with its first parameter applied. Using PAF, it would be
def sum(x: Int, y: Int) = x + y
def addTwo = sum(2, _: Int)
It is more convenient to use:
withStreamingContext(ssc) {
doSomething()
doSomethingElse()
}
vs
withStreamingContext(ssc, { doSomething(); doSomethingElse() })
First of all
def a(x: Int)(y: Int) = x * y
Is a syntactic sugar for
def a(x: Int) = (y: Int) => x * y
That means that you define a method that returns a function (closed over x)
You can invoke such method without all parameter lists and pass returned function around. You can also partially apply any other method but I think this syntax is cleaner.
Moreover, functions/methods with unary parameter lists can be invoked with expression syntax.
withStreamingContext(ssc) {
// your code block passed to function
}
This style of declaring functions is referred to as currying. It was independently introduced by Moses Schönfinkel, and then later by Haskell Curry from where it takes its name. The concept actually originates in mathematics and then introduced into computer science.
It is often conflated with partial function application; the main difference is that a call to a partially applied function returns the result immediately, not another function down the "currying" chain.
scala> def foo (x:Int, y:Int, z:Int) : Int = x + y + z
foo: (x: Int, y: Int, z: Int)Int
scala> val pa = foo(1, _:Int, _:Int)
pa: (Int, Int) => Int = <function2>
scala> pa(2,3)
res0: Int = 6
In contrast, given f:(x,y,z) -> n, currying produces f':x -> (y -> (z -> n)). In other words, applying each argument in turn to a single argument function returned by the previous invocation.
After calling f'(1), a function that takes a single argument and returns another function is returned, not a function that takes two arguments.
In contrast partial function application refers to the process of fixing a number of arguments to a function, producing another function of smaller arity. These two are often conflated.
The benefits/advantages of currying have already been mentioned elsewhere. The main issue you had was understanding the syntax and it's origins which has been explained.
I've been experimenting with Scala. I am trying to understand implicits and came across this situation.
Is behaviour of parameter b same for both functions?
Are paramareters list just syntax sugar over returning function?
My experiments show, they behave the same.
Thanks
implicit val v = 2
// 1.
def testB(a: Int)(b: Int)(implicit i: Int): Int = {
println(a + b + i)
11
}
println(testB(7)(8))
println(testB(7) {
8
})
// 2.
def testC(a: Int): (Int) => Int = {
def innerTest2C(b: Int)(implicit i: Int) = {
println(a + b + i)
11
}
innerTest2C
}
println(testC(7)(8))
println(testC(7) {
8
})
The rule is that whenever a function takes exactly one parameter, you can replace the normal brackets () with curly brackets {}. Curly brackets define a block and allow you to place several statements inside it. The block will evaluate to the value of the expression in the last line like in all blocks.
In 2., the function testC returns another function from Int to Int, so you cann call the result of testC(7) again with one parameter: testC(7)(x). If you just consider the println statements, there is nothing different here.
What you need to understand is that
def testB(a: Int)(b: Int)
is different from
def testB(a: Int, b: Int)
insofar that the former represents two functions like in your second case. You can call testB(x) and will obtain another function from Int to Int. Applying only part of the paramters of a function in order to obtain another function is called currying.
def adder(a:Int,b:Int):Int = {a+b}
def doubler(a:Int):Int = {a*2}
def doubleAdd = doubler _ compose adder
I get the error: type mismatch
found: (Int,Int)=>Int
required: ? => Int
Then if I just try doubleAdd = doubler(adder _) I get the same error except required Int instead of ? => Int
Is there a way of composing a function with two parameters? Sorry if this is pretty basic, I'm pretty new to the language, and I couldn't find an example with two parameters anywhere.
You're attempting to compose a Function2 (adder) with a Function1, hence the issue. One workaround is to change your definition of Adder to a curried version:
def adder(a: Int)(b: Int):Int = a + b
Then doubleAdd to partially apply adder like this:
def doubleAdd(x: Int) = doubler _ compose adder(x)
What's happening under the hood is transforming adder from a Function2 (Int, Int) => Int, to a Function1 (Int) => (Int) => Int, or a function that returns a function. You're then able to compose the function returned from adder with the first parameter already applied.
I heard that Scala contains a feature called named and default arguments but I don't know what such parameters do or how to use them.
Can someone explain their usage?
Some special functions call type in Scala
Named arguments:
Named arguments allow you to pass arguments to a function in a different order.For example:
def speed(distance: Float, time: Float): Float = distance / time
And the it can be used like this:
speed(distance = 100, time = 10)
or
speed(time = 10, distance = 100)
Default arguments:
Scala lets you specify default values for function parameters. For example:
def printTime(out: java.io.PrintStream = Console.out) =
out.println("time = "+ System.currentTimeMillis())
Then you can call printTime without giving any output stream like this:
printTime()
Repeated arguments:
Scala allows you to indicate that the last parameter to a function may be repeat. For example:
def echo(args: String*) =
for (arg <- args)
println(arg)
Then you can use it like this:
echo()
echo("one")
echo("hello", "world!")
Default arguments solve the problem other programming languages normally solve with method overloading. When there is a method
def addNumbers(a: Int, b: Int, c: Int, d: Int) = a+b+c+d
that takes multiple parameters it can be useful to set some default values in overloaded methods to provide an API that is easier to use if one doesn't want to fill all parameters:
def addNumbers(a: Int, b: Int, c: Int) = addNumbers(a, b, c, 0)
def addNumbers(a: Int, b: Int) = addNumbers(a, b, 0, 0)
With default arguments it is no longer necessary to overload such a method:
def addNumbers(a: Int, b: Int, c: Int = 0, d: Int = 0) = a+b+c+d
The compiler automatically calls the method with the specific default arguments if they are not specified:
scala> addNumbers(1, 2, 3)
res2: Int = 6
A useful place for default arguments is in constructors. It is easier to write
class A(i: Int, s: String = "")
than
class A(i: Int, s: String) {
def this(i: Int) = this(i, "")
}
Named arguments on the other side can improve the readability of a method call:
def compute(xs: List[Int], executeInParallel: Boolean) = ???
compute(xs, executeInParallel = true) is easier to read than only compute(xs, true)
One can always specify the name of a parameter regardless of its order. This means compute(executeInParallel = true, xs = xs) is the same as compute(xs, true). The compiler often just needs a hint which parameter must be placed at which position when the ordering of the parameters is changed.
A use case where both named and default arguments can be used lies in the copy method of case classes, which are automatically generated by the compiler:
scala> case class Person(name: String, age: Int)
defined class Person
scala> val p = Person("Ruben", 43)
p: Person = Person(Ruben,43)
scala> val oneYearOlder = p.copy(age = p.age+1)
oneYearOlder: Person = Person(Ruben,44)
It may be important to mention that named arguments only work for methods defined in Scala. Parameters of methods defined in Java can't be called by their name.
Furthermore named arguments don't work on function literals:
scala> val f = (i: Int) => i
f: Int => Int = <function1>
scala> f(i = 1)
<console>:9: error: not found: value i
f(i = 1)
^
For further information to this feature one can take a look to docs.scala-lang.org.