Ruby operator method calls vs. normal method calls
The implementation doesn't have the additional complexity that would be needed to allow generic definition of new operators.
Instead, Ruby has a Yacc parser that uses a statically defined grammar. You get the built-in operators and that's it. Symbols occur in a fixed set of sentences in the grammar. As you have noted, the operators can be overloaded, which is more than most languages offer.
Certainly it's not because Matz was lazy.
Ruby actually has a fiendishly complex grammar that is roughly at the limit of what can be accomplished in Yacc. To get more complex would require using a less portable compiler generator or it would have required writing the parser by hand in C, and doing that would have limited future implementation portability in its own way as well as not providing the world with the Yacc input. That would be a problem because Ruby's Yacc source code is the only Ruby grammar documentation and is therefore "the standard".
How method call works
The reason is that nested method are always applied to the containing class. The second method will be added to the A
class, since it's the containing class of the first method.
However, it will be added only when its body code is evaluated, and it is evaluated when you first call the outer method.
class Test
def foo
puts "outside method"
def bar
puts "inside method"
end
end
end
test = Test.new
test.methods - Object.methods # => [:foo]
test.foo
test.methods - Object.methods # => [:foo, :bar]
In ruby, defining a method with the same name within a class twice will override the first version.
class Test
def foo
"first version"
end
def foo
"second version"
end
end
test = Test.new
test.foo # => "second version"
Therefore, after the first execution of A#a
, the inner implementation remains.
Ruby operator and method invoking
This is one of the things many people refer to as Ruby's syntax sugar. The language recognizes these mathematical operators as well as other ASCII symbol operators, such as the <<
insertion operator, and allows them to be called with white space and without the method dot. This allows for a more natural usage of the method.
Your #add
method is not recognized by Ruby to be a standard operator and so this syntax help is not performed.
In ruby, should I use instance variables or direct method calls
Instead of defining the method bigcat
you may rename your instance variable and use a accessor method.
Example based on dimitris answer:
class Foo
def cat
@bigcat ||= "This is a cat"
end
attr_reader :bigcat
end
mycat = Foo.new
mycat.cat
mycat.bigcat
If you want to keep your variable name, you could combine it with an alias
:
class Foo
def cat
@cat_talk ||= "This is a cat"
end
attr_reader :cat_talk
alias :bigcat :cat_talk
end
mycat = Foo.new
mycat.cat
mycat.cat_talk
mycat.bigcat
Beyond your question, just for information: You could also define a writter method with attr_writer
.
Ruby `send` vs `call` method
To begin with, send
and call
are two very different methods.
In ruby, the concept of object orientation takes its roots from Smalltalk. Basically, when you call a method, you are sending that object a message. So, it makes sense that when you want to dynamically call a method on an object, the method you call is send
. This method has existed in ruby since at least 1.8.7.
In ruby, we also have a concept of "blocks". Blocks are the do...end
things attached to the end of method calls. Blocks can be traditionally yield
ed to; or, it is entirely possible to create an object out of a block (a Proc
), and pass that around. In order to execute the block, you can call call
on the block.
call
has never been defined on Object
, whereas send
is defined on everything.
(note: for some reason, call
doesn't seem to have documentation in the 2.3.0 documentation; however, it still exists and does the same thing from 2.2.0, so I linked that one instead.)
Why base class method is being called inside inherited?
No magic here.
When you declare B
the things happen in the following order (roughly speaking):
B
(an instance ofClass
) is created (which inherits everything fromA
). At this moment it doesn't have anything specific.A.inherited
hook is invoked.B
class is opened and processed. Only at this point, it gets its own properties and methods (except the ones that could be created inside the hook).
So, when (2) happens the only name
that is available for B
is the one defined in A
.
This is very easy to check using the following code:
class A
def self.name
"a"
end
def self.inherited(subclass)
puts "B own methods, point 1: #{subclass.methods(false).join(', ')}"
end
end
class B < A
puts "B own methods, point 2: #{self.methods(false).join(', ')}"
def self.name
"b"
end
puts "B own methods, point 3: #{self.methods(false).join(', ')}"
end
# B own methods, point 1:
# B own methods, point 2:
# B own methods, point 3: name
Everything is clear now, right?
Ruby class methods. Is it getting called on main object?
What is hello being called on?
Whenever there isn't an explicit receiver, the receiver is self
. So the call is implicitly:
self.hello
... where self
is the class Test
, on which you have just defined the self.hello
method.
goodbye
is not found because it is defined on an instance of class Test
, not the class itself, where it's currently called.
Why does Ruby call the `call` method when I don't supply the method name?
Proc#call
:
Invokes the block, setting the block’s parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array). Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
I did some research and found method #()
is a syntactic sugar of the method #call
..Look at the error as below :
module Foo
def self.bar
12
end
end
Foo.()
#undefined method `call' for Foo:Module (NoMethodError)
As OP defined the #call
method in module Foo
class,Foo#call
is called in an attempt of Foo.()
.
Here is some more examples :
"ab".method(:size).() # => 2
"ab".method(:size).call # => 2
"ab".() # undefined method `call' for "ab":String (NoMethodError)
See here what Matz said So compromise with object.() syntax introduced in 1.9...
Related Topics
Ruby Pipes: How to Tie the Output of Two Subprocesses Together
Ruby: Array Contained in Array, Any Order
Why Doesn't Relative_Require Work on Ruby 1.8.6
How to Stringize/Serialize Ruby Code
How to Correctly Install Rvm in Docker
Undefined Method 'Name' for "Actionmailer":String
How to Memoize a Method That May Return True, False, or Nil in Ruby
Problem Using Openstruct with Erb
How to Find Gems That Depend on a Given Gem
Error Installing SQLite3 Gem via Bundler
How to Specify the Location of the Chromedriver Binary
How to Store an Instance Variable Across Multiple Actions in a Controller
Ruby on Linux Pty Goes Away Without Eof, Raises Errno::Eio
Rails: Methods Shared by Multiple Controllers