Scala的"if ... else"可以作为库函数实现吗?

Jea*_*let 7 if-statement scala keyword control-flow

我想知道是否if … else可以Predef使用特殊的编译器处理来实现,与执行的操作类似classOf[A]:定义在Predef,实现由编译器填充.

当然,无论背景如何,许多人都会惊讶地发现,无论是一个if总是一个if,一个else总是一个else.但是,else在结果类型上定义方法if会将其从关键字列表中删除,并允许库设计者定义自己的else方法.(我知道我可以使用任何关键字作为带有反引号的标识符,但是`else`在代码中看起来很糟糕.)这种方法可能适用于在这种情况下讨论的情况,在邮件列表中讨论,人们被迫otherwise在定义实际应该命名的方法时使用else.(此处此处也讨论了SO .)

所以:

  • 即使在理论上,这样的方法是否可行,或者它是否打破了Scala中的一些基本原则?
  • 缺点是什么?

Kim*_*bel 10

也许我不明白你的问题,但你已经可以实现if ... else ...库函数了.考虑一下:

class If[A](condition: =>Boolean)(ifBlock: =>A) {
  def els(elseBlock: =>A):A = condition match {
    case true => ifBlock
    case false => elseBlock
  }
}

new If(2==3)(
  println("equal")
) els (
  println("not equal")
)
Run Code Online (Sandbox Code Playgroud)

当然,这并不做究竟是什么if ... else ...呢,但也有一些抛光,我认为它会.我曾经为一种内置模式匹配的语言实现了一个非常简单的解释器,if ... else ...其执行方式与我在此处实现的方式非常相似.


小智 8

简短的回答是"是"; 某些谓词上的分支逻辑可以实现为库函数.

值得指出的是,正如Viktor Klang和其他人所指出的那样,if/else实质上是折叠一个布尔值.折叠是我们经常做的事情 - 有时它是清晰明确的,有时不是.

// Either#fold is explicit
scala> Left[String, Double]("fail") fold(identity, _ + 1 toString)
res0: java.lang.String = fail

scala> Right[String, Double](4) fold(identity, _ + 1 toString)
res1: java.lang.String = 5.0
Run Code Online (Sandbox Code Playgroud)

折叠选项不能明确地完成,但我们会一直这样做.

// Option has no fold - wont compile!
Some(5) fold(1+, 0)

// .. but the following is equivalent and valid
scala> Some(5) map(1+) getOrElse(0)
res3: Int = 6
Run Code Online (Sandbox Code Playgroud)

布尔值上的分支逻辑也是一个折叠,您可以相应地对其进行布尔运算.注意使用by-name参数来实现延迟评估.如果没有此功能,则无法实现此类实现.

// pimped Boolean - evaluates t when true, f when false
class FoldableBoolean(b: Boolean) {
  def fold[A](t: => A, f: => A) =
    if(b) t else f
}

implicit def b2fb(b: Boolean) = new FoldableBoolean(b)
Run Code Online (Sandbox Code Playgroud)

现在我们可以折叠布尔人:

scala> true fold("true!", "false")
res24: java.lang.String = true!

scala> false fold("true!", "false")
res25: java.lang.String = false
Run Code Online (Sandbox Code Playgroud)