我今天看到有人提到reword
功能,但是文档非常简短。它看起来像shell脚本环境变量替换,或者可能是正则表达式替换,但不同。我如何使用此功能以及我将遇到什么样的问题?
答案 0 :(得分:14)
reword
函数是一种尝试,以一种与我们的工作方式一致的方式向Rebol添加shell样式的字符串插值。与许多Rebol的系列函数不同,它实际上是针对字符串类型进行优化的,而设计则反映了这一点。当前版本是一个设计原型,最终可以作为原生版重做,但它确实按设计工作,因此讨论它是如何工作以及如何使用它是有意义的。
reword
做什么?基本上这个:
>> reword "$a is $b." [a "This" b "that"]
== "This is that."
它接受一个模板字符串,它搜索转义序列,并用相应的替换值替换它们。这些值也作为对象,映射或键和值块传递给函数。键可以是几乎任何东西,甚至是数字:
>> reword "$1 is $2." [1 "This" 2 "that"]
== "This is that."
如果密钥已经不是字符串,则将其转换为字符串。如果将它们转换为相同的字符串,那么键被认为是相同的,这就是当你做这样的事情时会发生的事情:
>> reword "A $a is $a." [a "fox" "a" "brown"]
== "A brown is brown."
它不像正则表达式替换那样,它是基于关键字的。如果您在值块中有多次指定的键,那么该键的最后一个值就是我们刚才看到的那个值。只是跳过任何未设置或无值的值,因为将这些值放入字符串时没有意义。
您也可以使用其他转义标志,即使是多字符转义标志:
>> reword/escape "A %%a is %%b." [a "fox" b "brown"] "%%"
== "A fox is brown."
甚至根本没有逃生标志,它将取代所有地方的钥匙:
>> reword/escape "I am answering you." [I "Brian" am "is" you "Adrian"] none
== "Brian is answerBrianng Adrian."
哎呀,这不起作用。这是因为密钥不区分大小写,并且它们不需要被空格或其他此类分隔符包围。但是,如果将它们指定为字符串,则可以在键中放置空格,因此效果更好:
>> reword/escape "I am answering you." ["I am" "Brian is" you "Adrian"] none
== "Brian is answering Adrian."
尽管如此,在没有转义字符的情况下执行reword
模板往往会变得棘手而且速度稍慢,所以不会经常这样做。
虽然有一个更好的技巧......
当reword
变得非常有趣时,当你使用函数作为替换值时,因为该函数在每次重写时都会被调用。说,你想用计数器代替:
>> reword "$x then $x and $x, also $x" object [y: 1 x: does [++ y]]
== "1 then 2 and 3, also 4"
或者甚至是位置,因为它可以将字符串位置作为参数:
>> reword "$x then $x and $x, also $x" object [x: func [s] [index? s]]
== "1 then 9 and 16, also 25"
等等,这看起来不正确,这些数字似乎已关闭。这是因为该函数返回模板字符串的索引,而不是结果字符串。在编写这些函数时要记住这一点很好。该功能甚至不必仅分配给一个密钥,它可以检测或使用它:
>> reword "$x or $y" object [x: y: func [s] [ajoin ["(it's " copy/part s 2 ")"]]]
== "(it's $x) or (it's $y)"
参见模板变量,转义和所有。并且该函数可能有副作用,如此行计数器:
>> reword/escape "Hello^/There^/nl" use [x] [x: 0 map reduce ["^/" does [++ x "^/"] "nl" does [x]]] ""
== "Hello^/There^/2"
它甚至带有/into
选项,因此您可以使用它来分阶段构建字符串。
但是对于那些来自插入内置语言的人来说,最大的问题是......
因为 Rebol不能正常工作。 Rebol没有词法绑定,它会做其他事情,所以在一个字符串中,没有办法知道从哪里获取变量的值而不这么说。在其中一种具有插值的shell语言中,它等同于必须将对整个环境的引用传递给插值函数。但是,嘿,我们可以在Rebol中做到这一点:
>> use [x] [x: func [s] [index? s] reword "$x then $x and $x, also $x" bind? 'x]
== "1 then 9 and 16, also 25"
bind?
方法将在use
,绑定循环和函数中起作用。如果您在对象中,也可以使用self
:
>> o: object [x: func [s] [index? s] y: func [s] [reword s self]]
== make object! [
x: make function! [[s][index? s]]
y: make function! [[s][reword s self]]
]
>> o/y "$x then $x and $x, also $x"
== "1 then 9 and 16, also 25"
但要小心,否则你最终可能会做这样的事情:
>> o/y "$x then $x and $x, also $x, finally $y"
** Internal error: stack overflow
龙! 这是保持变量和替换键分开的一个很好的理由......