Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour of Array bang methods

Tags:

arrays

ruby

Some bang version of Array methods are like compact!, reject!, flatten!, uniq! return nil if no changes were made:

[1,[2]].flatten!
# => [1, 2]
[1,2].flatten!
# => nil
[1,[2]].flatten
# => [1, 2]
[1,2].flatten
# => [1, 2]

[1,2,nil].compact!
# => [1, 2]
[1,2].compact!
# => nil
[1,2,nil].compact
# => [1, 2]
[1,2].compact
# => [1, 2]

If they did it this way, there has to be a reason. Any ideas what it might be?

like image 357
artemave Avatar asked Sep 18 '10 13:09

artemave


People also ask

What are bang methods?

Simply put, a bang method is a method with an exclamation mark at the end. We may often come across a statement that the bang method is, in a sense, a dangerous method and the exclamation mark at the end of its definition tells us to be vigilant when using this method.

What does bang do in Rails?

Bang or exclamation mark means that you are making a permanent saved change in your code. If you use for example Ruby's method for global substitution gsub! the substitution you make is permanent. Another way you can imagine it, is opening a text file and doing find and replace, followed by saving. !

What is array method in Ruby?

An array is a built-in Ruby class, which holds a list of zero or more items, and includes methods that help you easily add, access, and loop over all these items. This is helpful, because if arrays didn't exist you would have to use many variables. Example: a = 1 b = 2 c = 3. But instead, you can do: numbers = [1, 2, 3 ...


2 Answers

The bang (!) methods do modify the current object in place, but they do return nil if there are no affected elements per the documentation. This is useful if, for whatever reason, you need to do something if you did modify the array in question.

if array.flatten!
  puts "Oh yeah... flattened that array!"
end
like image 199
Dave Pirotte Avatar answered Oct 17 '22 18:10

Dave Pirotte


I was always under impression that bang version of Array methods are only different in the way that they modify object in place.

Perhaps the problem here is that this impression is not really a correct one: according to David A. Black, ! does not mean that the method changes its receiver; ! means that this method is the "dangerous" version of an otherwise equivalent method, which has the same name minus the !.

Now danger takes many forms (emphasis mine):

Sometimes you get more than one kind of "danger" even within one bang method. Take String#gsub!. This method changes its receiver:

str = "David" 
str.gsub!(/$/, " Black")
str                        # David Black

It also differs from gsub (non-bang) in that if the string does not change, gsub returns a copy of the unchanged string but gsub! returns nil:

str.gsub(/xyz/, "blah")    # David Black
str.gsub!(/xyz/, "blah")   # nil
str                        # David Black

The ! in gsub! gives you a heads-up: it warns you of danger, and that means that before you use the method, you should find out exactly how it behaves. (A simple "ri String#gsub!" should do it.)

This "heads-up" semantics also applies to the bang methods of Array.

like image 22
Yaser Sulaiman Avatar answered Oct 17 '22 20:10

Yaser Sulaiman