Perlを使ってみた時に覚えておこうって思った特徴・ライブラリ・ツールについてメモする。

目次

データ型は3つ

公式ドキュメントのデータ型を読んでおけば良い。 読んだら下の使い方があって興味を持った。

@days[3,4,5] # as ($days[3], $days[4], $days[5])

外部モジュールを読み込む

use,require命令の2つが存在する。

use, require を比較する

命令 評価タイミング 使えるサブルーチン バージョン
use コンパイル時評価 BEGIN, CHECK, INIT >= 5系
reuqire 実行時評価 BEGIN 全バージョン

useはコンパイル時評価であり特別なコードブロックを定義可能で、これらのコードブロックはモジュール読み込み時などに実行可能。

名前 実行タイミング
BEGIN 出来るだけ早く実行される(パース直後など)
END 出来るだけ遅く実行される(プログラム終了時など, シグナルで撃沈されたりevalだと実行されない, LIFO実行)
UNITCHECK 対象コンパイル単位のコンパイル直後に実行される
CHECK 最初のコンパイルフェーズ終了後に実行開始(LIFO)
INIT ランタイム実行直前(FIFO)

ref. Perlのモジュール

PATHを追加する

相対パスで読み込み先を指定したくなる。そういう時はFile, libモジュールを使う。 例えば、以下を読み込む前に追加しておけば../lib/配下を探索する様になる。

use File::Basename;
use lib dirname(__FILE__). "/../lib/";

ファイルを行単位で処理する

行単位で処理するには以下のスニペットが綺麗。

open (IN, $file_name) or die "$!";
my $line;
while (<IN>) {
  $line = $_;
  chomp($line);
  print $line;
}

行入力演算子<>を利用してファイルハンドラから受け取る。 標準入力は特別なファイルハンドラSTDIN から受け取る。 行末のEnterも入力に含まれるのでchomp関数で行末Enterを削除するのが良い。

ガード節

異常な入力値を弾くためガード節を使うが、Perlでは後置を使う事がある。

$v = "apple"
print "v is apple." if $v eq "apple"
print "v is not orange." unless $v eq "orange"

定義済み変数

perlvarを参考にすると良い。以下抜粋。

変数 意味
$_ デフォルト入力などのスペース
@_, @ARG サブルーチンの引き数が入っている・配列演算子のデフォルト引き数
%SIG シグナルハンドラを持つハッシュ
$PID, $$ プログラムのPID
$BASETIME, $^T ブログラムが起動したUnixTime

定番の正規表現処理

置換、存在の判別は以下の様にする。デフォルトでは\ $_ が対象になる。\ () を使ってキャプチャを行なう。

if (/pattern/) {
  print '$_ にpatternが含まれる';
}
if (!/pattern/) {
  print '$_ にpatternが含まれない';
}
if ($word =~ /pat(tern)/) {
  print '$word にpatternが含まれる';
  print $1; # ternが含まれる
}
if ($word !~ /pattern/) {
  print '$word にpatternが含まれない';
}
if (m|pattern|) {
  print 'm でパターン文字を変更する';
}

die, exit関数

異常系の処理には2つの方法がある。 1つめはdie() 関数で例外を発生させる方法。 2つめはexec()関数でプロセス終了させる方法。

die 関数

詳細はリンク先を読めば良い。 die()関数は例外を発生させるのでevalブロックに囲まれてない場合、プログラムを終了させる。 evalに囲まれている場合はdie()に渡した値が$@に格納されるので以下の様に使う事になる。 サブルーチン外部でエラーを捕捉しようとしてる可能性がある場合はこれをつかう。

eval {
  die "in eval";
}
if $@ {
  print "error処理". $@;
}

これを応用した\ Error <http://search.cpan.org/~shlomif/Error-0.17022/lib/Error.pm> モジュールが存在する。これを使うと\ try, catch, except, throw などが使える様になる。

exit 関数

evalで捕捉されずプログラムを終了させる。各モジュールの\ END サブルーチンを実行してから終了する。 引き数には終了コードを渡す。

サブルーチンの宣言・定義

組み込み関数一覧を参考にする。

全ての引き数・返り値はスカラのリストに潰される。リスト・ハッシュともに潰されて渡される。 サブルーチン内部では@_として見える。リスト・ハッシュの構造を失わずに渡すには参照渡しを行なう必要がある。

プロトタイプ宣言

&を使わない呼び出しで組み込み関数の様に振る舞わせる事が可能で、その受け取り方を定める。 下みたいな感じでブロックを受け取るサブルーチンを作ったり出来る。

sub safe(&@) {
  my $code = shift;
  start()
  eval {
    $code->();
  }
  if $@ {
    print "error"
  }
  end()
}

カリー化とか関数中心な書き方をするためのモジュールも存在するから、その辺を参考に使い方を覚えるとよさそう。 functionals

use strict, warings モジュール

Perlを(比較的)厳格に書く為に各スクリプトの先頭で以下を記述する必要がある。

use strict;
use warnings;

bless 使ってクラスを定義する

Perlでオブジェクトを参考に書けばだいたいOK。 メソッド、継承、委譲、オーバーライドとか出来る。 肝はblessを使いオブジェクトを与えたパッケージ名と結びつけパッケージ内のサブルーチンをオブジェクト経由で呼べる様にする事。 これがメソッドになる。 そしてメソッドの呼び出しは第1引き数にインスタンスが入ってくる。 パッケージでの->呼び出しでは先頭にクラス名が入っているという事。

package ClassName;
sub new {
  my ($class, $arg) = @_;
  $self = {}
  bless $self, $class
  return $self
}
package main;
$a = Classname->new();

tie の使い方

オブジェクトをメソッド経由でアクセスさせる代わりにネイティブなデータ型としてアクセスさせる方法がある。 tie()関数はスカラ・配列・ハッシュ・ハンドラとしてオブジェクトを結びつけられる。 詳細はリンクから読めばよし。TIESCALAR, FETCH, STOREなどを定義して使う。 PHPでのArrayObjectインタフェースの実装を書くみたいな感じ。

local, my を使った変数の名前解決

localは動的スコープ, myは静的スコープで名前解決を行なう。

global変数は名前空間を明示して利用する

したみたいな感じ

$::val = "global variable";
sub hoge {
  print $::val;
}
hoge;
# $VAR1 = 'global variable';

コマンドオプション解析の方法

Getopt::Long モジュールが定番でバッドノウハウが溜まっているらしい。 バッドノウハウと注意点はこの記事 がまとまっているらしい。

テストコードの書き方

Test::More パッケージが単体テストが気楽な定番っぽい。 マニュアル読めば直ぐに使える。perlのテストコードの拡張子はtが使われる。

Data::Dumperでプリントデバッグ

下の2つの記事を読めば使い方はだいたい思い出せる。

他の言語を利用したい

使わなかったけれど選択肢は以下があるみたい。

モジュール 提供機能
Inline::C 他のプログラム言語で直接Perlサブモジュールを作る
XS 外部のCコード, Cライブラリを利用する
Swig 高級言語でC/C++を使うためのツール(perlも可能)