Scala "def" method declaration: Colon vs equals - function

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!

Related

How to decorate an immutable object graph from scala case classes

I'm reading structured JSON, using Play Frameworks' JSON Reads to build up an object graph with case classes.
An example:
case class Foo (
id: Int,
bar_id: Int,
baz_id: Int,
x: Int,
y: String
)
{
var bar: Bar = null
var baz: Baz = null
}
After building the Foo, I must come back later and decorate it by setting bar and baz. Those are defined in other JSON files and only known when all parsing is complete. But this means Foo can't be immutable.
What is the "right" way in Scala to make an immutable object, and then a decorated version of it, without repeating every field of Foo multiple times, over and over?
I know several ways that feel wrong:
make "bar: Option[Bar]" and "baz: Option[Baz]" case class parameters, and then I can use "copy" to make new versions of the Foo class with them set to something; but then I have to check them every single time they're accessed - inefficient, unsafe, not able to make a DecoratedFoo that just is guaranteed to have the right structure
make a second case class that is a copy-paste of all the structure in the first, but adding the two extra decorated parameters - but this means echoing the entire parameter list in the definition, and again when creating instances of it
Case class inheritance is apparently controversial, and in any case also appears to require me to repeat every single parameter anyway, in the subclass constructor?
Make a non-case superclass listing the common case class parameters. Then extend it in the case class. But this would seem to still require repeating every single parameter in the subclass constructor as well.
I see blogs with people talking about this problem and using reflection at runtime to populate the base attributes of their decorated copies - this avoids echo but now you have no type safety, specifying attribute names as strings, overhead, etc...
Surely Scala must have a way to let people compose more complicated immutable objects out of simpler ones without having to copy each and every part of them by hand?
You could introduce a new trait for the processed types, a class that extends that trait, and an implicit conversion:
case class Foo(bar: Int)
trait HasBaz {
val baz: Int
}
class FooWithBaz(val foo: Foo, val baz: Int) extends HasBaz
object FooWithBaz {
implicit def innerFoo(fwb: FooWithBaz): Foo = fwb.foo
implicit class RichFoo(val foo: Foo) extends AnyVal {
def withBaz(baz: Int) = new FooWithBaz(foo, baz)
}
}
So then you can do:
import FooWithBaz._
Foo(1).withBaz(5)
And, although withBaz returns a FooWithBaz, we can treat the return value like a Foo when necessary, because of the implicit conversion.
Combining Option and type parameters you can flag your case class, and track whether the processed fields are empty, statically:
import scala.language.higherKinds
object Acme {
case class Foo[T[X] <: Option[X] forSome { type X }](a: Int,
b: String,
c: T[Boolean],
d: T[Double])
// Necessary, Foo[None] won't compile
type Unprocessed[_] = None.type
// Just an alias
type Processed[X] = Some[X]
}
Example use case:
import Acme._
val raw: Foo[Unprocessed] = Foo[Unprocessed](42, "b", None, None)
def process(unprocessed: Foo[Unprocessed]): Foo[Processed] =
unprocessed.copy[Processed](c = Some(true), d = Some(42d))
val processed: Foo[Processed] = process(raw)
// No need to pattern match, use directly the x from the Some case class
println(processed.c.x)
println(processed.d.x)
I used this once in my current project. The main problem I encountered is when I want Foo to be covariant.
Alternatively, if you don't care about the bound on T:
case class Foo[+T[_]](a: Int, b: String, c: T[Boolean], d: T[Double])
then you can use Foo[Unprocessed] or Foo[Processed] when you need a Foo[Option].
scala> val foo: Foo[Option] = processed
foo: Acme.Foo[Option] = Foo(42,b,Some(true),Some(42.0))
One other strategy might be to create yet another case class:
case class Foo(
id: Int,
bar_id: Int,
baz_id: Int,
x: Int,
y: String
)
case class ProcessedFoo(
foo: Foo,
bar: Bar,
baz: Baz
)

`return` in a scala function literal

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.

Scala type parameters by declaring the type inside the function

I'm just starting to learn Scala, coming from a Java background. I have been trying to understand type parameters in functions and inference of types. This is a standard example in the Scala docs:
class Decorator(left: String, right: String) {
def layout[A](x: A) = left + x.toString() + right
}
object FunTest extends Application {
def apply(f: Int => String, v: Int) = f(v)
val decorator = new Decorator("[", "]")
println(apply(decorator.layout, 7))
}
If I try to apply a type parameter to the apply function and keep v a strong type, a type mismatch occurs. Why doesn't the type get inferred here?
def apply[B](f: B => String, v: String) = f(v) //Type mismatch
def apply[B](f: B => String, v: B) = f(v) //Works fine
Thanks
Let's take a look at apply without it's body:
def apply[B](f: B => String, v: String)
That reads "apply is a function (method) parameterized on a type B, that takes a function from B to String, and a String".
Think of B as a type variable; it will need to be instantiated at some point. That point is not the declaration of apply. It is when apply is, well, applied to ;-)
By this contract, usage like this must be allowed:
def g(i: Int): String = "i is " + i
apply(g, "foo") // Here the type variable `B` is "instantiated" to the type Int,
But given that you have a body like f(v), just substituting, we see the contradiction:
Substitute
f(v)
With
g("foo") // can't compile; g takes a B, which is an Int

return value "constrained" by function type in Scala

It seems empowering that one can effectively make assertions about legal return values of implementing methods just based on the type of the abstract function/method.
I intuitively feel (most of) the compiler behaviour below makes sense but I would appreciate a clear explanation of why I should be able to assert that
def f[T](t: T): T
can only be the identity function (except that class E compiles too). I can appreciate that we know nothing about T as it is not bounded, but there are gaps in that explanation.
The compiler reporting "found scala.Int(42) required Int" is not getting me closer to the light.
trait A{ def f[T](t: T): T }
// compiles
class B extends A{ override def f[Int](t: Int): Int = t }
// does not compile
class C extends A{ override def f[Int](t: Int): Int = t + 1 }
// does not compile
class D extends A{ override def f[Int](t: Int): Int = 42 }
// compiles
class E extends A{ override def f[Int](t: Int): Int = 42.asInstanceOf[Int] }
// compiles
class F extends A{ override def f[Int](t: Int): Int = identity(t) }
The problem in your examples is that the Int in your examples is not the normal 32-bit integer type (which is scala.Int); instead, you have a type parameter that happens to be named Int. That's confusing you: you think your Int is scala.Int, but it isn't, it's a type parameter with a confusing name.
So, for example this:
class C extends A{ override def f[Int](t: Int): Int = t + 1 }
Does not mean you are defining a method that takes a scala.Int; you're defining a method with a type parameter that has the name Int. You could give it any other name, for example X, then it would be exactly the same:
class C extends A{ override def f[X](t: X): X = t + 1 }
It doesn't compile because there are no constraints on the type parameter, so the compiler doesn't know that the type has a + method.
Jesper has the correct answer with the main question: [Int] isn't filling in a type of Int for T, it's creating a new generic type parameter confusingly named Int.
But I also have an addendum:
You are being a little too trusting that the user won't do something sneaky, even if it's valid at runtime.
def f[T](t: T): T = (t match {
case i: Int => -i
case s: String => s.reverse
case b: Boolean => !b
case o: Option[_] => None
case s: Seq[_] => throw new Exception("Ack")
case _ => t
}).asInstanceOf[T]
Not exactly the identity function any more, is it? If you forbid matches and asInstanceOf and exceptions and so on, then it's got to be identity.
Since nobody's answered the other part of the question yet:
In general, this property is called parametricity, and the guarantees you get from it are called free theorems. This only holds, by the way, if you ignore typecase (and unmarked side effects), so a huge part of Scala doesn't count.

Defining Scala Function Differently [duplicate]

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.