也许从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! :P
唉,通过搜索SO和谷歌以及ScalaDocs(特别是Any和AnyRef)和The Book已经找不到任何合适的东西了。我希望也许会这样:n.child{ list => ( list.size > 0 ) && ( list.filter( ! _.isInstanceOf[Text] ).size == 0 ) }
甚至
n.child.with{ list => ... }
这样的事情存在吗?或者我只是陷入一种不变的热情中?
答案 0 :(得分:20)
{
import n.child._
( size > 0 ) && ( filter( ! _.isInstanceOf[Text] ).size == 0 )
}
答案 1 :(得分:18)
“with”当然是Scala中的保留字,所以让我们称它为“let”,来自Lisp和Haskell中的类似绑定形式。原来“let”只是编写函数应用程序的一种向后方式。
def let[A,B](param:A)(body: A=>B):B = body(param)
let(n.child){list=> ...}
如果绑定变量只使用一次,那么你当然可以使用匿名函数形式,但这会破坏目的。
答案 2 :(得分: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 )
}
答案 3 :(得分: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
答案 4 :(得分:1)
您可以将match
用于此目的。
n.child match {
case list => ( list.size > 0 ) && ( list.filter( ! _.isInstanceOf[Text] ).size == 0 )
}
答案 5 :(得分:0)
从Scala 2.13
开始,标准库现在提供了一种完全适合此需求的链接操作方法pipe
:
import scala.util.chaining._
n.child.pipe(list => list.size > 0 && list.filterNot(_.isInstanceOf[Text]).size == 0)
n.child
的值已“传递”到目标函数。