2010-12-30 22 views
5

probablemente ya pidió pero no pudo encontrarlo .. Aquí hay 2 situación común (para mí mientras rieles de programación ..) que son frustrantes para escribir en rubí:rubí azúcar sintáctico: se trata de Nils

"a string".match(/abc(.+)abc/)[1] 

en este caso me sale un error porque la cadena no concuerda, por lo tanto, el operador [] se llama a nulo. Lo que me gustaría encontrar una alternativa más agradable de lo siguiente:

temp="a string".match(/abc(.+)abc/); temp.nil? ? nil : temp[1] 

en breve, si no coincide simplemente nula regresar sin el error

La segunda situación es la siguiente:

var = something.very.long.and.tedious.to.write 
var = something.other if var.nil? 

en este caso quiero asignar algo a var sólo si no es nula, en caso de que sea nula voy a asigno something.other ..

Cualquier sugerencia? Gracias!

+0

Ok Estoy muy cansado, me disculpo por la segunda pregunta era estúpida (sí, es un simple O ..), el primero sigue siendo interesante aunque .. En realidad – luca

+0

, el segundo también fue interesante. Brevemente lo entendí mal, porque me olvidé de la precedencia del operador 'o'. El mal uso de 'o' es un paso en falso muy común y vale la pena destacarlo. –

+0

Esto es muy similar a esta pregunta: http://stackoverflow.com/questions/4371716/looking-for-a-good-way-to-avoid-hash-conditionals-in-ruby/ – mpd

Respuesta

0

Por primera lo recomiendo ick 's maybe (equivalente a andand)

"a string".match(/abc(.+)abc/).maybe[1] 

No estoy seguro de entender el segundo, quieres esto?

var = something.very.long.and.tedious.to.write || something.other 
3

en Ruby on Rails que tienen el método try disponible en cualquier objeto. De acuerdo con la API:

Invoca el método identificado por el método del símbolo, pasándole los argumentos y/o el bloque especificado, al igual que lo hace el objeto # Ruby regular.

A diferencia de ese método, sin embargo, no se generará una excepción NoMethodError y se devolverá nula, si el objeto receptor es un objeto nil o NilClass.

Así, por primera pregunta que puede hacer esto:

"a string".match(/abc(.+)abc/).try(:[], 1) 

Y o le dará [1] o nula y sin error.

+0

Este código es difícil de leer y solo funciona si ActiveSupport está presente. –

+0

La pregunta se etiquetó originalmente con ruby-on-rails antes de modificarla, por lo que presenté la solución más limpia incorporada en Ruby on Rails. ¿Y difícil de leer? La mayoría de los programadores de Ruby están acostumbrados a cómo funciona el método de "envío", y esto es apenas menos legible que la respuesta aceptada, usando la biblioteca Ick externa. También podrías rechazar eso, porque "solo funciona si Ick está presente". En general, un voto negativo injustificado. – icecream

+0

Considerando que la segunda mitad de la respuesta de tokland es 100% correcta, que * sería * un voto negativo injustificado. Mientras que la pregunta original fue etiquetada ruby-on-rails, nada sobre la pregunta tiene algo que ver con los rieles. Las dependencias innecesarias se encuentran entre los errores más desagradables que cometen los programadores de Ruby. Pero en su caso, no acaba de agregar una dependencia innecesaria. Su implementación también introduce un despacho de envío innecesario y lento, y como se dijo anteriormente, es difícil de leer. Nunca permitiría que código como este en vivo a través de la revisión del código. Entonces sí, voto abajo. –

0
"a string".match(/foo(bar)/).to_a[1] 

NilClass#to_a devuelve una matriz vacía, y la indexación fuera de ella le da nil valores.

alternativa (lo que hago) se puede splat los partidos:

_, some, more = "a string".match(/foo(bar)(jim)/).to_a 
+1

Ewww. Por favor no hagas esto –

+0

@BobAman ¿Te gustaría elaborar? ¿A qué parte te opones? ¿El uso de la variable de subrayado para ignorar silenciosamente la coincidencia completa en los casos en que lo único que te importa son las subclasificaciones? No ayuda a nadie a menospreciar, decir "Ewww" y marcharse. – Phrogz

+1

Me refiero al uso del método 'NilClass # to_a' más la indexación fuera de rango. Tan divertido como escribir patos, estás siendo demasiado inteligente aquí. Clever es malo. Y salpicando los partidos es más legible de todos modos. Sin embargo, solo haría esto si estuviera asignando múltiples grupos de captura a la vez. De lo contrario, debe usar el método 'String # []' ya que es para lo que está diseñado. –

3
"a string"[/abc(.+)abc/, 1] 
# => nil 
"abc123abc"[/abc(.+)abc/, 1] 
# => "123" 

Y:

var = something.very.long.and.tedious.to.write || something.other 

Tenga en cuenta que or tiene una precedencia del operador diferente que || y || debería haber preferido para este tipo de uso. El operador or es para uso de control de flujo, como ARGV[0] or abort('Missing parameter').

3

¡Olvídate de atavismo de Python!

"a string"[/abc(.+)abc/,1] # => nil 
+2

+1 para usar la palabra "atavismo" en un contexto relacionado con la programación. – zetetic

+0

El único propósito de 'match' que conozco es http://stackoverflow.com/questions/4472848/is-there-a-shorthand-for-assigning-from-1-n-after-matching-in-ruby/4472857 # 4472857 – Nakilon

+0

En realidad, hace un tiempo escribí un mecanismo de enrutamiento que pato-tipeaba en un par de métodos 'match' /' captures'. Eso me permitió introducir de manera trivial la coincidencia de plantillas de URI con el sistema de enrutamiento. De hecho, he encontrado muchas ventajas de tener una forma menos idiomática de ejecutar una expresión regular. Simplemente tienden a ser cosas que usted escribe en el contexto de la metaprogramación o cuando crea DSL. –

0

Para la primera pregunta, creo que la respuesta de Bob es buena.

Para la segunda pregunta,

var = something.very.long.and.tedious.to.write.instance_eval{nil? ? something.other : self} 
Cuestiones relacionadas