sci

最果て風呂

Perl の Cpanm と Minilla を使ってみる

Perl でのパッケージ作成をしてみます。デフォルトでの支援はないので、cpanm と minilla をインストールして、ライブラリはローカルにインストールするように環境変数を設定しました。

雛形の作成

Ruby の gem にあたる cpanm が必要らしいので、次のコマンドを入力してインストール。

curl -L https://cpanmin.us | perl - App::cpanminus

でも何かエラーが出ているような?それとも ~/bin の中で curl -LOk http://xrl.us/cpanm を実行する方法のほうが良いのかな?

!
! Can't write to /Library/Perl/5.18 and /usr/local/bin: Installing modules to /Users/home/perl5
! To turn off this warning, you have to do one of the following:
!   - run me as a root or with --sudo option (to install to /Library/Perl/5.18 and /usr/local/bin)
!   - Configure local::lib in your existing shell to set PERL_MM_OPT etc.
!   - Install local::lib by running the following commands
!
!         cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
!
--> Working on App::cpanminus
Fetching http://www.cpan.org/authors/id/M/MI/MIYAGAWA/App-cpanminus-1.7044.tar.gz ... OK
Configuring App-cpanminus-1.7044 ... OK
Building and testing App-cpanminus-1.7044 ... OK
Successfully installed App-cpanminus-1.7044
1 distribution installed

ホームディレクトリに perl5 というディレクトリが作成されていました。~/perl5/bin/cpanm を実行すれば良さそう。

プロジェクトの雛形を作成するには Minilla が必要らしいです。~/perl5/bin/cpanm Minnila でインストール。関連するライブラリが多くてかなり時間がかかる。一度目はエラーになってしまったけれど、--force を付けて再実行するとインストールできました。ネット回線の速度が遅いからかな?

~/perl5/bin/minil new Mto としてもエラーになってしまう。次のようにして環境変数を設定しておかなければいけなかったのでした。.bashrc にでも書いておこうっと。

export PERL_CPANM_OPT='--local-lib=~/perl5'
export PATH=$HOME/perl5/bin:$PATH;
export PERL5LIB=$HOME/perl5/lib/perl5:$PERL5LIB;

これでモジュールプロジェクトの雛形ができました。

> minil new Mto
Writing lib/Mto.pm
Writing Changes
Writing t/00_compile.t
Writing .travis.yml
Writing .gitignore
Writing LICENSE
Writing cpanfile
Initializing git Mto
[Mto] $ git init
Initialized empty Git repository in /Users/home/Mto/.git/
Retrieving meta data from lib/Mto.pm.
Name: Mto
Abstract: It's new $module
Version: 0.01
[Mto] $ git add .
Finished to create Mto

この中で触るのは lib/Mto.pm と t/00_complie.t くらいかな?

プロジェクトの設定

Build.PL や cpanfile があるのだけれど、編集する必要はないみたい。

プロジェクトの実装

lib/Mto.pm に内容をコピペして終了。

テストの記述

以前書いたものの内容をコピペして minil test してみると、Bareword "Exporter" not allowed while "strict subs" in use at lib/Mto.pm line 9. というエラーになってしまった。次の行を use strict; の上に移動すると解決しました。

use Exporter;
@ISA = (Exporter);
@EXPORT = qw();

どうやら minilla は テンポラリディレクトリを作成し、その中でいろいろするらしい。この過程で、test-jisyo, test-text がそのディレクトリにコピーされないので、ファイルを開けないよと言われてるようです。

git と連携しているようで、トラッキングしていないファイルはコピーされないみたい。git add . するとコピーされるようになり解決。

テストの内容が厳しくなったようで、Mto.pm 中で my を付け忘れていた変数の部分でエラーが出てしまった。

read ($a_file, my $text, -s $a_file);
my @input = <STDIN>;

関数への引数に配列を渡すときは \@arg のようにバックスラッシュを入れないといけないそうです。これは、@_ で受けとる時の区切りがわからなくなるためらしい。

内部辞書の作成過程に問題があることがわかりました。正規表現で空行を考慮に入れてなかった……。

unless ($line =~ /^;.*$/) {
unless ($line =~ /^;.*$|^$/) {

配列の配列がどうなっているのかがわからない。コンスセルリストのようなものを想像していたのだけれど、Perl では多次元配列というものは存在せず、擬似的に表現しているらしいです。リファレンスという言葉が出てきた。ポインタみたいなやつかな?

sub create_dictionary{
  my @dict_arr = ();
  ...
      my @pairs = split(/\s* \/\s*/, $line);  # ペアの配列にする
      push @dict_arr, [ @pairs ];             # 配列の配列にする
  ...
  return @dict_arr;
}

空の配列を () で作成し、それに [hoge, fuga] というものを追加していくことで内部辞書を作成していたようです。つまり

@dict_arr = ([hoge, fuga], [foo, bar], [nyan, wan], [piyo, koke])

となっているわけですね。自分で書いているのに覚えてない……。@ を付けた変数名にすれば配列として扱ってくれるものとばかり思っていました。

自分が最初にテストで書いた「期待する配列の結果」は RubyPython のように

@valid_arr = [[hoge, fuga], [foo, bar], [nyan, wan], [piyo, koke]]

としていたのだけれど、これは正しくないものらしい。[] で囲われたものは配列ではなくスカラ値というものらしいので、$ を使って

$valid_arr = [[hoge, fuga], [foo, bar], [nyan, wan], [piyo, koke]]

のように書かなければいけません。でもこれは自分が作成した内部辞書とは異なっているので、is() で比較することができないのでした。つまり @valid_arr は、はじめに書いたように、@dict_arr = ([, ], [, ], ...) という形にしなければならないのです。こうすることで比較が可能になりテストが OK になりました。

テストの実行は minil test でも perl t/00_comple.t でも OK になりました。

パッケージの作成

現状ではディレクトリの中で cpanm -i . -l ~/perl5 と実行することにより、~/perl5/lib 以下に Mto.pm がインストールできるようになりました。あとは実行ファイルを bin にインストールできるようにするだけです。

script 以下に実行ファイルを入れることで ~/perl5/bin にインストールしてくれるらしいです。これで完了!ちなみに削除する時は cpanm -U Mto -l ~/perl5 とすること。

minil clean とすることでビルド時に作成されたものを削除してくれます。

GitHub からのインストール

capnm git://github.com/user_name/plmto.git

でインストールできるはずなんだけどな?

正規表現

旧から新への変換のテストを追加したら、エラーが出てしまいました。文字列置換の部分に問題があるのですが、リテラルではなく正規表現で置換しているのが原因らしいです。'(´・_・`)' がグルーピングの意味になってしまうのでした。

my $hoge ="あ!(´・_・`)さんだ";
$hoge =~ s/(´・_・`)/たなこふ/g;
print $hoge;  => あ!(たなこふ)さんだ

いろいろと調べてみると、C 言語のように substr と index を組み合せてやる方法がありましたが、繰り返しで処理するところで詰まってしまいました。クオートすれば動くのですけれど、内部辞書から繰り返しで持ってくるために使えないのです。

my $hoge ="あ!(´・_・`)さんだ";
$hoge =~ s/\(´・_・`\)/たなこふ/g;
print $hoge;  => あ!たなこふさんだ

たまたまクオートする方法を発見できましたのでそれを採用しました。下記のようにして挟めばその内側がクオートされるそうです。

$hoge =~ s/\Q(´・_・`)\E/たなこふ/g;`

オフトピだけれども、minil は git でステージングしていないファイルは処理の対象にしないというのを忘れていて、新規に追加したサンプル文章が見つからないというエラーでずいぶんと時間を使ってしまいました。