• ベストアンサー

Perl ハッシュの値のリストをスカラーコンテキストで評価すると?

こんにちわ。 初めての利用です。 Perlの事で質問なのですが、 my $score=($hash{"fred"},$hash{"barney"},$hash{"wilma"}); とすると$scoreにはキー「wilma」に対応した値が代入される様です。 リスト形式をスカラーコンテキストで評価すると、リストの要素数を返すと記憶していたので、この場合$scoreには3が代入されると思っていたのですが・・・。 試しに my @scores=($hash{"fred"},$hash{"barney"},$hash{"wilma"}); $score=@score; とすると$scoreに3が代入された様です。 この二つの式では一体何が違うのでしょう・・・?

  • Perl
  • 回答数6
  • ありがとう数6

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

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

$a = (3, 2, 1); の場合, 左辺がスカラー変数だから右辺もスカラーコンテキストで評価されます. で, スカラーコンテキストの場合には「(」, 「)」は普通の「優先順位を変える」意味になりかつ「,」は「順に評価する」という意味を持つ演算子になります. そのため, 上の例では 3, 2, 1 と順に評価しその最後の値である 1 が右辺の値となって $a に代入されます. 一方 @a = (3, 2, 1); の場合, 左辺が配列変数なので右辺は配列コンテキストで評価されます. この場合「(」, 「)」は配列要素をまとめるという意味, 「,」は配列要素を区切るという意味になります. で, @a は 3個の要素からなる配列になります. この状態で $a = @a; とやると, 最初の例と同様に左辺はスカラー変数だから右辺もスカラーコンテキストで評価されます. ところがこの例では右辺が配列変数 @a となっており, これをスカラーコンテキストで評価するとその要素数 (今の例では 3) が得られます. 従って, この文を実行すると $a の値は 3 となります. で, #2 の最後でやりたいことって $a = @{[3, 2, 1]}; かなぁ? 無名配列を作る「[」や無名ハッシュを作る「{」は, 同時に対応するコンテキストを強制します.

mihosaku
質問者

お礼

お返事ありがとうございます。 とても丁寧な回答で、おかげで私のような初心者でも納得がいきました。 コンテキストが変わると右辺の式の性質(カッコやカンマの役割)まで変わってしまうなんて、思いもしませんでした・・・。 Perlは奥が深いですね。 ありがとうございました。

その他の回答 (5)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.6

> #2 の最後でやりたいことって > $a = @{[3, 2, 1]}; > かなぁ? いえ、リファレンスを持ち出していいものか判断できなかったので とりあえずそれは考えていませんでした。 というかここまできてちゃぶ台返しなんですが、実際のところ 無名の配列の長さを知りたいというニーズがあったりしての 質問だったのでしょうか? 思考実験としては面白いかもしれませんが、実際のスクリプトで 使う場面がありうるのかなあと。

mihosaku
質問者

お礼

お返事ありがとうございます。 実際は無名の配列の長さを知りたかったのではなく、間違えてスカラコンテキストで評価してしまい、一度そのプログラムを走らせた後に間違いに気づいたのですが、スカラコンテキストで評価した時の動作が予想に反していたので煮詰まってしまった次第です。 ですが、おかげでリストと配列、コンテキストへの理解が少し深まりました。 何度も目を通していただき、ありがとうございました。

  • kapura
  • ベストアンサー率50% (48/95)
回答No.5

既に回答されていますが、簡単に言えば、リストと配列は微妙に扱いが違うということだと思います (多くの場合同じように考えて大丈夫)。つまり、@num = (2, 4, 6, 8, 10) とすると、(2, 4, 6, 8, 10) というコードの部分を機械的に @num とか $num と書き換えても異なる結果になり得る (でも多くの場合同じ結果になると考えて大丈夫)。 $list = (2, 4, 6, 8, 10); では右辺はリストというか、右辺のコンマ (カンマ) はコンマ演算子で、コンマで区切られたコードを左から順に実行していって、最後のコード (右端のコード) の値10が $list に代入される (丸括弧はそこを先に評価するように優先順位を上げている)。この場合は、右辺を @num と書いたのと結果が異なります (要素数の5が $list に代入される)。 # 右辺に丸括弧がない場合は、=が優先されて $list = 2 というコードと見なされる ($list) = (2, 4, 6, 8, 10); と書けば、右辺のリストの要素のうち、左辺にない余分な要素は無視されて、2が $list に代入される。この場合は、右辺を @num と書いても同じ結果になります。

mihosaku
質問者

お礼

お返事ありがとうございます。 おかげで納得する事ができました。 代入演算子「=」はカンマ演算子より優先度が高いから、 $listに左端の2の値が代入されるのですね。 ありがとうございました。

  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.4

らくだ本の第3版の日本語版のp.84から始まる 話題だと思います. 曰く, ・(LIST)はリストリテラル ・リストリテラルはリストコンテキストだけで その内容をならべたリストとなる ・リストリテラルは式の中では 「スタックにその値をプッシュする」だけで スタックに詰まれた値は,リストを必要とする演算子によって リストとしてポップされて回収される ・スカラコンテキストではリストリテラルは 各要素が順番評価されて「最後の値」が返される などなど・・・ つまり,sakusaker7さんの説明は 正鵠を得たものだと思います. #というか,sakusaker7さんの説明で #らくだ本の記述を思い出して紐解いた(^^;; 蛇足ですが,以下のような感じでしょうか. $x = (1,2,3,4); とした場合は (1,2,3,4) は式の中であって リストを必要とする演算子もなく, スカラコンテキストなので 4 が返される. $x = (1,2,3,4)[0] とした場合は,式の中であって[0]によって スタックにつまれたものはリストとなって さらに配列になって 1 がでてくる. >my @scores=($hash{"fred"},$hash{"barney"},$hash{"wilma"}); >$score=@score; これに関しては,本質的にまったく同じ例が らくだ本のp.85にでています. 一行目の右辺はリストコンテキストなので 配列の値として使われて @score に入ります. そして,二行目では 「配列@score」がスカラコンテキストで評価されるので その要素数 3 が返されるということです. らくだ本にそのまま同じフレーズがありますが 「リストと配列は違うものである」ということです. >リスト形式をスカラーコンテキストで評価すると、リストの要素数を返すと記憶していたので、 ここに誤解の根元があって, やはり「リストと配列は違う」ということだと思いますよ. >@{(1, 2, 3, 4, 5)} これは(1,2,3,4,5)がスカラコンテキストなので @5 になりますね. (a,b,c,d,e) を評価して ``要素数'' を出すということなら scalar map {$_} (a,b,c,d,e) scalar @{[(a,b,c,d,e)]}; とか,とにかくリストリテラルをどこかでリストコンテキストにおいて 配列にしてからそれをスカラコンテキストで評価することになるのだと 思います.

mihosaku
質問者

お礼

お返事ありがとうございます。 らくだ本に書いてあるのですね。 らくだ本はまだ買ってませんでした。 ようやくリャマ本を終えたところでして、続・初めてを終えた後に買ってみようと思います。 「リストと配列は違う」、よく噛みしめておこうと思います。 ありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

すみません。 , と = の優先順位を勘違いしていました。 ですので、カッコ抜きで書いたときに先頭のものの値が代入されるのは それであってます。 ちょっとうまい具合に説明できないのですが、 $x = (1, 2, 3, 4); としたときに右辺はリストではないのですが、 $x = (1, 2, 3, 4)[0]; のようにしたときには、[]の働きによってカッコの中がリスト扱いになります。 そのため >my $list=(1,2,3,4,5)[3]; >こうすると$listには4が代入されますよね。 という結果になります。 @{(1, 2, 3, 4, 5)} とかいう記述もだめだしどうしたもんですかねえ。 ちょっと考えてみます。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

最初の例の右辺はリストじゃないですよ。 カッコ抜きで my $score= $hash{"fred"},$hash{"barney"},$hash{"wilma"}; と書いたのと同じことなので、 最後の値が左辺にあるスカラー変数に代入されたのです。 後の例だと代入の右辺もリストと見なされますので リスト同士の代入になり、 リスト変数をスカラーコンテキストで評価した結果を $scoreに格納しているので、要素数の3が入ったというわけです。

mihosaku
質問者

お礼

早速のお返事ありがとうございます。 右辺はリストでは無い、との事ですが・・・。 正直、イメージが掴めないでいます。 my $list=(1,2,3,4,5)[3]; こうすると$listには4が代入されますよね。 という事は右辺の「(1,2,3,4,5)」の部分は「1~5の数からなるリスト」で、「そのリストのうち添え字が3番の要素を代入する」という意味にはならないのでしょうか・・・? それと、sakusaker7さんの言うとおり、カッコ抜きで my $score=$hash{"fred"},$hash{"barney"},$hash{"wilma"}; と書いてみましたが、予想に反して$scoreには最後のハッシュのキー「wilma」の値ではなく、最初のキー「fred」の値が代入されました。 カッコでくくるとwilmaの値に・・・。 どういうプロセスでこの様な結果になるのでしょう?

関連するQ&A

  • リストの最後の要素がリストリテラルの値になる?

    上級ウィザードを目指してプログラミングPerlを読んでいます! 53ページのリスト値の説明によると スカラーコンテキストでは、リストの最後の要素の値がリストリテラルの値になる。 とあり $stuff = ("one", "two", "three"); では、threeだけが変数$stuffに代入される。 とあります。 しかし、このコードを実際に試してみると $stuffにはoneが代入されました。 この本の記述が誤っているのでしょうか。 それとも私のやり方が何か間違っているのでしょうか。 誰か教えてください。

    • ベストアンサー
    • Perl
  • split後のデータ数でなくて、リスト値を代入したい。

    my %hash = (); $hash{'NAMAE'} = "田中"; $hash{'TEN'} = split(/,/, "100, 50, 70"); 名前はスカラーデータなので、問題ないのですが点数はリストなので このまま代入し、 $has{'TEN'}で見てみると3というデータ数が入ります。 これをリストで代入させたいのですがどうすればよいのでしょうか?

    • ベストアンサー
    • Perl
  • 紙谷氏の「Perl/CGI入門」、ハッシュeach関数の例題について

    ハッシュのeach関数を使って「猫はcat犬はdogお茶tea」と表示させるプログラムの主要部分です。 %list = ("猫"=>"cat" , "犬"=>"dog" , "お茶"=>"tea"); while( ($key,$val) = each( %list ) ){   print "$keyは$val"; } whileの条件部分の意味が分かりません。 ・なんで条件部分なのに代入みたいな式が入るのか? ・$keyと$valというのは普通のスカラー変数とは違うのか? 良く分からないので質問の仕方もおぼつかないですが、どなたか分かりやすく説明して頂けないでしょうか?

    • ベストアンサー
    • Perl
  • hashをスカラー変数に渡す

    最近、perlを勉強し始めたのですが下記のようなサンプルコードを 見たことがあります。 hashをスカラー変数「$test」に渡している。そして「%$test」でhashに変換してeachで回している。最初から「%test」のようにしてeachで回せばよいと思うのですが実際の業務とかでhashをスカラー変数で受け取るようなことってありえるのでしょうか? my $test = { a=>'test_a', b=>'test_b', c=>'test_c' }; while( my ($key, $value) = each %$test ) { print $key ." : " . $value . "\n"; }

    • ベストアンサー
    • Perl
  • ハッシュキーの内容について

    こんばんは。perlをはじめて一ヶ月あまりの初心者です。 また疑問に思うことが見つかり、質問させていただきました。 以下のようなコードがあります。 ----------------------------------------- my @array = ( 'a','b','c'); my %hash; for (@array) {   $hash{$_}{OK} = 1;   $hash{$_}{WAVE} = 2;   $hash{$_}{Perl} = 3; } print $hash{a}->{OK}; print $hash{"b"}->{WAVE}; print $hash{c}->{"Perl"}; ----------------------------------------- 1、2、3を格納するときなのですが、 ハッシュのキーになる値(OK、WAVE、Perl)は、 ダブルクォートや、シングルクォートで囲っていません。 でも、エラーも発生せず、普通に実行できてしまいます("123"を表示します)。 ハッシュのキーは、 "OK","WAVE"や、'Perl'のように ダブルクォートや、シングルクォートで 囲む必要はないのでしょうか?? C言語みたいに厳密に型が決まっているわけではないので、 OKでも"OK"でもよいのかなー、という思いはあるのですが、、、 よろしくお願いします。

    • ベストアンサー
    • Perl
  • redoを実行するとスカラー変数の値がundefになってしまうのはどうしてでしょうか?

    はじめまして。 質問があります。 まずは以下のコードを見てください。 ---------------------------------------------------------------- use strict; use warnings; open(FILE,'redo01.txt') or die "$!"; while(my $line = <FILE>) { print "undef\n" unless( defined($line) ); chomp($line); if($line =~ /---$/) { $line .= <FILE>; redo; } print $line,"\n"; } close(FILE); ---------------------------------------------------------------- --redo01.txt---------------------------------------------------- zero--- one--- two--- three--- four ---------------------------------------------------------------- ファイルから一行を読み込んできてスカラー変数$lineに代入して、 redoを実行しながら$lineの値をどんどん連結していき最後に文字列を 表示させようと思っていたのですが、なぜかredoを実行後 ループ内の先頭行に制御を移してから$lineの値を調べてみると、 undefになってしまいます。事実、chomp()関数やパターンマッチ、 print関数を実行すると、エラーになってしまいます。なぜ$lineの値 がundefになってしまうのでしょうか?どうかご教授お願いします。

    • ベストアンサー
    • Perl
  • コンテキストについて

    パターンマッチを用いて、変数$numに、文字列$strが正の整数の場合はその値を代入し、そうでない場合はデフォルト値として定数を代入したいのですが、 ($num) = ($str =~ /^([1-9][0-9]*)$/) || 1; としても、正の整数としてマッチした場合でも、||の影響で||の左辺がスカラーコンテキストとして評価され、真値としての1が代入されて上手くいきません。 上記の用件を1行で満たすPerlらしいスクリプトがあったら是非教えてください。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • リファレンスについて教えて下さい

          KEY     VALUE %hResult----RetCode ---- 0     ----Contents --- \%Hash1       KEY     VALUE %Hash1------MainContents--\@ArrayRef1    ------List     \%Hash2       KEY     VALUE %Hash2------NAME----------SCALAR1    ------TYPE----------SCALAR2 上のようなデータ構造をしている%hResultを サブルーチンから返却してきます。 %hResult から記述して、 1.ArrayRef1の要素を使用したい 2.SCALAR1,SCALAR2を使用したい のですが、記述が良く分かりません。 どなたか教えて頂けませんか?

    • ベストアンサー
    • Perl
  • 初歩的な質問です 変数の値を保持

    perlの勉強中なのですが、 例えばCGIを呼び出した際にある特定の処理により、 変数$hogeにスカラーコンテキストを格納したとします。 そして次にCGIが呼び出されるまで、その$hogeに格納されているスカラーコンテキストは保持されたままでいるのでしょうか?保持されていれば、その保持されていた値を利用してまた新たな値を生成して$hogeに格納できて非常に便利だと思っています。実際、今私がしたい処理は、これができればかなり楽なはずなんです。 ですが、私自身は、保持できないのでは?と思っています。ですので、その保持しておきたい値を外部ファイルにいちいち格納してやる必要があるのかなと思っています。そして必要なときはその値を外部ファイルから得て、そしてまた外部ファイルの値を書き換えてという作業が必要になるのでは?と思っています。 また、保持できるのであるならば、どのようなことをすればリセットできるのでしょうか。つまり、そのサイトから一度離れればいいのでしょうか?

    • ベストアンサー
    • CGI
  • foreachについて

    ポケットリファレンスより foreach[★](□){■} 配列などの一連のスカラー値を持つリスト□から順に要素を取り出し、スカラー変数★に代入してからブロック内の■を繰り返し実行します。リスト値□がなくなった段階で終了します。 とあります。今解析しているプログラムで下記のようなコードがあり、数点質問があります。(このコードの前にあるDBを呼んで、$RECにデータを返しています) undef @BCOL; my($KU_REC); while ($rc = $DBr->fetchrow_hashref) { $flg_find_ku = 1; foreach $KU_RECt (@BCOL) { if ($KU_RECt->{KU_CODE} eq $REC{KU_CODE}) { $KU_REC = $KU_RECt; $flg_find_ku = 0; last; } $KU_REC = $KU_RECt; } if ($flg_find_ku == 1) { (1) push(@BCOL, {}); (2) $KU_REC = $BCOL[$#BCOL]; } } (1)@BCOLは最初要素を含んでいないように思うのですが、リファレンスの(リストの値がなくなるまで)という部分をみて疑問ですが、リストに値がないのに、foreachの中をとおるのでしょうか? (2)たとえば、とおったとして、このロジックはおなじ区コードを見つけて、見つかればフラグを0にするという処理だと思うのですが、最初の一回目は(1)(2)をとおると思います。この処理が何をしているかわかりません。@BCOLに{}を入れるとどうなるのでしょうか? また、$#BCOLは配列の引数をあらわしているように見えるのですが、いったい何番目の意味なのでしょうか? (3)スカラー変数は基本的にmyなどで宣言するかと思うのですが、foreachで使われる変数$KU_RECtの定義がみつかりません。ということはこの場合変数定義はいらないものと思ってよいのでしょうか? 私が何か勘違いしている部分もあるかと思うのですが、わかる方、どうぞよろしくお願いいたします。

    • ベストアンサー
    • Perl