Perlの勘所をマスターしよう! コンテキストとリファレンスを我が物に!

Post on 11-May-2015

7.086 views 3 download

description

YAPC::Asia 2012で行なったトークのスライドです(2012/9/29)

Transcript of Perlの勘所をマスターしよう! コンテキストとリファレンスを我が物に!

.

......

Perlの勘所をマスターしよう!コンテキストとリファレンスを我が物に!

近藤嘉雪

@yoshiyuki kondo

YAPC::Asia 2012 (2012/9/29)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 1 / 57

自己紹介

近藤嘉雪 (こんどうよしゆき)

Twitter: @yoshiyuki_kondoホームページ

http://www.kondoyoshiyuki.com/訳書

「プログラミング Perl」「初めての Perl」

著書「定本Cプログラマのためのアルゴリズムとデータ構造」「定本 Javaプログラマのためのアルゴリズムとデータ構造」

ヤフー株式会社で働いています

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 2 / 57

自己紹介

近藤嘉雪 (こんどうよしゆき)Twitter: @yoshiyuki_kondo

ホームページhttp://www.kondoyoshiyuki.com/

訳書「プログラミング Perl」「初めての Perl」

著書「定本Cプログラマのためのアルゴリズムとデータ構造」「定本 Javaプログラマのためのアルゴリズムとデータ構造」

ヤフー株式会社で働いています

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 2 / 57

自己紹介

近藤嘉雪 (こんどうよしゆき)Twitter: @yoshiyuki_kondoホームページ

http://www.kondoyoshiyuki.com/

訳書「プログラミング Perl」「初めての Perl」

著書「定本Cプログラマのためのアルゴリズムとデータ構造」「定本 Javaプログラマのためのアルゴリズムとデータ構造」

ヤフー株式会社で働いています

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 2 / 57

自己紹介

近藤嘉雪 (こんどうよしゆき)Twitter: @yoshiyuki_kondoホームページ

http://www.kondoyoshiyuki.com/訳書

「プログラミング Perl」「初めての Perl」

著書「定本Cプログラマのためのアルゴリズムとデータ構造」「定本 Javaプログラマのためのアルゴリズムとデータ構造」

ヤフー株式会社で働いています

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 2 / 57

自己紹介

近藤嘉雪 (こんどうよしゆき)Twitter: @yoshiyuki_kondoホームページ

http://www.kondoyoshiyuki.com/訳書

「プログラミング Perl」「初めての Perl」

著書「定本Cプログラマのためのアルゴリズムとデータ構造」「定本 Javaプログラマのためのアルゴリズムとデータ構造」

ヤフー株式会社で働いています

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 2 / 57

自己紹介

近藤嘉雪 (こんどうよしゆき)Twitter: @yoshiyuki_kondoホームページ

http://www.kondoyoshiyuki.com/訳書

「プログラミング Perl」「初めての Perl」

著書「定本Cプログラマのためのアルゴリズムとデータ構造」「定本 Javaプログラマのためのアルゴリズムとデータ構造」

ヤフー株式会社で働いています近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 2 / 57

好きなもの:

エディタ:Emacs

日本語入力方式:

T-Code (2ストローク直接入力)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 3 / 57

好きなもの:

エディタ:

Emacs日本語入力方式:

T-Code (2ストローク直接入力)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 3 / 57

好きなもの:

エディタ:Emacs

日本語入力方式:

T-Code (2ストローク直接入力)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 3 / 57

好きなもの:

エディタ:Emacs

日本語入力方式:

T-Code (2ストローク直接入力)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 3 / 57

好きなもの:

エディタ:Emacs

日本語入力方式:

T-Code (2ストローク直接入力)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 3 / 57

本日お話する内容

コンテキストリファレンス以上

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 4 / 57

本日お話する内容

コンテキスト

リファレンス以上

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 4 / 57

本日お話する内容

コンテキストリファレンス

以上

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 4 / 57

本日お話する内容

コンテキストリファレンス以上

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 4 / 57

コンテキストの話

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 5 / 57

コンテキストとは?

式を評価する際に、スカラー値とリスト値のどちらを期待しているか、ということ

スカラーコンテキストはスカラー値を期待リストコンテキストはリスト値を期待「スカラー変数への代入は、スカラーコンテキストを与える」などと言う操作、演算子、関数の中には、コンテキストに応じて違う値を返すものがある

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 6 / 57

コンテキストとは?

式を評価する際に、スカラー値とリスト値のどちらを期待しているか、ということスカラーコンテキストはスカラー値を期待

リストコンテキストはリスト値を期待「スカラー変数への代入は、スカラーコンテキストを与える」などと言う操作、演算子、関数の中には、コンテキストに応じて違う値を返すものがある

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 6 / 57

コンテキストとは?

式を評価する際に、スカラー値とリスト値のどちらを期待しているか、ということスカラーコンテキストはスカラー値を期待リストコンテキストはリスト値を期待

「スカラー変数への代入は、スカラーコンテキストを与える」などと言う操作、演算子、関数の中には、コンテキストに応じて違う値を返すものがある

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 6 / 57

コンテキストとは?

式を評価する際に、スカラー値とリスト値のどちらを期待しているか、ということスカラーコンテキストはスカラー値を期待リストコンテキストはリスト値を期待「スカラー変数への代入は、スカラーコンテキストを与える」などと言う

操作、演算子、関数の中には、コンテキストに応じて違う値を返すものがある

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 6 / 57

コンテキストとは?

式を評価する際に、スカラー値とリスト値のどちらを期待しているか、ということスカラーコンテキストはスカラー値を期待リストコンテキストはリスト値を期待「スカラー変数への代入は、スカラーコンテキストを与える」などと言う操作、演算子、関数の中には、コンテキストに応じて違う値を返すものがある

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 6 / 57

ほかのコンテキスト (1)

無効コンテキスト (void context)

値を必要としない場所use warnings;

my $a = 100;

$a + 20;

Useless use of addition (+) in void context at - line 3.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 7 / 57

ほかのコンテキスト (1)

無効コンテキスト (void context)値を必要としない場所

use warnings;

my $a = 100;

$a + 20;

Useless use of addition (+) in void context at - line 3.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 7 / 57

ほかのコンテキスト (1)

無効コンテキスト (void context)値を必要としない場所use warnings;

my $a = 100;

$a + 20;

Useless use of addition (+) in void context at - line 3.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 7 / 57

ほかのコンテキスト (2)

スカラーコンテキストはさらに分類される

文字列コンテキスト (string context).演算子、xの左側、ne、ltなど

数値コンテキスト (numeric context)+, -, *, /など

不定コンテキスト (don’t care context)どっちでもいいよ

ブール値コンテキスト (boolean context)不定コンテキストの一種条件式

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 8 / 57

ほかのコンテキスト (2)

スカラーコンテキストはさらに分類される文字列コンテキスト (string context)

.演算子、xの左側、ne、ltなど

数値コンテキスト (numeric context)+, -, *, /など

不定コンテキスト (don’t care context)どっちでもいいよ

ブール値コンテキスト (boolean context)不定コンテキストの一種条件式

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 8 / 57

ほかのコンテキスト (2)

スカラーコンテキストはさらに分類される文字列コンテキスト (string context)

.演算子、xの左側、ne、ltなど数値コンテキスト (numeric context)

+, -, *, /など

不定コンテキスト (don’t care context)どっちでもいいよ

ブール値コンテキスト (boolean context)不定コンテキストの一種条件式

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 8 / 57

ほかのコンテキスト (2)

スカラーコンテキストはさらに分類される文字列コンテキスト (string context)

.演算子、xの左側、ne、ltなど数値コンテキスト (numeric context)

+, -, *, /など不定コンテキスト (don’t care context)

どっちでもいいよ

ブール値コンテキスト (boolean context)不定コンテキストの一種条件式

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 8 / 57

ほかのコンテキスト (2)

スカラーコンテキストはさらに分類される文字列コンテキスト (string context)

.演算子、xの左側、ne、ltなど数値コンテキスト (numeric context)

+, -, *, /など不定コンテキスト (don’t care context)

どっちでもいいよブール値コンテキスト (boolean context)

不定コンテキストの一種条件式

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 8 / 57

リストコンテキストを与える場所 (1)

配列変数、ハッシュ変数、リスト、スライスへの代入の右辺$x = func(); # スカラーコンテキスト@a = func(); # リストコンテキスト%h = func(); # リストコンテキスト($x, $y) = func(); # リストコンテキスト($x) = func(); # 要素が1個でもリストコンテキストになる!!!@a[0,1,2] = func(); # リストコンテキスト

組み込み関数(複数のパラメータを受け取るもの、例えば print)への引数

詳しくは次の次のページで

ユーザ定義のサブルーチンへの引数foreachの ()の内側スライスの添え字

@array[LIST], @hash{LIST}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 9 / 57

リストコンテキストを与える場所 (1)

配列変数、ハッシュ変数、リスト、スライスへの代入の右辺$x = func(); # スカラーコンテキスト@a = func(); # リストコンテキスト%h = func(); # リストコンテキスト($x, $y) = func(); # リストコンテキスト($x) = func(); # 要素が1個でもリストコンテキストになる!!!@a[0,1,2] = func(); # リストコンテキスト

組み込み関数(複数のパラメータを受け取るもの、例えば print)への引数

詳しくは次の次のページで

ユーザ定義のサブルーチンへの引数foreachの ()の内側スライスの添え字

@array[LIST], @hash{LIST}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 9 / 57

リストコンテキストを与える場所 (1)

配列変数、ハッシュ変数、リスト、スライスへの代入の右辺$x = func(); # スカラーコンテキスト@a = func(); # リストコンテキスト%h = func(); # リストコンテキスト($x, $y) = func(); # リストコンテキスト($x) = func(); # 要素が1個でもリストコンテキストになる!!!@a[0,1,2] = func(); # リストコンテキスト

組み込み関数(複数のパラメータを受け取るもの、例えば print)への引数

詳しくは次の次のページで

ユーザ定義のサブルーチンへの引数foreachの ()の内側スライスの添え字

@array[LIST], @hash{LIST}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 9 / 57

リストコンテキストを与える場所 (1)

配列変数、ハッシュ変数、リスト、スライスへの代入の右辺$x = func(); # スカラーコンテキスト@a = func(); # リストコンテキスト%h = func(); # リストコンテキスト($x, $y) = func(); # リストコンテキスト($x) = func(); # 要素が1個でもリストコンテキストになる!!!@a[0,1,2] = func(); # リストコンテキスト

組み込み関数(複数のパラメータを受け取るもの、例えば print)への引数

詳しくは次の次のページで

ユーザ定義のサブルーチンへの引数

foreachの ()の内側スライスの添え字

@array[LIST], @hash{LIST}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 9 / 57

リストコンテキストを与える場所 (1)

配列変数、ハッシュ変数、リスト、スライスへの代入の右辺$x = func(); # スカラーコンテキスト@a = func(); # リストコンテキスト%h = func(); # リストコンテキスト($x, $y) = func(); # リストコンテキスト($x) = func(); # 要素が1個でもリストコンテキストになる!!!@a[0,1,2] = func(); # リストコンテキスト

組み込み関数(複数のパラメータを受け取るもの、例えば print)への引数

詳しくは次の次のページで

ユーザ定義のサブルーチンへの引数foreachの ()の内側

スライスの添え字@array[LIST], @hash{LIST}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 9 / 57

リストコンテキストを与える場所 (1)

配列変数、ハッシュ変数、リスト、スライスへの代入の右辺$x = func(); # スカラーコンテキスト@a = func(); # リストコンテキスト%h = func(); # リストコンテキスト($x, $y) = func(); # リストコンテキスト($x) = func(); # 要素が1個でもリストコンテキストになる!!!@a[0,1,2] = func(); # リストコンテキスト

組み込み関数(複数のパラメータを受け取るもの、例えば print)への引数

詳しくは次の次のページで

ユーザ定義のサブルーチンへの引数foreachの ()の内側スライスの添え字

@array[LIST], @hash{LIST}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 9 / 57

リストコンテキストを与える場所 (2)

リストコンテキスト以外の場所はスカラーコンテキストとなるscalar関数によって、強制的にスカラーコンテキストを適用できるmyや our宣言は、コンテキストに影響を与えないmy $x = func(); # スカラーコンテキストmy ($x, $y) = func(); # リストコンテキストmy (@a) = func(); # リストコンテキスト

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 10 / 57

リストコンテキストを与える場所 (2)

リストコンテキスト以外の場所はスカラーコンテキストとなる

scalar関数によって、強制的にスカラーコンテキストを適用できるmyや our宣言は、コンテキストに影響を与えないmy $x = func(); # スカラーコンテキストmy ($x, $y) = func(); # リストコンテキストmy (@a) = func(); # リストコンテキスト

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 10 / 57

リストコンテキストを与える場所 (2)

リストコンテキスト以外の場所はスカラーコンテキストとなるscalar関数によって、強制的にスカラーコンテキストを適用できる

myや our宣言は、コンテキストに影響を与えないmy $x = func(); # スカラーコンテキストmy ($x, $y) = func(); # リストコンテキストmy (@a) = func(); # リストコンテキスト

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 10 / 57

リストコンテキストを与える場所 (2)

リストコンテキスト以外の場所はスカラーコンテキストとなるscalar関数によって、強制的にスカラーコンテキストを適用できるmyや our宣言は、コンテキストに影響を与えないmy $x = func(); # スカラーコンテキストmy ($x, $y) = func(); # リストコンテキストmy (@a) = func(); # リストコンテキスト

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 10 / 57

リストコンテキストを与える場所 (3)

Perl関連のドキュメントで LISTと書いてあるところ。

perlのマニュアルページ、ラクダ本man perlfunc, man perlop

特定の関数のマニュアルを表示するperldoc -f printfprintf FILEHANDLE FORMAT, LIST

printf FILEHANDLE

printf FORMAT, LIST

printf

Equivalent to "print FILEHANDLE sprintf(FORMAT, LIST)", except that

perldoc.jpに日本語訳があります

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 11 / 57

リストコンテキストを与える場所 (3)

Perl関連のドキュメントで LISTと書いてあるところ。

perlのマニュアルページ、ラクダ本man perlfunc, man perlop

特定の関数のマニュアルを表示するperldoc -f printfprintf FILEHANDLE FORMAT, LIST

printf FILEHANDLE

printf FORMAT, LIST

printf

Equivalent to "print FILEHANDLE sprintf(FORMAT, LIST)", except that

perldoc.jpに日本語訳があります

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 11 / 57

リストコンテキストを与える場所 (3)

Perl関連のドキュメントで LISTと書いてあるところ。

perlのマニュアルページ、ラクダ本man perlfunc, man perlop

特定の関数のマニュアルを表示するperldoc -f printfprintf FILEHANDLE FORMAT, LIST

printf FILEHANDLE

printf FORMAT, LIST

printf

Equivalent to "print FILEHANDLE sprintf(FORMAT, LIST)", except that

perldoc.jpに日本語訳があります

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 11 / 57

コンテキストによって異なる値を返すもの:配列変数名

配列変数名

リストコンテキストでは、配列の要素から成るリスト値を返すスカラーコンテキストでは、配列の要素の個数を返す# リストコンテキスト  @bの内容が@aにコピーされる@a = @b;

# スカラーコンテキスト @bの要素の個数が$nに入る$n = @b;

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 12 / 57

コンテキストによって異なる値を返すもの:配列変数名

配列変数名リストコンテキストでは、配列の要素から成るリスト値を返す

スカラーコンテキストでは、配列の要素の個数を返す# リストコンテキスト  @bの内容が@aにコピーされる@a = @b;

# スカラーコンテキスト @bの要素の個数が$nに入る$n = @b;

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 12 / 57

コンテキストによって異なる値を返すもの:配列変数名

配列変数名リストコンテキストでは、配列の要素から成るリスト値を返すスカラーコンテキストでは、配列の要素の個数を返す

# リストコンテキスト  @bの内容が@aにコピーされる@a = @b;

# スカラーコンテキスト @bの要素の個数が$nに入る$n = @b;

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 12 / 57

コンテキストによって異なる値を返すもの:配列変数名

配列変数名リストコンテキストでは、配列の要素から成るリスト値を返すスカラーコンテキストでは、配列の要素の個数を返す# リストコンテキスト  @bの内容が@aにコピーされる@a = @b;

# スカラーコンテキスト @bの要素の個数が$nに入る$n = @b;

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 12 / 57

配列名とコンテキストの落とし穴

サブルーチン、組込関数の引数リストは、リストコンテキストで評価される@array = qw(foo bar zot);

my $n = @array; # $nは 3になるprint "Array has ", @array, "elements\n"; # ダメ

scalar疑似関数を使えば、リストコンテキストの中で、引数をスカラーコンテキストで評価できる。print "Array has ", @array, "elements\n"; # ダメ

print "Array has ", scalar @array, "elements\n"; # OK

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 13 / 57

配列名とコンテキストの落とし穴

サブルーチン、組込関数の引数リストは、リストコンテキストで評価される@array = qw(foo bar zot);

my $n = @array; # $nは 3になるprint "Array has ", @array, "elements\n"; # ダメ

scalar疑似関数を使えば、リストコンテキストの中で、引数をスカラーコンテキストで評価できる。print "Array has ", @array, "elements\n"; # ダメ

print "Array has ", scalar @array, "elements\n"; # OK

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 13 / 57

リストからスカラー変数への代入にご用心

リストと配列の違いに注意a=one two threeと表示される@a = (’one’, ’two’, ’three’);

print "a=@a\n";

x=threeと表示される!! oneではない!!これはカンマ演算子と解釈されるため$x = (’one’, ’two’, ’three’);

print "x=$x\n"; #

要素の個数 3が得られる$y = @a;

print "y=$y\n"; # y=3

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 14 / 57

リストからスカラー変数への代入にご用心

リストと配列の違いに注意a=one two threeと表示される@a = (’one’, ’two’, ’three’);

print "a=@a\n";

x=threeと表示される!! oneではない!!これはカンマ演算子と解釈されるため$x = (’one’, ’two’, ’three’);

print "x=$x\n"; #

要素の個数 3が得られる$y = @a;

print "y=$y\n"; # y=3

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 14 / 57

リストからスカラー変数への代入にご用心

リストと配列の違いに注意a=one two threeと表示される@a = (’one’, ’two’, ’three’);

print "a=@a\n";

x=threeと表示される!! oneではない!!これはカンマ演算子と解釈されるため$x = (’one’, ’two’, ’three’);

print "x=$x\n"; #

要素の個数 3が得られる$y = @a;

print "y=$y\n"; # y=3

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 14 / 57

コンテキストによって異なる値を返すもの:入力演算子 <>

入力演算子 <>

スカラーコンテキストでは、次の1行を返す$line = <INPUT>;

リストコンテキストでは、残りのすべての行を読んでリストにして返す@date = <INPUT>;

次の1行を読み込んで表示するにはprint <INPUT>; # ダメprint scalar(<INPUT>); # OK

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 15 / 57

コンテキストによって異なる値を返すもの:入力演算子 <>

入力演算子 <>スカラーコンテキストでは、次の1行を返す$line = <INPUT>;

リストコンテキストでは、残りのすべての行を読んでリストにして返す@date = <INPUT>;

次の1行を読み込んで表示するにはprint <INPUT>; # ダメprint scalar(<INPUT>); # OK

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 15 / 57

コンテキストによって異なる値を返すもの:入力演算子 <>

入力演算子 <>スカラーコンテキストでは、次の1行を返す$line = <INPUT>;

リストコンテキストでは、残りのすべての行を読んでリストにして返す@date = <INPUT>;

次の1行を読み込んで表示するにはprint <INPUT>; # ダメprint scalar(<INPUT>); # OK

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 15 / 57

コンテキストによって異なる値を返すもの:入力演算子 <>

入力演算子 <>スカラーコンテキストでは、次の1行を返す$line = <INPUT>;

リストコンテキストでは、残りのすべての行を読んでリストにして返す@date = <INPUT>;

次の1行を読み込んで表示するにはprint <INPUT>; # ダメprint scalar(<INPUT>); # OK

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 15 / 57

ここで注意!

リスト値を返す関数を、スカラーコンテキストで評価すると、返すリストの個数を返す *わけではない*ので注意。

答えは、それぞれ関数によって、スカラーコンテキストで筋が通った (と考える)値を返す。

これについては、この後すぐに…

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 16 / 57

ここで注意!

リスト値を返す関数を、スカラーコンテキストで評価すると、返すリストの個数を返す *わけではない*ので注意。答えは、それぞれ関数によって、スカラーコンテキストで筋が通った (と考える)値を返す。

これについては、この後すぐに…

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 16 / 57

コンテキストによって動作が変わる関数 (1)

コンテキストによって、違う値を返す組み込み関数は、マニュアルにそのように明記されている。「perldoc -f関数名」で組み込み関数のマニュアルが表示されます。

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 17 / 57

getpwnam関数

ユーザ名を受け取り、そのユーザに関する情報を返す

リストコンテキストでは、/etc/passwdの情報をリスト値で返す($name,$passwd,$uid,$gid,$quota,$comment,

$gcos,$dir,$shell,$expire) = getpwnam

スカラーコンテキストでは、UIDを返す

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 18 / 57

getpwnam関数

ユーザ名を受け取り、そのユーザに関する情報を返すリストコンテキストでは、/etc/passwdの情報をリスト値で返す($name,$passwd,$uid,$gid,$quota,$comment,

$gcos,$dir,$shell,$expire) = getpwnam

スカラーコンテキストでは、UIDを返す

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 18 / 57

getpwnam関数

ユーザ名を受け取り、そのユーザに関する情報を返すリストコンテキストでは、/etc/passwdの情報をリスト値で返す($name,$passwd,$uid,$gid,$quota,$comment,

$gcos,$dir,$shell,$expire) = getpwnam

スカラーコンテキストでは、UIDを返す

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 18 / 57

localtime関数

いわゆるUnix time値を、年月日時分秒に変換して返す

リストコンテキストでは、9要素のリスト値を返す# 0 1 2 3 4 5 6 7 8

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)

スカラーコンテキストでは、日時を表わす文字列を返す$ perl -le ’print scalar(localtime)’

Sat Sep 29 05:49:52 2012

scalarを入れないと$ perl -le ’print localtime’

4650529811262720

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 19 / 57

localtime関数

いわゆるUnix time値を、年月日時分秒に変換して返すリストコンテキストでは、9要素のリスト値を返す# 0 1 2 3 4 5 6 7 8

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)

スカラーコンテキストでは、日時を表わす文字列を返す$ perl -le ’print scalar(localtime)’

Sat Sep 29 05:49:52 2012

scalarを入れないと$ perl -le ’print localtime’

4650529811262720

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 19 / 57

localtime関数

いわゆるUnix time値を、年月日時分秒に変換して返すリストコンテキストでは、9要素のリスト値を返す# 0 1 2 3 4 5 6 7 8

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)

スカラーコンテキストでは、日時を表わす文字列を返す$ perl -le ’print scalar(localtime)’

Sat Sep 29 05:49:52 2012

scalarを入れないと$ perl -le ’print localtime’

4650529811262720

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 19 / 57

localtime関数

いわゆるUnix time値を、年月日時分秒に変換して返すリストコンテキストでは、9要素のリスト値を返す# 0 1 2 3 4 5 6 7 8

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)

スカラーコンテキストでは、日時を表わす文字列を返す$ perl -le ’print scalar(localtime)’

Sat Sep 29 05:49:52 2012

scalarを入れないと$ perl -le ’print localtime’

4650529811262720

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 19 / 57

reverse関数

リストコンテキストでは、渡されたリストを逆順にしたリストを返す

Q:スカラーコンテキストでは何を返す?A:引数を文字列として連結して、その文字列を逆順にした文字列を返す

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 20 / 57

reverse関数

リストコンテキストでは、渡されたリストを逆順にしたリストを返すQ:スカラーコンテキストでは何を返す?

A:引数を文字列として連結して、その文字列を逆順にした文字列を返す

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 20 / 57

reverse関数

リストコンテキストでは、渡されたリストを逆順にしたリストを返すQ:スカラーコンテキストでは何を返す?A:引数を文字列として連結して、その文字列を逆順にした文字列を返す

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 20 / 57

reverse関数をスカラーコンテキストで評価すると

引数を文字列として連結して、その文字列を逆順にした文字列を返す

my @array = qw(one two three);

my @list = reverse(@array);

print "@list\n"; # three two one

print scalar(reverse(@array)), "\n"; # eerhtowteno

my $reversed = reverse("hello");

print $reversed, "\n"; # olleh

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 21 / 57

reverse関数をスカラーコンテキストで評価すると

引数を文字列として連結して、その文字列を逆順にした文字列を返すmy @array = qw(one two three);

my @list = reverse(@array);

print "@list\n"; # three two one

print scalar(reverse(@array)), "\n"; # eerhtowteno

my $reversed = reverse("hello");

print $reversed, "\n"; # olleh

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 21 / 57

reverse関数をスカラーコンテキストで評価すると

引数を文字列として連結して、その文字列を逆順にした文字列を返すmy @array = qw(one two three);

my @list = reverse(@array);

print "@list\n"; # three two one

print scalar(reverse(@array)), "\n"; # eerhtowteno

my $reversed = reverse("hello");

print $reversed, "\n"; # olleh

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 21 / 57

reverse関数をスカラーコンテキストで評価すると

引数を文字列として連結して、その文字列を逆順にした文字列を返すmy @array = qw(one two three);

my @list = reverse(@array);

print "@list\n"; # three two one

print scalar(reverse(@array)), "\n"; # eerhtowteno

my $reversed = reverse("hello");

print $reversed, "\n"; # olleh

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 21 / 57

番外: chomp演算子

文字列の末尾に改行文字があればそれを削除する

引数には、左辺値 (スカラー変数や配列要素)を渡すリストを渡すと、すべての要素から、末尾の改行文字を取り除く配列を渡すと、一括して chompできるmy @lines = <>;

chomp(@lines);

イディオムとして次のように書くchomp(my @lines = <>);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 22 / 57

番外: chomp演算子

文字列の末尾に改行文字があればそれを削除する引数には、左辺値 (スカラー変数や配列要素)を渡す

リストを渡すと、すべての要素から、末尾の改行文字を取り除く配列を渡すと、一括して chompできるmy @lines = <>;

chomp(@lines);

イディオムとして次のように書くchomp(my @lines = <>);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 22 / 57

番外: chomp演算子

文字列の末尾に改行文字があればそれを削除する引数には、左辺値 (スカラー変数や配列要素)を渡すリストを渡すと、すべての要素から、末尾の改行文字を取り除く

配列を渡すと、一括して chompできるmy @lines = <>;

chomp(@lines);

イディオムとして次のように書くchomp(my @lines = <>);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 22 / 57

番外: chomp演算子

文字列の末尾に改行文字があればそれを削除する引数には、左辺値 (スカラー変数や配列要素)を渡すリストを渡すと、すべての要素から、末尾の改行文字を取り除く配列を渡すと、一括して chompできるmy @lines = <>;

chomp(@lines);

イディオムとして次のように書くchomp(my @lines = <>);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 22 / 57

番外: chomp演算子

文字列の末尾に改行文字があればそれを削除する引数には、左辺値 (スカラー変数や配列要素)を渡すリストを渡すと、すべての要素から、末尾の改行文字を取り除く配列を渡すと、一括して chompできるmy @lines = <>;

chomp(@lines);

イディオムとして次のように書くchomp(my @lines = <>);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 22 / 57

コンテキストに応じてサブルーチンの動作を変える

サブルーチンの中でwantarray関数を呼び出すと、コンテキストを識別できる

リストコンテキストなら真スカラーコンテキストなら偽

wantarrayの返り値によって、戻り値を変えるsub mysub {

my @ans; # 処理の結果がここに入る

# コンテキストに応じて返す値を変えるreturn wantarray ? @ans : "@ans";

}

This function should have been named wantlist() instead.

「本当はwantlist()という名前にすべきだったんだけどね、てへぺろ」

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 23 / 57

コンテキストに応じてサブルーチンの動作を変える

サブルーチンの中でwantarray関数を呼び出すと、コンテキストを識別できる

リストコンテキストなら真スカラーコンテキストなら偽

wantarrayの返り値によって、戻り値を変えるsub mysub {

my @ans; # 処理の結果がここに入る

# コンテキストに応じて返す値を変えるreturn wantarray ? @ans : "@ans";

}

This function should have been named wantlist() instead.

「本当はwantlist()という名前にすべきだったんだけどね、てへぺろ」

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 23 / 57

コンテキストに応じてサブルーチンの動作を変える

サブルーチンの中でwantarray関数を呼び出すと、コンテキストを識別できる

リストコンテキストなら真スカラーコンテキストなら偽

wantarrayの返り値によって、戻り値を変えるsub mysub {

my @ans; # 処理の結果がここに入る

# コンテキストに応じて返す値を変えるreturn wantarray ? @ans : "@ans";

}

This function should have been named wantlist() instead.

「本当はwantlist()という名前にすべきだったんだけどね、てへぺろ」

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 23 / 57

コンテキストに応じてサブルーチンの動作を変える

サブルーチンの中でwantarray関数を呼び出すと、コンテキストを識別できる

リストコンテキストなら真スカラーコンテキストなら偽

wantarrayの返り値によって、戻り値を変えるsub mysub {

my @ans; # 処理の結果がここに入る

# コンテキストに応じて返す値を変えるreturn wantarray ? @ans : "@ans";

}

This function should have been named wantlist() instead.

「本当はwantlist()という名前にすべきだったんだけどね、てへぺろ」

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 23 / 57

コンテキストに応じてサブルーチンの動作を変える

サブルーチンの中でwantarray関数を呼び出すと、コンテキストを識別できる

リストコンテキストなら真スカラーコンテキストなら偽

wantarrayの返り値によって、戻り値を変えるsub mysub {

my @ans; # 処理の結果がここに入る

# コンテキストに応じて返す値を変えるreturn wantarray ? @ans : "@ans";

}

This function should have been named wantlist() instead.

「本当はwantlist()という名前にすべきだったんだけどね、てへぺろ」

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 23 / 57

//演算子とコンテキスト (1)

スカラーコンテキストでは、マッチしたか否かを示す。

$_ = "apple=10";

if (/ˆ(.+)=(\d+)$/) {

print "key=[$1] value=[$2]\n"; # key=[apple] value=[10]

} else {

# マッチしなかった}

リストコンテスキストでは、カッコでキャプチャした文字列のリストを返す。

マッチしたが、カッコにマッチしない場合には、(1)を返す$_ = "apple=10";

my @a = /ˆ(.+)=(\d+)$/;

if (@a) {

print "@a\n"; # apple 10

} else {

# マッチしなかった}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 24 / 57

//演算子とコンテキスト (1)

スカラーコンテキストでは、マッチしたか否かを示す。$_ = "apple=10";

if (/ˆ(.+)=(\d+)$/) {

print "key=[$1] value=[$2]\n"; # key=[apple] value=[10]

} else {

# マッチしなかった}

リストコンテスキストでは、カッコでキャプチャした文字列のリストを返す。

マッチしたが、カッコにマッチしない場合には、(1)を返す$_ = "apple=10";

my @a = /ˆ(.+)=(\d+)$/;

if (@a) {

print "@a\n"; # apple 10

} else {

# マッチしなかった}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 24 / 57

//演算子とコンテキスト (1)

スカラーコンテキストでは、マッチしたか否かを示す。$_ = "apple=10";

if (/ˆ(.+)=(\d+)$/) {

print "key=[$1] value=[$2]\n"; # key=[apple] value=[10]

} else {

# マッチしなかった}

リストコンテスキストでは、カッコでキャプチャした文字列のリストを返す。

マッチしたが、カッコにマッチしない場合には、(1)を返す

$_ = "apple=10";

my @a = /ˆ(.+)=(\d+)$/;

if (@a) {

print "@a\n"; # apple 10

} else {

# マッチしなかった}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 24 / 57

//演算子とコンテキスト (1)

スカラーコンテキストでは、マッチしたか否かを示す。$_ = "apple=10";

if (/ˆ(.+)=(\d+)$/) {

print "key=[$1] value=[$2]\n"; # key=[apple] value=[10]

} else {

# マッチしなかった}

リストコンテスキストでは、カッコでキャプチャした文字列のリストを返す。

マッチしたが、カッコにマッチしない場合には、(1)を返す$_ = "apple=10";

my @a = /ˆ(.+)=(\d+)$/;

if (@a) {

print "@a\n"; # apple 10

} else {

# マッチしなかった}近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 24 / 57

//演算子とコンテキスト (2)

マッチの結果を、スカラー変数のリストに代入する

$_ = "apple=10";

my ($key, $val) = /ˆ(.+)=(\d+)$/;

print "key=[$key] value=[$val]\n"; # key=[apple] value=[10]

さらに、それを if文の条件式にする$_ = "apple=10";

if (my ($key, $val) = /ˆ(.+)=(\d+)$/) {

print "key=[$key] value=[$val]\n";

} else {

# マッチしなかった}

リスト代入をスカラーコンテキストで評価すると、代入された要素の個数が得られるif文以外の条件式としても同じことができる

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 25 / 57

//演算子とコンテキスト (2)

マッチの結果を、スカラー変数のリストに代入する$_ = "apple=10";

my ($key, $val) = /ˆ(.+)=(\d+)$/;

print "key=[$key] value=[$val]\n"; # key=[apple] value=[10]

さらに、それを if文の条件式にする$_ = "apple=10";

if (my ($key, $val) = /ˆ(.+)=(\d+)$/) {

print "key=[$key] value=[$val]\n";

} else {

# マッチしなかった}

リスト代入をスカラーコンテキストで評価すると、代入された要素の個数が得られるif文以外の条件式としても同じことができる

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 25 / 57

//演算子とコンテキスト (2)

マッチの結果を、スカラー変数のリストに代入する$_ = "apple=10";

my ($key, $val) = /ˆ(.+)=(\d+)$/;

print "key=[$key] value=[$val]\n"; # key=[apple] value=[10]

さらに、それを if文の条件式にする

$_ = "apple=10";

if (my ($key, $val) = /ˆ(.+)=(\d+)$/) {

print "key=[$key] value=[$val]\n";

} else {

# マッチしなかった}

リスト代入をスカラーコンテキストで評価すると、代入された要素の個数が得られるif文以外の条件式としても同じことができる

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 25 / 57

//演算子とコンテキスト (2)

マッチの結果を、スカラー変数のリストに代入する$_ = "apple=10";

my ($key, $val) = /ˆ(.+)=(\d+)$/;

print "key=[$key] value=[$val]\n"; # key=[apple] value=[10]

さらに、それを if文の条件式にする$_ = "apple=10";

if (my ($key, $val) = /ˆ(.+)=(\d+)$/) {

print "key=[$key] value=[$val]\n";

} else {

# マッチしなかった}

リスト代入をスカラーコンテキストで評価すると、代入された要素の個数が得られるif文以外の条件式としても同じことができる

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 25 / 57

//演算子とコンテキスト (2)

マッチの結果を、スカラー変数のリストに代入する$_ = "apple=10";

my ($key, $val) = /ˆ(.+)=(\d+)$/;

print "key=[$key] value=[$val]\n"; # key=[apple] value=[10]

さらに、それを if文の条件式にする$_ = "apple=10";

if (my ($key, $val) = /ˆ(.+)=(\d+)$/) {

print "key=[$key] value=[$val]\n";

} else {

# マッチしなかった}

リスト代入をスカラーコンテキストで評価すると、代入された要素の個数が得られる

if文以外の条件式としても同じことができる

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 25 / 57

//演算子とコンテキスト (2)

マッチの結果を、スカラー変数のリストに代入する$_ = "apple=10";

my ($key, $val) = /ˆ(.+)=(\d+)$/;

print "key=[$key] value=[$val]\n"; # key=[apple] value=[10]

さらに、それを if文の条件式にする$_ = "apple=10";

if (my ($key, $val) = /ˆ(.+)=(\d+)$/) {

print "key=[$key] value=[$val]\n";

} else {

# マッチしなかった}

リスト代入をスカラーコンテキストで評価すると、代入された要素の個数が得られるif文以外の条件式としても同じことができる

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 25 / 57

リファレンス

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 26 / 57

リファレンスとは?

リファレンス(reference)は、他のデータを指すデータ型である

スカラー型の一種

C言語のポインタに相当するものリファレンスを利用して、複雑なデータ構造を表現できる

連結リスト、木構造、グラフ etc.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 27 / 57

リファレンスとは?

リファレンス(reference)は、他のデータを指すデータ型である

スカラー型の一種

C言語のポインタに相当するもの

リファレンスを利用して、複雑なデータ構造を表現できる

連結リスト、木構造、グラフ etc.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 27 / 57

リファレンスとは?

リファレンス(reference)は、他のデータを指すデータ型である

スカラー型の一種

C言語のポインタに相当するものリファレンスを利用して、複雑なデータ構造を表現できる

連結リスト、木構造、グラフ etc.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 27 / 57

変数へのリファレンスを得る

変数の前に逆スラッシュをつけると、リファレンスが得られる

Cの単項&演算子に相当$scaler_ref = \$scalar; # スカラー

$array_ref = \@array; # 配列

$hash_ref = \%hash; # ハッシュ

$func_ref = \&function; # サブルーチン

$glob_ref = \*STDOUT; # グロブ

リファレンス値はスカラーとして扱える

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 28 / 57

変数へのリファレンスを得る

変数の前に逆スラッシュをつけると、リファレンスが得られる

Cの単項&演算子に相当$scaler_ref = \$scalar; # スカラー

$array_ref = \@array; # 配列

$hash_ref = \%hash; # ハッシュ

$func_ref = \&function; # サブルーチン

$glob_ref = \*STDOUT; # グロブ

リファレンス値はスカラーとして扱える

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 28 / 57

変数へのリファレンスを得る

変数の前に逆スラッシュをつけると、リファレンスが得られる

Cの単項&演算子に相当$scaler_ref = \$scalar; # スカラー

$array_ref = \@array; # 配列

$hash_ref = \%hash; # ハッシュ

$func_ref = \&function; # サブルーチン

$glob_ref = \*STDOUT; # グロブ

リファレンス値はスカラーとして扱える

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 28 / 57

変数へのリファレンスを得る

変数の前に逆スラッシュをつけると、リファレンスが得られる

Cの単項&演算子に相当$scaler_ref = \$scalar; # スカラー

$array_ref = \@array; # 配列

$hash_ref = \%hash; # ハッシュ

$func_ref = \&function; # サブルーチン

$glob_ref = \*STDOUT; # グロブ

リファレンス値はスカラーとして扱える

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 28 / 57

変数へのリファレンスを得る

変数の前に逆スラッシュをつけると、リファレンスが得られる

Cの単項&演算子に相当$scaler_ref = \$scalar; # スカラー

$array_ref = \@array; # 配列

$hash_ref = \%hash; # ハッシュ

$func_ref = \&function; # サブルーチン

$glob_ref = \*STDOUT; # グロブ

リファレンス値はスカラーとして扱える

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 28 / 57

変数へのリファレンスを得る

変数の前に逆スラッシュをつけると、リファレンスが得られる

Cの単項&演算子に相当$scaler_ref = \$scalar; # スカラー

$array_ref = \@array; # 配列

$hash_ref = \%hash; # ハッシュ

$func_ref = \&function; # サブルーチン

$glob_ref = \*STDOUT; # グロブ

リファレンス値はスカラーとして扱える

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 28 / 57

デリファレンス

リファレンスをたどって、指しているデータにアクセスすることをデリファレンス(dereference)という

Perlでは、変数の種別を表すプレフィクス文字$、@、%、&などを使う

これらの文字をシジル (sigil)というCでは単項の*によってデリファレンスを行う

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 29 / 57

デリファレンス

リファレンスをたどって、指しているデータにアクセスすることをデリファレンス(dereference)というPerlでは、変数の種別を表すプレフィクス文字$、@、%、&などを使う

これらの文字をシジル (sigil)というCでは単項の*によってデリファレンスを行う

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 29 / 57

スカラーのデリファレンス

デリファレンスした結果はその型の変数として扱える

スカラーへのリファレンスを取得$sref = \$x;

スカラー値にアクセスする$a = $$ref;

コード例my $x = 100;

my $sref = \$x; # スカラーリファレンスを$srefに代入

print "$$sref $x\n"; # 100 100 と表示$$sref += 5;

print "$$sref $x\n"; # 105 105 と表示

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 30 / 57

スカラーのデリファレンス

デリファレンスした結果はその型の変数として扱えるスカラーへのリファレンスを取得$sref = \$x;

スカラー値にアクセスする$a = $$ref;

コード例my $x = 100;

my $sref = \$x; # スカラーリファレンスを$srefに代入

print "$$sref $x\n"; # 100 100 と表示$$sref += 5;

print "$$sref $x\n"; # 105 105 と表示

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 30 / 57

スカラーのデリファレンス

デリファレンスした結果はその型の変数として扱えるスカラーへのリファレンスを取得$sref = \$x;

スカラー値にアクセスする$a = $$ref;

コード例my $x = 100;

my $sref = \$x; # スカラーリファレンスを$srefに代入

print "$$sref $x\n"; # 100 100 と表示$$sref += 5;

print "$$sref $x\n"; # 105 105 と表示

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 30 / 57

スカラーのデリファレンス

デリファレンスした結果はその型の変数として扱えるスカラーへのリファレンスを取得$sref = \$x;

スカラー値にアクセスする$a = $$ref;

コード例my $x = 100;

my $sref = \$x; # スカラーリファレンスを$srefに代入

print "$$sref $x\n"; # 100 100 と表示$$sref += 5;

print "$$sref $x\n"; # 105 105 と表示

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 30 / 57

配列のデリファレンス

配列へのリファレンスを取得する$array_ref = \@array;

配列全体にアクセス@s = @$array_ref;

配列の要素にアクセス$$array_ref[10] = 10;

foreach文で配列の要素を順に処理するforeach (@$array_ref) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 31 / 57

配列のデリファレンス

配列へのリファレンスを取得する$array_ref = \@array;

配列全体にアクセス@s = @$array_ref;

配列の要素にアクセス$$array_ref[10] = 10;

foreach文で配列の要素を順に処理するforeach (@$array_ref) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 31 / 57

配列のデリファレンス

配列へのリファレンスを取得する$array_ref = \@array;

配列全体にアクセス@s = @$array_ref;

配列の要素にアクセス$$array_ref[10] = 10;

foreach文で配列の要素を順に処理するforeach (@$array_ref) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 31 / 57

配列のデリファレンス

配列へのリファレンスを取得する$array_ref = \@array;

配列全体にアクセス@s = @$array_ref;

配列の要素にアクセス$$array_ref[10] = 10;

foreach文で配列の要素を順に処理するforeach (@$array_ref) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 31 / 57

配列のデリファレンス

配列へのリファレンスを取得する$array_ref = \@array;

配列全体にアクセス@s = @$array_ref;

配列の要素にアクセス$$array_ref[10] = 10;

foreach文で配列の要素を順に処理するforeach (@$array_ref) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 31 / 57

配列のデリファレンスの例

関数 compute_sum: 配列リファレンスを受け取って、要素の和を返すsub compute_sum {

my ($aref) = @_; # リファレンスを$arefへ代入my $sum = 0;

foreach (@$aref) { # 配列をデリファレンス$sum += $_;

}

return $sum;

}

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 32 / 57

ハッシュのデリファレンス

ハッシュへのリファレンスを取得する$href = \%h;

ハッシュの要素にアクセス$x = $$href{’a’};

keys関数で、ハッシュのすべてのキーを取り出すforeach (keys %$href) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 33 / 57

ハッシュのデリファレンス

ハッシュへのリファレンスを取得する$href = \%h;

ハッシュの要素にアクセス$x = $$href{’a’};

keys関数で、ハッシュのすべてのキーを取り出すforeach (keys %$href) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 33 / 57

ハッシュのデリファレンス

ハッシュへのリファレンスを取得する$href = \%h;

ハッシュの要素にアクセス$x = $$href{’a’};

keys関数で、ハッシュのすべてのキーを取り出すforeach (keys %$href) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 33 / 57

ハッシュのデリファレンス

ハッシュへのリファレンスを取得する$href = \%h;

ハッシュの要素にアクセス$x = $$href{’a’};

keys関数で、ハッシュのすべてのキーを取り出すforeach (keys %$href) {

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 33 / 57

サブルーチンのデリファレンス

コードレフ (coderef)とも呼ばれる

サブルーチンへのリファレンスを取得する$fref = \&func;

サブルーチンを呼び出す&$fref($param);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 34 / 57

サブルーチンのデリファレンス

コードレフ (coderef)とも呼ばれるサブルーチンへのリファレンスを取得する$fref = \&func;

サブルーチンを呼び出す&$fref($param);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 34 / 57

サブルーチンのデリファレンス

コードレフ (coderef)とも呼ばれるサブルーチンへのリファレンスを取得する$fref = \&func;

サブルーチンを呼び出す&$fref($param);

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 34 / 57

デリファレンスの失敗

リファレンスの本来の型以外にデリファレンスしようとするとエラーになる$aref = \@array;

$$aref = 10;

Not a SCALAR reference at - line 7.

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 35 / 57

ref関数

引数がリファレンスなら真、そうでなければ偽を返す真の値は、リファレンスが指すものの種類を示す文字列

リファレンス REF

スカラー SCALAR

配列 ARRAY

ハッシュ HASH

サブルーチン CODE

型グロブ GLOB

オブジェクト 所属するクラス名

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 36 / 57

リファレンスから文字列への変換

リファレンスは必要に応じて文字列に変換される

例えば print文の引数として使った場合具体的には「型名+16進表記のアドレス」となる

例: CODE(0xbb5b48), HASH(0xbb59f8)

eq演算子を使って、リファレンスの等価性(=同じものを指す)をチェックできる文字列からリファレンスへの逆変換は不可

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 37 / 57

リファレンスから文字列への変換

リファレンスは必要に応じて文字列に変換される例えば print文の引数として使った場合

具体的には「型名+16進表記のアドレス」となる例: CODE(0xbb5b48), HASH(0xbb59f8)

eq演算子を使って、リファレンスの等価性(=同じものを指す)をチェックできる文字列からリファレンスへの逆変換は不可

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 37 / 57

リファレンスから文字列への変換

リファレンスは必要に応じて文字列に変換される例えば print文の引数として使った場合

具体的には「型名+16進表記のアドレス」となる例: CODE(0xbb5b48), HASH(0xbb59f8)

eq演算子を使って、リファレンスの等価性(=同じものを指す)をチェックできる文字列からリファレンスへの逆変換は不可

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 37 / 57

リファレンスから文字列への変換

リファレンスは必要に応じて文字列に変換される例えば print文の引数として使った場合

具体的には「型名+16進表記のアドレス」となる例: CODE(0xbb5b48), HASH(0xbb59f8)

eq演算子を使って、リファレンスの等価性(=同じものを指す)をチェックできる

文字列からリファレンスへの逆変換は不可

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 37 / 57

リファレンスから文字列への変換

リファレンスは必要に応じて文字列に変換される例えば print文の引数として使った場合

具体的には「型名+16進表記のアドレス」となる例: CODE(0xbb5b48), HASH(0xbb59f8)

eq演算子を使って、リファレンスの等価性(=同じものを指す)をチェックできる文字列からリファレンスへの逆変換は不可

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 37 / 57

ブロックを使ったデリファレンス

変数名やサブルーチン名のうち、英数字の識別子の変わりにブロックを置ける

ブロックは正しいリファレンス値を返さなければならないスカラーのデリファレンス${$sref}

関数を呼び出すこともできる@{&get_array_ref()}

${$a[2]}と$$a[2]の違いに注意$$a[2]は${$a}[2]と解釈される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 38 / 57

ブロックを使ったデリファレンス

変数名やサブルーチン名のうち、英数字の識別子の変わりにブロックを置けるブロックは正しいリファレンス値を返さなければならない

スカラーのデリファレンス${$sref}

関数を呼び出すこともできる@{&get_array_ref()}

${$a[2]}と$$a[2]の違いに注意$$a[2]は${$a}[2]と解釈される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 38 / 57

ブロックを使ったデリファレンス

変数名やサブルーチン名のうち、英数字の識別子の変わりにブロックを置けるブロックは正しいリファレンス値を返さなければならないスカラーのデリファレンス${$sref}

関数を呼び出すこともできる@{&get_array_ref()}

${$a[2]}と$$a[2]の違いに注意$$a[2]は${$a}[2]と解釈される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 38 / 57

ブロックを使ったデリファレンス

変数名やサブルーチン名のうち、英数字の識別子の変わりにブロックを置けるブロックは正しいリファレンス値を返さなければならないスカラーのデリファレンス${$sref}

関数を呼び出すこともできる@{&get_array_ref()}

${$a[2]}と$$a[2]の違いに注意$$a[2]は${$a}[2]と解釈される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 38 / 57

ブロックを使ったデリファレンス

変数名やサブルーチン名のうち、英数字の識別子の変わりにブロックを置けるブロックは正しいリファレンス値を返さなければならないスカラーのデリファレンス${$sref}

関数を呼び出すこともできる@{&get_array_ref()}

${$a[2]}と$$a[2]の違いに注意$$a[2]は${$a}[2]と解釈される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 38 / 57

${$a[2]}と$$a[2]の違い

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 39 / 57

->によるデリファレンス

$a->[3]は$$a[3]を表す

$h->{key}は$$h{key}を表す$f->($param)は&$f($param)を表す多次元配列を表現する

$a->[3]->[2]->の両側が [],{}、()の場合、->を省略できる

$a->[3]->[2]は$a->[2][3]と書ける

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 40 / 57

->によるデリファレンス

$a->[3]は$$a[3]を表す$h->{key}は$$h{key}を表す

$f->($param)は&$f($param)を表す多次元配列を表現する

$a->[3]->[2]->の両側が [],{}、()の場合、->を省略できる

$a->[3]->[2]は$a->[2][3]と書ける

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 40 / 57

->によるデリファレンス

$a->[3]は$$a[3]を表す$h->{key}は$$h{key}を表す$f->($param)は&$f($param)を表す

多次元配列を表現する$a->[3]->[2]

->の両側が [],{}、()の場合、->を省略できる$a->[3]->[2]は$a->[2][3]と書ける

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 40 / 57

->によるデリファレンス

$a->[3]は$$a[3]を表す$h->{key}は$$h{key}を表す$f->($param)は&$f($param)を表す多次元配列を表現する

$a->[3]->[2]

->の両側が [],{}、()の場合、->を省略できる$a->[3]->[2]は$a->[2][3]と書ける

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 40 / 57

->によるデリファレンス

$a->[3]は$$a[3]を表す$h->{key}は$$h{key}を表す$f->($param)は&$f($param)を表す多次元配列を表現する

$a->[3]->[2]->の両側が [],{}、()の場合、->を省略できる

$a->[3]->[2]は$a->[2][3]と書ける

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 40 / 57

多次元配列のエミュレーション

$a[3][2][5]のように書けば、あたかも多次元配列のように使える

これは実際は$a[3]->[2]->[5]である$a->[3][2][5]との違いに注意

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 41 / 57

多次元配列のエミュレーション

$a[3][2][5]のように書けば、あたかも多次元配列のように使えるこれは実際は$a[3]->[2]->[5]である

$a->[3][2][5]との違いに注意

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 41 / 57

多次元配列のエミュレーション

$a[3][2][5]のように書けば、あたかも多次元配列のように使えるこれは実際は$a[3]->[2]->[5]である$a->[3][2][5]との違いに注意

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 41 / 57

$a[2][1]と$a->[2][1]の違い

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 42 / 57

無名配列、無名ハッシュの自動生成

Perlでは、配列の大きさを宣言する必要はない要素に値を代入すると、自動的に配列の領域が確保される

$a[2][3]のような多次元配列風記法でも同様に、自動的に無名配列、無名ハッシュが生成される$a[2][1] = 100を実行すると、下のような配列の

実体が確保される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 43 / 57

無名配列、無名ハッシュの自動生成

Perlでは、配列の大きさを宣言する必要はない要素に値を代入すると、自動的に配列の領域が確保される

$a[2][3]のような多次元配列風記法でも同様に、自動的に無名配列、無名ハッシュが生成される

$a[2][1] = 100を実行すると、下のような配列の実体が確保される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 43 / 57

無名配列、無名ハッシュの自動生成

Perlでは、配列の大きさを宣言する必要はない要素に値を代入すると、自動的に配列の領域が確保される

$a[2][3]のような多次元配列風記法でも同様に、自動的に無名配列、無名ハッシュが生成される$a[2][1] = 100を実行すると、下のような配列の

実体が確保される

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 43 / 57

無名配列、無名ハッシュ

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 44 / 57

配列リファレンスを取得するには

配列リファレンスを受け取る関数 compute_sumを呼び出すmy @tmp_array = (1, 3, 5, 7, 9);

print "Total: ", compute_sum(\@tmp_array), "\n";

sub compute_sum {

my ($aref) = @_;

my $sum = 0;

foreach (@$aref) {

$sum += $_;

}

return $sum;

}

わざわざ配列@tmp_arrayを用意するのは面倒くさい

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 45 / 57

配列リファレンスを取得するには

配列リファレンスを受け取る関数 compute_sumを呼び出すmy @tmp_array = (1, 3, 5, 7, 9);

print "Total: ", compute_sum(\@tmp_array), "\n";

sub compute_sum {

my ($aref) = @_;

my $sum = 0;

foreach (@$aref) {

$sum += $_;

}

return $sum;

}

わざわざ配列@tmp_arrayを用意するのは面倒くさい

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 45 / 57

無名配列

Perlは、無名配列 (anonymous array)がサポートしている

ブラケット []で要素を囲んで指定する無名の配列が生成されて、それへのリファレンスが返される

例)5要素の名前のない配列へのリファレンスを$arefに代入$aref = [1, 2, 3, 4, 5]

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 46 / 57

無名配列

Perlは、無名配列 (anonymous array)がサポートしている

ブラケット []で要素を囲んで指定する無名の配列が生成されて、それへのリファレンスが返される

例)5要素の名前のない配列へのリファレンスを$arefに代入$aref = [1, 2, 3, 4, 5]

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 46 / 57

無名配列

Perlは、無名配列 (anonymous array)がサポートしている

ブラケット []で要素を囲んで指定する無名の配列が生成されて、それへのリファレンスが返される

例)5要素の名前のない配列へのリファレンスを$arefに代入$aref = [1, 2, 3, 4, 5]

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 46 / 57

無名配列

関数 compute_sumを呼び出すprint "Total: ", compute_sum([1, 3, 5, 7, 9]), "\n";

リスト (1, 2, 3)と無名配列 [1, 2, 3]を混同しないこと

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 47 / 57

無名配列

関数 compute_sumを呼び出すprint "Total: ", compute_sum([1, 3, 5, 7, 9]), "\n";

リスト (1, 2, 3)と無名配列 [1, 2, 3]を混同しないこと

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 47 / 57

無名ハッシュ

ハッシュに関しては、無名ハッシュ(anonymoushash)がある

ブレース{}で要素を囲んで指定する要素は「キー、値」のペアで指定する無名のハッシュが生成されて、それへのリファレンスが返される

例)キーと値のペアを 3個持った名前のないハッシュへのリファレンス$href = {one => 1, two => 2, three => 3};

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 48 / 57

無名ハッシュ

ハッシュに関しては、無名ハッシュ(anonymoushash)がある

ブレース{}で要素を囲んで指定する要素は「キー、値」のペアで指定する無名のハッシュが生成されて、それへのリファレンスが返される

例)キーと値のペアを 3個持った名前のないハッシュへのリファレンス$href = {one => 1, two => 2, three => 3};

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 48 / 57

ハッシュと=>

=>は太い矢印 (thick arrow)と呼ばれる (「初めてのPerl」p@@@@)

基本的には、カンマと同じ意味=>の左側に英数字と下線のみの文字列 (先頭は数字以外)を置く場合、クォートを省略可—前ページの例$href = {one => 1, two => 2, three => 3};

カンマを使うと次のようになる$href = {’one’, 1, ’two’, 2, ’three’, 3 };

キーと値の対応が明確になるので、ハッシュを記述する場合には=>を使うのが普通(キーをクォートしないで済むので楽ちん)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 49 / 57

ハッシュと=>

=>は太い矢印 (thick arrow)と呼ばれる (「初めてのPerl」p@@@@)

基本的には、カンマと同じ意味

=>の左側に英数字と下線のみの文字列 (先頭は数字以外)を置く場合、クォートを省略可—前ページの例$href = {one => 1, two => 2, three => 3};

カンマを使うと次のようになる$href = {’one’, 1, ’two’, 2, ’three’, 3 };

キーと値の対応が明確になるので、ハッシュを記述する場合には=>を使うのが普通(キーをクォートしないで済むので楽ちん)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 49 / 57

ハッシュと=>

=>は太い矢印 (thick arrow)と呼ばれる (「初めてのPerl」p@@@@)

基本的には、カンマと同じ意味=>の左側に英数字と下線のみの文字列 (先頭は数字以外)を置く場合、クォートを省略可—前ページの例$href = {one => 1, two => 2, three => 3};

カンマを使うと次のようになる$href = {’one’, 1, ’two’, 2, ’three’, 3 };

キーと値の対応が明確になるので、ハッシュを記述する場合には=>を使うのが普通(キーをクォートしないで済むので楽ちん)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 49 / 57

ハッシュと=>

=>は太い矢印 (thick arrow)と呼ばれる (「初めてのPerl」p@@@@)

基本的には、カンマと同じ意味=>の左側に英数字と下線のみの文字列 (先頭は数字以外)を置く場合、クォートを省略可—前ページの例$href = {one => 1, two => 2, three => 3};

カンマを使うと次のようになる$href = {’one’, 1, ’two’, 2, ’three’, 3 };

キーと値の対応が明確になるので、ハッシュを記述する場合には=>を使うのが普通(キーをクォートしないで済むので楽ちん)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 49 / 57

ハッシュと=>

=>は太い矢印 (thick arrow)と呼ばれる (「初めてのPerl」p@@@@)

基本的には、カンマと同じ意味=>の左側に英数字と下線のみの文字列 (先頭は数字以外)を置く場合、クォートを省略可—前ページの例$href = {one => 1, two => 2, three => 3};

カンマを使うと次のようになる$href = {’one’, 1, ’two’, 2, ’three’, 3 };

キーと値の対応が明確になるので、ハッシュを記述する場合には=>を使うのが普通

(キーをクォートしないで済むので楽ちん)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 49 / 57

ハッシュと=>

=>は太い矢印 (thick arrow)と呼ばれる (「初めてのPerl」p@@@@)

基本的には、カンマと同じ意味=>の左側に英数字と下線のみの文字列 (先頭は数字以外)を置く場合、クォートを省略可—前ページの例$href = {one => 1, two => 2, three => 3};

カンマを使うと次のようになる$href = {’one’, 1, ’two’, 2, ’three’, 3 };

キーと値の対応が明確になるので、ハッシュを記述する場合には=>を使うのが普通(キーをクォートしないで済むので楽ちん)

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 49 / 57

無名配列と無名ハッシュを組み合わせる

自由に組み合わせることができる。(C風の)構造体やオブジェクトを表現するのに無名ハッシュを使うのが定石my $userinfo = { name => $name,

uid => $uid,

gid => [1, 200, 201, 203],

env => {

HOME => $ENV{HOME},

TERM => "VT100"

}

};

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 50 / 57

Data::Dumperモジュール

リファレンスで複雑なデータ構造を作れるのはいいけど、表示するにはどうするの?

単にプリントするとHASH(0x116360)そこでData::Dumperモジュールの出番です。$VAR1 = {

’uid’ => 1001,

’env’ => {

’HOME’ => ’/home/cond’,

’TERM’ => ’VT100’

},

’name’ => ’John’,

’gid’ => [

1,

200,

201,

203

]

};

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 51 / 57

Data::Dumperモジュール

リファレンスで複雑なデータ構造を作れるのはいいけど、表示するにはどうするの?単にプリントするとHASH(0x116360)

そこでData::Dumperモジュールの出番です。$VAR1 = {

’uid’ => 1001,

’env’ => {

’HOME’ => ’/home/cond’,

’TERM’ => ’VT100’

},

’name’ => ’John’,

’gid’ => [

1,

200,

201,

203

]

};

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 51 / 57

Data::Dumperモジュール

リファレンスで複雑なデータ構造を作れるのはいいけど、表示するにはどうするの?単にプリントするとHASH(0x116360)そこでData::Dumperモジュールの出番です。$VAR1 = {

’uid’ => 1001,

’env’ => {

’HOME’ => ’/home/cond’,

’TERM’ => ’VT100’

},

’name’ => ’John’,

’gid’ => [

1,

200,

201,

203

]

};

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 51 / 57

無名サブルーチン (コードレフ)、クロージャ

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 52 / 57

無名サブルーチン

Perlは、無名サブルーチン(anonymoussubroutine)をサポートしている

sub { ..... }と書く無名のサブルーチンが生成されて、それへのリファレンスが返される

無名サブルーチンのリファレンスを frefに代入$fref = sub { print "Hello, $_[0]\n"; }

無名サブルーチンを呼び出す&$fref("world");

->を使って、無名サブルーチンを呼び出す (こちらの書き方が好まれる)$fref->("world");

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 53 / 57

無名サブルーチン

Perlは、無名サブルーチン(anonymoussubroutine)をサポートしている

sub { ..... }と書く

無名のサブルーチンが生成されて、それへのリファレンスが返される

無名サブルーチンのリファレンスを frefに代入$fref = sub { print "Hello, $_[0]\n"; }

無名サブルーチンを呼び出す&$fref("world");

->を使って、無名サブルーチンを呼び出す (こちらの書き方が好まれる)$fref->("world");

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 53 / 57

無名サブルーチン

Perlは、無名サブルーチン(anonymoussubroutine)をサポートしている

sub { ..... }と書く無名のサブルーチンが生成されて、それへのリファレンスが返される

無名サブルーチンのリファレンスを frefに代入$fref = sub { print "Hello, $_[0]\n"; }

無名サブルーチンを呼び出す&$fref("world");

->を使って、無名サブルーチンを呼び出す (こちらの書き方が好まれる)$fref->("world");

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 53 / 57

無名サブルーチン

Perlは、無名サブルーチン(anonymoussubroutine)をサポートしている

sub { ..... }と書く無名のサブルーチンが生成されて、それへのリファレンスが返される

無名サブルーチンのリファレンスを frefに代入$fref = sub { print "Hello, $_[0]\n"; }

無名サブルーチンを呼び出す&$fref("world");

->を使って、無名サブルーチンを呼び出す (こちらの書き方が好まれる)$fref->("world");

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 53 / 57

無名サブルーチン

Perlは、無名サブルーチン(anonymoussubroutine)をサポートしている

sub { ..... }と書く無名のサブルーチンが生成されて、それへのリファレンスが返される

無名サブルーチンのリファレンスを frefに代入$fref = sub { print "Hello, $_[0]\n"; }

無名サブルーチンを呼び出す&$fref("world");

->を使って、無名サブルーチンを呼び出す (こちらの書き方が好まれる)$fref->("world");

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 53 / 57

無名サブルーチン

Perlは、無名サブルーチン(anonymoussubroutine)をサポートしている

sub { ..... }と書く無名のサブルーチンが生成されて、それへのリファレンスが返される

無名サブルーチンのリファレンスを frefに代入$fref = sub { print "Hello, $_[0]\n"; }

無名サブルーチンを呼び出す&$fref("world");

->を使って、無名サブルーチンを呼び出す (こちらの書き方が好まれる)$fref->("world");

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 53 / 57

クロージャ

クロージャ(closure)とは?無名サブルーチンを生成する際に、その時点で見えるレキシカル変数 (my変数)の実体も閉じ込められる。これをクロージャと言う。

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 54 / 57

関数adder: 指定した数を加算して返す関数を返す

sub adder {

my ($increment) = @_; # この変数が閉じ込められる

return sub {

my ($x) = @_;

return $x + $increment;

}

}

my $add1 = adder(1); # 1を加算する関数my $add20 = adder(20); # 20を加算する関数

print $add1->(10), "\n"; # 11

print $add20->(10), "\n"; # 30

print $add1->(30), "\n"; # 31

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 55 / 57

関数make counter: カウンタ関数を返す

sub make_counter {

my ($counter) = @_; # この変数が閉じ込められる

return sub { return ++$counter };

}

my $foo = make_counter(0); # 初期値 0のカウンタmy $bar = make_counter(100); # 初期値 100のカウンタ

print $foo->(), "\n"; # 1

print $bar->(), "\n"; # 101

print $bar->(), "\n"; # 102

print $foo->(), "\n"; # 2

print $bar->(), "\n"; # 103

print $foo->(), "\n"; # 3

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 56 / 57

ご静聴ありがとうございました

近藤嘉雪 (@yoshiyuki kondo) コンテキストとリファレンスを我が物に! YAPC::Asia 2012 (2012/9/29) 57 / 57