switch pattern for scala pattern-matching

pattern - scala for



Coincidencia de patrones con conjunciones(PatternA AND PatternB) (2)

Scala tiene una función de idioma para admitir disyunciones en la coincidencia de patrones (''Alternativas de patrón''):

x match { case _: String | _: Int => case _ => }

Sin embargo, a menudo necesito activar una acción si el escrutinio cumple con PatternA y PatternB (conjunción).

Creé un combinador de patrones ''&&'' que agrega esta capacidad. ¡Tres pequeñas líneas que me recuerdan por qué amo a Scala!

// Splitter to apply two pattern matches on the same scrutiny. object && { def unapply[A](a: A) = Some((a, a)) } // Extractor object matching first character. object StartsWith { def unapply(s: String) = s.headOption } // Extractor object matching last character. object EndsWith { def unapply(s: String) = s.reverse.headOption } // Extractor object matching length. object Length { def unapply(s: String) = Some(s.length) } "foo" match { case StartsWith(''f'') && EndsWith(''f'') => "f.*f" case StartsWith(''f'') && EndsWith(e) && Length(3) if "aeiou".contains(e) => "f..[aeiou]" case _ => "_" }

Puntos para discusión

  1. ¿Hay alguna forma de hacerlo?
  2. ¿Hay problemas con este enfoque?
  3. ¿Puede este enfoque crear cualquier otro combinador útil? (por ejemplo, Not )
  4. ¿Se debería agregar tal combinador a la biblioteca estándar?

ACTUALIZACIÓN Me acaban de preguntar cómo interpreta el compilador el case A && B && C Estos son patrones de operador infijo (Sección 8.1.9 de la Referencia de Scala). También podría expresar esto con patrones de extracto estándar (8.1.7) como &&(&&(A, B), C).'' Notice how the expressions are associated left to right, as per normal infix operator method calls like &&(&&(A, B), C).'' Notice how the expressions are associated left to right, as per normal infix operator method calls like Boolean # && in val b = true && false && true`.


Me gusta mucho este truco. No conozco ninguna forma de hacerlo, y no preveo ningún problema, aunque eso no significa mucho. No puedo pensar en ninguna forma de crear un Not

En cuanto a agregarlo a la biblioteca estándar ... tal vez. Pero creo que es un poco difícil. Por otro lado, ¿qué hay de hablarle a la gente de Scalaz para que lo incluya? Se parece mucho más a su propia bailía.


Un posible problema con esto es la traducción inflada que genera el generador de patrones. Aquí está la translation del programa de ejemplo, generado con scalac -print . Incluso -optimise no simplifica if (true) "_" else throw new MatchError() expresiones if (true) "_" else throw new MatchError() .

Las coincidencias de patrones grandes ya generan más bytecode de lo que es legal para un solo método, y el uso de este combinador puede amplificar ese problema.

Si && fue construido en el idioma, quizás la traducción podría ser más inteligente. Alternativamente, pequeñas mejoras a la -optimise podrían ayudar.