“使用”语句相当于Scala?

时间:2010-07-13 20:14:10

标签: 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! :P

唉,通过搜索SO和谷歌以及ScalaDocs(特别是Any和AnyRef)和The Book已经找不到任何合适的东西了。我希望也许会这样:

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

甚至

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

这样的事情存在吗?或者我只是陷入一种不变的热情中?

6 个答案:

答案 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的值已“传递”到目标函数。