一般来说:将字符串转换为 WORD!s 很容易!(例如to-word "foo")。但是,很难神奇地制作那个单词!参考绑定到“你的意思的变量”。这样做的狡猾原因与没有范围这一事实有关。见:
Is there a overall explanation about definitional scoping in Rebol and Red
因此,无论如何,您尝试做的事情都会有点狡猾。有更好的方法。但为了避免不问问题,我将解释这里发生的事情以及如何以您尝试的方式解决它。
修正版仅供参考。请以其他方式执行此操作。
compose rejoin [namelist/:i "f/text"]
REJOIN 应用于块,并合并内容,结果类型 loosely 基于第一个元素。 (这是一个 questionable operation,但在 Rebol 代码中很流行。)
由于namelist/:i 是一个字符串,您的REJOIN 将产生一个字符串...并且这个字符串最终将被传递给COMPOSE。但是 COMPOSE 旨在应用于 BLOCK!s...并在其中搜索带括号的组inside,对它们进行评估,同时保留其余代码。这是一种用于块的模板系统,对其他类型的输入没有影响......所以你会得到相同的字符串。
TO-SET-PATH 因此被输入了一个字符串! (例如“var1f/text”)。我什至不知道路径转换接受字符串。我发现此操作的行为令人费解,因为它显然会加载字符串,然后使其成为长度为 1 SET-PATH! 的奇异元素。
>> p: to-set-path "foo/bar"
== foo/bar: ;-- huh? really, did that work?
>> type? p
== set-path! ;-- ok, good, I guess.
>> length? p
== 1 ;-- wait, what?
>> type? first p
== path! ;-- a PATH! inside a SET-PATH!...?
>> length? first p
== 2
>> type? first first p
== word!
>> foo: 10
>> get first first p
== 10 ;-- well, at least it's bound
那不是 SET-PATH 的那种!你要;你想要一个 SET-PATH!有2个字!元素。转换一个块!到 SET-PATH!将是这样做的一种方式。
to-set-path compose [(load rejoin [namelist/:i "f"]) text]
现在我们看到 COMPOSE 被正确使用,它将在括号内运行评估,并单独留下 text 单词。这会生成一个包含 2 个元素的块,可以轻松地将其转换为 SET-PATH!。我使用 LOAD 而不是 TO-WORD 来处理连接到纯单词转换无法做到的实际变量的一些“魔力”。但这只是一种解决方法——不确定,也不一定能解决问题。
但是会生成一个 SET-PATH!并不意味着它运行。如果我说:
s: to-set-word "x"
probe type? s
没有 SET-WORD!被执行,它只是生成。在这种情况下,存储在变量 s 中。但是如果我没有将它存储在一个变量中,那么评估产品就会被丢弃......如果我写1 + 1 print "hi",方式2就会被简单地丢弃。要执行 SET-PATH!,您需要将其置于将组合成源代码并进行评估的上下文中。
(注意:Ren-C 有一个 primitive called EVAL 可以即时执行此操作,例如 eval (quote x:) 10 将分配 10 给 x。)
但在 Red 中,您需要执行以下操作:
namelist: ["var1" "var2"]
var1: 5
var2: 10
process: [
repeat i length? namelist [
do probe compose [
(to-set-path compose [(load rejoin [namelist/:i "f"]) text])
to-string
(load namelist/:i)
]
]
]
lay: layout [
text "Values to appear here: "
var1f: field "a"
var2f: field "b"
button "Click" [do process]
]
view lay
现在您的外部 COMPOSE 正在构建一个 3 元素块,其中第一个元素将是 SET-PATH!,第二个元素是 WORD!这实际上是单独将您的整数转换为字符串,第三个是单词!将被评估为相关的整数。该块的DO会有赋值效果。
我将您的 to-word namelist/:i 更改为 load namelist/:i。同样,出于我提到的原因……TO-WORD 本身并没有“绑定”。
我在那里留下了一个 PROBE,以便您可以看到构建和执行的内容:
[var1f/text: to-string var1]
[var2f/text: to-string var2]
PROBE 是一个非常有用的工具,它输出它的参数,但也传递它。您可以在代码中的不同位置插入它,以便更好地了解正在发生的事情。
(注意:如果您想知道为什么我不建议编写仅适用于 SET-PATH 的窄 EVAL-2 辅助操作!,这是因为这样的东西以更好的名称存在。它被称为设置。试试set (quote x:) 10 然后print x。事实上,这是你真正想做的事情的变体......obj: make object! [a: 10] 然后set (in obj 'a) 20 然后print obj/a。正如我所说,有很多更好的做你正在做的事情的方法,但我试图继续专注于你正在尝试的方式。)