红色语言中带有to-word和to-path的代码 [英] code with to-word and to-path in Red language

查看:79
本文介绍了红色语言中带有to-word和to-path的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用compose通过单个功能创建2个面板:

I am trying to create 2 panels through single function using compose:

make-panel: func [sentchar][
     probe compose/deep [
        text "N1:"    
        (to-set-word rejoin["fld1" sentchar ":"]) field    ; TO BE NAMED fld1A and fld1B for 2 panels
        text "N2: "   
        (to-set-word rejoin["fld1" sentchar ":"]) field    ; TO BE NAMED fld2A and fld2B for 2 panels      
        text "Product: "    
        (to-set-word rejoin ["txt_out" sentchar ":"]) text    ; TO BE NAMED txt_outA and txt_outB for 2 panels
        button "Get product" [ 
           x: to-path to-word (rejoin ["face/parent/pane/fld1" sentchar "/text"])
           y: to-path to-word (rejoin ["face/parent/pane/fld2" sentchar "/text"])
           (to-set-path (to-path rejoin ["face/parent/pane/txt_out" sentchar "text"] )) 
                form multiply get x get y  ]  ] ]

view compose [
    (make-panel "A") return 
    (make-panel "B") return ]

但是,即使尝试了不同的组合,我也遇到了关于字词"和路径"的错误.问题出在哪里?

However, I am getting errors regarding to-word and to-path even though I have tried different combinations. Where is the problem?

推荐答案

您的错误是试图创建带有"/"字符的单词.

Your error is in trying to create a word with a "/" character.

>> to-word "foo/bar"
*** Syntax Error: invalid character in: "foo/bar"
*** Where: to
*** Stack: to-word  

我的第二个倾向是,您不应该使用字符串来构成值引用-如果没有其他事情,您将失去绑定.可以尝试以下操作:

My second inclination is that you shouldn't be using strings to compose value references—if nothing else you lose binding. Can try the following:

to path! compose [face parent pane (to word! rejoin ["fld2" sentchar]) text]

我的第一个倾向是您过于复杂了,但这超出了您的问题范围.

我将尝试解决此代码中的其他一些问题:

I will attempt to address some of the other issues in this code:

关于make-panel的注释-这是一个误称,因为您没有制作panel,只是将一些元素规格分组在一起.出于此答案的目的,我将使用名称make-row.另外,我永远不会喜欢fld1tout这样的名字(这是一个真实的词!),但会坚持不懈.

A note on make-panel—it's a misnomer as you are not making a panel, just grouping some element specs together. For the purposes of this answer, I'll use the name make-row. Also, I will never have any love for names like fld1 or tout (which is an actual word!) but will persevere.

如上所述,从词与字符串开始总是比较好的,就像在Rebol/Red中一样,在评估过程中,单词会获取上下文,而从字符串加载的单词则不会.例如:

As I mentioned above, you are always better off starting with words vs. strings as in Rebol/Red, words acquire context during evaluation—words loaded from strings do not. For example:

make object! [
    foo: "bar"
    probe get first [foo] ; "bar"
    probe get first load "[foo]" ; error
]

在创建三个新词时,让我们明确地做到这一点:

As you're creating three new words, let's do that explicitly:

make-row: function [row-id [string!]][
    fld1: to word! rejoin ["fld1-" row-id]
    fld2: to word! rejoin ["fld2-" row-id]
    tout: to word! rejoin ["tout-" row-id] ; note that 'tout is an English word

    ...
]

从这里开始,我们可以开始在规范中建立唯一的引用.

From here, we can start to build unique references in our spec.

make-row: func [row-id [string!] /local fld1 fld2 tout][
    fld1: to word! rejoin ["fld1-" row-id]
    fld2: to word! rejoin ["fld2-" row-id]
    tout: to word! rejoin ["tout-" row-id]

    compose/deep [
        text "N1:"
        (to set-word! fld1) field
        text "N2:"
        (to set-word! fld2) field
        text "Product:"
        (to set-word! tout) text
        button "Get Product" [
            ...
        ]
        return
    ]
]

现在,通过以下按钮操作进入粘性区域:

Now we get into a sticky area with this button action:

x: to-path to-word (rejoin ["face/parent/pane/fld1" sentchar "/text"])
y: to-path to-word (rejoin ["face/parent/pane/fld2" sentchar "/text"])
(to-set-path (to-path rejoin ["face/parent/pane/tout" sentchar "text"] )) 
     form multiply get x get y  ]  ] ]

我认为可以用伪代码表示您要执行的操作:

I think can express in pseudo-code what you're trying to do:

Product = text of product of N1 for this row * N2 for this row

此处代码的主要错误是您将邻近引用与命名引用混合在一起.如果检查face/parent/pane,则其中没有fld1*fld2*tout*引用,它只是一个面部对象块.在努力创建唯一名称的过程中,让我们暂时介绍一下.记住,我们仍在进行compose/deep操作:

The main error in your code here is you're mixing proximity references with your named references. If you examine face/parent/pane, it has no fld1*, fld2* or tout* references in there, it's just a block of face objects. As you've gone to the effort to make unique names, let's roll with that for the moment. Remember, we're still deep in a compose/deep operation:

x: get in (fld1) 'data
y: get in (fld2) 'data
set in (tout) 'text form x * y

我们现在更加简洁了,一切都应该正常工作(请注意,'data为您提供了'text的加载值).

We're much more concise now and everything should be working (note that 'data gives you the loaded value of 'text).

尽管如此,我担心的是,我们有很多新词在浮动,我们需要xy.因此,让我们回到接近的想法.

My concern though by this point is we've a lot new words floating about and we needed that x and y. So let's return to the idea of proximity.

当您查看自己的视图规格时:

When you look at your composed View spec:

view probe compose [
    (make-row "A")
    (make-row "B")
]

您将看到您的主视图面部将包含许多子级.要在您单击的按钮附近找到面孔,我们首先需要在面孔内找到按钮.让我们这样做:

You'll see that your main view face will contain a lot of children. To find faces within proximity of the button you're clicking, we first need to find the button within the face. Let's do this:

button "Get Product" [
    this: find face/parent/pane face
]

由于该按钮有六个前面的面孔,让我们转到该集合的开头:

And as there's six preceding faces associated with the button, let's go to the beginning of this set:

button "Get Product" [
    this: skip find face/parent/pane face -6
]

现在,我们可以基于接近度进行计算了:

Now we can do our calculations based on proximity:

button "Get Product" [
    here: find face/parent/pane face
    here/6/text: form here/2/data * here/4/data
]

景气!我们有相同的产品,只带有一个单词here,而不是rows-count * 3 + x + y.太棒了!

Boom! We have the same product with only one word here as opposed to rows-count * 3 + x + y. Awesome!

由于我们没有生成任何其他单词,因此甚至不需要生成行的函数,归结为以下内容:

As we're not generating any additional words, we don't even need a function to generate our rows, boils down to the following:

row: [
    text "N1:" field
    text "N2: " field
    text "Product: " text 100
    button "Get product" [
        ; go back six faces from current face
        here: skip find face/parent/pane face -6
        here/6/text: form here/2/data * here/4/data
    ]
    return
]

view compose [
    (row)
    (row)
]

组选择器

由于您似乎有复杂的需求并且不能总是枚举所需的字段,因此可以使用extra字段将字段分组在一起.我们可以通过使用block来包含row-idfield-id:

Group Selectors

As you seem to have complex needs and can't always enumerate the fields you need, you can use the extra field to group fields together. We can do this by using block to contain the row-id and the field-id:

make-row: func [row-id][
    compose/deep [
        text "N1:" field extra [(row-id) "N1"]
        text "N2: " field extra [(row-id) "N2"]
        text "Product: " text 100 extra [(row-id) "Output"]

        button "Get product" extra (row-id) [
            ...
        ]
        return
    ]
]

view compose [
    (make-row "A") 
    (make-row "B")
]

在按钮操作内,我们可以收集与该行关联的所有面:

Within the button action, we can collect all of the faces associated with the row:

faces: make map! collect [
    foreach kid face/parent/pane [
        if all [
            block? kid/extra
            face/extra = kid/extra/1
        ][
            keep kid/extra/2
            keep kid
        ]
    ]
]

这给你一张漂亮的地图!以及所有相关的面孔和简单的计算:

This gives you a nice map! with all associated faces and a simple calculation:

faces/("Output")/text: form faces/("N1")/data * faces/("N2")/data

如果您只打算将其用于产品,那么您甚至不需要收集:

If you're only going to use it for the product, then you don't even need to collect:

product: 0
foreach kid face/parent/pane [
    if all [
        block? kid/extra
        face/extra = kid/extra/1
    ][
        product: product + kid/value
    ]
]

这篇关于红色语言中带有to-word和to-path的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆