在 Red 例程中通过引用传递
Pass by reference in Red routines
所以我目前正在将一个下降大小的程序从 Rebol 3 迁移到 Red。所述程序依赖于对 C 库 (clang) 的大量绑定。我重写了 Red/System 中的绑定部分,并通过包装器例程将该代码与 Red 连接起来。我一直在使用的当前约定是将需要的指针和 void 指针转换为参数并由 C 代码返回为 red/system 整数,并将它们作为红色整数装箱。这相当简单方便。
因为我只能访问原始整数! data 而不是实际的结构,我怀疑我不能再使用上述方法通过参数传回指针(因为装箱数据在传递之前被复制)。
那么,是否有推荐的方法来通过参数传回指针,也就是我们如何使用例程通过引用传递?
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
当您执行 twiddle a
时,您并不是将单词 a
传递给函数,而是传递它的值。 Rebol-like 语言中的单词与许多其他语言中的单词并不完全 variables。它们是第一个 class 值,可以引用上下文中的其他值,又名 命名空间 。所以一个词不包含任何值,它指向一个包含值的上下文table。您可以将上下文描绘成具有两列的 table,左列包含单词,右列包含它们各自的值。
所以,严格来说,没有"passing by reference",你只能在红色级别操作值,而这些值总是从上下文中复制table 到红色内部堆栈。如果要更改 a
引用的值,则需要将 a
设置为该新值。这也可以在 Red/System 级别使用 Red 运行时 API 实现,但是 API 目前是非正式的并且没有完全稳定(但无论如何在内部大量使用)。
处理您的需求的一个好方法是构建一个值块,而不是为单词分配单独的值,但我对您想要实现的目标了解不多,无法确定它是否合适。
所以在这个序言之后,为了更直接地回答你的问题:你不能通过对例程的引用传递,你只能通过值传递(要么获取编组值,要么获取指向装箱值的指针在堆栈上,而不是在上下文中table)。如果那个值恰好是一个像块一样的系列!例如,然后您可以从例程中修改其内容(如更改、添加、删除元素)。
无论如何,如果您真的想在例程中更改单词引用的值,请按以下方法实现:
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
如您所见,您需要传递一个未计算的词(一个亮词!),然后从例程中设置它的值,以实现您期望的副作用。但这不是推荐的方式,最好使用块!或一个对象!将值从 Red/System 级别推到红色级别,或者只是将返回值分配给一个词,就像您对 b
.
所做的那样
希望对您有所帮助。
所以我目前正在将一个下降大小的程序从 Rebol 3 迁移到 Red。所述程序依赖于对 C 库 (clang) 的大量绑定。我重写了 Red/System 中的绑定部分,并通过包装器例程将该代码与 Red 连接起来。我一直在使用的当前约定是将需要的指针和 void 指针转换为参数并由 C 代码返回为 red/system 整数,并将它们作为红色整数装箱。这相当简单方便。
因为我只能访问原始整数! data 而不是实际的结构,我怀疑我不能再使用上述方法通过参数传回指针(因为装箱数据在传递之前被复制)。
那么,是否有推荐的方法来通过参数传回指针,也就是我们如何使用例程通过引用传递?
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
当您执行 twiddle a
时,您并不是将单词 a
传递给函数,而是传递它的值。 Rebol-like 语言中的单词与许多其他语言中的单词并不完全 variables。它们是第一个 class 值,可以引用上下文中的其他值,又名 命名空间 。所以一个词不包含任何值,它指向一个包含值的上下文table。您可以将上下文描绘成具有两列的 table,左列包含单词,右列包含它们各自的值。
所以,严格来说,没有"passing by reference",你只能在红色级别操作值,而这些值总是从上下文中复制table 到红色内部堆栈。如果要更改 a
引用的值,则需要将 a
设置为该新值。这也可以在 Red/System 级别使用 Red 运行时 API 实现,但是 API 目前是非正式的并且没有完全稳定(但无论如何在内部大量使用)。
处理您的需求的一个好方法是构建一个值块,而不是为单词分配单独的值,但我对您想要实现的目标了解不多,无法确定它是否合适。
所以在这个序言之后,为了更直接地回答你的问题:你不能通过对例程的引用传递,你只能通过值传递(要么获取编组值,要么获取指向装箱值的指针在堆栈上,而不是在上下文中table)。如果那个值恰好是一个像块一样的系列!例如,然后您可以从例程中修改其内容(如更改、添加、删除元素)。
无论如何,如果您真的想在例程中更改单词引用的值,请按以下方法实现:
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
如您所见,您需要传递一个未计算的词(一个亮词!),然后从例程中设置它的值,以实现您期望的副作用。但这不是推荐的方式,最好使用块!或一个对象!将值从 Red/System 级别推到红色级别,或者只是将返回值分配给一个词,就像您对 b
.
希望对您有所帮助。