Primeiro, * Rest: lista de processamento em Ruby

Contexto

Em linguagens funcionais, as listas são frequentemente manipuladas obtendo o primeiro argumento e, em seguida, associando o restante da lista a um local separado para processamento futuro. No clojure, a API se parece com:

(rest [1 2 3]) ; => (2,3)
(first [1 2 3]) ; => 1

Argumentos Splat para criar uma matriz de expressão

Esses idoms são geralmente bons em linguagens OO ao lidar com retornos do tipo array. Por exemplo, uma expressão regular em Ruby:

regex = /(d{3})/
# the normal way
match_data
= "555-867-5309".match(regex)
# normally we don't really care about the match data
# what we really want are the memoized matches
match_data
[1] #=> "555"

# splat the return
match_data
, area_code = *"555-867-5309".match(regex)
area_code
#=> "555"

Portanto, no trecho de código anterior, usamos o operador splat para ‘lançar’ o retorno de String#matchem uma matriz e, em seguida, desestruturar essa matriz com atribuição paralela.

Primeiro, tarefa de descanso em Ruby

De forma semelhante, também podemos usar argumentos splat no lado da atribuição para imitar o idioma funcional, conforme demonstrado em clojure:

# first, rest
a
, *b = [1,2,3]

a
#=> 1
b
# => [2,3]

# rest, last
*a, b = [1,2,3]
a
#=> [1,2]
b
#=> 3

Inscrição

Voltando ao nosso exemplo de Expressão Regular:

#works even better with more captures
regex
= /(d{3})-(d{3})-(d{4})/
match
, area_code, *locals = *"555-867-5309".match(regex)
locals
#=> ["867", "5309"]
area_code
#=> "555"

Como podemos usar isso em outras situações?

Faça uma consulta no Rails

users = Users.where(...)
first_user
= users.first #=> this is a query
other_users
= users[1..-1] #=> back to the database

# or we could just go to the db once
first_user
, *others = Users.where(...) #=> one query

Happy Splatting!