Why Ocaml Is Better Than Perl «!Caml Programmers Do‹ It Statically.!» XL
«!If you’re interested in text-based I/O with no data structures, forget about C++ and Caml, and use Perl.!» XL why OCaml is better than Perl «!Caml programmers do‹ it statically.!» XL
YAPC::Europe Ronan Le Hy Paris, August 2003 Lyon.pm [email protected]
OCaml, a pragmatic functional language with inferred strict typing.
1 symbolic datastructures being manipulated ] somewhere in a compiler (not so) far, far away… PIR Perl 6 abstract if $I9<$I8 goto L2 if (cond) $I12=$P26 { ternary( $I10=$I12-1 do_this cond, $P27=$I10 4 do_this, 4 } goto L1 do_that) L2: else $P27=$P26 { L1: do_that $P32=$P27 }
This is about going from concrete code in Perl, to concrete code in IMCC assembler. The emphasis here is on the symbolic middle part: a tree of nodes. How do you define and process the datastructures in the middle - how do you construct and transform them? So let’s think about generating IMC code from the tree.
2 choose your poison ^ objects: P6C::ternary, P6C::Binop, P6C::incr… using Class::Struct ^ methods: tree, val… sub P6C::ternary::val { code(< _ code organised around node types _ adding a type is easy, adding an operation is harder _ no declaration of possible nodes -- runtime debugging In the current Perl 6 compiler, we have a class for each possible node type. Each node has methods, for instance val which converts a node to assembler. The val method is used to generate code for a node of the abstract syntax tree. The val method for an if-then-else calls the val method on the condition, the then part, and the else part. 3 the OCaml way [1] ^ type node = | Binop of op * node * node | Unop of op * node | Ternary of node * node * node | … ^ let val n = match n with | Ternary(cond,then,else) -> … val cond … val then … val else … | Binop(op, n1, n2) -> … | … _ code organised around operations _ adding an operation is easy, adding a node type is harder _ static checking of type/operations adequacy _ this organisation of code makes sense (for me) My main point here: When manipulating abstract datatypes, it makes sense to define datatypes firsthand, and then write the processings. By the way, in the P6C sources, all val methods are defined together -- visually, things are grouped by methods instead of objects: this is somewhat going around the classical object framework -- and it’s a small step in the modular (OCaml) way of doing things. 4 conclusion? ] good old modules/objects disagreement [2] [3]: 2 (at least) ways to do it ] Perl would only allow the object style? (OCaml allows both) ] would a form of enumerated datatype declaration + typechecking be feasible/practical? [4] ] Class::Variant as a partner to Class::Struct? The module/object thing is about what should be easier: adding a possible node type, or adding an operation (an optimizing pass, a new transformation of the tree…) The object organisation is probably not inferior, it’s just DIFFERENT :). There’s a matter of taste in there. Extensibility of treatments, and extensibility of datatypes are at stake, along with the possibility of static typechecking. 5 references ][1] why ML/OCaml are good for writing compilers, D. VandenBerghe http://flint.cs.yale.edu/cs421/case-for-ml.html ] [2] Mixing modules and objects, D. Remy http://cristal.inria.fr/~remy/cours/appsem/ocaml- mixins.html ] [3] Objects and classes vs modules in OCaml, X. Leroy http://pauillac.inria.fr/~xleroy/talks/icfp99.ps.gz ] [4] Strong typing and Perl, M.-J. Dominus http://perl.plover.com/yak/typing/ 6