通过Red例程中的引用传递 [英] Pass by reference in Red routines

查看:167
本文介绍了通过Red例程中的引用传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我目前正在将后裔大小的程序从Rebol 3迁移到Red.所述程序依赖于对C库(clang)的大型绑定.我已经在Red/System中重写了绑定部分,并通过包装程序将该代码与Red接口.我一直在使用的当前约定是将指针和void指针转换为参数,并由C代码返回为red/system整数,并将它们包装为Red整数.这是相当容易和方便的.

So I'm currently in the process of migrating a descent sized program from Rebol 3 to Red. Said program relies on a large binding to a C library (clang). I have rewritten the binding portion in Red/System, and am interfacing that code with Red through wrapper routines. The current convention I have been using is to cast the pointers and void pointers needed as parameters and returned by the C code to red/system integers and box them up as Red integers. This is fairly easy and convenient.

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

Since I can only access the raw integer! data instead of the actual struct, I would suspect then that I can't pass a pointer back out through a parameter (as the boxed data is being copied before being passed) using the above methodology, anymore.

那么,是否有推荐的方法可以通过参数将指针传递回去,又如何通过例程引用进行传递?

So, is there a recommended methodology to passing pointers back out through parameters, aka how do we pass by reference with routines?

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的语言中的单词与其他许多语言中的变量并不完全相同.它们是第一类值,可以引用上下文中的其他值,也称为 namespace .因此,单词不包含任何值,它指向保存该值的上下文表.您可以将上下文描述为具有两列的表,左列包含单词,右列保留各自的值.

When you do twiddle a, your are not passing the word a to the function, but its value. Words in Rebol-like languages are not exactly variables like in many other languages. They are first class values that can reference other values inside a context, aka namespace. So a word does not hold any value, it points to a context table that holds the value. You can picture a context as a table with two columns, the left column contain words, the right column holds their respective value.

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

So, strickly speaking, there is no "passing by reference", you can only manipulate values at Red level, and those values are always copied from the context table to the Red internal stack. If you want to change the value referred by a, you need to set a to that new value. That could be also achieved at Red/System level using the Red runtime API, but that API is currently informal and not fully stabilized (but anyway heavily used internally).

一种满足您需求的好方法是构建一个值块,而不是为单词分配单个值,但是我对您要实现的目标知之甚少,以确保它非常合适.

One good way to handle your needs is to build a block of values instead of assigning individual values to words, but I do not know enough of what you want to achieve to be sure it would be a good fit.

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

So after this preamble, to answer your question more directly: you cannot pass by reference to a routine, you can only pass by value (either getting a marshalled value, or getting a pointer to the boxed value on stack, and not in the context table). If that value happens to be a series like a block! for example, then you can modify its content from the routine (like changing, adding, removing elements).

无论如何,如果您真的想在例程中更改单词引用的值,请按以下步骤操作:

Anyway, if you really want to change the value referenced by a word from within a routine, here is how to achieve it:

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

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

As you can see, you need to pass an unevaluated word (a lit-word!), and then set its value from the routine in order to achieve the side-effect you were expecting. That is not the recommended way though, better use a block! or an object! to push values from the Red/System level to Red level, or just assign the returned value to a word, as you do for b.

希望这会有所帮助.

这篇关于通过Red例程中的引用传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆