Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

変数、リファレンス

3,884 views

Published on

Hokkaido.pm #4

Published in: Technology
  • Be the first to comment

変数、リファレンス

  1. 1. 変数、リファレンス February 19, 2011 Hokkaido.pm #4 Kenichi Ishigaki (charsbar)
  2. 2. 始める前に…
  3. 3. Perl の変数なんて 別にむずかしくないよね という方?
  4. 4. 『言語設計者たちが考えること』
  5. 5. Larry がこんなことを 言っていました
  6. 6. 「自然言語の原理を コンピュータ言語へと 組み込む最善の 方法を探求」
  7. 7. Perl はもともと C 、 sed 、 awk 、 sh の よいとこどりをした言語
  8. 8. 英語っぽさを 感じることもあります
  9. 9. たとえば 英語の名詞
  10. 10. 無冠詞 : pen 単数 : a pen 複数 : pens
  11. 11. 無冠詞 (pen)   「~というもの」
  12. 12. そのままでは 数えられないもの   # または数えないもの
  13. 13. 辞書の見出し語   固有名詞 抽象名詞
  14. 14. Perl の場合
  15. 15. foo   裸のワード # 英数字と下線だけからなる単語
  16. 16. 昔はよくこんな使い方を していたものです   open FOO, 'bar';
  17. 17. 定数を定義するときにも よく使われています   use constant PI => 3.14; print PI * 2; # 6.28
  18. 18. 具体的なものの 代入は不可   foo = 'bar'; # エラー
  19. 19. 具体的なものを 扱うにはどうするか
  20. 20. そのものが 単数か複数かで 変わります
  21. 21. 単数の場合
  22. 22. 英語では冠詞を つけるのでした   pen -> a pen
  23. 23. Perl の場合は 「 $ 」という記号を つけます   foo -> $foo
  24. 24. この記号は あくまでも 冠詞扱い   # 変数名の一部ではありません
  25. 25. だからこんな 書き方も可能です   $ foo = 1; print $ foo; # 1
  26. 26. 真似しないで くださいね
  27. 27. どうして $ なのか
  28. 28. スカラー (scalar) の 頭文字   # 高校の物理で習いましたよね # 「矢印」がつかない値
  29. 29. 複数の場合
  30. 30. 英語では語形が 変わったり   a pen -> pens a man -> men
  31. 31. 数をあらわす 形容詞句がついたり   two pens a lot of men
  32. 32. 単複同型というのも ありました   単数 : a sheep 複数 : sheep
  33. 33. Perl の場合は @ という 記号をつけます   @foo = (1, 2, 3);
  34. 34. 配列 (array) の 頭文字から perldata では「 these とか those 」
  35. 35. 細かくいうと 配列とリストは別物
  36. 36. $foo と @foo の関係
  37. 37. 名前は同じです
  38. 38. いっぺんに扱う 手段もあります
  39. 39. 中身は別物です   a pen ≠ pens
  40. 40. 「複数」の性質
  41. 41. 単数+単数=複数   @pens = ($red_pen, $blue_pen);
  42. 42. 複数+複数=複数   @pens = (@red_pens, @blue_pens);
  43. 43. 要素の個数は あまり気にしません   # 複数は複数です
  44. 44. 配列の要素を 扱うときは for などで   foreach (@pens){ print $_ }   # $_ は英語の it と同じ単数の代名詞 # 中身については空気を読んで
  45. 45. コアレベルでは 省略できることも多い   foreach (@pens) { print } print for @pens;
  46. 46. 他動詞だから目的語をとるはず、というのが 暗黙の了解
  47. 47. 誤解を避けたければ 明示して   for $pen (@pens) { print $pen }
  48. 48. 処理の順番は?
  49. 49. リストの場合は左から右 ということになっています   print for (1, 2, 3);
  50. 50. でも、左ってどこ?   print for @pens;
  51. 51. どこかにはあるはずです が、隠れています
  52. 52. という記号をつけると 起点の位置を 取得できます   @pens;
  53. 53. 具体的にどこにあるかは 気にしなくていいです
  54. 54. @ という具体的な 文脈をあらわす記号を 打ち消しているイメージ
  55. 55. 起点がわかったら 向きと長さを指定すれば 個々の要素に アクセスできます   (@pens)->[0];
  56. 56. この起点のことを Perl の文脈では リファレンスと呼びます
  57. 57. 「よく使われる表現は、 あまり使われない表現 よりも短くあるべき」 ( 『言語設計者たちが考えること』 )
  58. 58. ふだんはもう少し 楽をしたいですよね
  59. 59. ひと頃は こんな風にも 書けました   @pens->[0];
  60. 60. Perl 5.8 で 廃止されました # 文脈がわかりづらくなるから # 複数のものから矢印 ?!
  61. 61. 起点はひとつしか ありません
  62. 62. ということは 単数扱いに なるはずです
  63. 63. Perl 5 では スカラーとしても 扱えるようになりました   $pens_ref = @pens; $pens_ref->[0];
  64. 64. 矢印が生えるのに !?
  65. 65. 普通のスカラーとは 違います
  66. 66. 中身を覗いて みましょう   perl -e "print @array" # ARRAY(0x33e288)
  67. 67. ぐちゃぐちゃに ならないよう 内部的には別扱い されています
  68. 68. Devel::Peek を使うと 詳しく調べられます   perl -MDevel::Peek -e "@a = (1, 2); print Dump(@a)" # Perl 5.6 以降はコアに入っています
  69. 69. むずかしいことは 忘れてください
  70. 70. 矢印が生えていれば (たいていは) リファレンスです   $pens_ref->[0];
  71. 71. ref でも確認できます   ref $scalar_or_ref ? 'ref' : 'scalar';
  72. 72. 誤解されそうな文脈では 名前を変えておきましょう   ○ $pens_ref = @pens; × $pens = @pens;
  73. 73. これでだいぶきれいに 書けるようになりました
  74. 74. でも、もう少し 楽をしたいです
  75. 75. できるように なっています   @pens; # $pens_ref = @pens; $pens[0]; # $pens_ref->[0];
  76. 76. $pens と $pens[0] と $pens->[0] は それぞれ文脈が 異なります
  77. 77. $pens は純然たるスカラー(たぶん) $pens->[0] の $pens はリファレンス $pens[0] は @pens の一要素
  78. 78. ベクトルの指す値は 矢印ひとつにつき ひとつのみです   $array_ref->[0] # 返り値はひとつのはずです
  79. 79. 配列にはスカラー (として扱えるもの) しか入れられない という制約が   $array_ref->[0] にわざわざ $ をつける必要はありません
  80. 80. 配列にはスカラー (として扱えるもの) しか入れられない という制約が   $array_ref->[0] にわざわざ $ をつける必要はありません
  81. 81. 配列から複数の値を 取り出したい場合も あります
  82. 82. ひとつひとつ列挙 してもかまいません   $first_pen = $pens[0]; $second_pen = $pens[1];   # 冗長ですよね
  83. 83. 一行にまとめてみました   ($first_pen, $second_pen) = ($pens[0], $pens[1]);
  84. 84. もう少し短くできます   ($first_pen, $second_pen) = pens; # 3 つめ以降の pen は無視されます
  85. 85. こんな書き方も できるのですが…   @two_pens = @pens[0, 1]; # @pens[0..1]
  86. 86. 必要がなければ 避けた方が無難
  87. 87. 意図とは異なる (かもしれない) 結果になるもの
  88. 88. 1 本なのに 複数扱い !? × @pens[0];
  89. 89. ベクトルの行き先はひとつのみです × $pens_ref->[0, 1]
  90. 90. 先にデリファレンスされて しまいますので… × @$pens_ref->[0, 1]
  91. 91. 配列にしてからなら OK ○ @$pens_ref[0, 1]
  92. 92. 便利に使える 場合もあります
  93. 93. 複数の配列を含む配列の場合
  94. 94. 赤だけ、青だけの 配列を区別できません   @pens = (@red_pens, @blue_pens); × (@red_pens, @blue_pens) = @pens;
  95. 95. 配列に入れられるのは スカラー扱いできる値のみ   配列をそのまま配列に 入れることはできません
  96. 96. 区別するには リファレンスを 使います   @pens = (@red_pens, @blue_pens);
  97. 97. 矢印をたどっていけば 目的地につきます   ($red_pens_ref, $blue_pens_ref) = @pens; $red_pen = $red_pens_ref->[0]; $blue_pen = $pens[1]->[0]; # = $pens[1][0];
  98. 98. 配列のなかの リファレンスから 生える矢印はふつう省略できます
  99. 99. 自動的にふられる 番号ではわかりづらい場合もあります   @pens = (@red_pens, @blue_pens);
  100. 100. 青ペンの 1 本目 には見えません ! $pens[1][0];
  101. 101. 要素が増減したら いちいち順番を直す必要があります
  102. 102. もっと明確に書きたいときは ハッシュという特殊な配列を使います   # 昔は連想配列と言っていました
  103. 103. ハッシュの場合は 届け先を明記します %pens = ( red_pens => @red_pens, blue_pens => @blue_pens, );
  104. 104. % -> c/o -> care of 「~様方」
  105. 105. 使い方は ふつうの配列と よく似ています
  106. 106. %pens = (...); $pens{red_pens}; $ pens {blue_pens};
  107. 107. $pens_ref = %pens; $pens_ref->{red_pens}; $ pens_ref -> {blue_pens};
  108. 108. それぞれの要素に アクセスしたいとき   for (keys %hash){ print $hash{$_} } for (values %hash){ print $_ } while(($key, $value) = each %hash) { ... } # 並び順は不定です
  109. 109. %pens = ( red_pens => @red_pens, blue_pens => @blue_pens, ); ハッシュのなかの 配列に名前は必要?
  110. 110. %pens = ( red_pens => ['mine', 'yours'], # @red_pens blue_pens => ['his', 'hers'], # @blue_pens ); $red_pens_ref = $pens{red_pens}; 必要なければ 省略してしまいましょう
  111. 111. [...] は無名配列の リファレンスです   (...) だと別の意味になるので要注意
  112. 112. ふつうの配列に したいときは 「冠詞」をつけて   @pens = @{['red_pen', 'blue_pen']};
  113. 113. もちろん 無名ハッシュへの リファレンスも つくれます   $pens_ref = { red_pens => 2, blue_pens => 3 }; %pens = %{{red_pen => 1, blue_pen => 2}};
  114. 114. どうして @{...} に なるのでしょう?
  115. 115. Perl にはシンボル テーブルと呼ばれる 特殊なハッシュが 用意されています
  116. 116. 中身を覗いて みましょう perl -MDevel::Symdump –e "print Devel::Symdump->rnew->as_string"
  117. 117. もう少し詳しく 見たいときはこちら   perl -MData::Dump=dump -e "print dump(%::)"
  118. 118. グローバル変数 パッケージ 関数/メソッド
  119. 119. 多くのものがこの 無名ハッシュのなかに 登録されています
  120. 120. $bl{HASH}{"Data::"}{HASH}{"Dump::"}{HASH}{"seen"} = { "16258dc" => ["k", []], "16258e8" => ["bl", ["*{HASH}"]], "1625900" => ["bl", []], "1625918" => ["al", []], } 変数名やリファレンスの ID は ハッシュのキーになっています
  121. 121. これまで見た変数は このようにも 書き換えられます
  122. 122. print ${foo}; # $foo print @{"bar"}; # @bar print ${ 'b' . 'az' }{foo}; # $baz{foo}
  123. 123. 文字列のなかに 変数を埋め込むときに便利なことも   $foo = "chars"; print "${foo}bar";
  124. 124. デリファレンスの 優先順位を明示したいときにも有効
  125. 125. 全部ひっくるめた 型グロブというものも あります   *{"foo"}
  126. 126. 昔はファイルハンドルの 受け渡しなどに 使っていました
  127. 127. いまはシンボルテーブルを いじるときにしか使いません
  128. 128. 型グロブは 「無冠詞」の変数も うまくさばいてくれます   open FOO, ‘file’; do_something(*FOO); # Perl 4 風
  129. 129. ゆるい世界では こんな書き方さえ できます
  130. 130. @array = (1, 2); print array->[0]; # 警告つき print *array->[0]; # 警告すらでません
  131. 131. 今日はあえて ゆるい世界の話に 終始しました   今日取り上げた例のいくつかは、 use strict; するとエラーになります
  132. 132. 後付けの説明なので 実際の歴史や実装とも ずれがあります
  133. 133. Perl 自体、当初の デザインからは さまざまな点で 変わってきています
  134. 134. そのすべてを覚えて いられる人は おそらくいません
  135. 135. 詳しいことを 知りたい人は perldoc.jp へ
  136. 136. perldata, perldsc, perlref, perlreftut, perlobj, perllol, perlsub, perlfaq4, perlfaq7
  137. 137. ご静聴ありがとう ございました

×