I can define a method on an instance like this:
object = Object.new
def object.foo
puts "5"
end
Trying something similar with a Fixnum doesn't work:
def 3.foo
puts "3"
end
def 3.foo
^
(irb):7: syntax error, unexpected keyword_end, expecting end-of-input
What's the reason for this?
I know this is something I should never do. I'm just wondering why this doesn't work like I expected it to.
There are two things at play here.
One thing is that Fixnums can't have singleton methods. But, we aren't even at that point yet, since your code has a syntax error, and thus Ruby doesn't even attempt to run it in the first place.
The second thing is that Ruby's syntax is complex, and thus there are many dark corner cases. You seem to have found one, where the differing uses of the . symbol to mean both a decimal separator and a method selector conflict with each other in mysterious ways.
Now, of course, this isn't actually much of a problem, since, as I mentioned earlier, Fixnums can't have singleton class anyway:
object = 3
def object.foo
puts "3"
end
# TypeError: can't define singleton
Related
Given the following module:
module Foo
def self.call
'foo'
end
end
I would of course expect the following to work:
puts Foo.call # outputs "foo"
However, I did not expect this to work:
puts Foo.() # outputs "foo"
Apparently when the method name is left off, Ruby assumes that I want to call the call method. Where is this documented, and why does it behave that way?
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...
Apparently, as Arup is saying, this is syntactic sugar introduced a while ago, possibly for the single cause of making Proc objects easier to work with. (You don't have to explicitly call them, but can just do prc.() instead).
I also concluded that this is definitely a Ruby 1.9+ feature. If I switch my JRuby to 1.8 mode, I get this instead:
SyntaxError: spam.rb:12: syntax error, unexpected tLPAREN2
So, somewhere in the changelogs for Ruby 1.9 it can probably be found, if someone really wants to dig it out from the caves... :)
This one's been keeping me up at night for a while.
class Foo
def bar
'bar'
end
# What the hell is going on here?!?
alias :baz :bar
end
Foo.new.baz #=> 'bar'
Why does alias take 2 symbol as arguments, but without a comma separating them? That doesn't seem to be any form of valid syntax in any other context. And in fact, if you do use a comma, it actually throws a syntax error.
alias :bar, :baz
# syntax error, unexpected ','
However, if I try to pass 2 symbol in the same way to my own method, it also explodes:
def somemethod(*args)
:whatever
end
somemethod :a :b
# syntax error, unexpected ':', expecting $end
So why is the alias method get to use a syntax nothing else gets to use?
Is it possible to use this syntax in any other context?
What is the benefit of using this odd syntax quirk, when nothing else in the language works this way? I see no discernable benefit to this language inconsistency.
The reason alias works is because it's a Ruby keyword, similar to class, def, etc. It's not a method.
The alias keyword doesn't need a comma because the Ruby designers decided it didn't. Keywords are essentially hardcoded in the interpreter.
There is a good reason for alias when you need to be certain the alias happens at parse time, not runtime.
The alias keyword may be confusing or surprising. For typical development, I believe it's better to use the Ruby method Module#alias_method, which does use a comma and works at runtime.
Here's a good blog post about alias and alias_method:
This is because alias is a keyword and it is lexically scoped. It
means it treats self as the value of self at the time the source code
was read. In contrast alias_method treats self as the value
determined at the run time.
Overall my recommendation would be to use alias_method. Since
alias_method is a method defined in class Module it can be overridden
later and it offers more flexibility.
It's not a method, and those aren't arguments. alias is one of the few keywords in Ruby (see them all here!). It bothers me as well, so I switched to alias_method (and there are other arguments for this).
I'm kind of confused about reserved words in Ruby.
"The Ruby Programming Language", co-authored by Matz, says that begin and end are reserved words of the language. They're certainly used syntactically to mark out blocks.
However, range objects in the language have methods named begin and end, as in
(1..10).end
=> 10
Now, testing this out, I find that, indeed, I can define methods named "begin" and "end" on objects, though if I try to name a variable "begin" it fails. (Here's a sample of using it as a method name, it actually works...:)
class Foo
def begin
puts "hi"
end
end
Foo.new.begin
So, I suppose I'm asking, what actually is the status of reserved words like this? I would have imagined that they couldn't be used for method names (and yet it seems to work) or that at the very least it would be terrible style (but it is actually used in the core language for the Range class).
I'm pretty confused as to when they're allowed to be used and for what. Is there even documentation on this?
Yes, they are reserved words. Yes, they can be used for method names. No, you can't call them without an explicit receiver. It's probably not a good idea anyway.
class Foo
def if(foo)
puts foo
end
end
Foo.new.if("foo") # outputs foo, returns nil
Update: Here's a quote from "The Ruby Programming Language", by Matz (the creator of Ruby) himself:
In most languages, these words would be called “reserved words” and
they would be never allowed as identifiers. The Ruby parser is
flexible and does not complain if you prefix these keywords with #,
##, or $ prefixes and use them as instance, class, or global variable
names. Also, you can use these keywords as method names, with the
caveat that the method must always be explicitly invoked through an
object.
When they are given in a form that is unambiguously a method call, you can use them. If you have a period in front of it .begin or have parentheses after is begin(), then it is unambiguously a method call. When you try to use it as a variable begin, it is ambiguous (in principle).
Actually, as Perry, notes, begin() might be tricky. I checked with irb with Ruby 1.9.3, and the following strange thing happens:
irb(main):001:0> def begin(foo)
irb(main):002:1> puts 'a'
irb(main):003:1> end
=> nil
irb(main):004:0> begin(3)
irb(main):005:1>
irb(main):006:1* end
=> 3
It is not defined, and what looks like a method call might be just a block returning the last-evaluated 3. But the lines around def begin(foo) remains mystery.
So Module can be used in Ruby to provide namespacing in addition to mixins, as so:
module SomeNamespace
class Animal
end
end
animal = SomeNamespace::Animal.new
But I've also seen the following used:
module SomeNamespace
end
class SomeNamespace::Animal
end
animal = SomeNamespace::Animal.new
My question is how they're different (if they are) and which is more idiomatic Ruby?
The difference lies in nesting.
In the example below, you can see that the former method using class Foo, can get the outer scope's constant variables BAR_A without errors.
Meanwhile, class Baz will bomb with an error of uninitialized constant A::B::Baz::BAR_A. As it doesn't bring in A::* implicitly, only A::B::*explicitly.
module A
BAR_A = 'Bar A!'
module B
BAR_B = 'Bar B!'
class Foo
p BAR_A
p BAR_B
end
end
end
class A::B::Baz
p BAR_A
p BAR_B
end
Both behaviors have their place. There's no real consensus in the community in my opinion as to which is the One True Ruby Way (tm). I personally use the former, most of the time.
The only difference between the two approaches is that the second one will throw uninitialized constant Object::SomeNamespace if the namespace hasn't previously been declared.
When declared in a single file, I would opt for the first one because you don't have to repeat SomeNamespace.
When using multiple files I also use the second one, to avoid running into the following problem:
# in a.rb
require 'b'
module SomeNamespace
def self.animal
Animal.new
end
end
# in b.rb
class SomeNamespace::Animal
end
# irb
require 'a' # explodes with the uninitialized constant error
This example may be contrived, but it's easy to trigger it if your code base is a little bit bigger. I usually use the explicit way (your first one) to avoid this.
One thing that may be helpful when using the second form is that it will detect typos in the namespace.
There doesn't seem to be an established way to create namespaces, Devise for example mixes both approaches: first one, second one.
One question that ran through my mind was how does the Ruby interpreter know that a method exists on a object if the definition is yet to be interpreted? Like, wouldn't it matter whether you define the method first than use it, rather than use it then define it?
It doesn't know, and it doesn't care - until execution. When a method call statement is executed, the interpreter looks to see if the class (object, not code!) has the named function. If it does not, it looks up the ancestor tree. If it does not find any, it calls the method_missing method. If that is not defined, you get your error.
If your function call does not get executed, you will not get any errors.
The interpreter doesn't know about undefined methods ahead of time, for example:
o = Object.new
o.foo # => Raises NoMethodError.
class Object
def foo
puts "Foo!"
end
end
o.foo # => prints "Foo!", since the method is defined.
However, Ruby has a neat feature called method_missing which let's the receiver of a method call take the method name and arguments as separate arguments and handle accordingly as long as no defined method already handles the call.
def o.method_missing(sym, *args)
puts "OK: #{sym}(#{args.inspect})"
# Do something depending on the value of 'sym' and args...
end
o.bar(1, 2, 3) #=> OK: bar(1, 2, 3)
"Method missing" is used by things like active record find methods and other places where it could make sense to have "dynamically defined" functions.
The problem is, the interpreter tried to find it when you use it, and since it won't be there, it may fail.
In ( some ) compiled languages, it doesn't matter, because while compiling, the compiler may say "I'll look for this on a second pass" but I don't think this is the case with Ruby.