martin odersky | 1 May 11:16
Picon
Picon
Favicon

Re: usefulness of OOP

On Fri, May 1, 2009 at 12:18 AM, FFT <fft1976 <at> gmail.com> wrote:
> On Thu, Apr 30, 2009 at 2:12 PM, Jon Harrop <jon <at> ffconsultancy.com> wrote:
>
>>  open List
>>
>>  type ('lambda, 'var) expr =
>>    | Num of int
>>    | Lambda of 'lambda
>>    | Var of 'var
>>    | Apply of ('lambda, 'var) expr * ('lambda, 'var) expr list
>>
>>  type value =
>>    | Closure of (value list -> value)
>>    | Int of int
>>
>>  let rec eval (apply, var as env) = function
>>    | Num i -> Int i
>>    | Lambda body -> Closure(apply body)
>>    | Var v -> var v
>>    | Apply(f, args) ->
>>        match eval env f, map (eval env) args with
>>        | Closure f, args -> f args
>>        | _ -> invalid_arg "Apply of non-function";;
>>
>>  type de_bruijn = DeBruijn of (de_bruijn, int * int) expr
>>
>>  let rec de_bruijn env =
>>    (fun (DeBruijn body) args -> eval (de_bruijn (args::env)) body),
>>    (fun (i, j) -> nth (nth env i) j)
>>
>>  type named = Named of string list * (named, string) expr
>>
>>  let rec named env =
>>    (fun (Named(xs, body)) vs ->
>>      eval (named(fold_left2 (fun s x v -> (x, v)::s) env xs vs)) body),
>>    (fun s -> assoc s env)
>>
>> The really elucidates the power of polymorphic variants if you compare with my
>> other code!
>>
>
> Thanks, this was great!
>
> Personally, I like the second version more. The only real differences
> are that you declare your types up-front, and I think it's good for
> readability and correctness. Conciseness is important, but it's not
> everything (and none of those compilation unit restrictions nonsense
> now!)
>
> In my humble opinion, this answers Martin's challenge nicely: straight
> up ML, no "exotic" features like OO, polymorphic variants, functors,
> type coercions, etc. Would be interesting to see a Scala version now,
> to compare :-)
>
> I suspect the ML programmers Martin talked about were too eager to use
> modules, which can be excessively boilerplate-y and verbose.
>
I do not claim to be an expert in ML things, but I guess there was a
reason for using modules. The point is to have a reusable interpreter
component. That implies that the abstract interpreter framework and
its instantiations have to live in different source units. And I think
it would also imply that you have to make the types explicit at the
interface. How else would you document the contract between a the
framework and its instances?

Cheers

 -- Martin


Gmane