IRB appears to have strange behaviour when defining a method called !.
To reproduce this, enter the following into IRB:
def !
puts "foo"
end
Upon creating the method, IRB infinitely prints foo:
irb(main):001:0> def !
irb(main):002:1> puts "foo"
irb(main):003:1> end
foo
foo
foo
...
As far as I know, you can't directly call a method named ! from Ruby syntax; you have to use send instead. Edit: You can invoke ! as a prefix operator; it's just negation: !x
Why does this definition cause IRB to loop infinitely? Does IRB rely on a method named ! for printing its prompt or something similar?
I'm using Ruby 2.4.3 and IRB 0.9.6 on Windows 10.
tl;dr: Overriding ! outside of a class is a very weird thing to do! There are countless ways that you can "break" ruby by doing crazy things like this - so you may find it fun to play around with such strange ideas, but obviously don't do this in important code!
In ruby, all classes inherit from the top-level base class: BasicObject. This class defines top-level object negation - i.e. Whenever you write
!foo
this is actually calling a method called ! on your object foo:
foo.send(:!)
This makes it possible (although it's a very rare thing to do!) to redefine the method on a specific class. For example, when implementing the null object pattern you could do something like this:
class NullObject
def !
true
end
end
my_null = NullObject.new
!!my_null #=> false
(Normally, the only objects that would return false in the above line are nil and false!)
Now then, back to your example. What you actually did here was define a method called ! on the class Object (and didn't call super to trigger the original method!). In other words, you basically re-defined the response a fundamental method that gets used all over the place internally. Something, somewhere (??) got confused by this bizarre behaviour and failed non-gracefully.
irb(main):001:0> def !
irb(main):002:1> puts "foo"
irb(main):003:1> super # <-- !! This stops it from breaking completely !!
irb(main):004:1> end
=> :!
irb(main):005:0* method(:!)
foo
foo
=> #<Method: Object#!>
irb(main):006:0> method(:!).source_location
foo
foo
=> ["(irb)", 1]
irb(main):007:0> method(:!).super_method
foo
foo
=> #<Method: BasicObject#!>
Here are some other ways you could re-define methods to cause bizarre behaviour/errors, for example:
def nil?
true
end
# Will now die in weird ways!
class String
def ===(other)
true
end
end
"ruby" === "awesome"
#=> true
Related
Given this script
def hash
puts "why?"
end
x = {}
x[[1,2]] = 42
It outputs the following
why?
/tmp/a.rb:6:in `hash': no implicit conversion of nil into Integer (TypeError)
from /tmp/a.rb:6:in `<main>'
It seems that the hash function defned in the script is overriding Array#hash in that case. Since the return value of my hash method is nil and not an Integer, it throws an exception. The following script seems to confirm this
puts [1,2,3].hash
def hash
puts "why?"
end
puts [1,2,3].hash
The output is
-4165381473644269435
why?
/tmp/b.rb:6:in `hash': no implicit conversion of nil into Integer (TypeError)
from /tmp/b.rb:6:in `<main>'
I tried looking into the Ruby source code but could not figure out why this happens. Is this behavior documented?
You're not overriding Array#hash, you're shadowing Kernel#hash by creating Object#hash:
puts method(:hash)
def hash
puts "why?"
end
puts method(:hash)
That prints:
#<Method: Object(Kernel)#hash>
#<Method: Object#hash>
Fix it so we can see more:
def hash
puts "why?"
super
end
x = {}
x[[1,2]] = 42
Now the output is:
why?
why?
And no error. Try it with x[[1,2,3,4,5,6,7]] = 42 and you'll instead see why? printed seven times. Once for each array element, since the array's hash method uses the hashes of its elements. And Integer#hash doesn't exist, it inherits its hash method from Object/Kernel, so yours gets used.
This is due to a kind of hack in Ruby top level. Have you ever wondered how this works?
def foo
end
p self
foo
class Bar
def test
p self
foo
end
end
Bar.new.test # no error
How are two totally different objects (main and a Bar) able to call foo like it's a private method call? The reason is because... it is a private method call.
When you define a method at the top level of your Ruby script, it gets included (via Object) in every object. That's why you can call top-level methods like they are global functions.
But why does this break only hash and not other common methods? def to_s;end won't break to_s, for example. The reason is because hash is recursive: most* class implementations ultimately call down to Object#hash for their implementations. By redefining that base case, you break it globally. For other methods like to_s you won't see a global change because it's way up the inheritance chain and doesn't get invoked.
* the only objects this doesn't break are a few literals that probably have hard-coded hash values e.g. [] {} "" true etc.
When I'm coding in Ruby, to avoid type checks and respond_to?s and nil checks I often coerce objects into the type I expect. If I expect an Array, instead of foo.nil? ? handle_nil(foo) : handle_array(foo) I prefer to just handle_foo(foo.to_a) since nil.to_a # => [].
This doesn't work for everything, 1.to_a raises NoMethodError: undefined method 'to_a' for 1:Integer. 1.to_ary raises the same error. Array() seems to solve the problem, handling what seems like any object and either making a sensible conversion to an Array or wrapping it in [].
Array(nil) # => []
Array('') # => [""]
Array(Class) # => [Class]
Array(1) # => [1]
Array(Object.new) # => [#<Object:0x007fdbd40df4c8>]
Array({}) # => []
Array(foo: :bar) # => [[:foo, :bar]]
You can do the same thing with other classes too. String(), Float()... I'd used it a lot without thinking about the unusual syntax. I wanted to learn more about the implementation. Is it syntactic sugar for a special method, similar to #[]?
Both of these raise a SyntaxError
def self.(foo)
puts foo
end
def self.()(foo)
puts foo
end
You use Array() like you would use a method. Looking at the docs for Kernel it becomes clear that that's what's going on. The following works as you'd expect:
class Thing
attr_accessor :name
def initialize(name)
#name = name
end
end
module Kernel
def Thing(name)
Thing.new(name)
end
end
thing = Thing('name') # => #<Thing:0x007fefef89d8e8 #name="name">
thing.name # => "name"
You can also do this
HI = 'hi'.freeze
def HI(word)
word
end
HI # => "hi"
HI("ho") # => "ho"
My question is: How does Ruby interpret this? How does it distinguish between the method and the constant? Is this a silly question? Given "normal" behavior, one might expect Ruby to complain with a name warning when you define the method, or raise a SyntaxError. Does anyone know how Ruby handles this under the hood?
Thanks!
How does Ruby interpret this? How does it distinguish between the method and the constant?
The rules are pretty much the same as with local variables: Ruby will assume it is a constant unless it's obvious that it isn't: constants can't have arguments, and constants can't have receivers.
FOO # constant
self.FOO # message send
FOO() # message send
FOO :bar # message send
Given "normal" behavior, one might expect Ruby to complain with a name warning when you define the method, or raise a SyntaxError.
Why? Defining a method is perfectly legal syntactically (after all, that's what OO is all about), and Array is a perfectly legal Ruby identifier.
Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.
In a unit test I need to test whether alias methods defined by alias_method have been properly defined. I could simply use the same tests on the aliases used for their originals, but I'm wondering whether there's a more definitive or efficient solution. For instance, is there a way to 1) dereference a method alias and return its original's name, 2) get and compare some kind of underlying method identifier or address, or 3) get and compare method definitions? For example:
class MyClass
def foo
# do something
end
alias_method :bar, :foo
end
describe MyClass do
it "method bar should be an alias for method foo" do
m = MyClass.new
# ??? identity(m.bar).should == identity(m.foo) ???
end
end
Suggestions?
According to the documentation for Method,
Two method objects are equal if that
are bound to the same object and
contain the same body.
Calling Object#method and comparing the Method objects that it returns will verify that the methods are equivalent:
m.method(:bar) == m.method(:foo)
bk1e's method works most of the time, but I just happened to hit the case where it doesn't work:
class Stream
class << self
alias_method :open, :new
end
end
open = Stream.method(:open)
new = Stream.method(:new)
p open, new # => #<Method: Stream.new>, #<Method: Class#new>
p open.receiver, new.receiver # => Stream, Stream
p open == new # => false
The output is produced in Ruby 1.9, not sure if it's a bug or not since Ruby 1.8 produces true for the last line. So, if you are using 1.9, be careful if you are aliasing an inherited class method (like Class#new), These two methods are bound to the same object (the class object Stream), but they are considered not equivalent by Ruby 1.9.
My workaround is simple - alias the original method again and test the equality of the two aliases:
class << Stream; alias_method :alias_test_open, :new; end
open = Stream.method(:open)
alias_test_open = Stream.method(:alias_test_open)
p open, alias_test_open # => #<Method: Stream.new>, #<Method: Stream.new>
p open.receiver, alias_test_open.receiver # => Stream, Stream
p open == alias_test_open # => true
Hope this helps.
UPDATE:
See http://bugs.ruby-lang.org/issues/7613
So Method#== should return false in this case since a super call would invoke different methods; it is not a bug.
Calling MyClass.instance_method(:foo) will result UnboundMethod instance, which has eql? method.
So the answer is:
describe MyClass do
subject { described_class }
specify do
expect(subject.instance_method(:foo)).to be_eql(subject.instance_method(:bar))
end
end
At the top level, method definition should result in private methods on Object, and tests seem to bear this out:
def hello; "hello world"; end
Object.private_instance_methods.include?(:hello) #=> true
Object.new.send(:hello) #=> "hello world"
However, the following also works at top level (self.meta is the eigenclass of main):
self.meta.private_instance_methods(false).include?(:hello) #=> true
It appears that the hello method is simultaneously defined on the eigenclass of main as well as on Object. What's going on? Note that the false parameter to private_instance_methods excludes super class methods from the method list.
First of all, this behavior and the underlying reasoning have always existed; it's nothing new to 1.9. The technical reason it happens is because main is special and treated differently than any other object. There's no fancy explanation available: it behaves that way because it was designed that way.
Okay, but why? What's the reasoning for main to be magical? Because Ruby's designer Yukihiro Matsumoto thinks it makes the language better to have this behavior:
Is so, why are top-level methods not made singleton-methods on this object,
instead of being pulled in as instance methods on the Object class
itself
(and hence into all other classes i.e. more namespace pollution than is
usually intended). This would still allow top-level methods to call other
top-level methods. And if the top-level object were referred to by
some
constant like Main, then those methods could be called from anywhere
with
Main.method(...).
Do you really wish to type
"Main.print" everywhere?
Further on in the discussion, he explains that it behaves this way because he feels the "assumption is natural."
EDIT:
In response to your comment, your question is aimed at why main's eigenclass seems to report hello as a private instance method. The catch is that none of the top-level functions are actually added to main, but directly to Object. When working with eigenclasses, the instance_methods family of functions always behave as if the eigenclass is still the original class. That is, methods defined in the class are treated as being defined directly in the eigenclass. For example:
class Object
private
def foo
"foo"
end
end
self.send :foo # => "foo"
Object.private_instance_methods(false).include? :foo # => true
self.meta.private_instance_methods(false).include? :foo # => true
class Bar
private
def bar
"bar"
end
end
bar = Bar.new
bar.send :bar # => "bar"
Bar.private_instance_methods(false).include? :bar # => true
bar.meta.private_instance_methods(false).include? :bar # => true
We can add a method directly to main's eigenclass, though. Compare your original example with this:
def self.hello; "hello world"; end
Object.instance_methods.include? :hello # => false
self.meta.instance_methods.include? :hello # => true
Okay, but what if we really want to know that a given function is defined on the eigenclass, not the original class?
def foo; "foo"; end #Remember, this defines it in Object, not on main
def self.bar; "bar"; end #This is defined on main, not Object
foo # => "foo"
bar # => "bar"
self.singleton_methods.include? :foo # => false
self.singleton_methods.include? :bar # => true