perlは単一変数を二重引用符で囲みます

Perlでは、単一の変数を二重引用符(連結なし)でカプセル化する理由はありますか?

私はこれまで、私が取り組んでいるプログラムのソースでこれを見つけることができます(10年前にもうこれ以上働かない人たちによって書かれました)。

my $sql_host = "something";
my $sql_user = "somethingelse";

# a few lines down
my $db = sub_for_sql_conection("$sql_host", "$sql_user", "$sql_pass", "$sql_db");

私が知る限り、これを行う理由はありません。私が古いスクリプトで作業するときは、通常は引用符を削除して、エディタで文字列ではなく変数として扱います。

私は彼らがこれをどこかに見て、それがなぜそうであるかを理解することなくスタイルをコピーしたと思う。何か不足していますか?

ありがとうございました。

7
これはよい質問です。なぜなら、ここでの答えは、古いコードを再組み立てする際にどのように注意する必要があるかを示しているからです。最初は悪いスタイルのように見えることがあるかもしれません。
追加された 著者 tangent,

5 答え

これは明示的に変数を文字列化します。 99.9%のケースでは、何らかの初心者のエラーです。

この呼び出しスタイルの副作用として起こりうることがあります:

my $foo = "1234";
sub bar { $_[0] =~ s/2/two/ }
print "Foo is $foo\n";
bar( "$foo" );
print "Foo is $foo\n";
bar( $foo );
print "Foo is $foo\n";

ここで、文字列化はコピーを作成し、それをサブルーチンに渡し、Perlのパスを参照セマンティクスで回避します。変数を呼び出すのは一般的に悪いマナーであると考えられているので、おそらく大丈夫です。

ここでオブジェクトやその他の値を文字列化することもできます。たとえば、 undef は空の文字列に文字列を変換します。オブジェクトは、文字列化されたときに実行する任意のコードを指定することができます。異なる数値と文字列の値を持つ二重値スカラを持つことは可能です。これは、文字列形式を指定する方法です。

また、深刻な恐ろしいことが起こっている可能性があります。関数へのスカラー引数に設定されているフラグを調べるXSコードで作業している場合、スカラーを文字列にすることは、文字列が唯一の文字列で「きれいな新しい文字列値にする」と、数値フラグはありません。

私は、99.9%のルールに他の奇妙な例外があると確信しています。これらはほんのわずかです。引用符を削除する前に、このような奇妙な駄目を確認するために秒を取る。正当な使用法で起こった場合は、引用符を実行可能なkludgeとして識別するコメントを追加して、その理由を示してください。

7
追加された
"関数に対するスカラー引数に設定されているフラグを調べるXSコードで作業している場合"、以前はPure Perlの例を示しました。 ref()を使用するものであれば十分です。
追加された 著者 ikegami,

この場合、二重引用符は不要です。さらに、これらを使用すると、元の文字列がコピーされるため、非効率的です。

しかし、このスタイルを使用してオブジェクトを「文字列化」したい場合があります。たとえば、 URI のオブジェクトは文字列をサポートしています:

my $uri = URI->new("http://www.perl.com");
my $str = "$uri";
6
追加された
@muが短すぎる:はい、 undef は(警告が有効かどうかに関係なく) ""
追加された 著者 Eugene Yarmash,
オブジェクトの明示的な文字列化を必要とするインターフェイスの不幸な衝突を想像することができます。このような状況では、クラスの基礎となるstringficationメソッドを明示的に呼び出す傾向があります。 $ foo-> as_string(); そうしないでください!)、あるいは、インターフェイスで共通のストリンジェンシーメソッドを共有していないオブジェクト間でポリモーフィズムに頼っています(sigh)。この場合、 my $ str = "$ foo"を実行する以外に選択肢はありません。 #意図的に$ fooを文字列に変換する - Foo :: Barはcurdsを必要とするが、乳清は必要ないコメントに注意してください。
追加された 著者 daotoad,
また、警告が有効になっていない場合、静かに undef を空文字列に変換しますか?私はそれを有効な使用と呼ぶつもりはないが、おそらく警告なしで何かが有効であるとは考えないだろう。
追加された 著者 mu is too short,
しかし、警告が表示されても静かには行きません。「連結されていない初期値」という苦情があります。
追加された 著者 mu is too short,
@ikegami:しかし、//の昔の歴史的なコードを見ています。そしてviはemacsを打ち負かし、LinuxはFreeBSDを打ち負かし、11人の天使がピンの頭で踊ることができます:)
追加された 著者 mu is too short,
@ikegami:私は、「二重引用符で単一変数をカプセル化する何らかの理由がある」という一般的な原則ではなく、特定の例に焦点を当ててその点を見逃していると言っています。
追加された 著者 mu is too short,
@muが短すぎると、 $ x//= ''; は、 $ x = "$ x"; それを行うための警告を出す。
追加された 著者 ikegami,
文字列を必要とするものは自動的にオブジェクトをストリング化するので、通常は行う必要はありません。
追加された 著者 ikegami,
@muが短すぎます。 undef を渡すよりも、DSNの "" を渡す方が良いですか?
追加された 著者 ikegami,
@ムが短すぎますね? $ x = "$ x"; »よりもundefを文字列化する方が、« $ x//= ''あなたは一例を挙げた人です。そして、//が存在する前に $ x || = ''; ? $ x: ''
追加された 著者 ikegami,

なぜかわからないけど、それは初心者がPerlによく使うパターンです。それは通常あなたが投稿したスニペットにあるように無駄ですが、私は2つの用途を考えることができます。


オリジナルと同じ値の新しい文字列を作成するという効果があり、非常にまれな状況で役に立ちます。

次の例では、サブがその引数を変更するため、$ xがサブの変更から保護されるように、明示的なコピーが行われます。

$ perl -E'
   sub f { $_[0] =~ tr/a/A/; say $_[0]; }
   my $x = "abc";
   f($x);
   say $x;
'
Abc
Abc

$ perl -E'
   sub f { $_[0] =~ tr/a/A/; say $_[0]; }
   my $x = "abc";
   f("$x");
   say $x;
'
Abc
abc

文字列のコピーを作成することによって、オブジェクトを文字列化します。これは、引数が参照であるかどうかに基づいて動作を変更するコードを処理する場合に便利です。

次の例では、 @ での参照を文字列とは別の方法で処理するため、 require

$ perl -MPath::Class=file -E'
   BEGIN { $lib = file($0)->dir; }
   use lib $lib;
   use DBI;
   say "ok";
'
Can't locate object method "INC" via package "Path::Class::Dir" at -e line 4.
BEGIN failed--compilation aborted at -e line 4.

$ perl -MPath::Class=file -E'
   BEGIN { $lib = file($0)->dir; }
   use lib "$lib";
   use DBI;
   say "ok";
'
ok
6
追加された
@dolmen、例の説明が追加されました。
追加された 著者 ikegami,
最初の場合は、「回避策@明示的コピーによるエイリアシング」と記述することができます。そのようなことをするコードにコメントを追加することをお勧めします。
追加された 著者 dolmen,

あなたのケースでは引用符はまったく役に立たない。他人が書いたように、これは慣用的ではないので、間違っていると言うことさえできます。

しかし、変数を引用することが必要になることがあります。これは、変数の値の文字列化を明示的にトリガーします。文字列化は、値が二重変数である場合、またはそれらが過負荷で祝福された値である場合、エージングストリング。

デュアルヴァースを使用した例を次に示します。

use 5.010;
use strict;
use Scalar::Util 'dualvar';

my $x = dualvar 1, "2";
say 0+$x;
say 0+"$x";

出力:

1
2

私の理論は、常に悪い習慣で他の言語から来る人たちだということでした。彼らは「私は二重引用符を常に使用する」と思っているわけではありませんが、彼らは考えていないだけです!

私は正直で、私はJavaからPerlに来たので、私はこのトラップに落ちていたと言います。そのため、筋肉の記憶があって、ちょうど発砲し続けました。

PerlCriticはようやく私を習慣から救い出した!

コードをより効率的にするのは間違いありませんが、文字列を補間したいかどうかを考えていなければ、間違ったことをする可能性が非常に高いので、さらに進んで危険です。

0
追加された