http://www.developer.com/

Back to article

Scala vs. F#: Comparing Functional Programming Features


May 19, 2010

F# and Scala, two relatively recent programming languages, provide most .NET and Java software developers with new functional programming features that are worth understanding and evaluating. (Read a Short Briefing on Functional Programming for a primer on how functional programming works.)

Scala is a Java-based, general-purpose language that is intended to appeal to both adherents of functional programming as well as devotees of more mainstream imperative and object-oriented programming. It compiles into Java bytecode and runs on top of the Java Virtual Machine (JVM).

While Scala is fundamentally a functional language, it also embodies all the elements of imperative and object-oriented languages, which gives it the promise of introducing functional programming features to a broader programming community.

F# is a general-purpose programming language developed by Microsoft to run as part of .NET's Common Language Runtime (CLR). It is based on another, orthodox functional language, Ocaml. Microsoft introduced F# into the .NET platform because of, among other reasons, the increased interest in functional programming and functional programming's suitability to high-performance computing and parallelism.

Although its syntax is distinctly functional, F# actually is a hybrid functional/imperative/object-oriented language. Its object-oriented and imperative features are present mostly for compatibility with the .NET platform, but F#'s tripartite nature is also pragmatic -- it allows programmers who use any or all of the three programming paradigms to program exclusively in one or to combine all three.

In this article, I will compare and contrast the functional features and related syntax of F# and Scala.

F# vs. Scala: First Order Functions

Functions in F# and Scala are treated as first order types. They can be passed in as arguments, returned from other functions, or assigned to a variable.

In this F# code snippet, I first define a function (increment) that adds 1 to a passed value, and then I define the function handler, which takes type myfunc and applies 2 to it as a parameter. Finally, I invoke the function handler with a parameter incremented to it. The function incrementis passed as a regular value, hence the function is being treated as a first order type:

let increment x = x + 1
let handler myfunc = (myfunc 2)   
printfn "%A" (handler increment)


Notice the type inference in the example above. F# will infer that x is an integer because I add 1 to it, and so x will be treated as an integer (Int) type.

Here is the same example in Scala:

def increment(x:Int) = x + 1
def handler( f:Int => Int) = f(2)
println( handler( increment ))


F# vs. Scala: Lazy Evaluation

F# supports lazy evaluation, but for performance reasons it is not enabled by default. Instead, F# supports so-called eager evaluation: functions can be marked for lazy evaluation by explicitly labeling them with the keyword lazy and running the program with the Lazy.force option specified.

let lazyMultiply = lazy ( let multiply = 4 * 4  )


Like F#, Scala is not lazy by default, but unlike F#, values -- not functions --have to be marked with the keyword lazy and therefore evaluated as call-by-need.

def lazyMultiply(x: => y:) = { lazy val y = x * x }


F# vs. Scala: Lambda Expressions and Currying

Currying is an essential feature of functional programming that allows for the partial application of functions and functional composition. F# supports currying. Here is an example of the curried function add in F#:

Declaration:

val add : int -> int -> int


Implementation:

let add = (fun x -> (fun y -> x + y) )


In Scala, the curried function add looks like this:

def add(x:Int)(y:Int) = x + y


F# vs. Scala: Lambda Expressions

F# also supports Lambda expressions (anonymous functions). In F#, lambda expressions are declared with the keyword fun. In the example below (adopted from F# documentation), an anonymous function is applied to a list of numbers to increment each number in the list and return a new, incremented list:

let list = List.map (fun i -> i + 1) [1;2;3] 
printfn "%A" list


Lambda expressions in Scala are defined in a very succinct fashion. This is how you would increment a function with a Lambda expression (x=>x+1) on a list of numbers (1,2,3) in Scala:

val list = List(1,2,3).map( x => x + 1 ) 
println( list )


F# vs. Scala: Pattern Matching

Pattern matching is a powerful feature of functional programming languages that allows blocks of code within the function to be 'activated' depending on the type of a value or an expression. (Think of pattern matching as a more powerful variation of the case statement.)

In F# , the vertical line character (|) is used to denote a case selector for the function match specification. Here is an F# version of a pattern-matched Fibonacci number function:

let rec fib n =
     match n with
     | 0 -> 0
     | 1 -> 1
     | 2 -> 1
     | n -> fib (n - 2) + fib (n - 1)


Like F#, Scala supports pattern matching on functions. Here is the example of a Fibonacci number calculation in Scala. Notice that Scala uses the keyword case:

def fib( n: Int): Int = n match {

    case 0 => 0
    case 1 => 1
    case _ => fib( n -1) + fib( n-2)
  }


F# vs. Scala: List Comprehensions

Originally popularized by Haskell (another, archetypical functional language), list comprehensions are in mathematical terms set-builder, notation-based expressions for the definition of lists. For example, in Haskell one would use the following list comprehension to produce a list of nums containing only squares of numbers greater than 2:

squares = [ x*x | x <- nums, x > 2 ]


The F# equivalent for list comprehension is called a generator comprehension, and it can be used for both lists and sequences. In functional languages, sequences are similar to lists except that elements in the sequences (e.g., 1…1000) are calculated only when requested, making them more storage efficient.

List generators have the following form:

[for x in collection do ... yield expr]


Sequence (seq) generators have this form:

seq {for x in collection do ... yield expr}


So, the F# version of the previously shown Haskell list-generation example for multiples of values over 2 has the following syntax:

del list = [for x in 0..100 if x > 2 do yield x*x]


In Scala, list comprehension has the following structure:

val type = for ( range ) [if (condition)] ) yield result


Here is a Scala version for multiple list comprehension:

val list = for (i <- 1 to 100; if (i > 2)) yield i*i


F# vs. Scala: Multiple Inheritance via Mixins

One notable difference between F# and Scala is the lack of support for multiple inheritance in F#. In Scala, programmers can declare that a child extends from one primary class, but that it can also inherit "traits" from other classes.

In so-called mixin class composition, subclasses inherit through mixin the delta of a class definition (i.e., a class will inherit all new definitions that are not inherited through direct inheritance). In the example below, OtherParentClass is used as a mixin.

Class MixinSubclass extends BaseClass with OtherParentClass


Base classes are declared with the keyword extends and mixins (zero or many) are declared with keyword with.

Inherited methods are explicitly overridden with the keyword override to prevent accidental overriding:

override def calculate(dx: Int, dy: Int): Distance =
    new Distance(x + dy, y + dy )


OtherParentClass would be declared with keyword trait:

trait OtherParentClass
      def count:Int
      def kmDistance = count * 1.66


Summary

For the most part -- except for Scala mixins -- F# and Scala offer similar expressive power when it comes to functional programming. They both are flexible, powerful programming languages with strong functional features. In this article, I presented an abbreviated comparative review of the most essential functional programming features of these two languages.

Why abbreviated? Because functional programming is perhaps the most flexible type of programming, offering a number of small features and subtleties that would make a detailed comparison of all features very lengthy -- far beyond the scope of a single article.

In the next installment, I will compare and contrast the features where these two languages most differ: application development models and runtime characteristics.

For Further Reading

  • The Scala Programming Language homepage
  • The Microsoft F# Developer Center
  • About the Author

    Edmon Begoli is a software architect with 14 years of professional experience on large commercial and public software projects. He is a member of the R&D staff at Oak Ridge National Laboratory.

    Sitemap | Contact Us

    Thanks for your registration, follow us on our social networks to keep up-to-date