Looking for an "inversion" pattern

I’m sure there’s a clean way to do this in Ruby, but I haven’t figured
it out.

I’d like to create a method +foo+ that transforms:

my_obj.foo.some_method(*args)

to

MyClass.some_method(my_obj, *args)

Maybe I’m overthinking this. I’ll keep working on this, but in the
meantime, I’m open to suggestions.

Thanks!

– ff

Fearless F. wrote in post #992929:

Maybe I’m overthinking this…

Meh. I s’pose I can substitute an underscore for a period:

my_obj.foo_some_method(*args)

… whereupon this become a simple mixin on my_obj’s class:

def foo_some_method(*args) {
MyClass.some_method(self, *args)
}

The only potential disadvantage is that I need to write one of these for
each method. The advantages include likely to run much faster (than
constructing lambdas or invoking method_missing processing) and possibly
easier to understand and maintain than what I was originally trying to
do.

Fearless F. wrote in post #992929:

I’d like to create a method +foo+ that transforms:

my_obj.foo.some_method(*args)

to

MyClass.some_method(my_obj, *args)

class MyClass
def self.some_method(obj, *args)
puts “MyClass.some_method:”
puts “obj: #{obj.inspect}”
puts “args: #{args.inspect}”
end
end

def define_foo(obj, clazz, method)
obj.singleton_class.class_eval do
define_method :foo do
Class.new do
define_method method do |*args|
clazz.send(method, obj, *args)
end
end.new
end
end
end

my_obj = “my_obj thing”
args = [1,2,3]
define_foo(my_obj, MyClass, :some_method)
my_obj.foo.some_method(*args)

=>

MyClass.some_method:

obj: “my_obj thing”

args: [1, 2, 3]

Returning facade or proxy objects like this can be an elegant solution
to certain problems. It’s rather high on the abstraction ladder, though,
and without knowing the context I would wonder if more direct solutions
are possible.

@Kevin:

Kevin M. wrote in post #992945:


def define_foo(obj, clazz, method)
obj.singleton_class.class_eval do
define_method :foo do
Class.new do
define_method method do |*args|
clazz.send(method, obj, *args)
end
end.new
end
end
end

That’s some mighty fine code-fu – back in the day I had no problem with
metaprogramming constructs in scheme, but I’m not yet at ease with the
syntax and class structure of Ruby.

Returning facade or proxy objects like this can be an elegant solution
to certain problems. It’s rather high on the abstraction ladder, though,
and without knowing the context I would wonder if more direct solutions
are possible.

Well, yes – as per my previous post. Since you must call define_foo()
for each object & method you want to cover, I don’t see a lot of
advantage to the approach. But it does show off Ruby’s function
defining tricks nicely.

On Fri, Apr 15, 2011 at 7:16 AM, Fearless F. [email protected] wrote:

Maybe I’m overthinking this. I’ll keep working on this, but in the
meantime, I’m open to suggestions.

I would create a method foo that returns a proxy that remembers which
was the original receiver. This proxy can have a method_missing
implementation that calls MyClass.xxxx passing the original receiver
and all params. For example:

ruby-1.8.7-p334 :003 > class Proxy
ruby-1.8.7-p334 :004?> def initialize target
ruby-1.8.7-p334 :005?> @target = target
ruby-1.8.7-p334 :006?> end
ruby-1.8.7-p334 :007?> def method_missing meth, *args, &blk
ruby-1.8.7-p334 :008?> MyClass.send(meth,@target,*args,&blk)
ruby-1.8.7-p334 :009?> end
ruby-1.8.7-p334 :010?> end
=> nil
ruby-1.8.7-p334 :011 > class Something
ruby-1.8.7-p334 :012?> def foo
ruby-1.8.7-p334 :013?> Proxy.new self
ruby-1.8.7-p334 :014?> end
ruby-1.8.7-p334 :015?> end
=> nil
ruby-1.8.7-p334 :016 > class MyClass
ruby-1.8.7-p334 :017?> def self.test1 obj, *args
ruby-1.8.7-p334 :018?> p [obj,*args]
ruby-1.8.7-p334 :019?> end
ruby-1.8.7-p334 :020?> end
=> nil
ruby-1.8.7-p334 :021 > my_obj = Something.new
=> #Something:0xb72c8514
ruby-1.8.7-p334 :022 > my_obj.foo.test1 1,2,3
[#Something:0xb72c8514, 1, 2, 3]

I don’t know if method foo is part of your class, or maybe you can
build a method and extend the required objects with it.

Jesus.

On Fri, Apr 15, 2011 at 8:27 AM, Fearless F. [email protected] wrote:

MyClass.some_method(self, *args)
}

The only potential disadvantage is that I need to write one of these for
each method. The advantages include likely to run much faster (than
constructing lambdas or invoking method_missing processing) and possibly
easier to understand and maintain than what I was originally trying to
do.

I am sorry, I still do not understand your motivation to have a class
method which receives an instance as first argument. Isn’t this
conceptually exactly what an instance method is for? Why do you need
this?

If you need this as general pattern you could always do

class X
def method_missing(m, *a, &b)
self.class.send(m, self, *a, &b)
end

def self.foo(obj, str)
printf “%p: %s\n”, obj, str
end
end

X.new.foo 123

But I would seriously question the wisdom of this. :slight_smile:

Other than that I would follow Jesus’s approach to make #foo create a
proxy instance. Here’s another way to do it which would also allow
method chaining on the proxy:

class Proxy < BasicObject
def initialize(orig, delegate)
@orig = orig
@delegate = delegate
end

def method_missing(m, *a, &b)
res = @delegate.send(m, @orig, *a, &b)
@orig.equal?(res) ? self : res
end
end

class Object

create proxy for delegation to given

instance

def proxy(delegate)
Proxy.new(self, delegate)
end
end

class YourClass
def proxy
super(MyClass)
end
end

Kind regards

robert

Fearless F. wrote in post #992947:


def define_foo(obj, clazz, method)
obj.singleton_class.class_eval do
define_method :foo do
Class.new do
define_method method do |*args|
clazz.send(method, obj, *args)
end
end.new
end
end
end

That’s some mighty fine code-fu…

Um, no it’s not. Inspecting from top to bottom: (a) open the singleton
class, (b) define a method, © create an instance of a new class (d)
define a method. This has nothing to do with code-fu.

One of the problems with Ruby is that the syntax changes depending on
the compile-time or run-time context, which is a totally arbitrary
distinction. It’s a disservice to programmers because it makes them
say “code-fu” when presented with the run-time counterparts of
familiar, mundane compile-time constructs.

Don’t get me started about using eval to “fix” that.

Since you must call define_foo() for each object & method you want to
cover, I don’t see a lot of advantage to the approach.

You can automate it as much as you like, including removing the need
for define_foo(). Perhaps you took my code too literally.

Thanks everybody!!

@Jesús:

I like your suggestion. It is simple and does what I’m looking for.

@Robert K:

I am sorry, I still do not understand your motivation to have a class
method which receives an instance as first argument.

My motivation is that I was writing a lot of code like this:

module HasXattr
def xattr_reference(key); Xattr.xattr_reference(self, key); end
def xattr_store(key, value); Xattr.xattr_store(self, key, value);
end
def xattr_has_key?(key); Xattr.xattr_has_key?(self, key); end
def xattr_delete(key); Xattr.xattr_delete(self, key); end

end

… and I thought to myself: this is Ruby. There must be a better way.
I guess I should have shown this concrete example earlier in the thread.

@Kevin:

One of the problems with Ruby is that the syntax changes depending on
the compile-time or run-time context, which is a totally arbitrary
distinction.

As I said, I came from a scheme background where everything was
syntactically simple and life was simple. Ah, for those days. I guess
I should have said “that’s mighty fine Ruby-fu”, since your
understanding of Ruby far outstrips mine.

Again, thanks all…

  • ff

Kevin M. wrote in post #992945:

Fearless F. wrote in post #992929:

I’d like to create a method +foo+ that transforms:

my_obj.foo.some_method(*args)

to

MyClass.some_method(my_obj, *args)

class MyClass
def self.some_method(obj, *args)
puts “MyClass.some_method:”
puts “obj: #{obj.inspect}”
puts “args: #{args.inspect}”
end
end

def define_foo(obj, clazz, method)
obj.singleton_class.class_eval do
define_method :foo do
Class.new do
define_method method do |*args|
clazz.send(method, obj, *args)
end
end.new
end
end
end

my_obj = “my_obj thing”
args = [1,2,3]
define_foo(my_obj, MyClass, :some_method)
my_obj.foo.some_method(*args)

=>

MyClass.some_method:

obj: “my_obj thing”

args: [1, 2, 3]

Returning facade or proxy objects like this can be an elegant solution
to certain problems. It’s rather high on the abstraction ladder, though,
and without knowing the context I would wonder if more direct solutions
are possible.

I don’t know what’s conceptually easier to understand, but in ruby there
is no limit to how high you can stack singleton methods, e.g.:

obj.foo
obj.foo.some_method

If obj.foo() returns obj’s singleton class, then some_method() is being
called as a class method of the singleton class. That means some_method
is a method inside the singleton class’s singleton class:

obj’s class
^
|
|
singleton2: some_method()
^
|
|
singleton1: foo() -> returns singleton1
^
|
|
obj

obj.foo.some_method

And you can add as many singleton classes to the method lookup path as
you want. For instance, if you have this call:

obj.foo.some_method.do_stuff

and obj.foo.some_method() returns singleton2, then do_stuff() is being
called as a class method of singleton2, i.e. do_stuff() is a method in a
parent class, singleton3, above singleton2.

So in the original example at the top of the post, if the
creating-a-new-anonymous-class-with-a-method-named-some_method-and-returning-an-instance-of-that-class
is too hard to follow, you could do this:

class MyClass
def self.some_method(obj, *args)
puts “MyClass.some_method:”
puts “obj: #{obj.inspect}”
puts “args: #{args.inspect}”
end
end

def define_foo(obj, clazz, method)
obj.singleton_class.class_eval do
singleton = self #see comment below

  define_method :foo do
    #Class.new do
      #define_method method do |*args|
        #clazz.send(method, obj, *args)
      #end
    #end.new


    #In here, self is equal to the obj that
    #will eventually call foo()--not obj.singleton_class.
    #Hence, the need to do singleton = self above.
    #Another way to think about it is, ruby is constantly
    #changing the value of self, so if you create a
    #a closure over self, ruby can change its value
    #to something you don't want.  By assigning self to
    #a local name, like 'singleton', ruby won't change
    #the value of singleton, and the code doesn't change
    #singleton's value, so it remains a fixed reference to
    #obj.singleton_class

    singleton.singleton_class.class_eval do
      define_method method do |*args|
        clazz.send(method, obj, *args)
      end
    end

    singleton #return the singleton class
  end

end

end

my_obj = “my_obj thing”
args = [1,2,3]
define_foo(my_obj, MyClass, :some_method)
my_obj.foo.some_method(*args)

–output:–
MyClass.some_method:
obj: “my_obj thing”
args: [1, 2, 3]

On 15.04.2011 17:40, Fearless F. wrote:

Thanks everybody!!

You’re welcome!

 def xattr_delete(key); Xattr.xattr_delete(self, key); end
 ...

end

… and I thought to myself: this is Ruby. There must be a better way.
I guess I should have shown this concrete example earlier in the thread.

With my code you could do

module HasXattr
def xattr # foo in your lingo
proxy(Xattr)
end
end

or directly use it in your class

module HasXattr
def xattr # foo in your lingo
proxy(Xattr)
end
end

Then you can do

obj.xattr.has_key? “k”

or

obj.xattr.tap |x|
x.store “k”, “v” unless x.has_key?
end

Btw, what is Xattr? Where does it come from and what does it do? From
the looks it seems to be some external storage for attributes associated
with your instance which you do not want to store in the instance itself
(for whatever reasons). What do you need that for?

Kind regards

robert

7stud – wrote in post #993237:

I guess since obj is visible in all the nested blocks, its not
strictly necessary to do the singleton = self trick–you can always get
the singleton class from obj using obj.singleton_class:

class MyClass
def self.some_method(obj, *args)
puts “MyClass.some_method:”
puts “obj: #{obj.inspect}”
puts “args: #{args.inspect}”
end
end

def define_foo(obj, clazz, method)

obj.singleton_class.class_eval do
  define_method :foo do
    obj.singleton_class.singleton_class.class_eval do
      define_method method do |*args|
        clazz.send(method, obj, *args)
      end
    end

    obj.singleton_class
  end

end

end

Fearless F. wrote in post #992929:

I’m sure there’s a clean way to do this in Ruby, but I haven’t figured
it out.

I’d like to create a method +foo+ that transforms:

my_obj.foo.some_method(*args)

to

MyClass.some_method(my_obj, *args)

Not sure, but would bound or unbound methods help you?

bound_method = my_obj.method(:foo)
bound_method.call(*args)

unbound_method = my_obj.class.instance_method(:foo)
unbound_method.bind(my_obj).call(*args)

On 16.04.2011 23:14, Brian C. wrote:

MyClass.some_method(my_obj, *args)

Not sure, but would bound or unbound methods help you?

bound_method = my_obj.method(:foo)
bound_method.call(*args)

unbound_method = my_obj.class.instance_method(:foo)
unbound_method.bind(my_obj).call(*args)

You can only bind to instances of the original type. You cannot use
#unbind and #bind to let a method be called on a different type. But
this would be necessary for the OP’s requirement to be fulfilled.

irb(main):001:0> class Foo
irb(main):002:1> def self.bar;123;end
irb(main):003:1> end
=> nil
irb(main):004:0> m=Foo.method(:bar).unbind
=> #<UnboundMethod: #Class:Foo#bar>
irb(main):005:0> f=Foo.new
=> #Foo:0x105a24a4
irb(main):006:0> m.bind(f)
TypeError: singleton method called for a different object
from (irb):6:in bind' from (irb):6 from /usr/local/bin/irb19:12:in
irb(main):007:0> m.bind(Foo)
=> #<Method: Foo.bar>
irb(main):008:0> m.bind(Foo).call
=> 123

Kind regards

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs