変数、リファレンス February 19, 2011 Hokkaido.pm #4 Kenichi Ishigaki (charsbar)
始める前に…
Perl の変数なんて 別にむずかしくないよね という方?
『言語設計者たちが考えること』
Larry がこんなことを 言っていました
「自然言語の原理を コンピュータ言語へと 組み込む最善の 方法を探求」
Perl はもともと C 、 sed 、 awk 、 sh の よいとこどりをした言語
英語っぽさを 感じることもあります
たとえば 英語の名詞
無冠詞 : pen 単数 : a pen 複数 : pens
無冠詞   (pen)   「~というもの」
そのままでは 数えられないもの   #  または数えないもの
辞書の見出し語   固有名詞 抽象名詞
Perl の場合
foo   裸のワード #  英数字と下線だけからなる単語
昔はよくこんな使い方を していたものです   open FOO, 'bar';
定数を定義するときにも よく使われています   use constant PI => 3.14; print PI * 2; # 6.28
具体的なものの 代入は不可   foo = 'bar'; #  エラー
具体的なものを 扱うにはどうするか
そのものが 単数か複数かで 変わります
単数の場合
英語では冠詞を つけるのでした   pen  ->  a pen
Perl の場合は 「 $ 」という記号を つけます   foo  ->  $foo
この記号は あくまでも 冠詞扱い   #  変数名の一部ではありません
だからこんな 書き方も可能です   $ foo = 1; print $ foo; # 1
真似しないで くださいね
どうして $ なのか
スカラー (scalar) の 頭文字   #  高校の物理で習いましたよね #  「矢印」がつかない値
複数の場合
英語では語形が 変わったり   a pen  ->  pens a man  ->  men
数をあらわす 形容詞句がついたり   two pens a lot of men
単複同型というのも ありました   単数 : a sheep 複数 : sheep
Perl の場合は @ という 記号をつけます   @foo = (1, 2, 3);
配列 (array) の 頭文字から perldata では「 these とか those 」
細かくいうと 配列とリストは別物
$foo と @foo の関係
名前は同じです
いっぺんに扱う 手段もあります
中身は別物です   a pen  ≠  pens
「複数」の性質
単数+単数=複数   @pens = ($red_pen, $blue_pen);
複数+複数=複数   @pens = (@red_pens, @blue_pens);
要素の個数は あまり気にしません   #  複数は複数です
配列の要素を 扱うときは for などで   foreach (@pens){ print $_ }   # $_ は英語の it と同じ単数の代名詞 #  中身については空気を読んで
コアレベルでは 省略できることも多い   foreach (@pens) { print } print for @pens;
他動詞だから目的語をとるはず、というのが 暗黙の了解
誤解を避けたければ 明示して   for $pen (@pens) { print $pen }
処理の順番は?
リストの場合は左から右 ということになっています   print for (1, 2, 3);
でも、左ってどこ?   print for @pens;
どこかにはあるはずです が、隠れています
 という記号をつけると 起点の位置を 取得できます   @pens;
具体的にどこにあるかは 気にしなくていいです
@ という具体的な 文脈をあらわす記号を 打ち消しているイメージ
起点がわかったら 向きと長さを指定すれば 個々の要素に アクセスできます   (@pens)->[0];
この起点のことを Perl の文脈では リファレンスと呼びます
「よく使われる表現は、 あまり使われない表現 よりも短くあるべき」 ( 『言語設計者たちが考えること』 )
ふだんはもう少し 楽をしたいですよね
ひと頃は こんな風にも 書けました   @pens->[0];
Perl 5.8 で 廃止されました   # 文脈がわかりづらくなるから #  複数のものから矢印 ?!
起点はひとつしか ありません
ということは 単数扱いに なるはずです
Perl 5 では スカラーとしても 扱えるようになりました   $pens_ref = @pens; $pens_ref->[0];
矢印が生えるのに !?
普通のスカラーとは 違います
中身を覗いて みましょう   perl -e "print @array"   # ARRAY(0x33e288)
ぐちゃぐちゃに ならないよう 内部的には別扱い されています
Devel::Peek を使うと 詳しく調べられます   perl -MDevel::Peek -e  "@a = (1, 2); print Dump(@a)" # Perl 5.6 以降はコアに入っています
むずかしいことは 忘れてください
矢印が生えていれば (たいていは) リファレンスです   $pens_ref->[0];
ref でも確認できます   ref $scalar_or_ref ? 'ref' : 'scalar';
誤解されそうな文脈では 名前を変えておきましょう   ○   $pens_ref = @pens; ×  $pens  = @pens;
これでだいぶきれいに 書けるようになりました
でも、もう少し 楽をしたいです
できるように なっています   @pens;  #  $pens_ref = @pens; $pens[0]; #  $pens_ref->[0];
$pens と $pens[0] と $pens->[0] は それぞれ文脈が 異なります
$pens は純然たるスカラー(たぶん)   $pens->[0] の $pens はリファレンス   $pens[0] は @pens の一要素
ベクトルの指す値は 矢印ひとつにつき ひとつのみです   $array_ref->[0]   #  返り値はひとつのはずです
配列にはスカラー (として扱えるもの) しか入れられない という制約が   $array_ref->[0] にわざわざ $ をつける必要はありません
配列にはスカラー (として扱えるもの) しか入れられない という制約が   $array_ref->[0] にわざわざ $ をつける必要はありません
配列から複数の値を 取り出したい場合も あります
ひとつひとつ列挙 してもかまいません   $first_pen  = $pens[0]; $second_pen = $pens[1];   #  冗長ですよね
一行にまとめてみました   ($first_pen, $second_pen) = ($pens[0], $pens[1]);
もう少し短くできます   ($first_pen, $second_pen) = pens; # 3 つめ以降の pen は無視されます
こんな書き方も できるのですが…   @two_pens = @pens[0, 1];  # @pens[0..1]
必要がなければ 避けた方が無難
意図とは異なる (かもしれない) 結果になるもの
1 本なのに 複数扱い !? ×  @pens[0];
ベクトルの行き先はひとつのみです ×  $pens_ref->[0, 1]
先にデリファレンスされて しまいますので… ×  @$pens_ref->[0, 1]
配列にしてからなら OK ○  @$pens_ref[0, 1]
便利に使える 場合もあります
複数の配列を含む配列の場合
赤だけ、青だけの 配列を区別できません   @pens = (@red_pens, @blue_pens); ×  (@red_pens, @blue_pens) = @pens;
配列に入れられるのは スカラー扱いできる値のみ     配列をそのまま配列に 入れることはできません
区別するには リファレンスを 使います   @pens = (@red_pens, @blue_pens);
矢印をたどっていけば 目的地につきます   ($red_pens_ref, $blue_pens_ref) = @pens; $red_pen  = $red_pens_ref->[0]; $blue_pen = $pens[1]->[0]; ...
配列のなかの リファレンスから 生える矢印はふつう省略できます
自動的にふられる 番号ではわかりづらい場合もあります   @pens = (@red_pens, @blue_pens);
青ペンの 1 本目 には見えません ! $pens[1][0];
要素が増減したら いちいち順番を直す必要があります
もっと明確に書きたいときは ハッシュという特殊な配列を使います   #  昔は連想配列と言っていました
ハッシュの場合は 届け先を明記します %pens = (   red_pens  => @red_pens,   blue_pens => @blue_pens, );
%  ->  c/o   ->  care of  「~様方」
使い方は ふつうの配列と よく似ています
%pens = (...); $pens{red_pens}; $ pens {blue_pens};
$pens_ref = %pens; $pens_ref->{red_pens}; $ pens_ref -> {blue_pens};
それぞれの要素に アクセスしたいとき   for (keys %hash){ print $hash{$_} } for (values %hash){ print $_ } while(($key, $value) = each %hash)...
%pens = (   red_pens  => @red_pens,   blue_pens => @blue_pens, ); ハッシュのなかの 配列に名前は必要?
%pens = (   red_pens  => ['mine', 'yours'], # @red_pens   blue_pens => ['his', 'hers'],  # @blue_pens ); $red_pens_ref = $...
[...] は無名配列の リファレンスです     (...) だと別の意味になるので要注意
ふつうの配列に したいときは 「冠詞」をつけて   @pens = @{['red_pen', 'blue_pen']};
もちろん 無名ハッシュへの リファレンスも つくれます   $pens_ref = { red_pens => 2, blue_pens => 3 }; %pens = %{{red_pen => 1, blue_pen => 2}};
どうして @{...} に なるのでしょう?
Perl にはシンボル テーブルと呼ばれる 特殊なハッシュが 用意されています
中身を覗いて みましょう perl -MDevel::Symdump –e  "print Devel::Symdump->rnew->as_string"
もう少し詳しく 見たいときはこちら   perl -MData::Dump=dump  -e "print dump(%::)"
グローバル変数 パッケージ 関数/メソッド
多くのものがこの 無名ハッシュのなかに 登録されています
$bl{HASH}{"Data::"}{HASH}{"Dump::"}{HASH}{"seen"} = {   "16258dc" => ["k&quot...
これまで見た変数は このようにも 書き換えられます
print ${foo};  # $foo print @{"bar"};  # @bar print ${ 'b' . 'az' }{foo}; # $baz{foo}
文字列のなかに 変数を埋め込むときに便利なことも     $foo = "chars"; print "${foo}bar";
デリファレンスの 優先順位を明示したいときにも有効
全部ひっくるめた 型グロブというものも あります   *{"foo"}
昔はファイルハンドルの 受け渡しなどに 使っていました
いまはシンボルテーブルを いじるときにしか使いません
型グロブは 「無冠詞」の変数も うまくさばいてくれます   open FOO, ‘file’; do_something(*FOO);  # Perl 4 風
ゆるい世界では こんな書き方さえ できます
@array = (1, 2); print  array->[0]; #  警告つき print *array->[0]; #  警告すらでません
今日はあえて ゆるい世界の話に 終始しました   今日取り上げた例のいくつかは、 use strict; するとエラーになります
後付けの説明なので 実際の歴史や実装とも ずれがあります
Perl 自体、当初の デザインからは さまざまな点で 変わってきています
そのすべてを覚えて いられる人は おそらくいません
詳しいことを 知りたい人は perldoc.jp へ
perldata, perldsc, perlref, perlreftut, perlobj, perllol, perlsub, perlfaq4, perlfaq7
Upcoming SlideShare
Loading in...5
×

変数、リファレンス

3,281

Published on

Hokkaido.pm #4

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,281
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

変数、リファレンス

  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. ご静聴ありがとう ございました

×