Ruby
0 views
Splat, ?:, and Array#* in one line
Question
What is the return value of the following Ruby code?
["a", *["b", "c"], "d"] * ?: # => ???
The correct answer is
-
["a:", "b:", "c:", "d:"] -
"a:b:c:d"Correct -
["a:", ["b", "c"], "d:"] -
It raises
SyntaxError
Explanation
TL;DR
Three idioms stack up in this line. The splat *["b", "c"] inlines the sub-array into the surrounding literal, giving ["a", "b", "c", "d"]. ?: is a character literal for the one-character string ":". And Array#* with a String argument behaves like Array#join. Result: "a:b:c:d".
The splat operator
["a", *["b", "c"], "d"] # => ["a", "b", "c", "d"]
* expands the sub-array's elements into the surrounding array literal. It is handy when part of a row is only known at runtime, CSV generation for example:
title = "Hello"
authors = ["Author 1", "Author 2"]
[title, *authors] # => ["Hello", "Author 1", "Author 2"]
Character literals
?: is shorthand for a single-character string:
?: # => ":"
?a # => "a"
Array#*
Array#* dispatches on its argument type: an Integer repeats the array, a String joins it:
[1, 2] * 3 # => [1, 2, 1, 2, 1, 2]
[1, 2] * ", " # => "1, 2"
So the full expression boils down to a join:
["a", "b", "c", "d"] * ":" # => "a:b:c:d"
["a", "b", "c", "d"].join(":") # => "a:b:c:d"
["a", *["b", "c"], "d"] * ?: # => "a:b:c:d"
Share this quiz
Comments
No comments yet. Be the first.