rewriting definition of `not` in Ruby's Object - ruby

really confused about what this RubyMonk examples does. class Not is supposed to return an object capable of inverting calls to Object#not.
class Object
def not
Not.new(self)
end
class Not
def initialize(original)
#original = original
end
def method_missing(sym, *args, &blk)
!#original.send(sym, *args, &blk)
end
end
end
class Person
def initialize(name)
#name = name
end
def smith?
#name == "Smith"
end
end
and this is how the test goes
puts Person.new("Smith").not.smith?
puts Person.new("Ziggy").not.smith?
what I don't understand is
in what ways does this change the built-in definition of method not?
when passing arguments to not, how does it "travel"? it goes to not method, after which a new instance of class Not is created and it gets passed to that instance?
what is need for the method_missing? what method could there possibly be missing in this scenario? and what does it do when there is a method missing? it's just being told to not send the arguments to #original and that's it?

Answering your question #1:
in what ways does this change the built-in definition of method not?
a) It doesn't, because b) not isn't a method, it's a keyword, and as such its definition is baked into the language specification.
More precisely: the not keyword is translated to a call to the method !, just like the ! operator, so all three of the following are equivalent:
not foo
!foo
foo.!

method_missing in Not class is the real magic. These is the scenario:
Person.new("Smith") # you create new person
Person.new("Smith").not # calls method #not on the person object instance
# the method #not will create new instance of the class Not and passing self as argument
# passing the person on which you have called the method
# then the initialize method of the Not class gets called
# because you want to create new object of the Not class and
# #original is the person on which you have called the method #not
Person.new("Smith").not.smith? # will call method #smith? on the Not object instance
what happened till now
person = Person.new("Smith")
not_class_object = person.not
not_class_object.smith? # there is no method named #smith? in the Not class
If no method exists it check all hierarchy and see if anything in the inheritance chain has implemented the smith? method. If none has implemented the smith? method then Ruby will call method_missing the same way, and you have changed the behavior of the method_missing for the Not class.
Now it will get the #original which is the person object and call the method on the person object, this Person instance object has implemented the method, and when the result comes we will just negate the outcome. So if the smith? method returns true for the person calling not.smith? will return false, because smith? method returns true we negate the value and get false, and if it returns false, when we negate you get true.
Edit:
Person is extension of Object, but there is no connection between Not and Person, Person is not extending Not and Not is not extending Person.
Not is class inside Object and it has no method named smith?, instance object of Person got smith? method. That is why it does not find smith? method on the Not instance object, and then it calls method_missing from the inheritance chain, and you have implemented method_missing for the Not class that it takes the object on which you have called not method of Object class and created instance object from Not class with parameter as Person instance object.
Edit2:
class NotPerson
...
# some code
...
end
p1 = Person.new("Smith")
p2 = Person.new("Ziggy")
p3 = NotPerson.new("something")
p1.smith? # -> true
p2.smith? # -> false
p3.smith? # Error there is no method named #smith? in NotPerson class
not_p1 = p1.not
not_p2 = p2.not
not_p3 = p3.not
not_p1.smith? # -> false
# Because there is no method #smith? on #not class, and #method_missing is called
not_p1.smith? # is eqivavlent to
!(p1.smith?)
not_p2.smith? # -> true
not_p3.smith? # Error there is no method #smith? definedin NotPerson class
Edit3:
check also some references how method_missing is working
method_missing
second_example

Related

To which object are top-level methods assigned in Ruby? [duplicate]

This question already has answers here:
Ruby what class gets a method when there is no explicit receiver?
(2 answers)
Closed 7 months ago.
In Ruby every method is assigned to an object (right?). Ruby provides a lot of "built in" methods and gives the ability to the user to create "user defined" methods.
Built in methods are all defined in a class like String, Integer, Array and so on. Built in methods are all invoked placing a dot after an object followed by the method call.
string = "example"
string = string.reverse
However, when I define a method with the syntax
def method_name (args)
#body
end
to which object is this method assigned? And why when I have to call a method that I have defined I don't use the "dot syntax" but I just write its name and pass it some arguments without applying it to an object, like this:
method_name args
In Ruby every method is assigned to an object (right?)
Incorrect. In Ruby, methods are assigned to modules (including classes). When you call a method on an object, Ruby runtime searches for the method along the object's class's ancestor chain (the object's singleton class -> the object's class ->
the superclass -> superclass's superclass -> ... -> BasicObject). If the method is found, it is bound to the object and gets called, otherwise the Ruby runtime searches for a special method called method_missing and bind it to the current object and calls it.
to which object is this method assigned?
It's assigned to the class Object, as a private instance method.
def foo
:foo
end
Object.private_instance_methods.grep(/foo/)
#=> [:foo]
I guess Ruby does this in order to make top-level "functions" look global.
class A
def self.a
foo
end
def a
foo
end
end
A.a #=> :foo
A.new.a #=> :foo
There is top-level object in Ruby -- main
def method_name(args)
# body
end
self
# => main
self.methods.grep(/method_name/)
# => [:method_name]
main is an instance of Object. Any methods defined in main become instance methods of Object
Object.private_instance_methods.grep(/method_name/)
# => [:method_name]
This makes them available everywhere (because all classes are descendants of Object), meaning that we can call the method without a receiver inside classes
For example
def foo
puts "foo"
end
class X
def y
foo
end
end
# will print foo
X.new.y
# will raise private method `foo' called for #<X:0x000055e406a0f060> (NoMethodError)
# to reproduce don't use irb, just usual file
X.new.foo
Read more

Location of public class method 'new' of 'Class'

Ruby's Class class lists two methods named 'new':
Class::new is a public class method
Class#new is a public instance method
But when I do:
Class.methods(false)
#=> []
which is supposed to list singleton methods (which I am assuming what class methods are), I get an empty array. Why is this so? Where is Class::new defined?
The methods shown as ::new in the documentation are usually #initialize, for example Range::new:
new(begin, end, exclude_end=false) → rng
Constructs a range using the given begin and end. If the exclude_end parameter is omitted or is false, the rng will include the end object; otherwise, it will be excluded.
This is because you create instances via:
r = Range.new(0, 2) #=> 0..2
Rather than:
r = Range.allocate #=> nil..nil
r.send(:initialize, 0, 2) #=> nil
r #=> 0..2
That's exactly what ::new does – it creates a new instance via allocate, sends it initialize (passing arguments) and returns the instance.
The actual new method is inherited from Class (since Range is an instance of Class) – Class#new:
new(args, ...) → obj
Calls allocate to create a new object of class’s class, then invokes that object’s initialize method, passing it args. This is the method that ends up getting called whenever an object is constructed using .new.
Just like allocate, inherited and superclass (and the instance methods from Class' ancestors like Module as well):
Range.method(:new)
#=> #<Method: Class#new>
Range.method(:allocate)
#=> #<Method: Class#allocate>
Range.method(:ancestors)
#=> #<Method: Class(Module)#ancestors>
So if you call Class.new:
my_string_class = Class.new(String)
#=> #<Class:0x007fdf5485b200>
you just invoke Class#new which is (again) equivalent to:
my_string_class = Class.allocate
my_string_class.send(:initialize, String)
my_string_class
#=> #<Class:0x007fdf5484beb8>
One notable exception is Struct which in fact provide its own new class method:
Struct.method(:new)
#=> #<Method: Struct.new>
Unlike other classes, Struct::new does not return instances of Struct but instances of Class (which are subclasses of Struct).
tl;dr summary:
Why is this so?
Because it's not a singleton method.
Where is Class::new defined?
It isn't. The call Class.new is just calling Class#new (since Class is an instance of itself). The documentation for Foo::new is actually the documentation for Foo#initialize for any class Foo, including Class itself.
If you want to know something about Ruby, it is often a good idea to ask her herself:
new_method = Class.method(:new)
#=> #<Method: Class#new (defined in Class at core/alpha.rb:90)>
The Object#method method returns a Method object representing the method. (Methods aren't objects in Ruby themselves, but you can get a reflective proxy object that represents a method.)
You can ask a Method where it is defined using the Method#owner method:
new_method.owner
#=> Class
As you can see, new is defined in Class and not in Class's singleton class.
You can also ask a Method about the location of its Ruby source code using the Method#source_location method:
new_method.source_location
#=> ['core/alpha.rb', 90]
What this tells us is that Class#new is defined in the file core/alpha.rb on line 90:
def new(*args)
obj = allocate()
Rubinius.asm(args, obj) do |args, obj|
run obj
run args
push_block
send_with_splat :initialize, 0, true
# no pop here, as .asm blocks imply a pop as they're not
# allowed to leak a stack value
end
obj
end
The method is partially implemented in bytecode for performance reasons, but it is basically just:
class Class
def new(*args, &block)
obj = allocate
obj.__send__(:initialize, *args, &block) # because initialize is private
#obj.initialize(*args, &block)
obj
end
end
Now, you might ask yourself: why is there an entry for Class::new in the RDoc documentation, if that method doesn't exist? Well, RDoc knows about the relationship between #initialize which is the method you define but usually don't call directly and Class#new which is the method you call but usually don't define, and it will document #initialize as ::new if it exists.
So, what we really want to look at, is Class#initialize:
initialize_method = Class.method(:initialize)
#=> #<Method: Class#initialize (defined in Class at core/class.rb:15)>
initialize_method.owner
#=> Class
initialize_method.source_location
#=> ['core/class.rb', 15]
This is the source:
def initialize(sclass=Object, name=nil, under=nil)
raise TypeError, "already initialized class" if #instance_type
raise TypeError, "can't make subclass of Class" if Class.equal?(sclass)
set_superclass sclass
# Things (rails) depend on the fact that a normal class is in the constant
# table and have a name BEFORE inherited is run.
under.const_set name, self if under
if sclass
Rubinius.privately do
sclass.inherited self
end
end
super()
end
private :initialize
Class#initialize essentially does three things:
set the superclass
optionally assign the class to a constant to give it a name
call the Class#inherited hook method of the superclass
If you want to know what the relationships between some of the core classes that magically spring into existence at the beginning are, you can take a look at the initialization code of some Ruby execution engines, e.g.
Rubinius: VM::bootstrap_class in machine/ontology.cpp
JRuby: org.jruby.Ruby.initRoot in core/src/main/java/org/jruby/Ruby.java
IronRuby: the initial classes are generated by a program, the generator is in the directory Src/ClassInitGenerator
MRuby: mrb_init_class in src/class.c
Note: depending on what Ruby implementation you use, obviously the places where those methods are defined and how exactly they are defined may vary.
new is defined as a instance method of Class class, rather than a singleton method:
Class.instance_method :new # => #<UnboundMethod: Class#new>
Tricky to note: Class (object) itself is also an instance of Class (class).
Class.instance_of? Class # => true

What is the usage of .self in this ruby example

I've been reading my textbook, and we have come to classes and the keyword self came up. I've been reading some tutorials on tutorialpoint and have read a bunch of SO questions, but for some reason it just isn't clicking in my head Use of ruby Self, so I decided I would tinker around with some examples
Consider
class Box
# Initialize our class variables
##count = 0
def initialize(w,h)
# assign instance avriables
#width, #height = w, h
##count += 1
end
def self.printCount()
puts "Box count is : ###count"
end
end
# create two object
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)
# call class method to print box count
Box.printCount()
Why will we get an error if we remove self. from our printCount() method? I know that self is important to distinguish between class variables and instance variables like in my example #width,#height and ##count.
So what I think is that since I am trying to modify the class variable ##count, I need to use the .self keyword since I am trying to modify a class variable. Thus whenever we want to change a class variable we must use the form def self.methodName.
Is my thought process correct?
There are two types of methods you are using here: instance methods and class methods. As you know, Ruby is an object oriented programming language, so everything is an object. Each object has its own methods that it can call. Let's look at your code
class Box
# Initialize our class variables
##count = 0
def initialize(w,h)
# assign instance avriables
#width, #height = w, h
##count += 1
end
def self.printCount()
puts "Box count is : ###count"
end
end
When you create a method with self.method_name, you are creating the method for the class itself. So the object of Box has a method called printCount(). That is why you can directly call the method.
Box.printCount()
However, if you declare a new instance of the class Box, calling printCount() would result in an error.
box1 = Box.new(1,1)
box1.printCount() #=> undefined method `printCount'
This is because box1 is an instance of the class Box, and the printCount method is only accessible to the class Box.
If you remove the self before the method printCount, it will become an instance method, and then box1 will have access to that method, but then the class Box will not.
And a few semantics, Ruby uses snake_case for method names, so printCount should be print_count. This is just standard practice, doesn't really affect how the code runs.
Also, you need to be careful with class variables, ie ##count. They don't behave as you would expect in Ruby. It does not just belong in the class it is declared in, it is also part of any of its descendants.
For example, let's say I define a new class call SmallBox and inherit from Box.
box1 = Box.new(1,1)
box1 = Box.new(1,1)
Now, the count should be 2 for Box. However, if you try to access the ##count from my new class,
class SmallBox < Box
p ##count
end
This would print 2 as well.
Any changes to the class variable from the descendants will change its value.
For example, I declare an instance of SmallBox, which would add 1 to ##count. You can see if you check the count in Box, it also added 1.
small1 = SmallBox.new(1,1)
class SmallBox
p ##count #=> 3
end
class Box
p ##count #=> 3
end
I would like to provide a more concrete definition which clarifies the lookup algorithm.
First, let's define self. self in Ruby is a special variable that always references the current object. The current object (self) is the default receiver on method calls. Second, self is where instance variables are found.
class MyClass
def method_one
#var = 'var'
method_two
end
def method_two
puts "#var is #{#var}"
end
end
obj = MyClass.new
obj.method_one
Above, when we call method_one, self will refer to the object instantiated, since we invoked method_one on an explicit receiver (the object instance). so self.method_one in the method definition in the Class will refer to the object instance not the Class object itself. #var will be stored in self. Note that when method_two is called, since there is no default receiver, the receiver is self. So when method_two is called, we remain in the same object instance. That is why #var in method_two will refer to the same #var in method_one. It is the same object.
Ruby supports inheritance. So if we call a method on self and it is not defined in its class, then Ruby will search for the instance method in the superclass. This happens until Ruby gets to BasicObject. If it cannot find the method in any of the superclasses, it raises a NoMethodError.
Now there is another important piece to the inheritance chain. There is an anonymous class called the singleton class that Ruby will inject into this inheritance chain. Where in the inheritance chain? It inserts it right before the original class of the object. This way, when ruby searches for the method, it will hit the singleton class before it hits the original class of the object.
> msg = 'Hello World'
=> "Hello World"
> def msg.hello_downcase
> puts 'Hello World'.downcase
> end
=> :hello_downcase
> msg.downcase
=> "hello world"
> msg2 = 'Goodbye'
=> "Goodbye"
> msg2.hellow_downcase
NoMethodError: undefined method `hellow_downcase' for "Goodbye":String
The lookup algorithm:
msg -> Anonymous Singleton Class (hello_downcase method is in here) -> String -> Object
msg2 -> String -> Object
In the above example, msg and msg2 are both object instances of the String class object. But we only opened up the singleton class of msg and not msg2. the hello_downcase method was inserted into the singleton class of msg. It's important to note that when we add another singleton method, it will reopen the same singleton class again; it will not open another anonymous singleton class. There will only be one anonymous singleton class per instance.
Notice above I said the String class object, and not just the String class. That's because a class itself is an object. A class name is simply a constant which points to an object:
class HelloWorld
def say_hi
puts 'Hello World'
end
end
More precisely, in the above example, HelloWorld is a constant which points to an object, whose class is Class. Because of this, the lookup chain will be different for HelloWorld and its instances. An instance's class is HelloWorld. And when we invoke a method with the instance as the receiver, inside HelloWorld method definitions, self will refer to that instance. Now HelloWorld's class is Class (Since Class.new is what created HelloWorld). And because of this, its inheritance chain looks different:
#<HelloWorld:0x007fa37103df38> -> HelloWorld -> Object
HelloWorld -> Class -> Module -> Object
Now since HelloWorld is also an object, just as with instances, we can open up its Singleton Class.
class HelloWorld
def self.say_hi_from_singleton_class
puts 'Hello World from the Singleton Class'
end
end
HelloWorld.say_hi_from_singleton_class
The lookup algorithm:
HelloWorld -> Anonymous Singleton Class -> Class (this is where the new method is defined) -> Module -> Object
Why does this work? As mentioned, a method call with an explicit receiver changes the value of self to point to that object. The second thing that changes the value of self is a class definition. self inside of the class definition refers to the class object, referred to by constant HelloWorld. This is only the case while inside of the class definition. Once we leave the class definition, self will no longer refer to the constant HelloWorld.
> puts self
main
> class HelloWorld
> puts self
> end
HelloWorld
=> nil
> puts self
main
Ultimately, there are two ways in which the special variable self will change: 1) when you call a method with an explicit receiver, 2) inside of a class definition.

Class Methods in Object Class of Ruby

I was trying to implement my own attr_accessor method. I implemented that as follow.
class Object
def my_attr_accessor(*args) # self.my_attr_accessor(*args)
args.each do |arg|
define_method "#{arg}" do
return instance_variable_get("##{arg}")
end
define_method "#{arg}=" do |val|
instance_variable_set("##{arg}", val)
end
end
end
end
Then I created a class which calls the my_attr_accessor method.
class Runner
my_attr_accessor :name
end
test= Runner.new
test.name = "runner"
puts test.name
My question is even though I haven't explicitly defined self.my_attr_accessor method, it is acting as a class method. Can someone help me in figuring out how it's happening.
EDIT: Irrespective of making self.my_attr_accessor or my_attr_accessor in Object class, it works if I say my_attr_accessor within my Runner class. Why?
This is called "inheritance". In Ruby, subclasses "inherit" methods from their superclasses. In other words, if you send a message to an object, Ruby will look up a method whose name matches the message in the class of the object, and if it can't find it, it will follow that classes' superclass pointer, and then that classes' superclass pointer, and so on, until it either finds a matching method or reaches a class which doesn't have a superclass.
Since Class is a subclass of Object (indirectly via Module), it inherits Object's methods.
[Note: inheritance is a fundamental concept in Ruby, you should probably go back and learn the fundamentals of Ruby before trying advanced reflective metaprogramming. In particular how the ancestry chain (the superclass pointers) are constructed and message dispatch works.]
Since everything is an instance of Object in ruby, you can call your method from anywhere:
class Object
def my_attr_accessor(*args)
end
end
puts self.class # => Object
puts self.is_a?(Object) # => true
puts self.respond_to?(:my_attr_accessor) # => true
class Runner
puts self.class # => Class
puts self.is_a?(Object) # => true
puts self.respond_to?(:my_attr_accessor) # => true
my_attr_accessor :name
end
You create a new Runner with Runner.new. So you have an instance of the Runner class.
Since you called my_attr_accessor in your class block, you have created the method .name on your instance. This is important. my_attr_accessor is a call to the method my_attr_accessor. And in the base class, i.e. in Object, Ruby finds this method and calls it.
Now, you can call test.name = "runner".

Ruby metaclass madness

I'm stuck. I'm trying to dynamically define a class method and I can't wrap my head around the ruby metaclass model. Consider the following class:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
end
Example.class_instance.class # => Class
Example.meta.class # => Class
Example.class_instance == Example # => true
Example.class_instance == Example.meta # => false
Obviously both methods return an instance of Class. But these two instances
are not the same. They also have different ancestors:
Example.meta.ancestors # => [Class, Module, Object, Kernel]
Example.class_instance.ancestors # => [Example, Object, Kernel]
What's the point in making a difference between the metaclass and the class instance?
I figured out, that I can send :define_method to the metaclass to dynamically define a method, but if I try to send it to the class instance it won't work. At least I could solve my problem, but I still want to understand why it is working this way.
Update Mar 15, 2010 13:40
Are the following assumptions correct.
If I have an instance method which calls self.instance_eval and defines a method, it will only affect the particular instance of that class.
If I have an instance method which calls self.class.instance_eval (which would be the same as calling class_eval) and defines a method it will affect all instances of that particular class resulting in a new instance method.
If I have a class method which calls instance_eval and defines a method it will result in a new instance method for all instances.
If I have a class method which calls instance_eval on the meta/eigen class and defines a method it will result in a class method.
I think it starts to make sense to me. It would certainly limit your possibilities if self inside an class method would point to the eigen class. If so it would not be possible to define an instance method from inside a class method. Is that correct?
Defining a singleton method dynamically is simple when you use instance_eval:
Example.instance_eval{ def square(n); n*n; end }
Example.square(2) #=> 4
# you can pass instance_eval a string as well.
Example.instance_eval "def multiply(x,y); x*y; end"
Example.multiply(3,9) #=> 27
As for the difference above, you are confusing 2 things:
The meta class defined by you, is what called in Ruby community as singelton class or eigen class. That singleton class is the class that you can add class(singleton) methods to.
As for the class instance you are trying to define using the class_instance method, is nothing but the class itself, to prove it, just try adding an instance method to the class Example and check if the class_instance method defined by you returns the class Example itself by checking the existence of that method:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
def hey; puts hey; end
end
Example.class_instance.instance_methods(false) #=> ['hey']
Anyway to sum it for you, when you want to add class methods, just add them to that meta class. As for the class_instance method is useless, just remove it.
Anyway I suggest you read this post to grasp some concepts of Ruby reflection system.
UPDATE
I suggest you read this nice post: Fun with Ruby's instance_eval and class_eval,
Unfortunately class_eval and instance_eval are confusing because they somehow work against their naming!
Use ClassName.instance_eval to define class methods.
Use ClassName.class_eval to define instance methods.
Now answering your assumptions:
If I have an instance method which
calls self.instance_eval and defines a
method, it will only affect the
particular instance of that class.
yes:
class Foo
def assumption1()
self.instance_eval("def test_assumption_1; puts 'works'; end")
end
end
f1 = Foo.new
f1.assumption1
f1.methods(false) #=> ["test_assumption_1"]
f2 = Foo.new.methods(false) #=> []
If I have an instance method which
calls self.class.instance_eval (which
would be the same as calling
class_eval) and defines a method it
will affect all instances of that
particular class resulting in a new
instance method.
no instance_eval in that context will define singleton methods(not instance ones) on the class itself:
class Foo
def assumption2()
self.class.instance_eval("def test_assumption_2; puts 'works'; end")
end
end
f3 = Foo.new
f3.assumption2
f3.methods(false) #=> []
Foo.singleton_methods(false) #=> ["test_assumption_2"]
For that to work replace instance_eval with class_eval above.
If I have a class method which calls
instance_eval and defines a method it
will result in a new instance method
for all instances.
Nope:
class Foo
instance_eval do
def assumption3()
puts 'works'
end
end
end
Foo.instance_methods(false) #=> []
Foo.singleton_methods(false) #=> ["assumption_3"]
That will make singleton methods, not instance methods. For that to work replace instance_eval with class_eval above.
If I have a class method which calls
instance_eval on the meta/eigen class
and defines a method it will result in
a class method.
well no, that will make so sophisticated stuff, as it will add singleton method to the singleton class, I don't think that will have any practical use.
If you define a method on a class, it can be invoked on its objects. It is an instance method.
class Example
end
Example.send :define_method, :foo do
puts "foo"
end
Example.new.foo
#=> "foo"
If you define a method on a metaclass, it can be invoked on the class. This is similar to the concept of a class method or static method in other languages.
class Example
def self.metaclass
class << self
self
end
end
end
Example.metaclass.send :define_method, :bar do
puts "bar"
end
Example.bar
#=> "bar"
The reason that metaclasses exist is because you can do this in Ruby:
str = "hello"
class << str
def output
puts self
end
end
str.output
#=> "hello"
"hi".output
# NoMethodError
As you can see, we defined a method that is only available to one instance of a String. The thing that we defined this method on is called the metaclass. In the method lookup chain, the metaclass is accessed first before searching the object's class.
If we replace the object of type String with an object of type Class, you can imagine why this means we're only defining a method on a specific class, not on all classes.
The differences between the current context and self are subtle, you can read more if you're interested.

Resources