There are a number of great simple, but challenging problems over at Rubeque. As such, going through all the Rubeque problems is a great way to learn some of the less-known ins-and-outs of Ruby.
Just recently, I have been working to solve the Redefining Splat problem. The splat operator, otherwise known as the asterisk, is one of the cooler little details about Ruby (and Python).
In its most common usage, the splat operator mops up extra arguments passed to a function into an array. For example:
def function(arg1, arg2, *other_ags) # => arg1, arg2, [other_args] end
In its opposite usage, the splat operator explodes an array into its individual elements. For example, with parallel assignment:
a, b, c = *[1, 2, 3] # => a = 1, b = 2, c = 3
To the unexperience eye, this all looks like magic, which makes the "Redefining Splat" problem a little mystifying at first. The challenge is to make the following code pass by redefining the behavior of the splat operator.
assert_equal "FOO", *"foo" *x = "BAR" assert_equal ["bar"], x
To start it's worth noting that the problem expects two distinct behaviors from the splat operator. First,
*"foo" should return an array of
"FOO". I assume
assert_equal works similarly to
puts in that it pulls whatever elements are in an array out before testing them, hence the first line above where
"FOO" does not appear within an array. Second, we need to redefine the way
* works in assigning strings to variables. The assignment in line two above should return a new string within an array and with the case swapped.
Defining these two behaviors is actually quite simple. The trick is to recognize that in the first case above the
* is synonymous with a call to
to_a. If we override the behavior of
to_a within the
String class, we'll have half the answer.
class String def to_a [self.swapcase] end end
While it might seem that
to_a handles both cases above, it actually does not. The other half of the problem depends upon redefining
to_ary which is called when the
* is used on a variable in an assignment. Since we can use the
swapcase method on both cases, there is no need to repeat ourselves. So for
to_ary, we can write:
class String alias to_ary to_a end
alias simply sends all calls to
to_ary right along to
to_a. And voila! We have the answer. We can now use the splat operator in front of a string and a variable with the desired behavior.