Skip to content

Instantly share code, notes, and snippets.

@weapp
Created April 20, 2017 07:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weapp/45a9256baed1ea0891a5e0724b7b4626 to your computer and use it in GitHub Desktop.
Save weapp/45a9256baed1ea0891a5e0724b7b4626 to your computer and use it in GitHub Desktop.

%title: Splats: beyond *args %author: weapp %date: 2017-04-20

-> # What is * (splat) <-

by urbandictionary

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 <-

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 <-

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 <-

ruby-doc

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 <-

ruby-doc

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]}

@weapp
Copy link
Author

weapp commented May 19, 2022

mdp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment