I have 2 classes whose object should act as "partners". The first one is my Thing class, whose instances should act as Tree::TreeNodes of the gem RubyTree.
Basically, this delegation can be implemented using Forwardable:
class Thing < NoClassInheritancePlease
extend Forwardable
def initialize(title = "node")
#node = Tree::TreeNode.new title
# Collect node methods that should be delegated
node_methods = #node.public_methods(false)
node_methods += #node.protected_methods
node_methods -= (public_methods(false) + protected_methods(false) + private_methods) # own methods should not been delegated
# Set up delegation of specified node methods as singleton methods
for method in node_methods
Base.def_delegator :#node, method
end
end
end
Problem:
A number of TreeNode methods refer to self. For example:
def each(&block) # :yields: node
yield self
children { |child| child.each(&block) }
end
Thus, my_thing.each {...} yields self, i.e. the Tree::TreeNode object that belongs to my_thing but not the Thing object itself.
Another example:
siblings = []
parent.children {|my_sibling| siblings << my_sibling if my_sibling != self}
siblings
parent.children returns an Array of Things and therefore the condition never evaluates to false as my_sibling is a Thing (which is fine) but self is a Tree::TreeNode
Question: How to evaluate the instance methods of a class (e.g. Tree::TreeNode) in the context of another class (e.g. Thing)? ("overwrite self")
I tried with UnboundMethods, but you can only bind an instance of the original receiving class to an unbound method.
If you really want, you could use evil-ruby to solve this.
require 'evil'
class A; def m; self; end; end
class B; end
A.instance_method(:m).force_bind(B.new).call
You probably want to use instance_exec.
From the docs:
Executes the given block within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj’s instance variables. Arguments are passed as block parameters.
class KlassWithSecret
def initialize
#secret = 99
end
end
k = KlassWithSecret.new
k.instance_exec(5) {|x| #secret+x } #=> 104
http://ruby-doc.org/core-1.8.7/Object.html#method-i-instance_exec
In your case you can use instance_exec to yield self.
def each(&block)
instance_exec{ yield self }
children { |child| child.each(&block) }
end
I'm not sure if you can. Maybe with instance_eval {unboundmethod.to_proc} or something?
Related
I'd like to reference an object while instantiating it in order to pass it to another object I'm instantiating. What I mean:
A.new(B.new(self))
In this case, self would refer to the scope in which I'm actually calling A.new. What I want is for self (or whatever other keyword) to refer to the newly instantiated A object, so that B would have a reference to A. Is there a way to do this?
The way you have written it (A.new(B.new(self))) is impossible, due to a circular reference.
In order to create an instance of A, you need an instance of B; in order to create the instance of B, you need the instance of A.
There are a few ways you tweak the implementation to make this possible, but you must first resolve this chicken-and-egg problem between the A and B. For example:
class A
def initialize
#b = yield(self)
end
end
class B
def initialize(a)
#a = a
end
end
A.new { |a| B.new(a) }
Note that in the above code, a is being initialized first. It is only being yielded in the scope after the object has been created.
Or, here's another way:
class A
def initialize
#b = B.new(self)
end
end
class B
def initialize(a)
#a = a
end
end
A.new
Like above, the instance of A is being created first. But this time, I've done all the initialization in one go rather than building it within the new() methed call.
One final example:
class A
attr_writer :b
def initialize
end
end
class B
def initialize(a)
#a = a
end
end
A.new.tap { |a| a.b = B.new(a) }
In this example, I have fully initialized a before defining its attribute of b. This could just as easily have been written in two lines of code, with a regular variable instead of the closure:
a = A.new
a.b = B.new(a)
Looking at this instance_eval example:
class KlassWithSecret
def initialize
#secret = 99
end
def get
#secret
end
end
k = KlassWithSecret.new
k.instance_eval { #secret }
print k.get
I added a get method to KlassWithSecret.
Here's the results of running the program:
>ruby InstanceEvalTest.rb
99
So, does instance_eval here somehow call the initialize method?
I think that I understand this method a bit from reading this helpful post. But I'm still in the dark.
The initialize method is automatically called by Ruby after the new method is called. instance_eval runs the block you supply in the context of the object. This means it has access to anything a normal line of code in the KlassWithSecret class would have.
#secret is an instance variable, meaning that it belongs to an instance of KlassWithSecret. Because we're evaluating { #secret } in the context of a KlassWithSecret instance, we can access #secret.
k.instance_eval gives you access to all of the instance variables (here just #secret) and all private methods (if there were any). It executes the code in the block, which in this case returns 99, the value of #secret. Then print k.get prints that value and returns nil.
If the block had been { #secret = 'cat' }, k.instance_val would have changed the value of #secret (and returned the new value).
When using instance_eval, class_eval, class < self and other metaprogramming constructs, you mind find it helpful to track the value of self using puts statements. For example:
k = KlassWithSecret.new #=> #<KlassWithSecret:0x00000101897810 #secret=99>
self #=> main
k.instance_eval { puts "self=#{self}"; #secret }
"self=#<KlassWithSecret:0x00000101897810>"
#=> 99
just for exercise I implemented a queue class with ruby. The elements in the queue are nodes, which are implemented in another class. These nodes hold a certain value and can also hold information on their successor when added to the queue. The node class looks as follows:
class Node
attr_accessor :value, :successor
def initialize(value)
#value = value
#successor = nil
end
def set_successor(successor)
#successor = successor
end
def get_successor()
#successor
end
def get_value()
#value
end
def to_s()
#value.to_s
end
end
After creating objects, such as object1 = Node.new(12) and object2 = Node.new("Foo"), I can use the get_value method to obtain the objects values, which is exactly what the method is supposed to do.
puts object1.get_value
==> 12
puts object2.get_value
==> Foo
Yet, when just using puts object1 or puts object2, still the objects values, 12 and Foo are
displayed. Here, I would expect a more cryptic message, telling me that this is an object of the class node, which is what the objects are.
puts object1.class
==> Node
So, does anybody know a hint, why the objects value is displayed, when actually the whole object is supposed to be shown?
puts calls the to_s method on objects before printing them. You have defined to_s in your class to call to_s of the #value. Therefore, instances of your class have the same string representation as the value they hold.
If you would write
class Node
# ...
def to_s
"Node<#{#value.to_s}>"
end
end
You would get
node = Node.new(42)
puts node
# Node<42>
As a side note: your Ruby code is not very idiomatic, here are some observations:
omit the empty parentheses ()
no need to write getters and setters, that's what attr_accessor is for
instance variables are automatically set to nil
outside of the constructor, better use the getter value instead of instance var #value
malformed indentation
Here's an equivalent implementation:
class Node
attr_accessor :value, :successor
def initialize(value)
#value = value
end
def to_s
value.to_s
end
end
In action:
node = Node.new(42)
node.value = 123
succ = Node.new(124)
node.successor = succ
puts node
# 123
puts node.successor
# 124
In case you didn't want a setter for value, use attr_reader instead of attr_accessor.
How does ruby call varz method by using varz[:foo]?
class Component
class << self
def varz
#varz ||= Hash.new
end
end
end
Component.varz[:foo] = 'bar'
puts Component.varz # {:foo=>"bar"}
class << self is used to define the class method,that will be called on the class.
where as #varz represents the instance variable. You might wonder, then why this instance object is doing in class method? This is because class itself is instance of Class.
One more thing to note, in ruby method returns it's last statement. So in your case Component.varz returning the instance variable #varz which is of hash type.
Component.varz[:foo] = 'bar'
this add the key-value pair foo and 'bar' to hash.
And finally,
p Component.varz
you are printing the value returened by the varz method.
You cut it in the wrong way. Component.varz is a method call. To the result of it (which is a hash), [:foo] = applies. The [] and []= methods are special in that you don't put a period between the receiver and the method.
I am reading the Module documentation but can't seem to understand their differences and which should be used where.
How is the eval different than exec?
I'm going to answer a bit more than your question by including instance_{eval|exec} in your question.
All variations of {instance|module|class}_{eval|exec} change the current context, i.e. the value for self:
class Array
p self # prints "Array"
43.instance_eval{ p self } # prints "43"
end
Now for the differences. The eval versions accepts a string or a block, while the exec versions only accept a block but allow you to pass parameters to it:
def example(&block)
42.instance_exec("Hello", &block)
end
example{|mess| p mess, self } # Prints "Hello" then "42"
The eval version does not allow to pass parameters. It provides self as the first parameter, although I can't think of a use for this.
Finally, module_{eval|exec} is the same as the corresponding class_{eval|exec}, but they are slightly different from instance_{eval|exec} as they change what is the current opened class (i.e. what will be affected by def) in different ways:
String.instance_eval{ def foo; end }
Integer.class_eval { def bar; end }
String.method_defined?(:foo) # => false
String.singleton_methods.include?(:foo) # => true
Integer.method_defined?(:bar) # => true
So obj.instance_{eval|exec} opens the singleton class of obj, while mod.{class|module}_{eval|exec} opens mod itself.
Of course, instance_{eval|exec} are available on any Ruby object (including modules), while {class|module}_* are only available on Module (and thus Classes)
To answer your last question first, eval (in all its variations) is completely different from exec. exec $command will start a new process to run the command you specify and then exit when that finishes.
class_eval and module_eval have the power to redefine classes and modules -- even those that you yourself did not write. For example, you might use class eval to add a new method that did not exist.
Fixnum.class_eval { def number; self; end }
7.number # returns '7'
class_eval can be used to add instance methods, and instance_eval can be used to add class methods (yes, that part is very confusing). A class method would be something like Thing.foo -- you're literally calling the foo method on the Thing class. An instance method is like the example above, using class_eval I've added a number method to every instance of Fixnum.
Okay, so that's the *_eval class of methods. The exec methods are similar, but they allow you to look inside a class and execute a block of code as though it was defined as a method on that class. Perhaps you have a class that looks like this:
class Foo
##secret = 'secret key'
##protected = 'some secret value'
def protected(key)
if key == ##secret
return ##protected
end
end
end
The class Foo is just a wrapper around some secret value, if you know the correct key. However, you could trick the class into giving you its secrets by executing a block inside the context of the class like so:
Foo.class_exec { ##secret = 'i'm a hacker' }
Foo.protected('i'm a hacker') #returns the value of ##protected because we overwrote ##secret
In general, with a lot of the tools in ruby, you could use any of these to solve a lot of problems. A lot of the time you probably won't even need to unless you want to monkey patch a class some library you use has defined (although that opens up a whole can of worms). Try playing around with them in irb and see which you find easier. I personally don't use the *_exec methods as much as the *_eval methods, but that's a personal preference of mine.
To avoid ambiguity I'm going to call a method that belongs to (owned by) a singleton class a singleton method. The rest are instance methods. Although one might say that a singleton method of an object is an instance method of its singleton class.
tl;dr Use class_eval/module_eval on a class/module to define instance methods, and instance_eval on a class/module to define class methods (or to be more precise, use instance_eval to define singleton methods). Additionally you can use instance_eval to access instance variables.
A terminology is a bit lacking in this case. ruby maintains a stack of class references (cref for short). When you open/reopen a class, the corresponding class reference is pushed to the stack. And the current class refernece affects where def defines methods (to which class/module they're added).
Now, class_eval/module_eval and class_exec/module_exec are aliases.
The *_exec() variants don't accept strings, and allow to pass arguments to the block. Since the *_eval() variants are mainly used I'll focus on them.
class_eval/module_eval changes cref and self to the receiver (Thing in Thing.module_eval(...)):
rb_mod_module_eval() -> specific_eval()
yield_under() (for blocks)
vm_cref_push()
eval_under() (for strings)
vm_cref_push()
instance_eval changes cref to the singleton class of the receiver, and self to the receiver.
Let's see them in action:
class A
p self #=> A
#a = 1
def initialize
#b = 2
end
end
p A.instance_variables #=> [:#a]
p A.new.instance_variables #=> [:#b]
#a on a class level adds an instance variable to the class A as an object. I'm adding it here for completeness. But that's not how you add a class variable.
A.instance_eval do
p self #=> A
p #a #=> 1
def m() puts 'm' end
end
sclass = A.singleton_class
p sclass.instance_methods(false).include? :m #=> true
A.m #=> m
a = A.new
a.instance_eval do
p self #=> #<A:0x00007fc497661be8 #b=2>
p #b #=> 2
def m2() puts 'm2' end
end
sclass = a.singleton_class
p sclass.instance_methods(false).include? :m2 #=> true
a.m2 #=> m2
So, inside instance_eval def adds a singleton method to the receiver (an instance method to the singleton class of the receiver). For a class/module that means a class/module method. For other objects, a method that is available for that particular object.
A.class_eval do
p self #=> A
p #a #=> 1
def m() puts 'm' end
end
p A.instance_methods(false).include? :m #=> true
A.new.m #=> m
And, inside class_eval def adds an instance method to the receiver itself (the class/module). class_eval is only available for classes/modules.
Also, when class_eval is passed a block, constant/class variable lookup is not affected:
module A
C = 1
##c = 1
class B
C = 2
##c = 2
end
A::B.class_eval { p [C, ##c] } #=> [1, 1]
A::B.class_eval 'p [C, ##c]' #=> [2, 2]
end
The naming is confusing. I might guess that instance in instance_eval suggests that receiver is treated as an instance (allows to change things for a particular instance), and class in class_eval as a class (allows to change things for a class of objects).