=> Tue Apr 13 19:27:43 -0400 2010
irb> Time.now() -t
irb> Time.now -t
NoMethodError: undefined method -@' for Tue Apr 13 19:27:43 -0400 2010:Time from (irb):5 from :0 irb> -t NoMethodError: undefined method -@’ for Tue Apr 13 19:27:43 -0400
The flexible syntax also lets you omit parentheses and in this case,
the “-t” is parsed as an argument to the Time.now method. Putting the
explicit (and empty) argument list on the call removes this ambiguity.
The ‘-@’ method is the unary minus method. The error message is
because there is no method that negates a Time instance.
I had understood that operators, like minus (-), had special “syntactic
sugar” that allowed me to include or omit spaces around them like this:
However, in some cases, spaces seem to matter:
t = Time.now
=> Tue Apr 13 13:40:24 -0700 2010
NoMethodError: undefined method `-@’ for Tue Apr 13 13:40:24 -0700
Time.now - t
Can someone explain what “undefined method `-@'” refers to?
Probably “unary -”.
x = 3
puts - x
NoMethodError: undefined method `-’ for nil:NilClass
Basically, Ruby is interpreting “-x” as a unary minus on x, rather
than as part of a larger expression. It turns out to be ambiguous
in this case, because Ruby can’t tell whether you mean
(Time.now()) - (t)
(Time.now(-1 * t))
Only unary - isn’t necessarily “-1 * t”, it’s just “whatever you get
calling -@ on t”.
In m *10 the * is the unary *, while in m * 10 it’s the infix
And what, may I ask, it the unary * operator? Is it what I’ve heard
Rubyists call the “splat” operator that you use in var args? How and
why would you override it?
It is indeed what people call the “splat” operator, though I’ve never
found that name very expressive. I think of it as the unar[r]ay
operator (that’s unary unarray It does an “unarray” operation in
the sense that it can turn an array into a bare list, in a method
You can’t define it directly (I believe that’s true in 1.9 as well as
earlier versions), but you can affect what it does via the #to_a
o = Object.new
def o.to_a; [1,2,3]; end
a = *o
p a # [1,2,3]
As for the why: I don’t think you’d often define #to_a just to get *
behavior. It’s more of an extra thing you get in cases where you need #to_a anyway.
minus (-) is interpreted as a binary object when preceded by object.
When preceded by a method name and parentheses are omitted, it is
interpreted as a unary operator acting on the object that follows it.
There is nothing special about Fixnum or String, here is an example with
t1 = Time.now
=> Wed Apr 14 15:11:33 -0700 2010
t2 = Time.now
=> Wed Apr 14 15:11:41 -0700 2010
Whew. Thanks everyone!
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.