2

我正在尝试使用这样的咖喱应用和更新方法:

def apply(i: Int)(j: Int) = matrix(i)(j)
def update(i: Int, j: Int, value: Int) = 
  new Matrix(n, m, (x, y) => if ((i,j) == (x,y)) value else matrix(x)(y))

Apply 方法正常工作,但 update 方法抱怨:

scala> matrix(2)(1) = 1
<console>:16: error: missing arguments for method apply in class Matrix;
follow this method with `_' if you want to treat it as a partially applied function
              matrix(2)(1) = 1

直接调用update(2)(1)(1)就可以了,所以是转换成update方法,不能正常工作。我的错误在哪里?

4

2 回答 2

7

将赋值语法的去糖化为update映射的调用将赋值 LHS 上的单个参数列表与赋值 RHS 上的值连接到方法定义的第一个参数块,而不管该方法update有多少其他参数块update定义有。虽然这种转换在某种意义上将单个参数块拆分为两个(一个在 LHS,一个在分配的 RHS),但它不会以您想要的方式进一步拆分左侧参数块。

我还认为您对显示的显式调用示例有误updateupdate这与您给出的定义不符,

scala> class Matrix { def update(i: Int, j: Int, value: Int) = (i, j, value) }
defined class Matrix

scala> val m = new Matrix
m: Matrix = Matrix@37176bc4

scala> m.update(1)(2)(3)
<console>:10: error: not enough arguments for method update: (i: Int, j: Int, value: Int)(Int, Int, Int).
Unspecified value parameters j, value.
              m.update(1)(2)(3)
                      ^

我怀疑在您的实验过程中,您实际上是这样定义更新的,

scala> class Matrix { def update(i: Int)(j: Int)(value: Int) = (i, j, value) }
defined class Matrix

更新去糖确实适用于这个定义,但可能不是您期望的方式:如上所述,它仅适用于第一个参数列表,这会导致类似的结构,

scala> val m = new Matrix
m: Matrix = Matrix@39741f43

scala> (m() = 1)(2)(3)
res0: (Int, Int, Int) = (1,2,3)

在这里,初始的单位参数块被拆分为赋值的 LHS 上的一个空参数块(即())和 RHS 上的一个单参数参数块(即1)。然后是原始定义中的其余参数块。

如果你对这种行为感到惊讶,你不会是第一个

您所追求的语法可以通过稍微不同的途径实现,

scala> class Matrix {
     |   class MatrixAux(i : Int) {
     |     def apply(j : Int) = 23
     |     def update(j: Int, value: Int) = (i, j, value)
     |   }
     | 
     |   def apply(i: Int) = new MatrixAux(i)
     | }
defined class Matrix

scala> val m = new Matrix
m: Matrix = Matrix@3af30087

scala> m(1)(2)      // invokes MatrixAux.apply
res0: Int = 23

scala> m(1)(2) = 3  // invokes MatrixAux.update
res1: (Int, Int, Int) = (1,2,3)
于 2013-05-27T08:43:15.270 回答
0

我的猜测是,它根本不受支持。可能不是由于明确的设计决定,因为我不明白为什么它在原则上不应该工作。

与 相关的翻译apply,即转换为时执行的m(i)(j)翻译m.apply(i, j)似乎能够应对柯里化。在您的程序上运行scala -print以查看翻译产生的代码。

另一方面,与 相关的翻译update似乎无法应对柯里化。由于错误消息是missing arguments for method apply,它甚至看起来好像柯里化使翻译者感到困惑,以至于它试图翻译m(i)(j) = vm.apply,但随后搞砸了所需参数的数量。scala -print不幸的是,这里没有帮助,因为类型检查器过早地终止了翻译。

这是语言规范(Scala 2.9,“6.15 作业”)对作业的说明。由于没有提到柯里化,我假设它没有被明确支持。我找不到 的相应段落apply,但我想柯里化在那里起作用纯属巧合。

赋值f(args) = e在 '=' 运算符左侧具有函数应用程序被解释为f.update(args, e),即调用由f定义的更新函数。

于 2013-05-27T08:30:49.063 回答