Meta methods to govern meta data?

I was intrigued by one of Matz's "Wild and Crazy Ideas" at RubyConf--the inclusion of meta data in the comments section before a method definition.

This got me thinking about the need for metadata and Ruby's fabulous introspective capabilities and I wondered if it might be better to have a governing "metamethod" for each method. Actually, more like accessor metamethods. These metamethods would be in charge of setting or getting key/value pairs describing things about the method it is associated with:

# Returns double the input
def double(i)
     i * 2
end

meta :double, :require => 'i.is_a? Fixnum'
meta :double, :comments
=> 'Returns double the input'

I don't quite like the syntax yet, (probably because we don't really have a facility yet to talk about methods like this); however, I do like the flexibility provided. Perhaps we could make a new syntax like this:

def double>require(i)
     i.is_a? Fixnum
end

def double>comment(original_comment)
     "Haha! I can over-ride the comment."
end

And we could even do some cool stuff like custom namespace selectors:

def double>visibility(looking_at_me)
     [Object, ActiveRecord].include? looking_at_me
end

(i.e. the method would be called prior to any reference to 'double' and it would return 'true' if it is visible from within the caller's scope / namespace).

We could even talk about meta-metamethods:

def double>visibility>comment
     "Comment for the 'double>visibility' metamethod"
end

Duane Johnson
(canadaduane)

Duane Johnson wrote:

I was intrigued by one of Matz's "Wild and Crazy Ideas" at RubyConf--
the inclusion of meta data in the comments section before a method
definition.

This got me thinking about the need for metadata and Ruby's fabulous
introspective capabilities and I wondered if it might be better to
have a governing "metamethod" for each method. Actually, more like
accessor metamethods. These metamethods would be in charge of
setting or getting key/value pairs describing things about the method
it is associated with:

# Returns double the input
def double(i)
     i * 2
end

meta :double, :require => 'i.is_a? Fixnum'
meta :double, :comments
=> 'Returns double the input'

See Facets annotation.rb. And I would urge you to call them annotations
and not metadata. metadata is more apt to describing langauge reflexion
and in general is too generic a terminology.

I don't quite like the syntax yet, (probably because we don't really
have a facility yet to talk about methods like this); however, I do
like the flexibility provided. Perhaps we could make a new syntax
like this:

def double>require(i)
     i.is_a? Fixnum
end

def double>comment(original_comment)
     "Haha! I can over-ride the comment."
end

And we could even do some cool stuff like custom namespace selectors:

def double>visibility(looking_at_me)
     [Object, ActiveRecord].include? looking_at_me
end

(i.e. the method would be called prior to any reference to 'double'
and it would return 'true' if it is visible from within the caller's
scope / namespace).

We could even talk about meta-metamethods:

def double>visibility>comment
     "Comment for the 'double>visibility' metamethod"
end

I fear more syntax.

T.

I think you could extend Object to define something working like this:

comment "Doubles the number"
params :n => "Number to be doubled"
def double(n)
  n * 2
end

Object could define 'comment' and 'params' and other metadata functions
(or annotations, it's just symantics) to store those values and apply
them to the next method defined.

Maybe I'll try and whip it up tonight?
  .adam sanderson

Hi --

I was intrigued by one of Matz's "Wild and Crazy Ideas" at RubyConf--the inclusion of meta data in the comments section before a method definition.

This got me thinking about the need for metadata and Ruby's fabulous introspective capabilities and I wondered if it might be better to have a governing "metamethod" for each method. Actually, more like accessor metamethods. These metamethods would be in charge of setting or getting key/value pairs describing things about the method it is associated with:

# Returns double the input
def double(i)
  i * 2
end

meta :double, :require => 'i.is_a? Fixnum'

It seems awkward (even leaving duck-typing issues aside :slight_smile: to have a
constraint like that stored in a kind of eval string, rather than just
executed as part of the method. I'm not sure what's gained.

meta :double, :comments
=> 'Returns double the input'

In some ways I prefer going in the other direction -- that is, letting
the method be its own comment as much as possible. I can't help
thinking that part of the beauty of the language is that

   def double(i)
     i * 2
   end

is so complete, and so completely transparent. I'd be loathe to add
even one line of comment to it, and even more so to add a separate
method call ("meta") to store comments.

I understand (a) that this was just an example, and (b) that some
people prefer to have comments for every method, no matter how
self-documenting it is. I don't; I prefer the source code to be as
clean as possible (though no cleaner :slight_smile:

David

···

On Wed, 26 Oct 2005, Duane Johnson wrote:

--
David A. Black
dblack@wobblini.net

It seems to me that if you want to associate annotations with a
particular method they need to be syntactically connected to the
def/end block. In your example there is no way to do that unless
you are proposing that comment and params etc. all become keywords.
I'd like to avoid that type of keyword explosion.

Thinking out loud...

The syntax of a method definition already has a structure that admits
to additional "clauses":

     def name(arg1, arg2)
         # body
     rescue
         # code
     ensure
         # code
     end

Why not extend this to something like:

     def name(arg1, arg2)
     notes
         comment "This is a comment"
     body
         # body
     rescue
         # code
     ensure
         # code
     end

Alternatively you could put the notes at the end to avoid
the addition of the 'body' keyword.

     def name(arg1, arg2)
         # do something
     notes
         comment "This is an example"
     end

Another variation would be to have the annotation keyword
be an alternate syntax for the start of a method definition:

     notes
         description "This method takes two arguments"
         status :experimental
     def name(arg1,arg2)
         # code
     ensure
         # code
     end

There is the question of the syntax of the text between
'notes' and 'def'. Probably best to reuse the existing
method syntax but treat the "methods" that appear between
'notes' and 'def' as no-ops.

A similar syntax could be used to annotate classes:

notes
     description "This is an annotated class"
     author "Gary Wright"
class Sample

   notes
     "This is an annotated method"
   def foo
   end
end

For what it is worth, this is very similar to Eiffel's "indexing"
clause.

Gary Wright

Gary Wright

···

On Oct 26, 2005, at 3:32 PM, Adam Sanderson wrote:

I think you could extend Object to define something working like this:
comment "Doubles the number"
params :n => "Number to be doubled"
def double(n)
  n * 2
end

I think the comments example isn't a good one, but there are some other
reasons to annotate. For instance, it may be useful to annotate
objects with information about how to display them in a gui for
instance.
  .adam

It's a plesant notation, but a couple issues with the ideas Gary
presents.

* How to dynamically set annotations? Even with this nice looking
notation you would still need a way to do via normal methods.

* It's important to allow annotations for methods that do not
neccessarily exit. In this way annotations would be reusable. For
example here is what you can do with facets/annotation.rb

  module MyAnnotations
    ann :foo, :comment => "foo is alwasy an example"
  end

  class MyClass
    include MyAnnotations

    ann self, :comment => "This is an annotated class."

    def foo
      puts "foo"
    end

    ann :foo, :author => "trans"

  end

  MyClass.ann.foo.author #=> "trans"
  MyClass.ann.foo.comment #=> "foo is alwasy an example"
  MyClass.ann.self.comment #=> "This is an annotated class."
  MyClass.annotation.comment #=> "This is an annotated class."

T.

* How to dynamically set annotations? Even with this nice looking
notation you would still need a way to do via normal methods.

How about adding methods to Class and Method?

     class Sample
         def foo(a1, a2); end
     end

     Sample.annotate(:author => "Gary Wright")

     method_obj = Sample.new.method("foo")

     method_obj.annotate( :comment => "this is the comment", :annotated => Time.now )

* It's important to allow annotations for methods that do not
neccessarily exit. In this way annotations would be reusable. For
example here is what you can do with facets/annotation.rb

It seems that if you extended Class and Method as I hinted at above that
you could handle run-time annotation with no change to the language syntax.
Reuse could be accomplished by passing hash objects around as needed.

On the other hand, if the desire is to make annotations useful as source code
documentation (or for use by language tools that are manipulating the *source*) then you
probably need some sort of change to the language syntax.

The problem with the facets/annotation.rb approach is that there is no way to
statically examine the source and discover the annotations since syntactically
the mechanism consists of standard method calls.

Gary Wright

···

On Oct 26, 2005, at 8:12 PM, Trans wrote: