4

所以我目前正在将一个下降大小的程序从 Rebol 3 迁移到 Red。所述程序依赖于与 C 库 (clang) 的大型绑定。我已经重写了 Red/System 中的绑定部分,并通过包装例程将该代码与 Red 连接。我一直在使用的当前约定是将需要作为参数并由 C 代码返回的指针和 void 指针转换为红色/系统整数并将它们装箱为红色整数。这是相当容易和方便的。

因为我只能访问原始整数!数据而不是实际的结构,我会怀疑我不能再使用上述方法通过参数将指针传回(因为在传递之前正在复制装箱数据)。

那么,是否有推荐的方法来通过参数将指针传回,也就是我们如何通过例程的引用传递?

twiddle: routine [
    arg [integer!]
    return: [integer!]
] [
    arg: 321
    test: declare struct! [
        dummy [integer!]
    ]
    test/dummy: 456
    as integer! test
]

a: 123
b: twiddle a

print a ;If I could pass by reference this would be 321
print b
4

1 回答 1

7

当你这样做时twiddle a,你不是将单词传递a给函数,而是传递它的值。类似 Rebol 的语言中的单词并不像许多其他语言那样完全是变量。它们是第一类值,可以引用上下文中的其他值,也就是命名空间。所以一个词不包含任何值,它指向一个包含该值的上下文表。您可以将上下文想象为具有两列的表,左列包含单词,右列包含它们各自的值。

所以,严格来说,没有“通过引用传递”,您只能在 Red 级别操作,并且这些值总是从上下文表复制到 Red 内部堆栈。如果要更改 引用的值a,则需要设置a为该新值。这也可以使用 Red 运行时 API 在 Red/System 级别实现,但该 API 目前是非正式的并且没有完全稳定(但无论如何在内部大量使用)。

处理您的需求的一种好方法是构建一个值块,而不是为单词分配单个值,但我对您想要实现的目标知之甚少,无法确定它是否合适。

所以在这个序言之后,更直接地回答你的问题:你不能通过引用传递给例程,你只能通过值传递(要么得到一个编组的值,要么得到一个指向stack 上的装箱值的指针,而不是在上下文中桌子)。如果该值恰好是一个像块一样的系列!例如,您可以从例程中修改其内容(如更改、添加、删除元素)。

无论如何,如果您真的想从例程中更改单词引用的值,以下是如何实现它:

twiddle: routine [
    w [word!]
    return: [integer!]
    /local test
] [
    test: declare struct! [
        dummy [integer!]
    ]
    test/dummy: 456
    _context/set w as red-value! integer/box as-integer test
    as integer! test
]

a: 123
b: twiddle 'a

如您所见,您需要传递一个未评估的单词(一个 lit-word!),然后从例程中设置它的值以实现您所期望的副作用。但这不是推荐的方式,最好使用块!或对象!将值从 Red/System 级别推送到 Red 级别,或者只是将返回的值分配给一个单词,就像对b.

希望这可以帮助。

于 2015-05-07T07:56:54.363 回答