#911 Does Fantom offer any metaprogramming features?

fury Thu 14 Jan 2010

Ruby has this concept of open classes, that is, you can add new methods to existing objects/classes, without modifying the original source code. Another nice feature of Ruby was that you could redefine an existing method, or intercept a call to a certain method, do something with the arguments, and then call it.

Does Fantom have such things?

katox Thu 14 Jan 2010

You can do most of these things using Dynamic Invoke by overriding Obj::trap.

Another possibility is to use compiler pod to load/reload class definitions - see 905.

DanielFath Thu 14 Jan 2010

Besides, metaprogramming is possible in nearly any language. Even C could meta-program itself by writing his own output to a file and then executing it (it was a pain though).

Quine example katox posted is in fact meta-programming minus execution.

brian Thu 14 Jan 2010

Another nice feature of Ruby was that you could redefine an existing method, or intercept a call to a certain method, do something with the arguments, and then call it.

I think one person's feature is another person's nightmare :-)

Fantom definitely eschews open classes for both performance and code maintenance reasons. But as katox said, you can still have eat your cake too with some other dynamic features such as the dynamic invoke operator.

In fact you can build a full alternate OO system with open classes using "->" if you wanted (we've actually done something like that for our commercial business).

Here is a simple way to build up a Python/JavaScript based object:

class Dict
{
  Str:Func funcs := Str:Func[:]  
  override Obj? trap(Str name, Obj?[]? args) { funcs[name].callOn(this, args) }

  static Void main()
  {
    obj := Dict()
    obj.funcs["a"] = |self->Int| { 3 }
    obj.funcs["b"] = |self->Int| { 4 }
    obj.funcs["add"] = |self->Int| { self->a->plus(self->b) }
    echo(obj->a)
    echo(obj->b)
    echo(obj->add)
  }
}

tactics Thu 14 Jan 2010

Let's not forget facets for metaprogramming. Facets let you flag methods and classes, optionally supplying a values to everything.

For example, if you were working with an ORM in Fantom, it would probably end up looking like this:

@table="customers"
class Customer
{
  @key Int id
  @ref CustomerGroup group 
  @field Str firstname
  @field Str lastname

  once Str fullname() { "$firstname $lastname" }
}

Then, the ORM framework would be able to automatically create/alter table definitions based on those facets.

Login or Signup to reply.