On Saturday 03 November 2007 14:36, Steve Lianoglou wrote:
> Hi Jon,
>
> > OCaml is much less
> > interesting for web programming and much more interesting for technical
> > users like scientists. I believe great things could be done with an ML
> > targetting the JVM.
>
> I believe you're actively looking at/working with scala as well, so
> I'm just wondering what (in your opinion) an OCaml-on-the-jvm
> implementation would add that can't currently be addressed by Scala
> (except for being able to run real/already-written Ocaml stuff on the
> JVM).
>
> In other words, what's scala missing that has you pining for OCaml?
>
> Just curious (from a person who hasn't done much work in either),

OCaml and F# have shown that ML's approach to structured programming using 
modules, variant types and pattern matching and extensive type inference is 
almost always preferable to OOP. When given the choice between OOP and FP, 
seasoned programmers rarely choose OOP.

However, Scala's design ignores many of the lessons learned over the past 35 
years from the ML family of languages and, instead, panders to OOP and tries 
to integrate OOP with pattern matching. While this might be of academic 
interest, it is of little practical relevance because the resulting language 
fails to capture the benefits of ML (let alone the benefits added by OCaml 
and F#).

OCaml programmers are typically over 10x as productive as Java or C++ 
programmers for a wide range of practical tasks. Despite being based upon a 
fundamentally OOP platform, F# goes a long way to capturing the productivity- 
boosting benefits of OCaml (and the whole ML family). In contrast, Scala 
fails to capture many of the benefits including some really basic ones and, 
consequently, writing correct code is much more difficult in Scala than in 
any real ML.

Moreover, the ML family of languages are designed to be succinct but Scala is 
needlessly verbose for everything from "Hello world!" upwards. The ML family 
of languages provide extensive type inference (OCaml more than most) but 
Scala has only rudimentary inference by comparison. OCaml has an unusually 
expressive type system but Scala adds little to OOP that is of practical 
importance.

For example, here is "Hello world!" in F#:

  printf "Hello world!"

and in Scala:

  object HelloWorld {
    def main(args: Array[String]) {
      println("Hello world!")
    }
  }

Here is a simple 5-line derivative function in OCaml:

# let rec d f x = match f with
    | `Var y when x=y -> `Int 1
    | `Int _ | `Var _ -> `Int 0
    | `Add(f, g) -> `Add(d f x, d g x)
    | `Mul(f, g) -> `Add(`Mul(f, d g x), `Mul(g, d f x));;
val d :
  ([< `Add of 'a * 'a | `Int of 'b | `Mul of 'a * 'a | `Var of 'c ] as 'a) ->
  'c -> ([> `Add of 'd * 'd | `Int of int | `Mul of 'a * 'd ] as 'd) = <fun>

OCaml inferred the sum type and checks the pattern match for exhaustiveness 
and redundancy. Type inference has even proven that the `Var construct will 
never survive an application of this derivative function "d".

Scala cannot infer the sum type used to represent a symbolic expression so you 
must start by declaring it explicitly:

  abstract class Expr
  case class Lit(f: Int) extends Expr
  case class Var[T](x: T) extends Expr
  case class Add(f: Expr, g: Expr) extends Expr
  case class Mul(f: Expr, g: Expr) extends Expr

Note that the declaration of the type is as big as the entire OCaml solution. 
This declaration contains numerous superfluous keywords such 
as "abstract", "case", "class", "extends" and the name of the ABC "Expr".

In Scala, the derivative function becomes another 6 lines of code:

  def d[T](f: Expr)(x: T): Expr = f match {
    case Var(y) => if (x==y) (Lit(1)) else (Lit(0))
    case Lit(_) => Lit(0)
    case Add(f, g) => Add(d(f)(x), d(g)(x))
    case Mul(f, g) => Add(Mul(f, d(g)(x)), Mul(g, d(f)(x)))
  }

The types of the arguments must be explicitly declared. You can sometimes omit 
the return type but in this case Scala is unable to infer it so you must also 
declare that explicitly.

Static checking for exhaustiveness and redundancy of such pattern matches is a 
critical feature in all other modern FPLs. OCaml is particularly clever is 
this respect:

# function
    | 0 -> true
    | 1 -> false;;
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
2
- : int -> bool = <fun>

Note how OCaml not only warns you that the pattern match is not exhaustive but 
even gives you an example of a value that is not handled.

This static checking becomes invaluable as more sophisticated pattern matches 
are used. Consider:

# let foo = function
    | true, _ -> 0
    | _, false -> 1;; 
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
(false, true)
val foo : bool * bool -> int = <fun>

OCaml correctly identifies the only value that is not handled. In constrast, 
Scala provides no such assurance, no warning, and just silently compiles this 
erroneous code:

scala> def foo(b: (Boolean, Boolean)): Int = b match {
     |   case (true, _) => 0
     |   case (_, false) => 0
     | }
foo: ((Boolean, Boolean))Int

scala> foo(false, true)
scala.MatchError: (false,true)
   at .foo(<console>:4)
   at .<init>(<console>:5)
   at .<clinit>(<console>)
   at java.lang.Class.initializeClass(libgcj.so.81)
   at RequestResult$.<init>(<console>:3)
   at RequestResult$.<clinit>(<console>)
   at java.lang.Class.initializeClass(libgcj.so.81)
   at RequestResult$result(<console>)
   at java.lang.reflect.Method.invoke(libgcj.so.81)
  ...

With the latest version of Scala you can add "sealed" to your abstract class 
to declare that it is a closed sum type (like an ordinary ML variant):

object E {
  sealed abstract class Expr
  case class Lit(f: Int) extends Expr
  case class Var[T](x: T) extends Expr
  case class Add(f: Expr, g: Expr) extends Expr
  case class Mul(f: Expr, g: Expr) extends Expr
}

in which case the Scala compiler will try to check patterns for exhaustiveness 
of redundancy but this is only available for sum types and not all types as 
all MLs do.

So, while Scala is unquestionably an improvement over Java, I do not consider 
it to be a front-runner among modern functional programming languages.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?e

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to