【问题标题】:Why does currying in Scala need multiple parameter lists?为什么 Scala 中的柯里化需要多个参数列表?
【发布时间】:2013-05-13 05:08:51
【问题描述】:

假设我有一个需要部分应用的 2 个参数的函数,我需要将其定义为:

def f(a: Int)(b: Int) = { /* some code */ }

然后我可以将其部分应用为def fWithA = f(a) _

我的问题是:为了 curry 一个函数,为什么 Scala 要求使用多个参数列表声明参数?最好能够根据需要对任何函数进行 curry。

【问题讨论】:

    标签: scala


    【解决方案1】:

    实际上,您可以部分应用您想要的任何方法。只需调用该方法并省略参数:

    scala> def foo(a: Int, b: Int) = a*b
    foo: (a: Int, b: Int)Int
    
    scala> val x = foo(1,_: Int)
    x: Int => Int = <function1>
    
    scala> def bar(x: Int, y: Int, z: Int) = x*y+z
    bar: (x: Int, y: Int, z: Int)Int
    
    scala> bar(2,_:Int,6)
    res0: Int => Int = <function1>
    

    唯一的区别是,您必须告诉编译器缺少参数的类型,否则它无法在重载方法之间做出决定。

    另一种方式,如果你有一个真正的函数而不是一个方法,那就是在函数上调用curried

    scala> val f = {(x:Int, y:Int) => x*y}
    f: (Int, Int) => Int = <function2>
    
    scala> f.curried
    res2: Int => (Int => Int) = <function1>
    

    您还可以使用 _ 从方法创建函数:

    scala> bar _
    res6: (Int, Int, Int) => Int = <function3>
    

    然后致电curried

    scala> (bar _).curried
    res5: Int => (Int => (Int => Int)) = <function1>
    

    【讨论】:

    • 关于如何对任何类型的函数进行柯里化的技巧将会很有用。谢谢:)
    【解决方案2】:

    “真正的”柯里化需要 Scala 中的多个参数列表的几个原因:

    • 重载。与纯函数式语言不同,在 Scala 中,您可以重载方法。如果您部分应用一个函数,编译器可能无法区分您的意思是哪个重载。规范将重载分辨率限制为第一个参数列表。

    • 错误消息。 “方法调用的参数不足”是一个非常有用(且易于理解)的错误消息。如果允许对任何方法进行柯里化,则错误消息将是“必需的:但“具有许多箭头的某些函数类型”类型。

    • 性能。在 JVM 上运行使得调用方法非常高效,而函数(通过接口调用)速度较慢。

    【讨论】:

      猜你喜欢
      • 2014-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      相关资源
      最近更新 更多