I'm currently reading "The Well-Grounded Rubyist", and on page 196 I see the following:
Suppose you define a method at the top level:
def talk puts "Hello" end
....
A method that you define at the top level is stored as a private instance method of the
Object
class. The previous code is equivalent to this:class Object private def talk puts "Hello" end end
...
To illustrate, let's extend the
talk
example. Here it is again, with some code that exercises it:puts "Trying 'talk' with no receiver..." talk puts "Trying 'talk' with an explicit receiver..." obj = Object.new obj.talk
The first call to
talk
succeeds; the second fails with a fatal error, because it tries to call a private method with an explicit receiver.
I wanted to reproduce this on my local, so I put the above code in a Ruby file I created. I did indeed get the results mentioned in the book:
$ ruby talk.rb
Trying 'talk' with no receiver...
Hello
Trying 'talk' with an explicit receiver...
Traceback (most recent call last):
talk.rb:22:in `<main>': private method `talk' called for #<Object:0x00007f9a8499c3e0> (NoMethodError)
I also tried the following, which produced the same error as running the code via the Ruby interpreter:
irb(main):008:0> load 'talk.rb'
Trying 'talk' with no receiver...
Hello
Trying 'talk' with an explicit receiver...
Traceback (most recent call last):
4: from /Users/richiethomas/.rbenv/versions/2.5.3/bin/irb:11:in `<main>'
3: from (irb):8
2: from (irb):8:in `load'
1: from talk.rb:22:in `<top (required)>'
NoMethodError (private method `talk' called for #<Object:0x00007ffb219c95e0>)
Next, I tried the same code in irb
, and this time I got the following strange results:
irb(main):001:0> def talk
irb(main):002:1> puts "Hello"
irb(main):003:1> end
=> :talk
irb(main):004:0> puts "Trying 'talk' with no receiver..."
Trying 'talk' with no receiver...
=> nil
irb(main):005:0> talk
Hello
=> nil
irb(main):006:0> puts "Trying 'talk' with an explicit receiver..."
Trying 'talk' with an explicit receiver...
=> nil
irb(main):007:0> Object.new.talk
Hello
=> nil
As you can see, in the last code example, I was able to call Object.new.talk
and have it print Hello
as if .talk
were a public method on the Object
instance.
My question is- why is the talk
method public on the Object class when I implement it directly in the REPL, but private when I implement it in a file and load it into the REPL (and also when I run that same file directly in my CLI via the Ruby interpreter)?
Because irb evaluates input immediately after it is syntactically complete, the results may be slightly different than directly using Ruby.
. This may refer to the public-level binding your article mentioned. - Richie Thomasruby 'src.rb'
has no problem with but irb can't handle. For example irb would choke onarr.map(&:to_i)
on one line and.sum
on the next (because it wouldn't know the first line continues). Here using irb you'd need to writearr.map(&:to).
on the first line and ``sum` on the next line. - Cary Swoveland