1

我想实现一个方法 dim(x,y) 为矩阵(y 行,x 列)分配空间。

我想通过传递一个可选函数'filler'来使“dim(x,y)”更强大,然后'dim'会将位于(x,y)的元素设置为filler(x,y)

我的代码如下:

List2D dim := method(x, y, z,
    target := list()
    filler := if(z == nil, 
        method(return nil),
        z)
    for(i, 1, y, 
        subTarget := list()
        for(j, 1, x,
            subTarget append( filler(i,j) ))
            target append(subTarget) )
    return target)

当使用 2 个参数调用“dim”时它运行良好,但失败了

List2D dim(3,2, method(x,y, 10*x+y))

在行filler := if(z == nil 抛出异常异常说nil does not respond to '*'

我意识到当与 nil 比较时,参数“z”被激活了。

所以我想知道如何让我的“List2D dim”正常工作?

4

1 回答 1

6

好吧,基本上,你会想要这样的东西:

List2D dim := method(x, y,
    target := list
    blk := call evalArgAt(2) # Get the third argument, and evaluate it in the context of the sender
    if(blk isNil, blk := block setScope(call sender))

    for(i, 1, y,
        subTarget := list
        for(j, 1, x,
            subTarget append(blk call(i, j))
            target append(subTarget)
        )
    )
    target
)

基本上,这里发生的事情是因为你的填充物,你想给它参数,最简单的方法就是传入一个Block. Block您可以使用消息来执行此操作,但实际上,如果您引入了一个新的范围,那么您最终会设置自己的副本,这是您应该这样做的。如果第三个参数计算为nil,然后我们将创建一个新函数并将其范围设置为调用上下文;就好像用户传入了一个没有参数的空函数一样,因此,即使它没有定义任何参数,您也可以将参数传递给它。事实上,我们并不真正需要将其范围限定为调用者,但如果您在方法调用中创建块,则应始终将块的范围限定为调用上下文。这将允许访问该块内调用上下文的词法范围;您可能正在推送用户在其中提供的一些消息。准备好后,只需使用该方法显式调用该call方法。

如果您的filler方法不需要任何参数,我只需在第二个索引处获取原始消息参数,而不是对其进行评估。这将对一些大型矩阵产生一些重大的性能改进。

于 2013-01-13T15:51:06.607 回答