The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Type-safe prototype-based programming with first-class selectors and namespaces in OCaml

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Eigen Class

Posts: 358
Nickname: eigenclass
Registered: Oct, 2005

Eigenclass is a hardcore Ruby blog.
Type-safe prototype-based programming with first-class selectors and namespaces in OCaml Posted: Feb 17, 2009 12:44 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Eigen Class.
Original Post: Type-safe prototype-based programming with first-class selectors and namespaces in OCaml
Feed Title: Eigenclass
Feed URL: http://feeds.feedburner.com/eigenclass
Feed Description: Ruby stuff --- trying to stay away from triviality.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Eigen Class
Latest Posts From Eigenclass

Advertisement

Adrien Friggeri presented a very simple way to do prototype-based programming in OCaml. He defines objects as a hash table (with one slot per instance variable/method) plus an optional reference to the parent, but in doing so completely bypasses the type discipline! As he says

it's horrible, but funny

Adrien's method loses the type of the object's fields and forces you to use manual annotations, which, if wrong, will easily cause a segfault:

((get o "bar") : 'a->'b) print_endline
(* slot "bar" of object o*)

Fortunately, there is a way to recover type-safety. All we have to do is to turn selectors into first-class values, which also carry the type of the slot. Sounds familiar? This is what you have to do to implement property lists in OCaml. This method has interesting consequences:

  • methods are statically typed: the type system verifies that method arguments have the right types

  • "duck-typing" is supported natively

  • selectors can be grouped in namespaces, and it is possible to parameterize code over a selector namespace

  • since selectors are first-class you can pass them around safely (think something like Ruby's obj.send(:foo) where the selector carries a type)

Object model

The basic object model is very simple: each object has got a table (implemented as a property list) with methods ("slots"), and an optional parent (it'd be trivial to extend it to multiple parents).

module P = Plist

type obj = { dict : P.t; mutable parent: obj option }

let clone x = { dict = P.create (); parent = Some x }

The base object is obj:

let obj = { dict = P.create (); parent = None }

Setting the value of a slot is trivial too:

let set obj selector v = P.set obj.dict selector v

Method lookup is a bit more involved, but still easy: it's just a recursive function that tries to find the method for the specified selector and tries again in the parent if not found:

exception Method_not_found

let (%) t meth =
  let rec dispatch t meth self = match P.get t.dict meth with
      Some f -> f self
    | None -> match t.parent with
          Some p -> dispatch p meth self
        | None -> raise Method_not_found
  in dispatch t meth t

The (%) operator is used as in object%selector. Since function application binds more tightly that any operator, parentheses are needed if the method takes arguments: (object%dostuff) arg1 arg2. This is a bit inconvenient, but easily solved with a prefix operator:

let (!!) meth obj = obj%meth

It is now possible to write

!!dostuff obj arg1 arg2

Selectors

The object model is almost complete, only selectors remain to be done. A selector is just a property that will be used as the key in the property list holding object methods:

type 'a selector = 'a P.property

let new_selector = P.new_property

It is often convenient to create a new selector and define the corresponding method for an object:

let define t f =
  let prop = P.new_property () in
    set t prop f;
    prop

The basic machinery is in place now:

let duck = clone obj
let quack = define duck (fun self -> print_endline "QUACK!")

(* ... *)

duck % quack;  (* or !!quack duck *)
whatever % quack

Selector namespaces

The name used to refer to a selector carries no meaning by itself:

(* duplicate the draw selector *)
let do_it = draw
...
!!draw obj;
!!do_it obj (* same thing *)

We only need different selector names to the extent that we need to refer to several selectors in the same context, but we could place selectors with the same name in different modules:

module Data =
struct
  let load = new_selector ()
  ...
end

module Guns =
struct
  let load = new_selector ()
  ....
end

and then discriminate at call time:

!!Guns.load gun 2; (* bullets *)
!!Data.load level;

We can also parameterize code in a functor over a module with the selectors, or even use objects as the namespaces:

obj % namespace1#doit;
obj % namespace2#doit;

A small example

I'm reusing this minimal sample OO program as an example method invocation. We have a shape prototype and two derived prototypes (rectangle and circle) with trivial move, rmove (relative move) and draw methods.

A function that uses subclass polymorphism (sub-prototype polymorphism here?) to move and draw a list of shapes looks like this:

let f l = List.iter (fun o -> o%draw; !!rmove o 100 100; !!draw o) l

I've used the two possible syntaxes to call o's draw method.

Read more...

Read: Type-safe prototype-based programming with first-class selectors and namespaces in OCaml

Topic: Block to Hash Conversion for Ruby Config Blocks Previous Topic   Next Topic Topic: Erich Gamma on Eclipse Lessons, Agility, and Open Source

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use