2010-07-13 22 views
13

Idle meditando da uno studente Scala forse, ma ... nei miei tinkerings ho scritto quanto segue:."With" equivalente alla versione per Scala?

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

('n' è una scala.xml.Node, ma che non è importante né . la logica particolare)

Calling bambino() due volte non è così buono, così mi stava per cambiare:

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

Ma visto quanto sono venuto a molto apprezzeranno la possibilità di filtrare() e map() e tali senza dover dichiarare variabili intermedie, Ho trovato questo immediatamente puzzolente. È così ... così ... così Java-ish! : p

Purtroppo, scavando attraverso SO e Google e gli ScalaDocs (in particolare Any e AnyRef) e Il libro non ha trovato nulla di appropriato. Speravo forse di qualcosa di simile:

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

o anche

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

fa qualcosa del genere esiste? O mi sto semplicemente ritrovando coinvolto in un fervore senza tregua?

+3

Inoltre, che cosa filtro/dimensione è inefficiente. Sostituiscilo con list.forall (_. IsInstanceOf [Testo]) –

+0

Questo è quello che pensavo inizialmente, ma non è esattamente la stessa cosa: ho bisogno di sapere che l'elenco contiene solo elementi di testo AND non è vuoto. Ho appena trovato il "conteggio" di Iterable che può accorciare un po 'le cose: (n.child.size> 0) && (n.child.count (! _.isInstanceOf [Testo]) == 0) –

+0

Ancora meglio: ! (n.child.isEmpty || n.child.exists (! _.isInstanceOf [Testo])) –

risposta

18

"with" è, ovviamente, una parola riservata in Scala, quindi chiamiamolo "let", dalla forma di associazione simile in Lisp e Haskell. Risulta che "let" è solo un modo al contrario di scrivere l'applicazione della funzione.

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

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

Se la variabile legato viene utilizzato solo una volta, si potrebbe naturalmente utilizzare il modulo funzione anonima, ma che sconfigge lo scopo.

+0

Bello! E ora ho un nuovo frammento di sintassi di Scala da risolvere.:-) –

+0

Puoi anche usare pimp my library. – Anonymous

+0

Non è la stessa lunghezza di "lista val = n.child" "lista ..."? –

4

Se si desidera solo per limitare l'ambito della variabile intermedia, si può anche solo creare un blocco attorno al predicato:

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

Ora c'è un'implementazione di Tocca in questa libreria: https://github.com/snowplow/scala-util –

+0

Il metodo 'tap (A => B)' dovrebbe probabilmente essere 'tap' (A => Unità): A' per consentire ulteriori concatenazioni o assegnazioni, ad esempio: 'val order = new Order(). Tap {o => o.setStatus ('UNPAID') }' – jsears

1

è possibile utilizzare match a tale scopo.

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