这种三元运算符的实现如何工作?

时间:2014-11-14 02:38:28

标签: scala ternary-operator

我最近使用了scala三元运算符的这个实现,尤其是切换启用/禁用图像,但是,我通常可以理解我发现的代码片段,这让我感到困惑。我也想稍微修改它以更好地满足我的需求。我喜欢运算符的语法,而不是详细的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子句?例如。 isTheSkyBlue()? goOutside()
  4. 嵌套三元运算符是否存在缺点,例如:

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

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

    甚至可以一起摆脱它

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

2 个答案:

答案 0 :(得分:3)

要回答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将如何解决问题,除非其他人知道如何做到这一点。

答案 1 :(得分:1)

补充@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语法,但我怀疑这会比有用的更令人困惑。