使用字符串以红色语言创建单词和路径

rns*_*nso 2 user-interface rebol variable-assignment red

我在a中有字符串namelist,它对应于变量以及应用程序中的字段名称.

该函数应从namelist读取字符串,添加'f'以获取field_names,然后将变量值放入相应的字段中.

我尝试了下面的代码,它没有给出任何错误,但也不起作用:

namelist: ["var1" "var2"]
var1: 5
var2: 10

process: [
    repeat i length? namelist [
        (to-set-path compose rejoin [namelist/:i "f/text"] (to-word namelist/:i))
    ]
]

lay: layout [ 
    text "Values to appear here: "
    var1f: field "a"
    var2f: field "b"

    button "Click" [do process]
]

view lay
Run Code Online (Sandbox Code Playgroud)

Hos*_*ork 6

一般来说:很容易将字符串转换成WORD!s (例如to-word "foo").然而,神奇地制造这个词可能很难!引用绑定到"你想要的变量".这种狡猾的原因与没有范围这一事实有关.看到:

在Rebol和Red中有关于定义范围的整体解释

所以你要做的就是变得有点狡猾.有更好的方法.但是为了避免不问这个问题,我会解释这里发生了什么以及如何以你正在尝试的方式修复它.

更正版本仅供参考.请以另一种方式这样做.

compose rejoin [namelist/:i "f/text"]

REJOIN应用于块,并根据第一个元素松散地合并内容和结果类型. (这是一个值得怀疑的操作,但在Rebol代码中历史上很流行.)

由于namelist/:i是一个字符串,你的REJOIN将生成一个字符串......这个字符串将最终传递给COMPOSE.但COMPOSE是为了应用于块!小号...和搜索括号的组里面的话,进行评价,同时保留代码的其余部分.它是一种块的模板系统,对其他类型的输入没有影响......所以你会得到相同的字符串.

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

这不是那种SET-PATH!你要; 你想要一个SET-PATH!2个字!元素.转换BLOCK!一个SET-PATH!这将是一种方式.

to-set-path compose [(load rejoin [namelist/:i "f"]) text]
Run Code Online (Sandbox Code Playgroud)

现在我们看到COMPOSE正确使用,它将在括号内运行评估并text单独留下单词.这会生成一个包含2个元素的块,可以很容易地转换为SET-PATH!.我正在使用LOAD而不是TO-WORD来处理连接到普通单词转换不会做的实际变量的一些"魔力".但这只是一种解决方法 - 不是肯定的事情,并不总是问题的答案.

但是产生一个SET-PATH!并不意味着它运行.如果我说:

s: to-set-word "x"
probe type? s
Run Code Online (Sandbox Code Playgroud)

没有SET-WORD!执行,它只是生成.在这种情况下,存储在变量s中.但是如果我没有将它存储在一个变量中,那么评估产品就会被抛弃......如果我写的话,2就会被抛出1 + 1 print "hi".要执行SET-PATH !,您需要将它放在一个上下文中,它将被组合成源并进行评估.

(注意:Ren-C有一个名为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
Run Code Online (Sandbox Code Playgroud)

现在你的外部COMPOSE正在构建一个3元素块,其中第一个元素是SET-PATH !,第二个元素是WORD!这实际上是单独将整数转换为字符串,第三个是WORD!将被评估为相关整数.该块的DO将具有分配效果.

我把你改成to-word namelist/:iload namelist/:i.再次,由于我提到的原因...... TO-WORD本身并没有"束缚".

我在那里留下了一个PROBE,所以你可以看到构建和执行的内容:

[var1f/text: to-string var1]
[var2f/text: to-string var2]
Run Code Online (Sandbox Code Playgroud)

PROBE是一个非常有用的工具,它输出它的参数但也传递它.您可以在代码中的各个位置插入它,以便更好地了解正在发生的事情.

(注:如果你想知道为什么我不建议写一个窄EVAL-2的辅助操作仅适用于SET-PATH!这是因为这样的事情有一个更好的名字存在这就是所谓的SET尝试.set (quote x:) 10然后print x在.事实上,这个变种是你如何预期的要去做的事情...... obj: make object! [a: 10]然后set (in obj 'a) 20然后print obj/a,正如我所说,有很多更好的办法去了解你在做什么,但我试图专注于做the-方式-你-是-努力.)


rgc*_*ris 5

这并没有直接回答你的问题,但似乎解决了你所面临的问题.它使用该face/extra字段将字段与您的值列表相关联:

namelist: [var1 var2]
var1: 5
var2: 10

process: function [][
    foreach face lay/pane [
        if find namelist face/extra [
            face/text: form get to word! face/extra
        ]
    ]
]

lay: layout [ 
    text "Values to appear here: "
    field "a" extra 'var1
    field "b" extra 'var2

    button "Click" [process]
]

view lay
Run Code Online (Sandbox Code Playgroud)

唯一的皱纹是:它适用get于在视图规范中设置的单词 - 它们需要与您正在处理的值处于相同的上下文中,并且 - 您无法获得lit-word!to word!之前必须更改它获得.

如果要在地图中包含值,则另一种方法:

values: #(foo: 5 bar: 10)

process: function [container [object!]][
    foreach face container/pane [
        if find values face/extra [
            face/text: form select values face/extra
        ]
    ]
]

view [ 
    text "Values to appear here: "
    field "a" extra 'foo
    field "b" extra 'bar

    button "Click" [process face/parent]
]
Run Code Online (Sandbox Code Playgroud)