Scala中方法的有条件调用

13
我在我的代码中发现了这个模式很多次:

...

  if (doIt)
    object.callAMethod
  else
    object

我想知道是否有更加语法优美的方式来编写上面的代码,特别是避免重复使用object变量。类似于:

   // using the Scalaz "pipe" operator
   // and "pimping" f: T => T with a `when` method
   object |> (_.callAMethod).when(doIt)

很不幸,上面的代码无法通过编译,因为类型推断需要(_.callAMethod)的参数类型。

目前,我最好的解决方案是:

    implicit def doItOptionally[T](t: =>T) = new DoItOptionally(t)
    class DoItOptionally[T](t: =>T) {
      def ?>(f: T => T)(implicit doIt: Boolean = true) = 
        if (doIt) f(t) else t
    } 

    implicit val doIt = true
    object ?> (_.callAMethod)

这并不完美,因为我需要声明一个implicit val,但如果有多个链接调用,这将会得到回报:

     object ?> (_.callAMethod) ?> (_.callAnotherMethod)

有没有更好的想法?我是否错过了一些Scalaz魔法呢?

3个回答

18
class When[A](a: A) {
  def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a
}
implicit def whenever[A](a: A) = new When(a)

示例:

scala> "fish".when(_.length<5)(_.toUpperCase)
res2: java.lang.String = FISH

我没有想到可以反转条件和函数,谢谢! - Eric
我还注意到,在这里使用名词比运算符更好,因为在“fish”之后需要使用“.”。 - Eric

4

我无法评论你的答案@Rex Kerr,但更简洁的方法是:

implicit class When[A](a: A) {
  def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a
}

implicit 放在类之前可以使您完全省略隐式函数。


0

如果您将callAMethod表示为自同态,那么可以使用幺半群功能。例如:

object |> valueOrZero(doIt, Endo(_.callAMethod))

(可能需要在Endo上添加类型参数)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接