Scala vs. F#: Comparing Functional Programming Features
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 increment
is 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)
}
Page 1 of 2
This article was originally published on May 19, 2010