After writing my last post about Pattern matching in Scala, I was curious about how pattern matching was solved in other languages.

So in this post, I'll use the examples from the last blog post to compare how this would be solved in Scala, Haskell, ML and OCaml.

List example

The first example was to create a recursive function that prints a list of Integers as cons cells. So, let's take a look at how we would solve this using the different languages.

Scala

def pCons(list: List[Int]): String = list match { case Nil => "nil" case x::xs => "(" + x + "." + pCons(xs) + ")" }

Haskell

pCons :: [Int] -> String pCons [] = "nil" pCons (x:xs) = "(" ++ show x ++ "." ++ pCons xs ++ ")"

ML

fun pCons [] = "nil" | pCons (x::xs) = (concat ["(",(Int.toString x),".",(pCons xs),")"]);

OCaml

let rec p_cons = function | [] -> "nil" | x::xs -> "(" ^ string_of_int x ^ "." ^ p_cons xs ^ ")"

Language example

The other example defined a small language that contains 4 different types of expressions. Number, Sum, Product and Fun (function). Using this language, we can build different expressions.

Then we created 2 methods:

prn - Takes an expression as an argument, then prints it in a Clojure-like way.

- Takes an expression as an argument, then prints it in a Clojure-like way. calc - Takes an expression as an argument, which it then evaluates.

Both these methods are solved using recursive functions and pattern matching.

Defining the language

First, let's define the language using case classes for Scala, and datatypes for Haskell, ML and OCaml.

Scala

abstract class Exp case class Number(n: Int) extends Exp case class Sum(e1: Exp, e2: Exp) extends Exp case class Product(e1: Exp, e2: Exp) extends Exp case class Fun(e: Exp) extends Exp

Haskell

data Exp = Number Int | Sum Exp Exp | Product Exp Exp | Fun Exp

ML

datatype exp = Number of int | Sum of exp * exp | Product of exp * exp | Fun of exp;

OCaml

type exp = Number of int | Sum of exp * exp | Product of exp * exp | Fun of exp

Print function

Next is the prn function, that prints a given expression in a Clojure-like way.

Scala

def prn(e: Exp): String = e match { case Number(x) => x.toString case Sum(e1, e2) => "(+ " + prn(e1) + " " + prn(e2) + ")" case Product(e1, e2) => "(* " + prn(e1) + " " + prn(e2) + ")" case Fun(e) => "(fn [] " + prn(e) + ")" }

Haskell

prn :: Exp -> String prn (Number x) = show x prn (Sum e1 e2) = "(+ " ++ prn e1 ++ " " ++ prn e2 ++ ")" prn (Product e1 e2) = "(* " ++ prn e1 ++ " " ++ prn e2 ++ ")" prn (Fun e) = "(fn [] " ++ prn e ++ ")"

ML

fun prn (Number(x)) = (Int.toString x) | prn (Sum(e1, e2)) = (concat ["(+ ", (prn e1), " ", (prn e2), ")"]) | prn (Product(e1, e2)) = (concat ["(* ", (prn e1), " ", (prn e2), ")"]) | prn (Fun(e)) = (concat ["(fn [] ", (prn e), ")"]);

OCaml

let rec prn = function | Number(x) -> string_of_int x | Sum(e1, e2) -> "(+ " ^ prn e1 ^ " " ^ prn e2 ^ ")" | Product(e1, e2) -> "(* " ^ prn e1 ^ " " ^ prn e2 ^ ")" | Fun(e) -> "(fn [] " ^ prn e ^ ")"

Calculate function

Last, is the calc function that evaluates the expression given as an argument.

Scala

def calc(e: Exp): Int = e match { case Number(x) => x case Sum(e1, e2) => calc(e1) + calc(e2) case Product(e1, e2) => calc(e1) * calc(e2) case Fun(e) => calc(e)

Haskell

calc :: Exp -> Int calc (Number x) = x calc (Sum e1 e2) = calc e1 + calc e2 calc (Product e1 e2) = calc e1 * calc e2 calc (Fun e) = calc e

ML

fun calc (Number(x)) = x | calc (Sum(e1, e2)) = (calc e1) + (calc e2) | calc (Product(e1, e2)) = (calc e1) * (calc e2) | calc (Fun(e)) = (calc e);

OCaml