次のスニペットがまったく機能しないのはなぜですか?そして、これを使用してどのような悪が可能でしょうか?しかし、真剣に、何らかの理由がありますか?のコードは${}
まったく評価されてから、スカラー参照として使用されますか?
use strict;
no strict 'refs';
our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
次のスニペットがまったく機能しないのはなぜですか?そして、これを使用してどのような悪が可能でしょうか?しかし、真剣に、何らかの理由がありますか?のコードは${}
まったく評価されてから、スカラー参照として使用されますか?
use strict;
no strict 'refs';
our $message = "Hello world!";
print "${ lc 'MESSAGE' }\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;};
その2番目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はそれsay
をコードとして解釈し、結果が参照ではないことを確認します。単純な文字列foo
です。Perlは、それが参照ではないことを認識しますが、現在は逆参照コンテキストにあるため、シンボリック参照を実行します(Greg Baconが説明しているように)。シンボリック参照はシンボルテーブル内の変数で機能する$foo
ため、パッケージ変数である必要がありました。
これを台無しにするのは簡単なので、それをstrict
チェックするのに便利です。ただし、オフにした場合でも、噛まれても驚かないでください。:)
変数名またはサブルーチン名の一部として識別子(または識別子のチェーン)を配置する場合はいつでも、識別子を正しいタイプの参照を返す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は、ケース2ではなくケース1の短縮版です。$$hashref{"KEY"} = "VALUE"; # CASE 0 ${$hashref}{"KEY"} = "VALUE"; # CASE 1 ${$hashref{"KEY"}} = "VALUE"; # CASE 2 ${$hashref->{"KEY"}} = "VALUE"; # CASE 3
ケース2は、おそらく参照しているハッシュを
%hashref
逆参照するのではなく、と呼ばれる変数にアクセスしているという点でも欺瞞的です。$hashref
それはケース3になります。
後の「シンボリックリファレンス」:
参照は、定義されていない場合は必要に応じて発生すると述べましたが、参照として使用される値がすでに定義されている場合はどうなるかについては述べていませんが、ハードリファレンスではありません。参照として使用する場合は、シンボリック参照として扱われます。つまり、スカラーの値は、(おそらく)匿名の値への直接リンクではなく、変数の名前と見なされます。
シンボリック参照を使用しない限り、問題ありません。次のコードを想定します。
my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";
同意します。その有用性はscalarrefsでは明らかではありませんが、arrayrefsでは非常に有用です。
print "keys: @{[keys %messages]}\n";