Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions vs methods in Scala

Tags:

scala

I am watching Runar Bjarnason present Functional Programming for Beginners, and at 14:45 he defines a method:

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0 

and a function:

val isEven = isDivisibleBy(2) 

What are the pros and cons of defining isEven as a function rather than a method?

I have read Scala Functions vs Methods as well as Difference between method and function in Scala, and I understand the semantic differences, but I wonder if there's some deeper reason in this case why a function might or might not be preferable to using a method:

def isEven = isDivisibleBy(2) 
like image 480
earldouglas Avatar asked Jan 29 '11 21:01

earldouglas


People also ask

What is the difference between functions and methods?

A function is a set of instructions or procedures to perform a specific task, and a method is a set of instructions that are associated with an object.

What are methods in Scala?

A Scala method is a part of a class which has a name, a signature, optionally some annotations, and some bytecode where as a function in Scala is a complete object which can be assigned to a variable. In other words, a function, which is defined as a member of some object, is called a method.

Should I use method or function?

Here's a simple rule of thumb: if the code acts upon a single instance of an object, use a method. Even better: use a method unless there is a compelling reason to write it as a function. Don't over think it.

What is function type in Scala?

Here, Scala function is first-class value. Scala also has methods, but these differ only slightly from Scala function. A method belongs to a class; it has a name, a signature, [optionally, ] some annotations, and some bytecode. A function is a complete object that we can store in a variable.


2 Answers

Under the hood, there are other differences between functions and methods. Generally, a plain method generated less overhead than a function (which technically is an object with an apply method).

However, if you try not to care about those differences and think of def, val and var as fields with different semantics, then it’s simply that def evaluates every time it gets called while val evaluates only once.

So, a val isEven = isDivisibleBy(2) should call isDivisibleBy(2) during its definition and assign the result of isDivisibleBy(2). E.g. it replaces the k in

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0 

with 2 and assigns the result of the final expression (in this case there is only one expression):

val isEven: Int => Boolean = i => i % 2 == 0 

def isEven on the other hand does no such evaluation and results in a call to isDivisibleBy(2) every time.

That means, later, when you execute the code, isEven(11) generates in case of a val

11 % 2 == 0 

and in case of a def, you’ll have

isDivisibleBy(2)(11) 

and only after evaluating isDivisibleBy you’ll get the result.

You can add some debug code to isDivisibleBy to see the difference:

def isDivisibleBy(k: Int): Int => Boolean = {   println("evaluating isDivisibleBy")   i => i % k == 0 } 
like image 191
Debilski Avatar answered Sep 30 '22 16:09

Debilski


I'd like to address another point here. This defines isEven as a method:

def isEven = isDivisibleBy(2) 

And this defines isEven as a method as well:

val isEven = isDivisibleBy(2) 

In both cases, isEven is a method which, when called, return a function.

In the first case, isDivisible(2) is called every time isEven is called. For example, this calls isDivisible(2) three times:

def isEven = isDivisibleBy(2) List(1,2,3).filter(isEven) 

In the second case, isDivisible(2) is called once (at construction time, or when that line in a definition is executed), and that value is retrieved every time isEven is called. The following example calls isDivisible(2) one time only:

val isEven = isDivisibleBy(2) List(1,2,3).filter(isEven) 
like image 45
Daniel C. Sobral Avatar answered Sep 30 '22 18:09

Daniel C. Sobral