我在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发布于 2017-09-21 20:07:01
一般的观点是:很容易将字符串转换为WORD!s (例如to-word "foo"__)。然而,要神奇地创造这个词是很困难的!引用绑定到“您所指的变量”。这样做的诡计多端的原因与没有范围这一事实有关。请参见:
所以不管你想做什么,你都会变得有点诡诈。有更好的方法。但是为了避免不问这个问题,我会解释这里发生了什么,以及如何用你所尝试的方式来解决这个问题。
更正版本仅用于教学目的。请换一种方法。
compose rejoin [namelist/:i "f/text"]
REJOIN应用于块,并根据第一个元素松散地将内容与结果类型合并。(这是一个https://forum.rebol.info/t/rejoin-ugliness-and-the-usefulness-of-tests/248,但在Rebol代码中历来很流行。)
因为namelist/:i是一个字符串,所以您的重新连接将生成一个string...and --这个字符串最终将被传递来编写。但是COMPOSE意味着要应用于阻止!s...and搜索其中括号大小的组,对它们进行评估,同时保留代码的其余部分。它是一种用于块的模板系统,对其他类型的input...so没有任何影响,您将得到相同的字符串。
设置路径就是这样一个字符串!(例如"var1f/text")。我甚至不知道路径转换接受字符串。我发现这个操作的行为令人费解,因为它显然加载了字符串,然后使它成为长度为1的集合路径的奇异元素!
>> 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那可不是一条设定好的路!你想要;你想要一条固定的路!用两个字!元素。转换一个街区!去一条固定的小路!就是这样做的。
to-set-path compose [(load rejoin [namelist/:i "f"]) text]现在,我们看到COMPOSE被正确地使用了,它将在括号内运行计算,并且不使用text单词。这会产生一个包含两个元素的块,这很容易转换成一个设置路径!我使用LOAD而不是TO-WORD来处理连接到一个普通单词转换所不能做到的实际变量的“魔力”。但这只是一个解决办法--不是一件确定的事情,也不会永远是问题的答案。
但却产生了一条固定的路径!并不意味着它会跑。如果我说:
s: to-set-word "x"
probe type? s没有设定字词!被执行,它仅仅是生成的。在这种情况下,存储在变量s中,但是如果我没有将它存储在变量中,那么评估产品就会被抛出out...the,如果我编写1 + 1 print "hi",就会抛出2。要执行SET-PATH!,需要将其放在将其组合为源并进行计算的上下文中。
(注:任C有一个https://forum.rebol.info/t/meet-the-eval-native/311,它可以动态执行,例如,eval (quote x:) 10将指定10到x。)
但在“红色”中,你需要做这样的事情:
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现在,您的外部组合正在构建一个3元素块,其中第一个元素将是一个设置路径!,第二个元素是一个单词!这实际上是单独将整数转换为字符串,而第三个则是一个单词!它将被计算为相关的整数。该块的DO将具有赋值效果。
我把你的to-word namelist/:i改成了load namelist/:i。再说一次,因为我提到的原因.单独的话并不能起到“约束”的作用。
我在那里留下了一个探针,这样您就可以看到构建并执行了什么:
[var1f/text: to-string var1]
[var2f/text: to-string var2]探测是一个非常有用的工具,它输出它的参数,但也传递它。您可以在代码中的各个点插入它,以便更好地了解正在发生的事情。
(注意:如果您想知道为什么我不建议编写一个仅适用于SET-PATH!的狭窄的EVAL-2助手操作,那是因为这样的东西有一个更好的名称。这叫布景。试试set (quote x:) 10然后是print x__。事实上,变体就是你想要做的事情.obj: make object! [a: 10]然后是set (in obj 'a) 20然后是print obj/a__。就像我说的,有很多更好的方法去做你正在做的事情,但是我试着集中精力去做你正在尝试的事情。)
发布于 2017-09-21 23:06:06
这并不能直接回答你的问题,尽管它似乎解决了你面临的问题。它使用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唯一的缺点是:它将get应用于在视图规范中设置的单词--它们需要在与您正在处理的值相同的上下文中,而且--您不能得到一个lit-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]
]发布于 2017-09-21 20:36:48
步骤1:重构
以下是重新格式化的代码和添加的print (1)语句:
namelist: ["var1" "var2"]
var1: 5
var2: 10
process: [
print "process: start" ; (1)
repeat i length? namelist [
(to-set-path compose rejoin [namelist/:i "f/text"] (to-word namelist/:i))
]
print "process: end" ; (1)
]
lay: layout [
text "Values to appear here: "
var1f: field "a"
var2f: field "b"
button "Click" [do process]
]
view lay当我在控制台中运行这个命令并按"Click“时,它会给出以下内容:
process: start
process: end所以我知道这个按钮至少能用
步骤2:使用print进行调试
现在我可以集中精力,将print移动到代码块中:
process: [
repeat i length? namelist [
print (
to-set-path compose rejoin [
namelist/:i "f/text"
] (to-word namelist/:i)
)
]
]我几乎马上就能看出这里出了什么问题:
var1 ; expecting `var1f` here
var2 ;第三步:我们需要更深入地研究probe
撇开
现在,在我进一步讨论之前,请注意这段代码没有访问视图块中的任何内容(因为它不工作!)。但好的是,你可以忽略这一点,然后回头再谈。
您需要的是一种以编程方式访问var1f/text的方法。
记住这一点,这里有一个更好的表达这个问题的方法:
步骤3a:如何动态创建具有不同名称的objects并为其设置值?
var1f/text: 5
(给定步骤2中的代码)
现在,我遇到了一个难题。这可能是最好的一个不同的,更简单的问题。
我决定继续假设你完成了这个任务(还有另外一个答案)
备注
在这一步中,最重要的是datatype红色视图的使用,您正在使用的是相同的东西: Red objects。
第四步:你完了!或者你是?
所以你可以为你的工作创造你想要的盖伊,你就完成了!对吗?
但你会问自己,这是最好的方法吗?如果你想要再加一些这个,或者完全不同的东西
但你还是不明白?别绝望,这很正常。许多东西的名字在概念上与你在其他语言中所熟悉的相似,但在微妙的方面却不同,这往往会使它们真正不同。最后,很多事情比你想象的要简单,但更奇怪(有更深层次的含义)
tl;dr
print、probe和dump-face进行调试https://stackoverflow.com/questions/46350543
复制相似问题