【问题标题】:Conditional invocation of a method in ScalaScala中方法的条件调用
【发布时间】:2011-09-05 23:36:48
【问题描述】:

我在我的代码中多次发现这种模式:

  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 魔法吗?

【问题讨论】:

    标签: scala scalaz


    【解决方案1】:
    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
    

    【讨论】:

    • 没想到条件和函数倒置,谢谢!
    • 我还注意到这里的名词比运算符更好,因为. 需要在"fish" 之后使用。
    【解决方案2】:

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

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

    只需将implicit 放在类之前,您就可以完全省略隐式函数。

    【讨论】:

      【解决方案3】:

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

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

      (可能需要Endo 上的类型参数)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-21
        • 2015-06-02
        • 1970-01-01
        • 1970-01-01
        • 2016-01-23
        • 1970-01-01
        • 2012-05-23
        • 1970-01-01
        相关资源
        最近更新 更多