是否存在阻止Scala在函数上实现模式匹配的基本限制?

是否存在阻止Scala在函数上实现模式匹配的基本限制?,scala,syntax,functional-programming,pattern-matching,Scala,Syntax,Functional Programming,Pattern Matching,在SML、Erlang和buch等语言中,我们可以定义如下函数: fun reverse [] = [] | reverse x :: xs = reverse xs @ [x]; 我知道我们可以像这样在Scala中编写模拟(我知道,下面的代码中有很多缺陷): 但我想知道,我们是否可以用Scala编写前一段代码,也许可以对后一段代码进行去糖化 将来实现这种语法有什么基本限制吗(我的意思是,真正的基本限制——例如,scala中类型推断的工作方式,或者除解析器之外的其他方式) UPD 下面是

在SML、Erlang和buch等语言中,我们可以定义如下函数:

fun reverse [] = []
|   reverse x :: xs  = reverse xs @ [x];
我知道我们可以像这样在Scala中编写模拟(我知道,下面的代码中有很多缺陷):

但我想知道,我们是否可以用Scala编写前一段代码,也许可以对后一段代码进行去糖化

将来实现这种语法有什么基本限制吗(我的意思是,真正的基本限制——例如,scala中类型推断的工作方式,或者除解析器之外的其他方式)

UPD
下面是它的一个片段:

type T
def reverse(Nil: List[T]) = Nil
def reverse(x :: xs: List[T]): List[T] = reverse(xs) ++ List(x)

我不知道SML或Erlang,但我知道Haskell。它是一种没有方法重载的语言。方法重载与这种模式匹配相结合可能导致歧义。想象一下下面的代码:

def f(x: String) = "String "+x
def f(x: List[_]) = "List "+x
这意味着什么?这可能意味着方法重载,即方法是在编译时确定的。这也意味着模式匹配。只有一个f(x:AnyRef)方法可以进行匹配

Scala也有命名参数,可能也会被破坏


我不认为Scala能够提供比一般情况下更简单的语法。简单的语法可能只在某些特殊情况下有效。

至少有两个问题:

  • [
    ]
    是保留字符,因为它们用于类型参数。编译器允许它们周围有空格,因此这不是一个选项
  • 另一个问题是
    =
    返回
    Unit
    。因此,
    |
    后面的表达式不会返回任何结果
  • 我能想到的最接近的是这个(注意,它非常专门针对您的示例):


    这真的取决于你所说的基本原则

    如果你真的问“是否有一个技术上的障碍物会阻止你实现这个功能”,那么我会说答案是。你说的是脱毛,你在这条路上是对的。所要做的就是基本上把几个独立的用例缝合成一个单一的函数,这可以作为一个简单的预处理步骤来完成(这只需要语法知识,不需要语义知识)。但为了让这一点更有意义,我将定义一些规则:

    • 函数签名是必需的(例如,在Haskell中,这是可选的,但无论您是一次性定义函数还是在多个部分中定义函数,它始终是可选的)。我们可以尝试在没有签名的情况下生活,并尝试从不同的部分提取签名,但是缺少类型信息会很快出现在我们面前。一个更简单的论点是,如果我们试图推断一个隐式签名,那么我们最好对所有方法都这样做。但事实是,有很好的理由在scala中使用显式信号,我无法想象要改变这一点
    • 所有零件必须在同一范围内定义。首先,它们必须在同一个文件中声明,因为每个源文件都是单独编译的,因此一个简单的预处理器不足以实现该功能。第二,我们最终仍然使用一个方法,所以所有部分都在同一范围内是很自然的
    • 重载对于这些方法是不可能的(否则我们需要为每个部分重复签名,以便预处理器知道哪个部分属于哪个重载)
    • 零件按声明顺序添加(缝合)到生成的
      匹配中
    下面是它的样子:

    def reverse[T](lst: List[T]): List[T] // Exactly like an abstract def (provides the signature)
    // .... some unrelated code here...
    def reverse(Nil) = Nil
    // .... another bit of unrelated code here...
    def reverse(x :: xs ) = reverse(xs) ++ List(x)
    
    可以简单地转化为:

    def reverse[T](list: List[T]): List[T] = lst match {
      case Nil     => Nil
      case x :: xs => reverse(xs) ++ List(x)
    }
    // .... some unrelated code here...
    // .... another bit of unrelated code here...
    
    很容易看出,上面的转换非常机械,只需操作源AST(由接受此新构造的稍微修改的语法生成的AST)并将其转换为目标AST(由标准scala语法生成的AST)即可完成。 然后我们可以像往常一样编译结果

    好了,通过一些简单的规则,我们可以实现一个预处理器,它完成了实现这个新特性的所有工作



    如果通过基本你在问“是否有任何东西会使此功能不合适”,那么可以说这感觉不太像scala。但更重要的是,它并没有带来那么多。Scala作者实际上倾向于使语言更简单(如在较少的内置功能中,尝试将一些内置功能移动到库中),并添加一种不太可读的新语法与简化目标背道而驰。

    在SML中,您的代码片段实际上只是语法糖(一种“派生形式”)在语言规范的术语中)用于

    这与您展示的Scala代码非常接近。因此,Scala不能提供同样的语法,这并没有“根本”的原因。主要的问题是Scala需要更多的类型注释,这使得这种速记语法在总体上远没有吸引力,而且可能不值得花时间


    还要注意,您建议的特定语法不会很好地运行,因为无法从语法上区分一个逐案函数定义和两个重载函数。您可能需要一些替代语法,类似于SML使用“
    |

    您不想这样编写它,因为这是一个非常低效的
    反向
    @Ingo它只是一个示例(我已经添加了关于代码可靠性的免责声明),我可以编写factorial作为一个示例,它将非常有效。或者你的意思是什么?对我来说,这两个看起来几乎一样,只是Scala要求参数带有类型注释,这是OOP/函数交叉繁殖的结果(与SML中的Hindley Milner相比)。所以我不是你想要看到的(除了改变Scala的语法,
    def reverse[T](lst: List[T]): List[T] // Exactly like an abstract def (provides the signature)
    // .... some unrelated code here...
    def reverse(Nil) = Nil
    // .... another bit of unrelated code here...
    def reverse(x :: xs ) = reverse(xs) ++ List(x)
    
    def reverse[T](list: List[T]): List[T] = lst match {
      case Nil     => Nil
      case x :: xs => reverse(xs) ++ List(x)
    }
    // .... some unrelated code here...
    // .... another bit of unrelated code here...
    
    val rec reverse = fn x =>
        case x of [] => []
                | x::xs  = reverse xs @ [x]