• ベストアンサー

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

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

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

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

具体的にどういう手順で確かめたかということと、お使いのバージョンとOSを教えていただけますか? c:\home>perl -d -e42 Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `perldoc perldebug' for more help. main::(-e:1): 42 DB<1> $stuff = ("one", "two", "three") DB<2> print $stuff three DB<3> print $] 5.008008 threeが入っているみたいですが?

zyousuke
質問者

お礼

ご返信ありがとうございます。 質問してちょっとたってから気づいたのですが、 私はまったくの教科書どおりにはやっていませんでした。 my($stuff) = ("one", "two", "three"); とやってしまったのです。 変数をかっこで囲んだためスライスと認識されてしまったのでしょうか あと、もうちょっと自力で調査してれば、恥をかかずにすんだものを・・・

その他の回答 (8)

回答No.9

実際のperl内部の動きはよく分りません。 my @data = split "\t", $line; として、@dataはポンイタとして格納されてるだけで、 my $data1 = $data[0]; ではじめて値を取得しているならば、記憶部分はあまり問題ないかも知れません。 それよりも私が言いたかったのは、 コードの見易さです。 行が減ればそれだけ見通しもよくなりバグも減ります。 これは経験値からです。 私も日々精進しておりますが、zyousukeさんも是非頑張ってください。

zyousuke
質問者

お礼

panerai777さん応援ありがとうございます! 分からない事ばっかりでイライラ気味の今日この頃。 この応援メッセージは、とても励みになります! 私も見やすいコードを書くのは、すごい重要だと思います。 この例とは逆に、時には長い1行の文を、短い複数行の文に書き換えることも重要ですね。 私は、何でもかんでも1行で書きたがる習性があるので・・・w それでは私は修行場へ戻ります。

回答No.8

その通りです。 またタブ区切りのファイルデータのパース時に my( $data1, $data2, $data3 ) = ( split "\t", $line )[0, 3, 6]; なんてこともしたりします。 my @data = split "\t", $line; my $data1 = $data[0]; my $data2 = $data[3]; my $data3 = $data[6]; よりはいい感じと思いますよ。

zyousuke
質問者

お礼

あ、この手法は私の教科書にも載っていました。 リスト中の特定の要素だけ欲しいのに、いちいち全データを配列に代入していたら主記憶と行がもったいないですものね!

回答No.7

DBからデータとひいたとき my @data = Class:DBI->search( hoge => "fuga" ); my $data = $data[0]; とするよりは、 my ( $data ) = Class:DBI->search( hoge => "fuga" ); の方がすっきりしませんか? ということでした。

zyousuke
質問者

お礼

なるほど、この例を見ると2個目のやり方の方がすっきりしますね。 やりたいことが1行で書けると、とっても気持ちがいいです! 私はまだ下級ウィザードなので、この例の処理の詳細は分かりませんが・・・ 何個の戻り値が来るか分からないけど、とりあえず先頭の情報がほしいんだったら わざわざ配列を使わずとも()で囲んだスカラー変数で十分だということですよね?

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

my とか our とか local は, 変数 (や値) のスコープを制御するだけで意味的には全く関係ありません. つまり, my ($stuff) = (...); というのは「変数 $stuff とその値が現在の静的スコープに制限される」ということを除いて ($stuff) = (...); と書いたのと全く同じです. この場合左辺がリストなので右辺もリストコンテキストで評価され, 先頭の要素が $stuff に代入され (他の要素は捨てられ) ることになります.

zyousuke
質問者

お礼

ご返信ありがとうございます。 今回の敗因は変数を()で囲んでしまったことですね。 ()で囲まなければ右辺のリストがスカラーコンテキストで評価され 無事に最後の要素を取得できて、駄スレを公開することもなかったのに・・・ しかし、これに懲りずに、今後もどんどん質問に来ますね! 私は遊び人なので悟りの書がなくても、いつの日かウィザードになれるはずだ!

回答No.5

my $stuff = ("one", "two", "three"); だと、 $stuff は "three" がはいってます。 一度、配列の変数に格納し、 my @stuff = ("one", "two", "three"); my $stuff = @stuff; とすると、 配列要素の数が入ります。3 my( $stuff1, $stuff2 ) = ("one", "two", "three"); $stuff1 には "one", $stuff2 には "two" が入ります。 お間違いになられたものが実は一番よく使うと思いますので、 いい間違いをされたと思いますよ。 たとえば、DBからデータをひいて配列に格納した結果を @data とすると、@dataにはデータがひとつしかないとき、 my $data; for( @data ){ $data = $_; } or $data = $data[0]; とするよりは、 my( $data ) = @data; の方がいい感じでしょう。

zyousuke
質問者

お礼

ご返信ありがとうございます。 いい間違いとはなによりです。 今いろいろ間違えを犯してレベルアップしています! でも私は配列の先頭を受け取るには ($data) = @data; とやるよりも $data = $data[0]; の方が好きかな。 どちらのやり方でも実行速度は同じぐらいだと思いますが、 コンパイル速度では2個目の方が、ちょっとだけ速そうな気がします。 特に根拠はないのですが・・・^^;

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

> my($stuff) = ("one", "two", "three"); > とやってしまったのです。 > 変数をかっこで囲んだためスライスと認識されてしまったのでしょうか スライスじゃあありませんけど、いいとこついてます。 my $hoge = ← 右辺はスカラーコンテキストで評価される my ($hoge) = ← 右辺はリストコンテキストで評価される ので今回のような結果になります。 my ($hoge) というのが、my ($foo, $bar, $baz) のような宣言の 特殊な形だと思えばいいでしょう。 こういうことがあるので、my で宣言する引数は迂闊にカッコでくくると 思わぬ挙動をしてしまうので要注意です。

zyousuke
質問者

お礼

なるほど よく分かりました。 おそらくmy関数を呼び出すよりも先に代入が行われるために、このような現象が起こるのでしょうね。 これを逆手にとって変数へリストの先頭の値を代入したい場合はこの手法が使えますね。 私は長年(というほどではないが)ビジュアルベーシックに親しんできたため 関数へ引数を渡すとき()で囲まないと、なんか気持ちわるい気がします^^

  • Werner
  • ベストアンサー率53% (395/735)
回答No.3

> $stuff = ("one", "two", "three"); このように書いた場合「("one", "two", "three")」はリストとは認識されずに、 カンマ演算子で値を結んだものを括弧で囲んだものと認識されていると思います。 カンマ演算子は、値を左から右に評価し、後に評価された値を返り値とするので、 「("one", "two", "three")」はすべて評価後には「"three"」となり、 $stuffには"three"が代入されます。 > $stuff = "one", "two", "three"; このように書いた場合は、=の優先順位が,より高いために 最初に「$stuff = "one"」が評価され このときに$stuffに"one"が代入されます。 なお、 > @array = ("one", "two", "three"); > $array_num = @array; このように配列をスカラーコンテキストで評価すると 配列の要素数が得られます。

参考URL:
http://www5c.biglobe.ne.jp/~can/perlpro/context.html
zyousuke
質問者

お礼

ご返信ありがとうございます。 私の早とちりのせいで3名ものウィザードをここへ召還してしまったとは、なんとも面目ないです。 配列をスカラーコンテキストで評価すると要素数を返すというのは次の解説に載っていました。 printはリストコンテキストを提供するためprintへ配列を渡しても要素数は取得できないのですよね!

  • leap_day
  • ベストアンサー率60% (338/561)
回答No.2

こんにちは $stuff = ("one", "two", "three"); print "$stuff\n"; として表示してみると three が表示されました $stuff = "one", "two", "three"; print "$stuff\n"; とすると one が表示されました とりあえず報告(^^)

zyousuke
質問者

お礼

ご返信ありがとうございます。 解決しました。 私がどのような間抜けなことをしでかしていたかは No.1さんのお礼欄へ書きましたのでご覧ください。 とりあえず今回の質問でひとつ利口になったと考えたいです。 ウィザードレベルとしてはヒャドを習得したといったところでしょうか