Выражение "With" эквивалентно для Scala?

Невозможно подумать об ученике Scala, но... в моих вокалистах я написал следующее:

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

('n' - это scala.xml.Node, но это не важно. Также не является конкретной логикой.)

Вызов child() дважды не очень хорош, поэтому я собирался его изменить:

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

Но учитывая, насколько я очень ценю возможность фильтровать() и map() и такие, не требуя объявления промежуточных переменных, я сразу обнаружил это вонючим. Это так... так... так Java-ish!: Р

Увы, прорываясь через SO и Google и ScalaDocs (особенно Any и AnyRef), и The Book не оказалось ничего подходящего. Я надеялся, возможно, на что-то вроде:

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

или даже

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

Есть ли что-то подобное? Или я просто увлекся переменным увлечением?

Ответы

Ответ 1

"с" является, конечно, зарезервированным словом в Scala, поэтому позвольте называть его "let" из аналогичной формы привязки в Lisp и Haskell. Оказывается, "пусть" - это просто обратный способ написания приложения-функции.

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

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

Если связанная переменная используется только один раз, вы можете, конечно, использовать анонимную форму функции, но это побеждает цель.

Ответ 2

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

Ответ 3

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 )
}

Ответ 4

Если вы просто хотите ограничить область своей промежуточной переменной, вы также можете просто создать блок вокруг предиката:

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

Ответ 5

вы можете использовать match для этой цели.

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