2010-07-13 10 views
13

inactivo ponderando de un estudiante de Scala tal vez, pero ... en mis tinkerings He escrito lo siguiente:.¿declaración "con" equivalente para Scala?

(n.child.size > 0) && (n.child.filter(! _.isInstanceOf[Text]).size == 0) 

('n' es un scala.xml.Node, pero eso no es importante ni es . la lógica particular)

Calling niño() dos veces no es tan bueno, así que estaba a punto de cambiarlo:

val list = n.child 
(list.size > 0) && (list.filter(! _.isInstanceOf[Text]).size == 0) 

Pero dado lo mucho que he llegado a apreciar mucho poder filtrar() y map() y tal sin necesidad de declarar variables intermedias, Encontré esto de mal olor. Es tan ... entonces ... ¡así que Java-ish! : p

Por desgracia, cavar a través de SO y Google y ScalaDocs (especialmente Any y AnyRef) y The Book no ha encontrado nada apropiado. Tenía la esperanza de tal vez por algo así como:

n.child{ list => (list.size > 0) && (list.filter(! _.isInstanceOf[Text]).size == 0) } 

o incluso

n.child.with{ list => ... } 

hace algo como esto existe? ¿O acabo de quedar atrapado en un fervor de menos?

+3

Además, ese filtro/tamaño es ineficiente. Reemplácelo con list.forall (_. IsInstanceOf [Text]) –

+0

Eso es lo que pensé inicialmente, pero no es exactamente lo mismo: necesito saber que la lista contiene solo elementos de texto Y no está vacía. Acabo de encontrar el "conteo" de Iterable que puede acortar un poco las cosas: (n.child.size> 0) && (n.child.count (! _.isInstanceOf [Text]) == 0) –

+0

Aún mejor: ! (n.child.isEmpty || n.child.exists (! _.isInstanceOf [Text])) –

Respuesta

18

"con" es, por supuesto, una palabra reservada en Scala, así que vamos a llamarlo "let", de la forma de enlace similar en Lisp y Haskell. Resulta que "let" es solo una forma de escritura de funciones hacia atrás.

def let[A,B](param:A)(body: A=>B):B = body(param) 

let(n.child){list=> ...} 

Si se utiliza la variable ligada sólo una vez, usted podría, por supuesto, utilice el formulario función anónima, pero que se pierde el propósito.

+0

¡Agradable! Y ahora tengo un nuevo bit de sintaxis de Scala para resolver.:-) –

+0

También puede usar proxeneta mi biblioteca. – Anonymous

+0

¿No tiene la misma longitud que "val list = n.child" "list ..."? –

4

Si lo que desea es limitar el alcance de la variable intermedia, también puede simplemente crear un bloque alrededor del predicado:

val n = getNodeByMagic() 
val passesTest = { 
    val child = n.child 
    child.length == 0 && !child.filter(_.isInstanceOf[Text]).isEmpty 
} 
// child is not defined outside of the block 
19
{ 
    import n.child._ 
    (size > 0) && (filter(! _.isInstanceOf[Text]).size == 0) 
} 
8
class Tap[A](underlying:A){ 
    def tap[B](func: A=>B) = func(underlying) 
} 

implicit def anyToTap[A](underlying:A)=new Tap(underlying) 

n.child.tap{x => 
    (x.size > 0) && 
    (x.filter(! _.isInstanceOf[Text]).size == 0) 
} 
+0

Ahora hay una implementación de Tap en esta biblioteca: https://github.com/snowplow/scala-util –

+0

El método 'tap (A => B)' probablemente debería ser 'tap (A => Unidad): A' para permitir encadenamientos o asignaciones adicionales, tales como: 'val order = new Order(). Tap {o => o.setStatus ('UNPAID') }' – jsears

1

puede utilizar match para ese propósito.

n.child match { 
case list => (list.size > 0) && (list.filter(! _.isInstanceOf[Text]).size == 0) 
} 
Cuestiones relacionadas