0

I'm familiar with Python and Java, and am trying to learn Ruby to broaden my scope a bit.

I'm not quite sure how to conceptualise the "!-notation" of self-assignment. In case I'm not using the right words to describe this, compare:

foo = 'Hello World!'
foo = foo.downcase

and

foo = 'Hello World!'
foo.downcase!

Both end up with foo reading 'hello world!'. It seems, then, that foo.<method>! is short-hand for foo = foo.<method>.

However, this doesn't seem to be universally true. When trying to call sort-by on a hash frequencies, for example, the suggested method is:

frequencies = frequencies.sort_by { |word, freq|
  freq
}

which works. If, however, I try:

frequencies.sort_by! { |word, freq|
  freq
}

I get

undefined method `sort_by!' for {<the_contents_of_my_hash>}:Hash

Is !-notation (what is that properly called, by the way?) only available on strings and arrays? Or is there some deeper concept I'm missing?

scubbo
  • 4,969
  • 7
  • 40
  • 71
  • 1
    Probably duplicate of http://stackoverflow.com/questions/612189/why-are-exclamation-marks-used-in-ruby-methods. In short, methods ending with an exclamation point will modify the object itself. – Ilya I Apr 05 '14 at 19:36

1 Answers1

2

In Ruby, the characters ? and ! are allowed in method names. It's not a special operator are anything. It's a Ruby convention that methods that are considered to perform "dangerous" operations, like modifying the calling collection (instead of returning a new collection), or throwing an exception on an error instead of returning nil or false, often have a ! suffix.

However, not all methods have a ! version. sort_by, for example, doesn't have one, if you look at the documentation.

! methods aren't only available on string and arrays. You can define them on anything.

  • Gotcha. I had naively assumed that it was a property of the language, rather than an explicitly added optional version of some methods. Thanks for clearing that up! – scubbo Apr 05 '14 at 19:44
  • @scubbo also worth noting, methods that end with `?` usually, if not always, return boolean values. Also, methods that end with `=` are used as setters, for assigning to properties. –  Apr 05 '14 at 19:45