【问题标题】:What's the inverse of block: load text in rebol / red块的反面是什么:以 rebol / red 加载文本
【发布时间】:2018-04-20 20:44:30
【问题描述】:

假设我有一些 rebol / red 代码。如果我加载源文本,我会得到一个块,但是如何从块中取回源文本?我尝试了表单块,但它没有返回源文本。

    text: {
        Red [Title: "Red Pretty Printer"]

        out: none   ; output text
        spaced: off ; add extra bracket spacing
        indent: ""  ; holds indentation tabs

        emit-line: func [] [append out newline]

        emit-space: func [pos] [
            append out either newline = last out [indent] [
                pick [#" " ""] found? any [
                    spaced
                    not any [find "[(" last out find ")]" first pos]
                ]
            ]
        ]

        emit: func [from to] [emit-space from append out copy/part from to]

        clean-script: func [
            "Returns new script text with standard spacing."
            script "Original Script text"
            /spacey "Optional spaces near brackets and parens"
            /local str new
        ] [
            spaced: found? spacey
            clear indent
            out: append clear copy script newline
            parse script blk-rule: [
                some [
                    str:
                    newline (emit-line) |
                    #";" [thru newline | to end] new: (emit str new) |
                    [#"[" | #"("] (emit str 1 append indent tab) blk-rule |
                    [#"]" | #")"] (remove indent emit str 1) break |
                    skip (set [value new] load/next str emit str new) :new
                ]
            ]
            remove out ; remove first char
        ]

        print clean-script read %clean-script.r
    }

    block: load text

【问题讨论】:

    标签: rebol red


    【解决方案1】:

    LOAD 是具有复杂行为的高级操作,例如它可以是一个文件!,一个字符串!,或一个块!。因为它做了很多不同的事情,所以很难说它是一种操作的确切补充。 (例如,SAVE 可能看起来与您从文件加载时的“相反”!)

    但是您的示例专门处理字符串!:

    如果我加载源文本,我会得到一个块,但是如何从块中取回源文本?

    一般来说,非常相关的问题:你不能“找回”源文本

    在上面的示例中,您的源文本包含 cmets,并且在 LOAD 之后它们将消失。此外,以每个值携带的 NEW-LINE 标志的形式保留了非常有限数量的空白信息。然而,您使用的特定缩进样式(或者您使用的是制表符还是空格)并未保留。

    在一个更微妙的音符上,少量的符号区别丢失了。细绳!加载的文字将不知道您是否编写了它们 "with quotes"{with curly braces}...Rebol 和 Red 都不会保留该位。 (即使他们这样做了,也无法回答突变后或使用新字符串后该做什么的问题。) DATE 有多种变化!输入格式,它不记得您使用了哪个特定的格式。等等。

    但是当谈到作为文本的代码往返时,与绑定发生的情况相比,格式是次要的。考虑到您可以构建如下结构:

    >> o1: make object! [a: 1]
    >> o2: make object! [a: 2]
    >> o3: make object! [a: 3]
    
    >> b: compose [(in o1 'a) (in o2 'a) (in o3 'a)]
    == [a a a]
    
    >> reduce b
    [1 2 3]
    
    >> mold b
    "[a a a]"
    

    您不能简单地将 b 序列化为"[a a a]" 的字符串,并且有足够的信息来获取等效源。红色比在 Rebol 中更能掩盖这一点的影响——因为甚至像 to block! 这样的操作在 STRING 上!和system/lexer/transcode 似乎绑定到用户上下文中。但除了最微不足道的例子之外,你在任何事情上都会遇到这个问题。

    Rebol2 和 Red 有一些二进制格式试图解决这个问题。例如在“RedBin”a WORD! saves its context(并索引到该上下文)。但是随后您必须考虑要将多少已加载环境拖入文件以保留上下文。所以它肯定会打开一罐蠕虫。

    这并不是说塑造事物的能力没有帮助。但是没有免费的午餐……所以 Rebol 和 Red 程序最终不得不像其他任何人一样考虑序列化。如果您正在考虑对任何源代码进行处理——出于注释保留的原因,如果没有别的原因——那么 PARSE 可能是您首先要做的事情。

    【讨论】:

    • 感谢您的详尽解释。仍然应该有更好的选择,比如在使用加载或保存时保留格式结构和注释。
    • @user310291 我建议通过一些您认为它应该 做的例子,并意识到这很困难。当源格式是文本字符和not able to reflect direct intention 时,保留格式结构和 cmets 有很多困难。您可能出于某种原因正在加载然后保存代码......例如对其进行一些操作。但是您不能真正将;-style cmets 或空格直接附加到他们正在评论的内容上。这需要很多猜测,而且很古怪。
    • 但是解析是非常复杂的提取嵌套子块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多