[Nitro] Serious discussion on Annotaitons - Part II

transfire at gmail.com transfire at gmail.com
Mon Nov 6 15:55:49 EST 2006


George Moschovitis wrote:
> >    harp:~ > cat a.rb
> > ...
> > :baz}
> >
> > Now this implementatin leaves out some of the needed shortcuts (like
> > implied class annotation) and it also leaves out the BIG issue of
> > inheritance, but those can of course can be worked in. The main thing
> > here is the simplicty of the interface. I realize it's a big change but
> > I think Ara has a point. The simplicy, uniformity and consistancy has
> > it's own merits over the elegance of the magic dot notation.
>
> Well I like this  simplicity as well. Could you introduce the
> inheritance feature?
> And what is implied class annotation? I would like to replace nitro's
> annotation with this simpler version. If you remember, I was always
> worried about the performance (and complexity) issues of the current
> implementation.

Your wish is my command. Here it is. The just about the most
straight-foward and concise implementation of Annotations possible. I
have only two outstanding issues with it. 1) Whether to use the global
variable or not (see remarks for the difference); and 2) Whether
#heritage should remain it's own method or be integrated into #ann
itself, or perhaps just rename it? FYI heritage returns the complete
inheritance chain of annotations.

I'm sure other improvments are possible. Please let me know it you have
any suggestions. Thanks.


# --- ann.rb

require 'facets/core/hash/to_h'
require 'facets/core/hash/symbolize_keys'
require 'facets/core/hash/op_add'

# By using a global veriable rather the definining a class instance
variable
# for each class/module, it is possible to quicky scan all annotations
for the
# entire system. To do the same without this would require scanning
through
# the ObjectSpace. (Still which is better?)

#$annotations = Hash.new { |h,k| h[k] = {} }

class Module

  def annotations
    #$annotations[self]  # global?
    @annotations ||= {}
  end

  def heritage(ref)
    ref = ref.to_sym
    ancestors.inject({}) { |memo, ancestor|
      ancestor.annotations[ref] ||= {}
      ancestor.annotations[ref] + memo
    }
  end

  # Set or read annotations.

  def ann( ref, keys_or_class=nil, keys=nil )
    return heritage(ref) unless keys_or_class or keys

    if Class === keys_or_class
      keys ||= {}
      keys[:class] = keys_or_class
    else
      keys = keys_or_class
    end

    if Hash === keys
      ref = ref.to_sym
      annotations[ref] ||= {}
      annotations[ref].update(keys.symbolize_keys)
    else
      key = keys.to_sym
      heritage(ref)[key]
    end
  end

  # To change an annotation's value in place for a given class or
module
  # it first must be duplicated, otherwise the change may effect
annotations
  # in the class or module's ancestors.

  def ann!( ref, keys_or_class=nil, keys=nil )
    return heritage(ref) unless keys_or_class or keys

    if Class === keys_or_class
      keys ||= {}
      keys[:class] = keys_or_class
    else
      keys = keys_or_class
    end

    if Hash === keys
      ref = ref.to_sym
      annotations[ref] ||= {}
      annotations[ref].update(keys.symbolize_keys)
    else
      key = keys.to_sym
      annotations[ref][key] = heritage(ref)[key].dup
    end
  end

end



More information about the Nitro-general mailing list