在红色例程中通过引用传递

ice*_*w19 4 red red-system

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

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

那么,是否有推荐的方法通过参数传递指针,又如何通过引用传递给例程?

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
Run Code Online (Sandbox Code Playgroud)

Doc*_*bel 7

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

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

处理您需求的一个好方法是构建一个值块而不是将单个值分配给单词,但我不知道您想要实现什么,以确保它是一个合适的.

所以在这个序言之后,更直接地回答你的问题:你不能通过引用传递给例程,你只能通过值传递(获取编组值,或者获取指向堆栈上的盒装值的指针,而不是在上下文中)表).如果该值恰好是一个像块一样的系列!例如,然后您可以从例程中修改其内容(如更改,添加,删除元素).

无论如何,如果你真的想要在例程中更改单词引用的值,这里是如何实现它:

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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,您需要传递一个未评估的单词(一个单词!),然后从例程中设置其值,以实现您期望的副作用.这不是推荐的方式,更好的使用块!还是一个物体!将值从红色/系统级别推送到红色级别,或者只是将返回的值分配给单词,就像您所做的那样b.

希望这可以帮助.