%title: Splats: beyond *args %author: weapp %date: 2017-04-20
-> # What is * (splat) <-
splat
\ an asterisk. Used by UK computer people. Because it looks like something \ squashy, like mashed potato, that has hit a wall in a comic (like the Beano) \ accompanied by the word SPLAT! \
\ IT help desk. 'Hit the splat key'
-> # * at ruby-doc <-
Prefixing an argument with * causes any remaining arguments to be converted to an Array:
def gather_arguments(*arguments) \ p arguments end
gather_arguments 1, 2, 3 # prints [1, 2, 3]
Also, note that a bare * can be used to ignore arguments:
def ignore_arguments(*) end
-> # Left-hand side <-
-> Like in def fun(*args) or *args = list <-
Works as a wildcard
Examples:
irb> list = [1, 2, 3, 4, 5] irb> foo, *splat, bar = list ^ => [1, 2, 3, 4, 5] ^
irb> p foo, splat, bar ^ 1 [2, 3, 4] 5 => [1, [2, 3, 4], 5]
-> # Splats and super <-
class Parent
attr_accessor :name
def initialize(name="Mr. Doe")
@name = name
end
end
class Boy < Parent
def initialize(*)
super()
end
end
irb> c1 = Boy.new("Johnny").name ^ => "Mr. Doe"
-> # Splats and super <-
class Parent
attr_accessor :name
def initialize(name="Mr. Doe")
@name = name
end
end
class Girl < Parent
def initialize(*)
super
end
end
irb> c2 = Girl.new("Janie").name ^ => "Janie"
-> # * at ruby-doc <-
Given the following method:
def my_method(argument1, argument2, argument3) end
You can turn an Array into an argument list with * (or splat) operator:
arguments = [1, 2, 3] my_method(*arguments)
or:
arguments = [2, 3] my_method(1, *arguments)
Both are equivalent to:
my_method(1, 2, 3)
-> # Right-hand side <-
-> Like in foo = *something or call(*something) or *[*something] <-
-> foo = \*something
== foo = [\*something]
== foo = splat1(something)
<-
def splat1(something) \ something.respond_to?(:to_a) ? something.to_a : [something] end
^
irb> [*[1, 2]] ^ => [1, 2]
^
irb> [*1] ^ => [1]
^
irb> [*[]] ^ => []
^
irb> [*[1]] ^ => [1]
^
irb> [*[nil]] ^ => [nil]
-> # Right-hand side <-
-> Like in foo = *something or call(*something) or *[*something] <-
^
irb> [*nil] ^ => []
^
irb> [*{a: 1, b: 2}] ^ => [[:a, 1], [:b, 2]]
^
irb> [*OpenStruct.new(to_a: [1,2])] ^ => [1, 2]
^
irb> [*OpenStruct.new(to_ary: [1,2])] ^ => [#<OpenStruct to_ary=[1, 2]>]
-> # Building lists <-
-> Array(...) <-
-> Array.new(...) <-
-> [...] or Array[...] or Array.[](...) <-
-> [*...] <-
-> Array.wrap(...) <-
class Ary
def to_ary
['a', 'r', 'y']
end
end
class Arr
def to_a
['a', 'r', 'r']
end
end
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with one argument <-
irb> Array(7) ^ => [7]
^ irb> [*7] ^ => [7]
^ irb> Array.new(7) ^ => [nil, nil, nil, nil, nil, nil, nil]
^ irb> Array[7] ^ => [7]
^ irb> Array.wrap(7) ^ => [7]
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with many arguments <-
irb> Array(1, 2, 3) ^ ArgumentError: wrong number of arguments (3 for 1)
^ irb> [(1, 2, 3)] ^ SyntaxError: (irb):20: syntax error, unexpected ',', expecting ')' [(1, 2, 3)] ^
^ irb> Array.new(1, 2, 3) ^ ArgumentError: wrong number of arguments (3 for 0..2) ^ irb> Array.new(2, 3) ^ => [3, 3]
^ irb> Array[1, 2, 3] ^ => [1, 2, 3]
^ irb> Array.wrap(1, 2, 3) ^ ArgumentError: wrong number of arguments (3 for 1)
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with list argument <-
irb> Array([1, 2, 3]) ^ => [1, 2, 3]
^ irb> [*[1, 2, 3]] ^ => [1, 2, 3]
^ irb> Array.new([1, 2, 3]) ^ => [1, 2, 3]
^ irb> Array[[1, 2, 3]] ^ => [[1, 2, 3]]
^ irb> Array.wrap([1, 2, 3]) ^ => [1, 2, 3]
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with nil argument <-
irb> Array(nil) ^ => []
^ irb> [*nil] ^ => []
^ irb> Array.new(nil) ^ TypeError: no implicit conversion from nil to integer
^ irb> Array[nil] ^ => [nil]
^ irb> Array.wrap(nil) ^ => []
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with boolean argument <-
irb> Array(false) ^ => [false]
^ irb> [*false] ^ => [false]
^ irb> Array.new(false) ^ TypeError: no implicit conversion of false into Integer
^ irb> Array[false] ^ => [false]
^ irb> Array.wrap(false) ^ => [false]
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with hash argument <-
irb> Array({key: :value}) ^ => [[:key, :value]]
^ irb> [*{key: :value}] ^ => [[:key, :value]]
^ irb> Array.new({key: :value}) ^ TypeError: no implicit conversion of Hash into Integer
^ irb> Array[{key: :value}] ^ => [{:key=>:value}]
^ irb> Array.wrap({key: :value}) ^ => [{:key=>:value}]
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with hash argument <-
irb> Array(Arr.new) ^ => ["a", "r", "r"]
^ irb> [*Arr.new] ^ => ["a", "r", "r"]
^ irb> Array.new(Arr.new) ^ TypeError: no implicit conversion of Arr into Integer
^ irb> Array[Arr.new] ^ => [#Arr:0x007fa189829830]
^ irb> Array.wrap(Arr.new) ^ => [#Arr:0x007fb9696eaa80]
-> ## Array(), Array.new(), Array[], [*], Array.wrap <- -> ## with hash argument <-
irb> Array(Ary.new) ^ => ["a", "r", "y"]
^ irb> [*Ary.new] ^ => [#Ary:0x007fb96a0af250]
^ irb> Array.new(Ary.new) ^ => ["a", "r", "y"]
^ irb> Array[Ary.new] ^ => [#Ary:0x007fb9695ffcd8]
^ irb> Array.wrap(Ary.new) ^ => ["a", "r", "y"]
-> # Making magic with splats <-
irb> [*7, *"", :no_splat, *[2,3], *nil, *false, "other"]
_ _
a) [7, :no_splat, 2, 3, "other"]
b) [7, "", :no_splat, 2, 3, false, "other"]
c) [7, :no_splat, 2, 3, nil, false, "other"]
d) [7, "", :no_splat, 2, 3, "other"]
e) ArgumentError
^
_ _
b) => [7, "", :no_splat, 2, 3, false, "other"]
-> # Making magic with splats <-
irb> [*:symbol, *Object.new, *true, *{key: :value}]
_ _
a) [:symbol, Object.new, true, [:key, :value]]
b) [:symbol, #Object:0x007fbbdf1c1d88, true, {key: :value}]
c) [:symbol, Object.new, true, {key: :value}]
d) [:symbol, #Object:0x007fbbdf1c1d88, true, [:key, :value]]
e) ArgumentError
^
_ _
d) => [:symbol, #Object:0x007fbbdf1c1d88, true, [:key, :value]]
-> # Making magic with splats <-
irb> [*:symbol, *true, *{key: :value, other_key: :other_value}]
_ _
a) [:symbol, true, [[:key, :value], [:other_key, :other_value]]]
b) [:symbol, true, [:key, :value], [:other_key, :other_value]]
c) [:symbol, true, [:key, :value, :other_key, :other_value]]
d) [:symbol, true, :key, :value, :other_key, :other_value]
e) ArgumentError
^
_ _
b) => [:symbol, true, [:key, :value], [:other_key, :other_value]]
-> # Making magic with splats <-
irb> [*:symbol, *true, *[{key: :value}], *[[:a, :b], [:c]]]
_ _
a) [:symbol, true, [:key, :value], [:a, :b], [:c]]
b) [:symbol, true, [[:key, :value]], [:a, :b], [:c]]
c) [:symbol, true, {:key=>:value}, [:a, :b], [:c]]
d) [:symbol, true, [[:key, :value]], :a, :b, [:c]]
e) ArgumentError
^
_ _
c) => [:symbol, true, {:key=>:value}, [:a, :b], [:c]]
-> Thanks <-
-> Find me on 🔥 Tinder: <-
-> @weapp <-
-> # Extra <-
is similar to multiple assignment:
a = *[1, 2, 3]
p a # prints [1, 2, 3]
You can splat anywhere in the right-hand side of the assignment:
a = 1, *[2, 3]
p a # prints [1, 2, 3]
-> # Extra II <-
You can use a * to collect the remaining arguments. This splits an Array into a first element and the rest:
def my_method((a, *b)) \ p a: a, b: b end
my_method([1, 2, 3])
This prints:
^
{:a=>1, :b=>[2, 3]}
mdp