• ベストアンサー

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が代入された様です。 この二つの式では一体何が違うのでしょう・・・?

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

  • ベストアンサー
  • 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