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 -~----------~----~----~----~------~----~------~--~---