【问题标题】:How does this implementation of a ternary operator work?三元运算符的这种实现是如何工作的?
【发布时间】:2015-01-11 08:59:00
【问题描述】:

我最近经常使用 scala 三元运算符的这种实现,尤其是在切换启用/禁用图像时,但是,我通常可以理解我发现的代码 sn-ps,这让我感到困惑。我还想稍微修改它以更好地满足我的需要。我喜欢运算符式语法而不是冗长的 if else 阻塞等。

implicit def BooleanBool(b: Boolean): Bool = Bool(b)

case class Bool(b: Boolean) {
  def ?[X](t: => X) = new {
    def |(f: => X) = if (b) t else f
  }
}

所以我理解隐式创建了一个 Bool 对象,用 ?作为一个函数。该函数必须返回 X 类型的值。其余的我很难理解。

这是我的问题:

  1. 嵌套函数如何工作?的|功能。
  2. 代码实际解析的顺序是什么?
  3. 如何更改它以便可以选择不包含 else 子句?例如。是天蓝()? goOutside()
  4. 嵌套三元运算符是否有缺点,例如:

    isTheSkyBlue() ? goOutside() | {
        isTheInternetOn() ? playVideoGame() | read() 
    }
    
  5. 可以将嵌套更改为类似于 case 语句。即使用 => 运算符或类似的。例如。

    isTheSkyBlue() ? goOutside() | =>
        isTheInternetOn() ? playVideoGame() | read() 
    

    甚至一起摆脱它

    isTheSkyBlue() ? goOutside() |
        isTheInternetOn() ? playVideoGame() | read() 
    

【问题讨论】:

    标签: scala ternary-operator


    【解决方案1】:

    回答1和2,嵌套函数很简单,字符?|只是方法名。我将? 重命名为question,将| 重命名为or,并添加了对Bool 的显式调用。这是脱糖后的样子:

      case class Bool(b: Boolean) {
        def question[X](t: => X) = new {
          def or(f: => X) = if (b) t else f
        }
      }
    
      Bool(isTheSkyBlue()).question(goOutside()).or(
        Bool(isTheInternetOn()).question(playVideoGame()).or(read())
      )
    

    3 有点困难,因为 if 需要 else 否则它会返回什么?如果你只是在做一个副作用,那么你可以做这样的事情:

      implicit def OneWayBooleanBool(b: Boolean): OneWayBool = OneWayBool(b)
    
      case class OneWayBool(b: Boolean) {
        def ??[X](t: => X) = if (b) t
      }
    
      isTheSkyBlue() ?? goOutside()
    

    对于问题 4,除了复杂的代码外,嵌套没有真正的问题。

    对于问题 5,您不能真正做到这一点,因为 scala 将如何解决问题,除非其他人知道如何做到这一点。

    【讨论】:

    • 那么 new{...} 是用函数“or”创建匿名对象吗?然后根据布尔值评估 t 或 f ?我现在明白了很多,谢谢!
    【解决方案2】:

    补充@Noah 的回答:

    ? 函数没有返回 X 类型的值,它返回的是一个匿名类。我们可以让它成为一个普通的类(暂时忽略懒惰):

    class PartiallyEvaluated[X](b: Boolean, t: X) {
      def |(f: X) = if(b) t else f
    }
    class Bool(b: Boolean) {
      def ?[X](t: X) = new PartiallyEvaluated(b, t)
    }
    

    Scala 总是将a b c d e 解析为a.b(c).d(e)。如果您愿意添加一个“结束链”方法,那么您可以让第一个表达式返回某种懒惰的东西,它知道在另一个对象上调用时该做什么。或者你可以为这些东西的链创建一个for/yield 语法,但我怀疑这会比有用更令人困惑。

    【讨论】:

      猜你喜欢
      • 2012-11-11
      • 2018-08-31
      • 2010-10-02
      • 2019-02-11
      • 1970-01-01
      • 2013-04-11
      • 2014-12-18
      • 2019-01-29
      • 2021-11-08
      相关资源
      最近更新 更多