2012-02-28 6 views
9

Tengo un conjunto de funciones que abarcan una matriz de objetos o un solo objeto diseñado para ser tratado como una matriz que contiene un objeto, y estoy buscando una manera más limpia de lograr esto. Básicamente, quiero saber cómo podría hacer que la parte unless en la siguiente función más concisa:Aceptando un parámetro como objeto individual o como conjunto de objetos

def foo(bar_or_bars) 
    unless bar_or_bars.is_a?(Array) 
    bar_or_bars = [bar_or_bars] 
    end 
    bar_or_bars.each { |baz| ... } 
end 

podrá apreciar cualquier ayuda! Gracias.

Respuesta

11

La primera cosa que podría hacer es escribir la lógica unless en una sola línea:

bars = bar_or_bars.is_a?(Array) ? bar_or_bars : [bar_or_bars] 

Como se puede ver, yo darle un nuevo nombre aquí, ya que ya no es una barra o barras, es ahora Definitivamente una colección.

El problema con esto y su enfoque original es que aunque su función podría funcionar en cualquier Enumerable, obligará a sus usuarios a darle un argumento de un tipo específico, que rompe el tipado de patos.

Un buen truco para resolver parcialmente esta cuestión es la siguiente:

def foo(bar_or_bars) 
    bars = [*bar_or_bars] 
    bars.each { |baz| ... } 
end 

yo no lo llamaría exactamente eso legible, sin embargo. En realidad huele mucho como un mal diseño de API. Probablemente, usted debe tener más en varios argumentos así:

def foo(*bars) 
    bars.each { |baz| ... } 
end 

Y dejar que la persona que llama decidir si quiere pasar un solo objeto o una matriz:

foo("XYZ") 
ary = ["abc", "def"] 
foo(*ary) 
+0

Gracias, ese segundo truco era lo que estaba buscando. Sé que no es lo ideal, pero de hecho simplifiqué demasiado: dado que tengo muchos parámetros consecutivos que se comportan como lo describí, no pude usar solo el antiguo símbolo en la lista de parámetros. – user2398029

18

La solución más limpia que he encontrado es el uso de la núcleo método de matriz:

Array(5) #=> [5] 
Array([1, 2, 3]) #=> [1,2,3] 

por lo

def foo(bar_or_bars) 
    bars = Array(bar_or_bars) 
    bars.each { |baz| ... } 

Esto va a trabajar incluso en las matrices anidadas que tienen matrices como elementos (que no será aplanadas)

1

actualmente estoy usando esto:

bars = [bar_or_bars].flatten 
Cuestiones relacionadas