Perl が文字列補間中に ${…} 内のコードを評価するのはなぜですか?
-
22-09-2019 - |
質問
次のスニペットはなぜ機能するのでしょうか?そして、これを使ってどんな悪事が可能でしょうか?しかし真面目な話、何か理由があるのでしょうか、 ${}
評価されてからスカラー参照として使用されますか?
use strict;
no strict 'refs';
our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
解決
大丈夫です、 シンボリック参照を使用しない限り. 。次のコードがあるとします。
my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";
同意します。scalarref ではその有用性は明らかではありませんが、arrayref では非常に役立ちます。
print "keys: @{[keys %messages]}\n";
他のヒント
私たちは中級のPerl の中に深さでこれを説明します。
変数のルックアップのための一般的な構文は次のとおりです。
SIGIL BLOCK INDEXY-THING
、単純なスカラーのためにそのようになります。
print $ { foo };
あなたがそれを取り巻くものから変数名を分離する必要があるときにあなたはおそらくこれを見ています:
print "abc${foo}def\n";
あなただけのブロックとなし、周囲の混乱でPerlの識別子を使用している場合、あなたは一般的なケースである、中括弧をオフに残すことができます:
print $foo;
しかし、これはリファレンスをデリファレンスのための同じことがあります:
SIGIL BLOCK-RETURNING-REFERENCE INDEXY-THINGS
あなたがブロックに入るという事は、参照がある場合は、あまりにもそれを求めたように、は、Perlはそれを逆参照しようとします:
my $ref = \ '12345';
print $ { $ref };
実際のブロックけれども、だけではなく、砂糖のです。あなたがそこに好きなようにあなたは多くのステートメントとして持つことができます:
print $ { my $ref = \ '1234'; $ref };
Perlはあなたがそれに識別子を与えているとそれがコードを実行し、参照として結果を使用することを前提としていませんので、今、あなたはちょうど、Perlの識別子を指定していません。これらのほとんど同じsay
文の違いを考えてみます:
use 5.010;
our $foo = "I'm the scalar";
sub foo { \ "I'm the sub" }
say ${foo};
say ${foo;};
その第二say
でPerlはセミコロンを見るは、それは、識別子ではないテキストとして括弧内のコードを解釈し、その結果を返し実現します。結果が基準となるので、それを逆参照する${...}
を使用します。あなたがこれを行うところ、それはあなたが二重引用符で囲まれた文字列の中にそれを行うことを特別なものではありません、問題ではない。
また、そこour
に気づきます。
use 5.010;
our $foo = "I'm the scalar";
sub foo { \ "I'm the sub" }
sub baz { 'foo' }
say ${foo};
say ${foo;};
say ${baz;};
コードとしてのPerl intrepretsその最後say
結果が基準ではない見て。それは単純な文字列foo
です。 Perlは、それが参照ではないことを見ているが、それは<のhref = "https://stackoverflow.com/questions/2332815/why-does-perl-evaluate-code-inとして(それがシンボリック参照を行いますので、デリファレンスコンテキストで今です-during列補間/ 2333649#2333649" >グレッグベーコンは)を説明します。シンボリック参照は、シンボルテーブル内の変数で動作するので、その$foo
は、パッケージ変数でなければなりませんでした。
それは混乱に簡単にこの次第ですので、strict
はそれのための便利なチェックがあります。しかし、あなたはそれがあなたを噛む時に驚かないでください、それをオフにします。 :)
から perlrefをドキュメントするのセクション "を参照の使用":
は、変数やサブルーチン名の一部として識別子(または識別子のチェーンを)置くところどこでも、あなたは適切な型のリファレンスを返すBLOCKとの識別子を置き換えることができます。つまり、先の例は次のように書くことができます:
$bar = ${$scalarref}; push(@{$arrayref}, $filename); ${$arrayref}[0] = "January"; ${$hashref}{"KEY"} = "VALUE"; &{$coderef}(1,2,3); $globref->print("output\n"); # iff IO::Handle is loaded
確かに、それはこの場合にはカーリーを使うには少し愚かだが、BLOCKは、具体的には、添字式を任意の式を含めることができます:
&{ $dispatch{$index} }(1,2,3); # call correct routine
ので
$$x
の単純なケースのために、中括弧を省略することができるという、人々は多くの場合、適切な演算子として逆参照記号を見てのミスを犯すと、その優先度についての不思議。彼らがいた場合は、しかし、あなたの代わりに中括弧の括弧を使用することができます。それはそうではないのです。下記の違いを考えてみましょう。ケース0、ケース1の短手バージョンではなく、ケース2:あなたは、それはおそらく参照のハッシュに$$hashref{"KEY"} = "VALUE"; # CASE 0 ${$hashref}{"KEY"} = "VALUE"; # CASE 1 ${$hashref{"KEY"}} = "VALUE"; # CASE 2 ${$hashref->{"KEY"}} = "VALUE"; # CASE 3
%hashref
を通じてデリファレンスない、$hashref
という変数にアクセスしているという点で、はケース2も欺瞞です。それはケース3になります。
その後 "シンボリックリファレンス" でます:
我々は、彼らが未定義されている場合の参照は、必要に応じて存在することにと言ったが、私たちは、リファレンスとして使用される値が既に定義されている場合はどうなりますが、ハード参照ではないものを言いませんでした。あなたはそれを参照として使用している場合、それはシンボリックリファレンスとして扱われます。すなわち、スカラーの値は、変数の名前ではなく、(おそらく)匿名の値への直接リンクであると解釈される。