今日のラクダ 6章 サブルーチン,8章 リファレンス

今回はかなり重要な情報が多し。

6章 サブルーチン

6.1 p.252
&$subref(LIST) # 間接呼び出しでは&を省略できない
$subref->(LIST) # (ただし間に->を置く場合を除く)


基本的には$subref->(LIST)を使いそう。

6.4 プロトタイプ p.263

プロトタイプ宣言に関して。

一番最初に逆スラッシュものはそのすぐ右の文字列から始まらなければならない

irl @> sub mykeys (\%) { my %hash = shift; return \%hash }
()

pirl @> mykeys("a" => "b")
ERROR: Type of arg 1 to Shell::Perl::sandbox::mykeys must be hash (not constant item) at (eval 4) line 3, near ""b")

"
Too many arguments for Shell::Perl::sandbox::mykeys at (eval 4) line 3, near ""b")

"
pirl @> %hash = ("a" => "b");
("a", "b")

pirl @> mykeys(%hash);
Reference found where even-sized list expected at (eval 3) line 1.
{ "HASH(0x185582c)" => undef }

リテラルではダメで,変数に入れてから渡す必要がある。

@と%は、残りすべての実引数を飲み込んで,リストコンテキストを要求する。

pirl @> myreverse "a", "b", "c"
("a", "b", "c")

pirl @> scalar myreverse "a", "b", "c"
3

&を最初の引数として指定した場合は,無名サブルーチンのsubを省略して「間接オブジェクトスロット」にブロックだけを置くことができる

Rubyのブロック構文のようなメソッドを定義する際に用いる。mapなど。

試しにRubyのinjectのようなものを作ってみる。

sub inject(&$@) { 
 my ($block, $init, @array) = @_; 
 my $prev_item = $init; 
 for my $item (@array) { 
    $prev_item = &$block($prev_item, $item);
  }
 return $prev_item; 
}

pirl @> inject { my ($init, $item) = @_; $init += $item;  } 1, (2,3,4,5);
#=> 15
6.4.1 定数関数のインライン化 p.264

その関数の結果が定数であるか,あるいは他のリファレンスを含まない,レキシカルスコープを持つスカラーであった場合,関数を呼び出す代わりにその値が使われる。

コンパイル時に結果の計算ができる関数は変数のような扱いにして関数呼び出し時にかかるオーバーヘッドをなくしますよという理解で良いかな。

6.5.2 lvalue属性

サブルーチンから変更可能なスカラー値を返すことができる

sub attr() : lvalue {
  our $attr;
}

Rubyでいうところの

def attr=(val)
  @attr = val
end

と同義。引数ありのケースは分かりづらいだけなのであまり想像できない。

7章 フォーマット

使われているところをほとんど見たことがないし,自分では使わなそうなのでざっと眺めるにとどめておく。

8章

8.1 リファレンスとは何か? p.281

例外的にPerlが暗黙的にデリファレンスするケース

  • ある種のファイルハンドルを使うとき (ex. *STDIN::IO)
  • 組み込み関数blessとlock
8.2.1 逆スラッシュ演算子 p.282

リストに適用すると,各要素へのリファレンスのリストを生成してくれる。

pirl @> \qw(abc efg hij klm)
(\"abc", \"efg", \"hij", \"klm")

知らなかった。

8.2.4 ハンドルへのリファレンス p.287

通常は型グロブと型グロブへのリファレンスを区別せずに使うことができるが以下の場合は例外。

  • bless: 型グロブをオブジェクトにはできない
  • スコープ外へ型グロブのリファレンスを返すことはできない
8.3.5 疑似ハッシュ p.294

配列のリファレンスのうち,先頭の要素がハッシュへのリファレンスとなっているもの。

見ない機能だと思ったらdeprecatedというエラーが表示された。

8.3.7 クロージャ p.302

クロージャを関数テンプレートとして使う

{
  no strict 'refs';
  *$hoge = sub { # ... };
}

Rubyのdefine_method(ブロック版)とほぼ同じ。

8.4 シンボリックリファレンス

ハードリファレンス以外の値をデリファレンスすると名前として扱われる。

9章 データ構造, 10章 パッケージ, 11章 モジュールまでは読んだのだけど,今日はちょっとまとめきれないのでまた明日。