Some time ago, I started calling Ruby’s unary * operator the “grenade operator”. After all, the glyph looks like an explosion, and the metaphorical operation is the taking of a container packed with stuff and blasting the container open so that the contents are strewn about, ready for more direct use. People seem to get a tickle out of the term when use it in IRC, and I have been coaxed into submitting to the urge to make a blog post about it, in order to concretize my claim to its coinage. So here’s the blog post.
You can apparently do a number of nifty things with the grenade operator. Here are the two that I tend to do most often.
Converting an array to a syntactic list
There’s probably some more appropriate and correct terminology for this operation, but I like to think of it as taking the elements of an array, and turning them into a list, as though that list were “typed out”, as it were, into your code. For example:
def tell_family_story( father, mother, child ) puts "#{father} married #{mother} and " puts "they loved each other so much that " puts "#{child} was born." end family = [ "John", "Marsha", "Jack" ] tell_family_story( *family )
John married Marsha and they loved each other so much that Jack was born.
Methods with a variable number of parameters
Sometimes you want to craft a method that can have a different number of parameters from call to call. You would then use the grenade operator to collect many method parameters into a single array, like so:
def list_favourites( format_str, *data ) format_str.scan( /\w/ ) do |fmt| per = data.shift fav = data.shift case fmt when 'l' puts "#{per} likes #{fav.downcase}" when 'u' puts "#{per} likes #{fav.upcase}" else puts "#{per} likes #{fav}" end end end list_favourites( "nlu", "John", "Fishing", "Marsha", "Shopping", "Jack", "Grenades" )
John likes Fishing Marsha likes shopping Jack likes GRENADES
Other uses
There are other feats of wizardry that some coders perform with the grenade operator, such as some assignment acrobatics, as described in the Pickaxe Book:
a = [1, 2, 3, 4] b, c = a # b == 1, c == 2 b, *c = a # b == 1, c == [2, 3, 4] b, c = 99, a # b == 99, c == [1, 2, 3, 4] b, *c = 99, a # b == 99, c == [[1, 2, 3, 4]] b, c = 99, *a # b == 99, c == 1 b, *c = 99, *a # b == 99, c == [1, 2, 3, 4] b, (c,*d), e = 1,[2,3,4],5 # b == 1, c == 2, d == [3, 4], e == 5
Final notes
You might get confused as to which side of the operand you should toss the grenade operator toward. Just keep in mind that if it were on the right side, it would be the binary * operator, and Ruby would expect something on the other side of the operator. Therefore, always throw to the left.
Have fun with your new explosives, but also note that, no matter how you interpret the first example, I am by no means suggesting that you hurl grenades at families trapped in boxes.
Related posts: