Re: Design Patterns and Functional programming



On Sun, 08 Jul 2007 04:28:17 +0100, Jon Harrop wrote:

You only need to extend this example slightly to glimpse more of the power
of the functional approach. Consider an abstract syntax tree:

struct Expr {
};

struct Int : public Expr {
int n;
Int(int m) : n(m) {}
};

struct Add : public Expr {
Expr *f, *g;
Add(Expr *f2, Expr *g2) : f(f2), g(g2) {}
};

struct Mul : public Expr {
Expr *f, *g;
Mul(Expr *f2, Expr *g2) : f(f2), g(g2) {}
};

This is equivalent to:

# type expr =
| Int of int
| Add of expr * expr
| Mul of expr * expr;;
type expr = Int of int | Add of expr * expr | Mul of expr * expr

Now consider adding infix operators to simplify symbolic expressions as they
are constructed. In the functional style:

# let rec ( +: ) f g = match f, g with
| Int n, Int m -> Int (n + m)
| Int 0, e | e, Int 0 -> e
| f, g -> Add(f, g);;
val ( +: ) : expr -> expr -> expr = <fun>
# let rec ( *: ) f g = match f, g with
| Int n, Int m -> Int (n * m)
| Int 0, e | e, Int 0 -> Int 0
| Int 1, e | e, Int 1 -> e
| f, g -> Mul(f, g);;
val ( *: ) : expr -> expr -> expr = <fun>

How do you add that to the object oriented design?

No problem actually. You first derive from abstract expression an abstract
infix operation (that is - two arguments one result) and then specialize it
to concrete operation.

BTW, in a real compiler you won't have them in the form you have proposed.
Think about optimizations made later during code generation. You would
really wish to factorize infix commutative operators like a+b+c+d out into
Sum(a,b,c,d). The number of arguments becomes variable.

How do you add precedence to your design? Association order? Association
checks? [this is when x and y or z is illegal without brackets] What about
types and types matching? Reasonable error diagnostic and recovery? Array
aggregates? Literals? Function calls? Keyed parameter association?
Defaulted parameters? Extension aggregates?

Do you honestly believe that a syntax + semantic analyzer can be 100 lines
long? If not, then what about readability, maintainability, reuse etc?

Object-oriented only means that the tree and its nodes are considered
objects of some types.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
.



Relevant Pages

  • [PATCH 7/9] kconfig: simplify symbol type parsing
    ... int token; ... struct symbol *symbol; ... struct expr *expr; ... static const unsigned short int yyrline= ...
    (Linux-Kernel)
  • Re: RAD vs. performance
    ... | Int of int ... | Plus of expr * expr ... could an IDE highlight erroneous declarations? ... I've never seen an IDE that would help with implicit casting bugs. ...
    (comp.lang.misc)
  • Re: Design Patterns and Functional programming
    ... struct Int: public Expr { ...
    (comp.object)
  • Re: variable help
    ... $ perldoc -f int ... int Returns the integer portion of EXPR. ... And you might want to note that submitting a *bad* answer to the beginners ...
    (perl.beginners)
  • Re: SML macros
    ... >> I've written a little rewrite system in SML. ... >> representing symbols as ints looked up via a symbol table rather than as ... Seq of expr * expr list ... | Int of int ...
    (comp.lang.functional)