I'm trying to do something like this:
var fun : (Int,Int) => Double = (a,b) =>
{
// do something
return 1.0
}
However, my IDE complaints with Return statement outside method definition. So how do I explicitly give a return statement in a function literal in scala?
In Scala a return statement returns from the enclosing method body. If return appears inside of a function literal, it is implemented with exception throwing. return will throw an exception inside of the function which will then be caught be the enclosing method. Scala works this way in order to make the use of custom control constructs that take functions invisible, for example:
def geometricAverage(l: List[Double]): Double = {
val product = l.foldLeft(1.0) { (z, x) =>
if (x == 0) return 0 else z * x
}
Math.pow(product, 1.0 / l.length)
}
The return in this example returns from the geometricAverage method, allowing it to complete instantly if a 0 is found. You don't need to know that foldLeft is a method that takes a function rather than a built-in construct to realize this.
The preference in Scala is to write functions in functional style, taking advantage of Scala's expression-oriented nature to make return unnecessary. For example:
val fun: (Int,Int) => Double = (a,b) => {
if (a == b) {
// side effect here, if desired
0.0
} else {
// side effect here, if desired
1.0
}
}
If you really want to use return in the definition of the function, you can implement the appropriate function interface manually instead of using a function literal:
val fun = new Function2[Int, Int, Double] {
def apply(x: Int, y: Int): Double = {
if (x == y)
return 0.0
1.0
}
}
But this is not idiomatic and strongly discouraged.
Don't use return, it makes Scala cry.
scala> var fun: (Int, Int) => Double = (a, b) => {
| // do something
| 1.0
| }
fun: (Int, Int) => Double = <function2>
scala> fun(1, 2)
res4: Double = 1.0
Or better yet:
scala> def fun: (Int, Int) => Double = (a, b) => {
| // do something
| 1.0
| }
fun: (Int, Int) => Double
scala> fun(1, 2)
res4: Double = 1.0
how do I explicitly give a return statement in a function literal in scala?
You can't. This is answered by the language specification section 6.20, Return Expressions:
A return expression return e must occur inside the body of some enclosing named
method or function.
An apply method which is generated by the compiler as an expansion of an anonymous function does not count as a named function in the source program, and
therefore is never the target of a return expression.
There is no return statement in Scala. In any function the last statement executed is the value returned. If this last statement doesn't comply with expected return type of the function, compiler will raise error.
Related
I am trying to pass a function to a function in Kotlin here is my code.
fun validateValueWithFunc(value: String, parsefun: (CharSequence) -> Boolean, type: String){
if(parsefun(value))
print("Valid ${type}")
else
print("Invalid ${type}")
}
The function I'm passing is from Regex class "containsMatchIn"
val f = Regex.fromLiteral("some regex").containsMatchIn
I know about the :: function reference operator but I don't know how to use it in this situation
In Kotlin 1.0.4, bound callable references (those with expressions on left-hand side) are not available yet, you can only use class name to the left of ::.
This feature is planned for Kotlin 1.1 and will have the following syntax:
val f = Regex.fromLiteral("some regex")::containsMatchIn
Until then, you can express the same using lambda syntax. To do it, you should capture a Regex into a single-argument lambda function:
val regex = Regex.fromLiteral("some regex")
val f = { s: CharSequence -> regex.containsMatchIn(s) } // (CharSequence) -> Boolean
One-line equivalent using with(...) { ... }:
val f = with(Regex.fromLiteral("some regex")) { { s: CharSequence -> containsMatchIn(s) } }
Here, with binds the Regex to receiver for the outer braces and returns the last and the only expression in the outer braces -- that is, the lambda function defined by the inner braces. See also: the idiomatic usage of with.
I am at the early stages of learning Scala and I've noticed different ways to declare methods.
I've established that not using an equals sign makes the method a void method (returning a Unit instead of a value), and using an equals sign returns the actual value so
def product(x: Int, y: Int) {
x*y
}
will return () (Unit), but
def product(x: Int, y: Int) = {
x*y
}
will return the product of the two arguments(x*y)
I've noticed a third way of declaring methods - with a colon. Here is an example
def isEqual(x: Any): Boolean
How does this differ from the = notation? And in what situations will it be best to use this way instead?
When you use colon (and use equal) you explicitly define return type of method.
// method return Boolean value
def m(a : Int) : Boolean = a > 0
When you don't use colon and use equal you allow scala compiler inferring return type itself.
// method has return type of last expression (Boolean)
def m(a : Int) = a > 0
When you use neither colon nor equal your method has return type of Unit class.
// method has Unit return type
def m(a : Int){
a > 0
}
Others have perfectly explained the differences between the different declarations:
def foo: Boolean = true // explicitly declare the return type
and
def foo = true // let the compiler to implicitly infer Boolean
That being said, I have to warn you against
def foo { }
This is called procedure-syntax, and you should never use it, as it's has been already deprecated (since Oct 29, 2013), although you'll get a deprecation warning only under the -Xfuture flag.
Whenever you have to declare a method returning Unit (which you should avoid as much as possible, since it means you're relying on side-effects), use the following syntax
def foo: Unit = { }
Also, as a personal advice, explicitly annotating return types makes your code often more readable and helps you in catching errors early. You know what the function should return, so explicitly annotating the type allows the compiler to check that the implementation returns an appropriate value, right at the declaration position (if you use the function you will catch an error eventually, but perhaps far from where the error really is).
Also, when declaring an abstract member, you'd better also annotate the types
trait {
def foo
}
is legal, but the type of foo is automatically inferred to be Unit, which almost never what you want.
Instead, do
trait {
def foo: Boolean
}
if you don't want the return type then you used
scala> def product(x: Int, y: Int) { //in lack of = it explicit uses Unit
| x*y
| }
product: (x: Int, y: Int)Unit
//equivalent to below
scala> def product(x: Int, y: Int):Unit={
| x*y
| }
product: (x: Int, y: Int)Unit
and when you write
scala> def product(x: Int, y: Int) = { //here it explicit detect return type
| x*y
| }
product: (x: Int, y: Int)Int
//equivalent to below
scala> def product(x: Int, y: Int):Int = {
| return x*y
| }
product: (x: Int, y: Int)Int
def foo(arg) { sideEffects() } is equivalent to def foo(arg) = { sideEffects(); Unit }. It is bad style because it hides your intention. (It's easy to overlook the missing =). I recommend you don't use it.
def foo(arg) = { expression } is a method that implicitly resolves to the type of the expression and is good style.
def foo(arg): Type is an abstract method definition with an explicit type. It is not equivalent to the other two examples, as no implementation is provided.
1) The procedure syntax is deprecated from scala-2.11, avoid it.
def product(x: Int, y: Int) {
x*y
}
// It always returns Unit.
// creates confusion for most beginners. deprecated for good.
2) The type inference syntax, mostly used with small/private methods.
def product(x: Int, y: Int) = {
x*y
}
It is a help from the compiler, but sometimes compiler's inference may be different from what you think.
3) The type annotation syntax.
def product(x: Int, y: Int): Int = {
x*y
}
For public APIs it is good practice to specify return type explicitly.
In some cases it is mandatory to specify return type.
For instance:
when defining recursive methods.
when compiler's inference is more specific but you need generic return type (Map in place of HashMap).
To override compiler's inference. def getId(): Long = 1
If return is used anywhere in the method body.
In Scala a function is defined as
def product(x: Int, y: Int): Int = {
x*y
}
but there there are few "shortcuts" that can be used
Since scala have good type Inference you can omit the type (unless the function is recursion one):
def product(x: Int, y: Int) = {
x*y
}
Everything is an expression. so function must return value. The last line of block of code is the return value. so if you use curved brackets {} the last line will be return. if the function has only one line there is no need for the curved brackets.
def product(x: Int, y: Int) = x*y
Since everything has to return a value "No value" is actually Unit. So if you dont want to return meaningful value (which mean you do some side effects) then use Unit as the return value:
def product(x: Int, y: Int): Unit = x*y
Using functions without the equal sign is just another way to return Unit (this also named "procedure syntax":
def product(x: Int, y: Int) { x*y }
Note that the procedure syntax is Deprecate and should be avoid!
Given an overloaded function, with one taking a function as parameter. This parameter-function takes no arguments:
def func(param: () => Unit): Unit = {
param()
}
def func(param: Int): Unit = {
println(param)
}
While calling func with an anonymous function works perfect:
func(() => println("it works"))
Using a plain function fails:
def functionAsParam(): Unit = {
println("it works")
}
func(functionAsParam)
Obviously, Scala evaluates functionAsParam and don't pass the function itself to func. Question: How can I (as a user of a library which provides funcs) pass in a non-anonymous function?
There are several ways to do this. Either you explicitly pass the function as parameter:
scala> func(() => functionAsParam)
it works
scala> func (functionAsParam _ )
it works
(These two cases are slightly different though, in the sense that in the first example, you construct new anonymous function with your other function, and in the second example, you indicate that this function should not yet be evaluated, by adding _)
Or you create a variable which is a function and pass it along:
val fval = () => println("It works")
scala> func(fval)
It works
The error comes from the fact that you defined a method, but your func expects a function. Yeah, there is a problem with overloading in scala (in other areas as well). To fix it you need manually convert your method into a function (it's called eta-expantion):
func(functionAsParam _)
If you turn on -Xprint:typer you'll see that scalac expands you method into a function:
val res4: Unit = func({
(() => functionAsParam())
});
I have some recursion code I want to refactor to use tail recursive from Enumerator, I can simplify that recursion to look like this, please ignore what functionality this functionality wants to achieve.
#tailrec
def doStuff: List[Int] => Int = {
case Nil => 0
case x :: xs => doStuff(xs)
}
If I get rid of tailrec annotation, it is working fine, the structure looks like this doStuff(doStuff(doStuff(..))). It will have stackoverflow exception.
So how can I make it tail recursive if it is a function
Anonymous functions cannot be made tail-recursive. Let us first do a very simple rewrite of your code to introduce a val to hold the resulting function.
#tailrec
def doStuff: List[Int] => Int = {
val result: List[Int] => Int = {
case Nil => 0
case x :: xs => doStuff(xs)
}
result
}
It should be clear, from there, that doStuff(xs) is not calling the anonymous function itself. It is calling the method doStuff, which returns the function you want to call. Worse, since it is a def, it actually returns a different function on every call. Hence the anonymous function is definitely not calling itself.
The problem generalizes to this simple fact: anonymous functions are, well, anonymous. So there's no way they can call themselves directly: they're always calling some other def or val that might return themselves, but the compiler doesn't know that.
For this reason, only proper defs like the one proposed by #dhg will truly be tail-recursive.
Now, if you really want to return a function value, that happens to be implemented with a tail-recursive case, you can simply convert a method into a function using theMethod _. Hence, the solution to your initial problem would be the following:
val doStuff = {
#tailrec
def rec(list: List[Int]): Int = list match {
case Nil => 0
case x :: xs => rec(xs)
}
rec _
}
Note that we declare a proper tail-recursive method (rec), that we then transform into a function value with rec _.
Probably you mean this?
#tailrec
def doStuff(list: List[Int]): Int = list match {
case Nil => 0
case x :: xs => doStuff(xs)
}
So how can I make it tail recursive if it is a function
You can't. I mean, of course you can write a tail-recursive function in Scala, but it won't help you because it won't get optimized.
Scala only optimizes direct tail-recursive method calls.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between method and function in Scala
Two ways of defining functions in Scala. What is the difference?
There are 2 ways to define a function.
scala> def a : (Int, Int) => Int = {(s:Int, t:Int) => s + t}
a: (Int, Int) => Int
scala> a
res15: (Int, Int) => Int = <function2>
scala> def b(s:Int, t:Int) : Int = s+t
b: (s: Int, t: Int)Int
scala> b
<console>:9: error: missing arguments for method b in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
b
^
scala> b(3,4)
res17: Int = 7
scala> a(3,4)
res18: Int = 7
Is there any difference in how I define functions a and b? Why do I have missing arguments error with b?
b is not a function, but a method. You can however turn b into a function by adding the _ as the compiler mentions. val f = b _. But you should only do this, if you want to pass a method of an object to a method/function that takes a function as parameter. If you just want to define a function go the normal way.
But to answer your question, there is another way:
val f = new Function2[Int,Int,Int] {
def apply(x: Int, y: Int) = x + y
}
Object Oriented languages (e.g. java) typically have classes and classes have methods, while functions are not "first-class citizens", meaning you can't assign a function directly to a variable or put a few functions in a list or send them as arguments to other functions.
If you want to send a function around in java, you have to create a class with a method and send the class around.
For instance, if you want to have a function that calculates the double of its input, you have to put it in a class, like this:
class Doubler
{
public int apply(int a)
{
return a * 2;
}
}
In functional programming languages, like Haskell, functions are "first-class", and you can store them in variables and send them around.
doubleIt :: Integer -> Integer
doubleIt x = 2 * x
As a beautiful combination of functional and object oriented, scala has both methods and functions.
// a function like in haskell
val doubleIt = (x:Int) => x * 2
// a method in an object like in java
object Doubler {
def apply(x:Int) = x * 2
}
In scala def always defines a method. Note that the REPL wraps everything you write in an object with a main (in order to be able to compile and execute it on the fly), but writing a def something not wrapped in a class/object/trait in a program would not compile.
Scala also has a few more perks to offer, to decrease the disconnect between object and first-class functions.
For one thing, the "apply" method over there in the Doubler object definition in scala is sort of magic.
Given the definition above, you can write Doubler(2) and scala's compiler will transform this into Doubler.apply(2) and happily return 4.
So you can sort of use objects as functions.
But also, you can (by putting a _ sign after the call to a method) transform the method into a real function and (say) assign it to a val.
scala> val d = Doubler.apply _
d: Int => Int = <function1>
scala> d(2)
res1: Int = 4
On the other hand, the way scala makes a function like val doubleIt = (x:Int) => x * 2 into a first class "thing" is by turning it into something like this behind your back.
object Doubler extends Function[Int, Int] {
def apply(x: Int) = x*2
}
val doubleIt = Doubler
So, yeah... a function is actually still a class with a method, more or less like in java. Except that scala does it for you and gives you a lot of syntactic sugar to use that generated class as you would use an actual function.
To make things even more interesting, since functions are first-class, one of the things you can do with them in scala is use them as return values from other functions or methods.
So when you wrote def a : (Int, Int) => Int = {(s:Int, t:Int) => s + t} you actually defined a method, called a that returns a function. It may be confusing at first (and at second, and at third....) but around the fourth time around it will probably start looking beautiful. At least that's what it did for me.