• Save
変数、リファレンス
Upcoming SlideShare
Loading in...5
×
 

変数、リファレンス

on

  • 3,383 views

Hokkaido.pm #4

Hokkaido.pm #4

Statistics

Views

Total Views
3,383
Views on SlideShare
1,953
Embed Views
1,430

Actions

Likes
1
Downloads
0
Comments
0

4 Embeds 1,430

http://hokkaido.pm.org 1327
http://d.hatena.ne.jp 96
http://localhost 4
http://s.deeeki.com 3

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

変数、リファレンス 変数、リファレンス Presentation Transcript

  • 変数、リファレンス 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[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_pens}; 必要なければ 省略してしまいましょう
  • [...] は無名配列の リファレンスです   (...) だと別の意味になるので要注意
  • ふつうの配列に したいときは 「冠詞」をつけて   @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", []], "16258e8" => ["bl", ["*{HASH}"]], "1625900" => ["bl", []], "1625918" => ["al", []], } 変数名やリファレンスの ID は ハッシュのキーになっています
  • これまで見た変数は このようにも 書き換えられます
  • 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
  • ご静聴ありがとう ございました