Ruby-dev summary 24298-24353

Let me see if I understand this correctly. This is essentially a quick way to
create an adapter class based on a preexisting object. Is that right, or is
there more to it?

Also, what are you using this for? It seems cool enough, but I'm trying to get
a fix on it's uses.

T.

···

On Friday 01 October 2004 03:50 am, Robert Klemme wrote:

class Adaptor
  def initialize(obj, mappings)
    @obj = obj
    scl = class<<self; self end

    # delegation of all public methods
    obj.public_methods.each do |m|
      m = m.to_sym

      unless mappings[m]
        scl.class_eval { define_method(m) { |*a| @obj.send(m,*a) } }
      end
    end

    # remapping
    mappings.each do |m,mapped|
      case mapped
        when Symbol
          scl.class_eval { define_method(m) {|*a| @obj.send(mapped,*a) } }
        when Proc
          scl.class_eval { define_method(m,&mapped) }
        else
          raise ArgumentError, "Must be Proc or Symbol"
      end
    end
  end
end

With this we can do

>> sample = %w{aa bb cc}

=> ["aa", "bb", "cc"]

>> fake_class = Adaptor.new(sample, :new => :dup, :=== => :==)

=> ["aa", "bb", "cc"]

>> x = fake_class.new

=> ["aa", "bb", "cc"]

>> "Is an instance of? #{fake_class === x}"

=> "Is an instance of? true"

>> x.id == sample.id

=> false

Here's one related to a recent thread:

  class Object
    def supers(klass=self.class.superclass)
      raise ArgumentError if ! self.class.ancestors.include?(klass)
      Functor.new do |meth, *args|
        klass.instance_method(meth).bind(self).call(*args)
      end
    end
  end

Hmm, maybe should cache the functor for efficiency.

T.

···

On Friday 01 October 2004 01:24 pm, gabriele renzi wrote:

trans. (T. Onoma) ha scritto:
> In that case you might want this:
>
> # functor.rb
>
> class Functor
> def initialize(&func)
> @func = func
> end
> def method_missing(op, *args)
> @func.call(op, *args)
> end
> end
>
> Shhh... Don't tell anyone. It's my favorite secret weapon :wink:

Ok, I don't have an use for this, but, well, indeed very cool :slight_smile:

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag news:200410011213.17426.transami@runbox.com...

class Adaptor
  def initialize(obj, mappings)
    @obj = obj
    scl = class<<self; self end

    # delegation of all public methods
    obj.public_methods.each do |m|
      m = m.to_sym

      unless mappings[m]
        scl.class_eval { define_method(m) { |*a| @obj.send(m,*a) } }
      end
    end

    # remapping
    mappings.each do |m,mapped|
      case mapped
        when Symbol
          scl.class_eval { define_method(m) {|*a| @obj.send(mapped,*a) } }
        when Proc
          scl.class_eval { define_method(m,&mapped) }
        else
          raise ArgumentError, "Must be Proc or Symbol"
      end
    end
  end
end

With this we can do

>> sample = %w{aa bb cc}

=> ["aa", "bb", "cc"]

>> fake_class = Adaptor.new(sample, :new => :dup, :=== => :==)

=> ["aa", "bb", "cc"]

>> x = fake_class.new

=> ["aa", "bb", "cc"]

>> "Is an instance of? #{fake_class === x}"

=> "Is an instance of? true"

>> x.id == sample.id

=> false

Let me see if I understand this correctly. This is essentially a quick way to
create an adapter class based on a preexisting object. Is that right, or is
there more to it?

That's it exactly. Kind of an extension of Delegator.

Also, what are you using this for? It seems cool enough, but I'm trying to get
a fix on it's uses.

Well, I presented one use, a fake class that implements important methods of a class. OTOH, it might be more appropriate to create a new class from scratch... In fact, this might be as easy:

fake_class = Class.new do

?> @sample = %w{a b c d}

def self.new() @sample.dup end
def self.===(x) @sample == x end
end

=> #<Class:0x101642b8>

fake_class.new

=> ["a", "b", "c", "d"]

fake_class.new.id

=> 134638608

fake_class.new.id

=> 134620092

fake_class === fake_class.new

=> true

Hm...

    robert

···

On Friday 01 October 2004 03:50 am, Robert Klemme wrote:

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag news:200410020857.29176.transami@runbox.com...

trans. (T. Onoma) ha scritto:
> In that case you might want this:
>
> # functor.rb
>
> class Functor
> def initialize(&func)
> @func = func
> end
> def method_missing(op, *args)
> @func.call(op, *args)
> end
> end
>
> Shhh... Don't tell anyone. It's my favorite secret weapon :wink:

Ok, I don't have an use for this, but, well, indeed very cool :slight_smile:

Here's one related to a recent thread:

class Object
   def supers(klass=self.class.superclass)
     raise ArgumentError if ! self.class.ancestors.include?(klass)
     Functor.new do |meth, *args|
       klass.instance_method(meth).bind(self).call(*args)
     end
   end
end

Hmm, maybe should cache the functor for efficiency.

Might not be a good idea since the method can change. Currently I don't know a way to detect that change as those method methods always return new instances.

Apart from that I still think that explicit super class method invocation other than a method invocing its own super implementation is a code smell that indicates the need for a refactoring.

Cheers

    robert

···

On Friday 01 October 2004 01:24 pm, gabriele renzi wrote:

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
> Hmm, maybe should cache the functor for efficiency.

Might not be a good idea since the method can change. Currently I don't
know a way to detect that change as those method methods always return new
instances.

Right. Makes me wish Ruby had an light-weight object class.

Apart from that I still think that explicit super class method invocation
other than a method invocing its own super implementation is a code smell
that indicates the need for a refactoring.

Hmm... I might say the same thing about instance_variable_set. In fact, one
might go further and say the same about class_eval, instance_eval,
define_method, etc. --in certain way all these "meta features" reek of code
smell! But it's all about the use case. There are core-language related use
cases for which these are must haves. I dare so, though, it might be better
if these features added via #require, rather then always be present.

T.

···

On Sunday 03 October 2004 06:49 am, Robert Klemme wrote:

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
news:200410041018.50833.transami@runbox.com...

> "trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
> > Hmm, maybe should cache the functor for efficiency.
>
> Might not be a good idea since the method can change. Currently I

don't

> know a way to detect that change as those method methods always return

new

> instances.

Right. Makes me wish Ruby had an light-weight object class.

What exactly do you want this for? What should it do?

> Apart from that I still think that explicit super class method

invocation

> other than a method invocing its own super implementation is a code

smell

> that indicates the need for a refactoring.

Hmm... I might say the same thing about instance_variable_set. In fact,

one

might go further and say the same about class_eval, instance_eval,
define_method, etc. --in certain way all these "meta features" reek of

code

smell! But it's all about the use case. There are core-language

related use

cases for which these are must haves. I dare so, though, it might be

better

if these features added via #require, rather then always be present.

I'd certainly put these into two different categories (different smells,
if you like). There are things that you just can't do without eval,
class_eval, instance_eval etc. But you usually can set instance variables
through normal setters (and you shouldn't if they are not present) and you
can do refactoring to access special functionality in a method. So these
are really two cups of tea.

Regards

    robert

···

On Sunday 03 October 2004 06:49 am, Robert Klemme wrote:

They have one in Evil. Essentially a Kernel-less object, which is good for
cases like this.

T.

···

On Monday 04 October 2004 10:49 am, Robert Klemme wrote:

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
> Right. Makes me wish Ruby had an light-weight object class.

What exactly do you want this for? What should it do?

Oh, I agree. I would suggest a different sets. E.g.

  require 'evaluators'
    eval
    class_eval
    instance_eval

  require 'instigators' # :wink:
    instance_variable_get
    instance_variable_set
    const_get
    const_set

and so one.

T.

···

On Monday 04 October 2004 10:49 am, Robert Klemme wrote:

I'd certainly put these into two different categories (different smells,
if you like). There are things that you just can't do without eval,
class_eval, instance_eval etc. But you usually can set instance variables
through normal setters (and you shouldn't if they are not present) and you
can do refactoring to access special functionality in a method. So these
are really two cups of tea.

where is Evil downloaded?

-a

···

On Tue, 5 Oct 2004, trans. (T. Onoma) wrote:

On Monday 04 October 2004 10:49 am, Robert Klemme wrote:

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag

Right. Makes me wish Ruby had an light-weight object class.

What exactly do you want this for? What should it do?

They have one in Evil. Essentially a Kernel-less object, which is good for
cases like this.

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

On Rubyforge.

For just the evil.rb file:
http://rubyforge.org/cgi-bin/viewcvs/cgi/viewcvs.cgi/evil/lib/evil.rb?rev=1.37&cvsroot=evil&content-type=text/vnd.viewcvs-markup

For the whole cvs:
http://rubyforge.org/cgi-bin/viewcvs/cgi/viewcvs.cgi/cvs_root.tar.gz?tarball=1&cvsroot=evil

And here she is:

# Like Object, but this provides no methods at all.
# You can derivate your own Classes from this Class
# if you want them to have no preset methods.

···

On Monday 04 October 2004 04:14 pm, Ara.T.Howard@noaa.gov wrote:

On Tue, 5 Oct 2004, trans. (T. Onoma) wrote:
> On Monday 04 October 2004 10:49 am, Robert Klemme wrote:
>> "trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
>>
>>> Right. Makes me wish Ruby had an light-weight object class.
>>
>> What exactly do you want this for? What should it do?
>
> They have one in Evil. Essentially a Kernel-less object, which is good
> for cases like this.

where is Evil downloaded?

#
# obj = KernellessObject.new
# obj.methods # ~> NoMethodError
class KernellessObject
  def self.new
    obj = ::Object.new
    obj.class = self
    return obj
  end

  self.superclass = nil
end

Seems to be that this is a bit more than just "Kernelless", this looks more
like the hollow ShellOfObject :slight_smile:

T.