2012-01-02 13 views
8

Tengo un método con un argumento opcional. ¿Cómo puedo decidir si el Argumento fue dado o no?Cómo decidir si un argumento opcional se dio o no en un método de ruby ​​

Se me ocurrieron las siguientes soluciones. Estoy haciendo esta pregunta ya que no estoy totalmente satisfecho con ninguno de ellos. Existe una mejor?

nil como valor por defecto

def m(a= nil) 
    if a.nil? 
     ... 
    end 
end 

El inconveniente de este es, que no se puede decidir si se le dio ningún argumento o nil.

encargo NoArgument como valor por defecto

class NoArgument 
end 

def m(a= NoArgument.new) 
    if NoArgument === a 
     ... 
    end 
end 

Si nil fue dado puede ser decidido, pero el mismo problema existe para los casos de NoArgument.

Evaluación del tamaño de una elipsis

def m(*a) 
    raise ArgumentError if m.size > 1 
    if m.size == 1 
     ... 
    end 
end 

En esta variante puede ser siempre decide si se le dio el argumento opcional. Sin embargo, el Proc#arity de este método ha cambiado de 1 a -1 (no es cierto, vea el comentario). Todavía tiene la desventaja de ser peor para documentar y necesitar subir manualmente el ArgumentError.

+1

El 'arity' de todos sus métodos es' -1'. El único inconveniente de la última solución es que debe verificar manualmente que no se proporcione más de un argumento y que se necesite documentación para saber cuáles son los argumentos. –

Respuesta

15

Jorg W Mittag tiene la following code snippet que puede hacer lo que quiera:

def foo(bar = (bar_set = true; :baz)) 
    if bar_set 
    # optional argument was supplied 
    end 
end 
+0

¿Cuál sería un caso de uso para esto? – AndrewF

+1

@AndrewF: esa pregunta sería mejor respondida por johannes o Jorg W Mittag. –

+0

Hay algunos métodos en la biblioteca principal que se comportan de manera diferente según la cantidad de argumentos proporcionados. En efecto, simulan un despacho basado en argumentos. En la mayoría de las implementaciones de Ruby, esos métodos se implementan en C, C++, Java, C# etc. y tienen acceso privilegiado a los internos de Ruby, por lo que * pueden * simplemente verificar el número de argumentos. Pero, si quieres escribir un método compatible en Ruby, debes recurrir a trucos como este. –

4

¿Qué tal

NO_ARGUMENT = Object.new 

def m(a = NO_ARGUMENT) 
    if a.equal?(NO_ARGUMENT) 
     #no argument given 
    end 
end 
+0

Este es el método empleado por Rubinius, por ejemplo. –

+1

La única desventaja de este enfoque es que el método puede decidir pasar 'NO_ARGUMENT' como argumento a otro método que usa este modismo. –

Cuestiones relacionadas