Ruby Operator Method Calls VS. Normal Method Calls

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 yielded 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):

  1. B (an instance of Class) is created (which inherits everything from A). At this moment it doesn't have anything specific.

  2. A.inherited hook is invoked.

  3. 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



Leave a reply



Submit