forループでの.substによる文字列置換


8

for名前付きキャプチャを使用して、ブロックで文字列置換を行いたいのですが。出力として1、2、3の数値が得られると思っていました。しかし、それはNil最初の実行の場合であり、次に2回目と3回目の実行の場合は1と2です。.substループ構造で正しく使用するにはどうすればよいですか?ループのmap代わりにコンストラクトを使用すると、同じ動作が見られforます。固定文字列値に置き換えると、期待どおりに機能します。

for <a1 b2 c3> -> $var {
    say $var;
    say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK      
}

#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11   
Output:

a1
Use of Nil in string context
  in block  at test3.pl6 line 3

b2
1
c3
2
]

気になります。$ <nr>とは何ですか?(rakuのドキュメントでは見つかりませんでした。)
p6steve


docs.raku.org/language/…-@valleに感謝-今すぐ見つけた!
p6steve

たぶんS///時々使用することを検討してください。この場合、次のことができますS[.$<nr>=(\d)] = $<nr> given $var
Jo King

@JoKingニース。私はあなたのコメントに賛成票を投じた後、何かを確認したいと思ったので(それは重要ではないことが判明しました)、反対票を取り消しました。だから私はあなたの良い提案を手動で+1するためにこれを書いています。私もそれを私の答えに統合しました。
レイフ

回答:


9

TL; DR$<nr>正規表現の評価後まで評価を延期します。@ JoKing ++は1つの方法を提案します。もう1つは、置換を中括弧({$<nr>})で囲むだけです。

元のコードが呼び出されるとどうなるか subst

Rakuはsubstルーチンを呼び出す前に、それに渡す引数のリストをまとめます。

2つの値があります。最初は正規表現です。それはないではない実行します。2番目の値は$<nr>です。これNilは、プログラムの開始時に、現在の一致オブジェクト変数がその値を主張する何かにバインドされており、そのNil中のキーの値にアクセスしようとすると$<nr>-も返されるため、評価されますNil。したがって、この時点で、substこれまでに実行される前に、事態はすでにうまくいっていません。

Rakuがこの引数のリストを組み立てると、を呼び出そうとしますsubst。成功してsubst実行されます。

次の一致を取得するにsubstは、正規表現を実行します。これにより、現在の一致オブジェクト変数が更新されます$/。ただし、すでにに渡された置換値に変更を加えるには遅すぎsubstます。

一致が得られたら、subst次に置換引数を調べます。それはそれを見つけ、それにNil応じて行動します。

2番目の呼び出しではsubst$<nr>はの最初の呼び出しから値を取得しましたsubst。等々。

の評価を延期する2つの方法 $<nr>

@JoKingはの使用を検討することを提案していますS///。この構成では、最初に(最初の/sのペアの間)正規表現を評価し、次に置換(最後の/sのペアの間)を評価します。(のSような他の有効な構文を使用する場合も同じ原則が適用されますS[...] = ...。)

を使用する場合subst、前のセクションで説明したように、Rakuはそれを呼び出す前に引数リストをまとめます。正規表現(実行されない)とクロージャー(実行されない)を検出します。次にsubst、それらの引数を使用して呼び出しを試み、成功します。

次に、subst実行を開始します。一致(正規表現)と置換(クロージャー)の両方のコードを受け取りました。

マッチング操作として正規表現を実行します。正規表現が一致を返した場合、substクロージャーを実行し、返された値を置換として使用します。

したがって、$<nr>ネイキッド値として渡すことからにフリーズすることを意味Nilするクロージャーに渡すことに切り替えたため、値$/が入力済みの<nr>エントリとの一致に設定されるまで評価が延期されたため、問題を解決しました。

これが機能するのは、ユーザーが望めば、設計/実装された人substが、一致引数置換引数の両方をCode(一致の正規表現と置換の通常のクロージャ)の形式にするのに十分なほどスマートで素晴らしいためです。次に、最初に一致実行し、最後の置換として後者の呼び出しの結果を使用して、置換クロージャーが渡された場合にのみ、それを実行します。同様にS///機能します。これは、置換が最初に評価された後にのみ置換を評価するように設計されているためです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.