今日誰かがそのreword
機能について言及しているのを見ましたが、そのドキュメントは非常に簡単です。シェルスクリプト環境変数の置換、または正規表現の置換のように見えますが、異なります。この関数をどのように使用すればよいですか。また、どのような落とし穴に遭遇するのでしょうか。
1 に答える
ここにドラゴンがいます!
このreword
関数は、シェルスタイルの文字列補間をRebolに追加して、私たちのやり方で機能するようにするためのちょっとした実験です。多くの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."
正規表現の置換のように位置付けではなく、キーワードベースです。値ブロックで複数回指定されているキーがある場合、そのキーの最後の値が、先ほど見たように使用される値になります。未設定またはnoneの値は、文字列に入力するときに意味がないため、スキップされます。
他のエスケープフラグも使用できます。複数文字のフラグも使用できます。
>> 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"
待ってください、それは正しく見えません、それらの数字はずれているようです。これは、関数が結果文字列ではなく、テンプレート文字列のインデックスを返すためです。これらの関数を作成するときは、このことを覚えておいてください。関数は、1つのキーに割り当てるだけでなく、それを検出または使用できます。
>> 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には字句バインディングがなく、他のことを行うので、文字列では、そう言わずに変数の値をどこから取得するかを知る方法はありません。補間機能を備えたシェル言語の1つでは、環境全体への参照を補間関数に渡す必要があるのと同じです。しかしねえ、私たちは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
りゅう!これが、変数と置換キーを分離しておく理由の1つです...