国民的表現の特徴

私たちの仕事で起こった1つの興味深い事例を野bar人-perlodovitesと共有したかった。 古いコードを修正する過程で、不思議な構造が発見されました(以下、実際のコードは多少削減され、招待されています)。

sort { my ($x, $y) = ($a, $b); ($x =~ s{/}g) <=> ($y =~ s{/}g); } @array;



オーバーライドされた比較関数を使用した通常のソートのように見えます。 著者の元の考えによれば、行の配列はこれらの行のスラッシュの数でソートされているはずでした(置換式は置換の数を値として返すことが知られています)が、この関数の何かは正しくありません。 式s / pattern / replace / gの「置換」部分決してオプションでなかったようですが、これは式$a =~ s{/}g



です。 どのように機能しますか? これは私たちが今対処するものです。



したがって、最初に頭に浮かぶのは、単純な例で式を試すことです。 OK、実行して結果を取得します:

$ perl -we 'my $a = "a/b/c"; $a =~ s{/}g; print "$a\n";'

Substitution replacement not terminated at -e line 1.




つまり、私たちの疑いは真実であり、表現は無効です。 元の例はどのように機能しますか? 自分で整理しようとして失敗した後、Deparseモジュールを呼び出して助けを求めました。

$ cat test.pl

my ($a, $b);

sub f {

return (($a =~ s{/}g) <=> ($b =~ s{/}g));

}

$ perl -MO=Deparse -w test.pl

BEGIN { $^W = 1; }

my($a, $b);

sub f {

return $a =~ s [ / ][ ) <=> ($b =~ s{/} ] ;

}

/home/tester/test.pl syntax OK




脳の短いきしみの後、最終的にパールが何をするかを理解することができました。 上記のログでは、注意が必要な括弧を青で強調表示しています。 動作はかなり論理的で文書化されていることが判明しましたが、やや予期していませんでした。 多くのPearlプログラマーが知っているように、 s ///演算子では、他の文字をスラッシュの代わりにブラケットとして使用することもできます(Deparseが角括弧を使用して非常に明確に示されているように) しかし、この時点まで、最も普通の文字「 g 」をブラケットとして使用できるのと同じようには思いませんでした! したがって、変数$ aを検索するための式として、あるべきであるもの取ります-1つの直接的なスラッシュですが、置換のための式として、文字「 g 」の間にあるテキストを取ります。



わかりやすくするために、元のコード行をもう一度記述します。今回は、検索式を赤で強調表示し、緑に置き換え、同じ色でより濃いトーンで「括弧」を示します。

(($a =~ s { / } g ) <=> ($b =~ s{/} g ))



結果として、2 つではなく1つの置換式があり、比較関数は実際には何も比較しませんでしたが、常に最初の引数にスラッシュの数だけを返し、ソートする代わりに配列を混合しました(そしてこれに気づきませんでした並べ替えは純粋に表面的な改善であり、プログラムを使用するとき、並べ替えられた文字列の出力順序に注意を払う人はいませんでした)。



それで、道徳は何でしょうか? はい、おそらくいいえ。 繰り返しになりますが、すでに知られている真実はすべての人によって確認されました。すべてが真実ではなく、コンパイルされます。



All Articles