Выражение "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 )
}