Scala的“ if…else”是否可以实现为库函数?

| 我想知道是否可以用特殊的编译器处理方法在
Predef
中实现
if … else
,类似于用
classOf[A]
进行的方式:定义在
Predef
中,实现由编译器填充。 当然,无论上下文如何,许多人都会放心地知道
if
总是
if
else
总是always6ѭ。但是,将
else
定义为结果类型
if
的方法会将其从关键字列表中删除,并允许库设计人员定义自己的
else
方法。 (我知道我可以在反引号中使用任何关键字作为标识符,但是像ѭ11这样的代码在代码中看起来却很糟糕。)在诸如此类的情况下(在邮件列表上讨论)这种情况下讨论的情况下,这种方法可能很有用。在定义应实际命名为“ 6”的方法时使用“ 12”。 (也在此处和此处对SO进行了讨论。) 所以: 即使从理论上讲,这种方法是否可行,还是打破了Scala的某些基本原理? 不利之处是什么?     
已邀请:
也许我不明白您的问题,但是您已经可以将
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\")
)
当然,这并不能完全像ѭ14那样,但是我认为可以做些打磨。我曾经为一种语言实现了一个非常简单的解释器,该语言内置了模式匹配,并以与我在此处执行的相同方式实现了
if ... else ...
。     
简短的答案是“是”。某些谓词上的分支逻辑可以实现为库函数。 值得指出的是,正如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
折叠选项不能明确完成,但我们一直都这样做。
// 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
布尔值上的分支逻辑也是一个折叠,您可以相应地将布尔值转换为布尔值。请注意使用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)
现在我们可以折叠布尔值:
scala> true fold(\"true!\", \"false\")
res24: java.lang.String = true!

scala> false fold(\"true!\", \"false\")
res25: java.lang.String = false
    
不只是
if-else
,任何语言功能都可以在称为“ Scala Virtualized”的语言分支中覆盖 https://github.com/TiarkRompf/scala-virtualized 这构成了斯坦福大学PPL的Delite项目的基础,也是Scala的欧盟赠款资助的研究的核心。因此,您可以合理地期望它在将来的某个时候成为核心语言的一部分。     
任何面向对象的语言(或具有运行时多态性的任何语言)都可以将条件实现为库功能,因为方法分派无论如何已经是条件的一种更为通用的形式。例如,Smalltalk除了方法分派之外,绝对没有条件。 除了语法上的方便之外,不需要任何类型的编译器魔术。 在Scala中,看起来可能像这样:
trait MyBooleanLike {
  def iff[T <: AnyRef](thenn: => T): T
  def iffElse[T](thenn: => T)(els: => T): T
  def &&(other: => MyBoolean): MyBoolean
  def ||(other: => MyBoolean): MyBoolean
  def nott: MyBoolean
}

trait MyTruthiness extends MyBooleanLike {
  def iff[T](thenn: => T) = thenn
  def iffElse[T](thenn: => T)(els: => T) = thenn
  def &&(other: => MyBoolean) = other
  def ||(other: => MyBoolean) = MyTrue
  def nott = MyFalse
}

trait MyFalsiness extends MyBooleanLike {
  def iff[T](thenn: => T): T = null.asInstanceOf[T]
  def iffElse[T](thenn: => T)(els: => T) = els
  def &&(other: => MyBoolean) = MyFalse
  def ||(other: => MyBoolean) = other
  def nott = MyTrue
}

abstract class MyBoolean extends MyBooleanLike

class MyTrueClass extends MyBoolean with MyTruthiness {}
class MyFalseClass extends MyBoolean with MyFalsiness {}

object MyTrue extends MyTrueClass {}
object MyFalse extends MyFalseClass {}
只需添加一些隐式转换:
object MyBoolExtension {
  implicit def boolean2MyBoolean(b: => Boolean) =
    if (b) { MyTrue } else { MyFalse }
}

import MyBoolExtension._
现在我们可以使用它:
object Main extends App {
  (2 < 3) iff { println(\"2 is less than 3\") }
}
[注意:我的打字功很弱。我不得不作弊以使其能够在合理的时间内被编译。某些对Scala的类型系统有更好了解的人可能希望对其进行修复。另外,现在我看一下,8个类,特征和对象(其中两个是抽象的)似乎有点过度设计;-)] 当然,模式匹配也是如此。任何具有模式匹配的语言都不需要其他类型的条件,因为模式匹配反而是更通用的。 [BTW:这基本上是我几年前写的这个Ruby代码的一部分,很有趣。]     

要回复问题请先登录注册