1 May 11:16
Re: usefulness of OOP
martin odersky <martin.odersky <at> epfl.ch>
2009-05-01 09:16:28 GMT
2009-05-01 09:16:28 GMT
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
RSS Feed