首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用字符串创建红色语言中的单词和路径

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

Stack Overflow用户
提问于 2017-09-21 18:06:23
回答 3查看 187关注 0票数 2

我在namelist中有字符串,这些字符串对应于应用程序中的变量和字段名。

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

我尝试了下面的代码,这不会给出任何错误,但也不工作:

代码语言:javascript
运行
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-09-21 20:07:01

一般的观点是:很容易将字符串转换为WORD!s (例如to-word "foo"__)。然而,要神奇地创造这个词是很困难的!引用绑定到“您所指的变量”。这样做的诡计多端的原因与没有范围这一事实有关。请参见:

对Rebol和Red的定义范围是否有全面的解释?

所以不管你想做什么,你都会变得有点诡诈。有更好的方法。但是为了避免不问这个问题,我会解释这里发生了什么,以及如何用你所尝试的方式来解决这个问题。

更正版本仅用于教学目的。请换一种方法。

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的集合路径的奇异元素!

代码语言:javascript
运行
复制
>> 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

那可不是一条设定好的路!你想要;你想要一条固定的路!用两个字!元素。转换一个街区!去一条固定的小路!就是这样做的。

代码语言:javascript
运行
复制
to-set-path compose [(load rejoin [namelist/:i "f"]) text]

现在,我们看到COMPOSE被正确地使用了,它将在括号内运行计算,并且不使用text单词。这会产生一个包含两个元素的块,这很容易转换成一个设置路径!我使用LOAD而不是TO-WORD来处理连接到一个普通单词转换所不能做到的实际变量的“魔力”。但这只是一个解决办法--不是一件确定的事情,也不会永远是问题的答案。

但却产生了一条固定的路径!并不意味着它会跑。如果我说:

代码语言:javascript
运行
复制
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。)

但在“红色”中,你需要做这样的事情:

代码语言:javascript
运行
复制
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。再说一次,因为我提到的原因.单独的话并不能起到“约束”的作用。

我在那里留下了一个探针,这样您就可以看到构建并执行了什么:

代码语言:javascript
运行
复制
[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__。就像我说的,有很多更好的方法去做你正在做的事情,但是我试着集中精力去做你正在尝试的事情。)

票数 6
EN

Stack Overflow用户

发布于 2017-09-21 23:06:06

这并不能直接回答你的问题,尽管它似乎解决了你面临的问题。它使用face/extra字段将这些字段与值列表相关联:

代码语言:javascript
运行
复制
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!,所以必须在得到它之前更改它。

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

代码语言:javascript
运行
复制
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]
]
票数 5
EN

Stack Overflow用户

发布于 2017-09-21 20:36:48

步骤1:重构

以下是重新格式化的代码和添加的print (1)语句:

代码语言:javascript
运行
复制
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“时,它会给出以下内容:

代码语言:javascript
运行
复制
process: start
process: end

所以我知道这个按钮至少能用

步骤2:使用print进行调试

现在我可以集中精力,将print移动到代码块中:

代码语言:javascript
运行
复制
process: [
    repeat i length? namelist [
        print (
            to-set-path compose rejoin [
                namelist/:i "f/text"
            ] (to-word namelist/:i)
        )
    ]
]

我几乎马上就能看出这里出了什么问题:

代码语言:javascript
运行
复制
var1    ; expecting `var1f` here
var2    ;

第三步:我们需要更深入地研究probe

撇开

现在,在我进一步讨论之前,请注意这段代码没有访问视图块中的任何内容(因为它不工作!)。但好的是,你可以忽略这一点,然后回头再谈。

您需要的是一种以编程方式访问var1f/text的方法。

记住这一点,这里有一个更好的表达这个问题的方法:

步骤3a:如何动态创建具有不同名称的objects并为其设置值?

var1f/text: 5

(给定步骤2中的代码)

现在,我遇到了一个难题。这可能是最好的一个不同的,更简单的问题。

我决定继续假设你完成了这个任务(还有另外一个答案)

备注

在这一步中,最重要的是datatype红色视图的使用,您正在使用的是相同的东西: Red objects。

第四步:你完了!或者你是?

所以你可以为你的工作创造你想要的盖伊,你就完成了!对吗?

但你会问自己,这是最好的方法吗?如果你想要再加一些这个,或者完全不同的东西

  1. 你有阅读官方的gui文档,特别是关于视图引擎的部分
  2. 您看过维德对象手动的例子
  3. 你看过示例代码和小应用程序在github上的回购
  4. 你甚至试过旧的,但稳定的rebol2

但你还是不明白?别绝望,这很正常。许多东西的名字在概念上与你在其他语言中所熟悉的相似,但在微妙的方面却不同,这往往会使它们真正不同。最后,很多事情比你想象的要简单,但更奇怪(有更深层次的含义)

tl;dr

  • 将视图代码与其他代码分开,以便更容易调试
  • 使用printprobedump-face进行调试
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46350543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档