• ベストアンサー

perlについて

my @a = qw(a b c); my @b = ( qw(e f g) ); これの違いは何なのでしょうか? perlにおいて()で囲むのはリストとして扱うということなのでしょうが、いまいちよく分かりません。 教えてください

  • Perl
  • 回答数4
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

まず本題を先に済ませてしまうと my @b = ( qw(e f g) ); と my @b = qw(e f g); の間に違いはありません. 全く同じことです. 「書き換えた後のコード」で my @t = ( qw(a b c) ); となっているのは, 単に無名配列を作る [ qw(a b c) ] と形を合わせたかっただけではないでしょうか. で余談: #1 ではなんだかんだ書いたけど, でも「perlにおいて()で囲むのはリストとして扱うということ」と思っちゃうのはまあ無理ないと思います. だいたい my @a = ("a", "b", "c"); って書くしね. ただ, ここのかっこは実は「リスト」とは全く関係ありません. じゃあなんでかっこがあるかというと 優先順位を変えるため です. Perl では代入演算子の方がコンマ演算子よりも優先順位が高いため my @a = "a", "b", "c"; と書くと (my @a = "a"), "b", "c"; と解釈されてしまうのですが, それでは困るので右辺にかっこをつけています. つまり $a * ($b + $c) のかっこと役割は全く同じです. 1 の my $a = qw(a b c); は my $a = ("a", "b", "c"); と同じ意味で, この右辺は (コンマ演算子の動作により) 「"a", "b" の値は評価だけして捨て, "c" の値を返す」ということになります. なので $a の値は "c" となります. 上の my @a = ("a", "b", "c"); では右辺がリストであるのに対し下の例ではリストになっていませんが, これは「代入演算子が左辺を見て右辺の評価の仕方を変えている」からです. つまり上の例では左辺が @a と配列になっているので「じゃあ右辺はリストとして計算しないとだめだな」としますし, 下の例なら左辺 $a がスカラー変数なので「右辺はスカラーとして計算しよう」となります. 専門的には, この「○○として計算しよう」というのを「コンテキスト」と呼びます. コンテキストにはいくつかの種類がありますが, とりあえずスカラーコンテキストとリストコンテキストの 2つをおさえておけばだいたい何とかなります. 2 の my @a = qw(a b c); my $a = @a; ではまず配列 @a に値を代入します. 次にスカラー変数 $a に配列@a を代入していますが, この場合代入する変数 $a がスカラーなので右辺はスカラーコンテキストで評価されます. そして スカラーコンテキストで配列を評価すると要素数が得られる ため, @a の要素数である 3 が $a に入ります. 3 と 4 は同じ結果になりますが, ここでは代入の左辺 ($a) が「リストである」ことに注意が必要です. つまり「左辺はリスト」なので, 「右辺もリスト」として計算します. そして得られた値を「要素ごとに代入」しているので $a の値は "a" です. 「代入する変数」そのものはスカラーであっても, ($a) となっていればリストです. なお, 無名配列を作る [] や無名ハッシュを作る {} は, その内部に対し (当然ですが) リストコンテキストで評価します. さらに余談ですが, 「かっこをつけなくてもリストになる」例として「リストを要求する演算子」を挙げることができます. print はそのような演算子なので, たとえば print $a, $b, "\n"; と書くと「$a, $b, "\n" からなるリスト」に対して print を適用する, という意味になります. もっとも, 現実的にはかっこをつけないといろいろ面倒なことがあったりしますが....

yamada11
質問者

お礼

丁寧に解説していただき、本当にありがとうございました。おかげで、より深い理解につながったと思います。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

うっぷ, 不適切な例を出しちゃった.... 数字を入れると「なぜそうなるのか」が却ってわからなくなっちゃうのに.... #1, #2 の例は次のように変えてください: 1: my $a = qw(a b c); 2: my @a = qw(a b c); my $a = @a; 3: my ($a) = qw(a b c); 4: my @a = qw(a b c); my ($a) = @a; この 4通りで最終的に $a にどのような値が入っているかを調べるといいかもしれない.

yamada11
質問者

お礼

お返事ありがとうございます、お礼が遅れまして大変申し訳ございませんでした。 まだ、少し疑問が解消できていません。よろしければ、さらに回答していただけると助かります。浅学で申し訳ございません。 まず、ご指摘された 括弧 に「リストとして扱う」などという機能はありません.というところですが、私が持っている本には、リストリテラルに関して、値をコンマで区切って括弧で囲んだものとあります。そういう意味で括弧で囲むのはリストとして扱うということを書きました。表現の仕方というか、言葉足らずというか、私の不備でした。申し訳ございません。 回答にありましたものは以下のようになりました 1: my $a = qw(a b c); #c 2: my @a = qw(a b c); my $a = @a; #3 3: my ($a) = qw(a b c); #a 4: my @a = qw(a b c); my ($a) = @a; #a まず 1: my $a = qw(a b c); #c についてですが、これについてまずqwについて復習しました。 qwとはリストリテラルに関するショートカットでした つまり qw(a b c) とは ("a", "b", "c") と同じであるということなんだと思います。 a b c を順番にスカラー変数に格納するので最初の a b が消されて c が表示されているんだと思います。 次に 2: my @a = qw(a b c); my $a = @a; ですが、まず配列にリストを格納しています。 そしてスカラー変数に配列の要素の個数を格納しているので 表示が3になりました。 次に 3: my ($a) = qw(a b c); ですが、さきほど書いたように、qw(a b c)は("a", "b", "c")なので、リスト値をスカラー変数に代入していることになります。 もしこれが、 my ($a, $b) = qw(a b c); であれば、 $aと$bにそれぞれaとbが格納されます。 つまり、リスト代入なので、aのみが$aに格納されて、他の値は捨てられたと思います。 で最後の 4: my @a = qw(a b c); my ($a) = @a; ですが、配列にリストを格納し、my ($a) = @a;がリスト代入の形なので$aにaが格納された。 以上を踏まえてもう一度最初の疑問について考えると my @b = ( qw(e f g) ); とは my @b = ( ("e", "f", "g") ); と同じということなので  特に意味は無い?? しかし、そもそもこの疑問は本に以下のように書かれていたので疑問に思ったのです ・・(省略)・・無名配列コンストラクタとは、他でもない角カッコのことです my $ref = [ qw(a b c) ]; この角カッコは・・(省略、無名配列を作成してリファレンスを返すと説明)・・このコードは以下のように書き換えられます。 my $ref { my @t = ( qw(a b c) ); $ref = \@t; } これは無名配列コンストラクタを分かりやすく説明するためにこうしたのでしょうか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

そうそう, #1 に追加するけど my ($a) = (1, 2, 3); とか my @a = (1, 2, 3); my ($a) = @a; とかも調べると面白いよ.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

代入する先の変数や代入する値が違う. 逆に言えば, 「指定した変数に指定したリストを代入する」という「意味」は全く同じ. そもそも「perlにおいて()で囲むのはリストとして扱うということなのでしょうが」というのが間違い. () に「リストとして扱う」などという機能はありません. たとえば my $a = (1, 2, 3); と my @a = (1, 2, 3); my $a = @a; のそれぞれで $a の値がどうなっているか調べてみてください.

関連するQ&A

  • perlでの、ファイル読み込みについて

    perlでの、ファイル読み込みについてお尋ねしたいことがあります。 a b c d e f g h i というような内容のテキストファイルがあったとき、この成分を「○行×列」の個別に読み込みたいのですが、 (C言語でいう、「A[0][0]=a A[0」[1]=b A[0][2]=c A[1][0]=d ・・・のように) どのようにしたらよいのでしょうか? perlに関しては全くの初心者なのですが、どうしてもperlを使わないといけない事情があり、 稚拙な質問かとは思いますが、どうぞよろしくお願いします。

    • ベストアンサー
    • Perl
  • perl $b=$a=~/パターン/

    perlで $b=$a=~/パターン/; ($b)=$a=~/パターン/; のような表現をまれにみかけるのですが、 $b=$a=~/パターン/; の$bには何が得られるのでしょうか。 どんなときに使うのでしょうか。 ($b)=$a=~/パターン/; に/g修飾子を付けると 何も得られなくなってしまいますが なぜでしょうか。 例えば、 (1)のように $bには1が入っているので最初は /\d\d\d/に一致した数が 得られているのかと思ったのですが、 (2)のようにしても1のままです。 また、(3)のようにしてみても1のままです。 $bには何が得られるのでしょうか。 (4)では$bに1つ目の(\d)にマッチした結果が、 $cに2つ目の(\d)にマッチした結果が 入っているのでこれは理解できますが、 (5)のようにgを付けると、$b,$cには 何も入らなくなってしまいますが なぜでしょうか。 $a=~/(\d)\d(\d)/g;からは、 (1,3,4,6)のリストが返されて、 このリストの頭の2つの要素(1と3)が ($b,$c)に得られるのではないのでしょうか。 (1) my $a='a123b456c'; my $b=$a=~/\d\d\d/; my $c; print "$b\n";---> 1 (2) $b=$a=~/\d\d\d/g; print "$b\n";---> 1 (3) $b=$a=~/(\d)\d(\d)/g; print "$b\n";---> 1 (4) ($b,$c)=$a=~/(\d)\d(\d)/; print "$b $c\n";---> 1 3 (5) ($b,$c)=$a=~/(\d)\d(\d)/g; print "$b $c\n";--->空白 よろしくお願いします。 Windows7 , ActivePerl(v5.16.3)

    • ベストアンサー
    • Perl
  • 【perl】重複した要素だけを書き出すスクリプト

    perlでスクリプトを作っているのですが、 あるリストから重複した要素だけを取り出すってのを 作りたいのですがうまく出来ません。 あるリストの例 a-a:0001 a-b:0002 a-c:0003 a-d:0004 a-b:0002 a-e:0005   ・   ・   ・ この場合 a-bだけを取り出したいんですが躓いています。 ご回答お願いします。

  • perlでアドバイスをお願いします。

    あるテキストファイルが以下の内容で記述されているとします。 a   file1 a   file1 a   file1 b   file1 b   file1 b   file1 c   file2 c   file2 d   file2 d   file2 e   file2 e   file2 f   file3 f   file3 f   file3 上記のように列が二つあるテキストファイルについて、 2列目のfile名が1列目のどの値とひもづいて いるかを処理するperlプログラムを作ることを考えます。 出来上がったperlによって上記テキストファイルを処理した結果は、 file1は aとb file2は cとdとe file3は f とひもづいていることが分かる ということにしたいです。 これをperlプログラムで書くとき、条件として 一行一行を読みとるとき if ( $_ =~ /(\S+)\s+(\S+)/ ){ を使っています。 そのため$1と$2に現在行の1列目,2列目が与えられた後、 ハッシュと配列を組み合わせて考えた場合どのようにすれば いいのでしょうか。 また仮にテキストファイルの続きが存在し、 1列目がg 、2列目がfile1 の行があるとき 2列目で既に出てきた同じfile名はエラーとすることも考えた 場合どう記述するのか合わせてお願い致します。 長くなってしまい申し訳ないのですが、 ご指導ご鞭撻宜しくお願い致します。

  • Perlの戻り値について

    配列の戻り値が理解できていないのですが、 Perlで正しく動作させるためには どのように記述したら良いのでしょうか? 戻り値の動作を詳しく書いてある(出来れば図入りで) 本はありますか? 例) sub a { my @a = ('A'); return (@a, "B", 2); } my (@a, $b, $c) = &a; print "a=[@a] b=[$b] c=[$c]\n"; # a=[A] b=[B] c=[2] # これを期待していたが # a=[A B 2] b=[] c=[] # こちらになる

    • ベストアンサー
    • Perl
  • Perlのsystemでdosコマンドの引数の指定

    Perlでfcコマンドを実行する場合、 system 'fc E:\A\B\x.exe F:E:\A\B\x.exe'; では、うまくいきますが、 引数を変数で指定するにはどのように 記述すればよいのでしょうか。 (Active Perl ,Windows7) my $filename1="E:\A\B\x.exe"; my $filename2="F:\A\B\x.exe"; system 'fc $filename1 $filename2'; <--- (NG) system "fc $filename1 $filename2"; <--- (NG) system fc $filename1 $filename2; <--- (NG)

    • ベストアンサー
    • Perl
  • Perlで足し算をするには

    Perl 初心者です。 いい足し算ができず、困っています。my $Aの数字を足していくだけなのですが、 うまくいきません。 何が悪いのかわかる方教えてください。 よろしくお願いいたします。 Perlではsumをつかわないでしょうか? 下記は4と2と3なので、9になるはずなのですが。。。。 その1 my $A = 4,2,3; $B = (sum($A)); print "$B" その2 my $A = 4,2,3; $B = subsum($A); print "$B"

  • perlで、後ろの行を読んで、前の行に書き込むには?

    perl初心者です。 後ろの行を読んで、戻って、指定の行に、書き込む方法が、よくわかりません。 下記のようなファイルを読み込んで ---------------------------- アルファベット= 1A 2B 3C アルファベット= 1A 2B アルファベット= 1A 2B 3C 4D 5E 6F ------------------------------ 下記のように、「アルファベット=」にアルファベットを入れるには、どうしたらいいでしょうか? ------------------------------ アルファベット=ABC 1A 2B 3C アルファベット=AB 1A 2B アルファベット=ABCDEF 1A 2B 3C 4D 5E 6F -------------------------------- よろしくお願い致します。

  • perlでご助言お願い致します。

    あるテキストファイルが以下の内容で記述されているとします。 a   file1 a   file1 a   file1 b   file1 b   file1 b   file1 c   file2 c   file2 d   file2 d   file2 e   file2 e   file2 f   file3 f   file3 f   file3 上記のように列が二つあるテキストファイルについて、 2列目のfile名が1列目のどの値とひもづいて いるかを処理するperlプログラムを作ることを考えます。 出来上がったperlによって上記テキストファイルを処理した結果は、 file1は aとb file2は cとdとe file3は f とひもづいていることが分かる ということにしたいです。 これをperlプログラムで書くとき、条件として 一行一行を読みとるとき if ( $_ =~ /(\S+)\s+(\S+)/ ){ を使っています。 そのため$1と$2に現在行の1列目,2列目が与えられた後、 ハッシュと配列を組み合わせて考えた場合どのようにすれば いいのでしょうか。 ご助言ご鞭撻宜しくお願い致します。

    • ベストアンサー
    • Perl
  • Lispでリストの中身もすべて反転する関数

    リストの中身をもすべて反転する関数を作っているのですが、 reverse関数を自分で実装はできたのですが、上記のような使用を持つ関数を作れません。どうぞどのようにしたらよいか教えていただけないでしょうか? ちなみに自分で作ったreverseはこれです。 (defun my-reverse (n) (if (null n) nil (append (my-reverse (cdr n)) (list (car n))))) 作りたい関数では以下のようになります。 (make-reverse '(a (b (c d))(e (f g)))) (((g f) e)((d c) b) a)

専門家に質問してみよう