Передача по ссылке в красных процедурах
Так что в настоящее время я нахожусь в процессе переноса программы размера спуска с 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
1 ответ
Когда вы делаете twiddle a
, вы не передаете слово a
к функции, но ее значение. Слова в Rebol-подобных языках не являются точно переменными, как во многих других языках. Это значения первого класса, которые могут ссылаться на другие значения внутри контекста, то есть пространства имен. Таким образом, слово не содержит никакого значения, оно указывает на контекстную таблицу, которая содержит значение. Вы можете представить контекст в виде таблицы с двумя столбцами, левый столбец содержит слова, а правый столбец содержит их соответствующее значение.
Так что, строго говоря, "передачи по ссылке" не существует, вы можете манипулировать только значениями на уровне Red, и эти значения всегда копируются из контекстной таблицы во внутренний стек Red. Если вы хотите изменить значение, указанное a
нужно установить a
к этому новому значению. Этого также можно достичь на уровне Red/System, используя API времени выполнения Red, но этот 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
Как видите, вам нужно пропустить неоцененное слово (залитое слово!), А затем установить его значение из рутины, чтобы получить ожидаемый побочный эффект. Это не рекомендуемый способ, хотя лучше использовать блок! или объект! чтобы переместить значения с уровня Red/System на уровень Red или просто присвоить возвращаемое значение слову, как вы это делаете для b
,
Надеюсь это поможет.