YAPC::Fukuokaに参加し、cpmの話をした

7/1に行われたYAPC::Fukuokaに参加し、cpmの話をした。

guest speakerとして

今回、僕はなぜかguest speakerとしての参加となった。 最初にpapixさんからこのお話しをいただいたとき、断ろうと思っていた。 もっと優秀なPerl Hackerが大勢いる中で、なぜ僕が、と思ったからだ。

しかし、いろいろ考えたあげく、受けるべきと考え直し、お受けした。

トーク

speakerdeck.com

github.com

(注: スライドのなかのdemoは https://asciinema.org/~skaji にある)

cpmについて話した。cpmについては、もう何度も発表しているのだが

  • まだまだCPANまわりはやることがたくさんあり、また何でもできると伝えたい
  • PerlCLIアプリケーションを並列化する例を伝えたい

の思いから再びcpmを選んだ。

発表後、いくつか質問、コメントをいただいた。

まず、もうcpmをどんどん使っていいのか、ということ。僕は毎日使っているし、相当バグは潰したつもりだ。僕が言えることのは、どうぞ使ってくださいということだけ:)

次に、Cartonとの関係性。実際のところcpmはcpanfile.snapshotをresolverとする機能を搭載している。よってsnapshot作成の部分以外は、Cartonと同じように使える。

Cartonとの関係性については、まだしっかりと言語化ができていないので、次のXX.pmにて、ぜひみなさんと議論したい。

印象に残ったトーク

印象に残ったトークをすこしだけあげる。

まずはmoznionさんのエラーメッセージに関するトーク。 moznionさんは、いつも対象を丁寧に捉え、そして的確な命名をし、分かりやすい説明をしてくれる。今回もまさにそういったトークだった。素晴らしかった。

次にkeynote 山本さんのトーク。家族をもつエンジニアが、どうNYでsurviveしていくかというトークだった。よかった。

最後に

papixさんをはじめとするスタッフの方々、 素晴らしい場を作ってくださりありがとうございました。 YAPC、とても楽しかったです!

次はokinawa!

travis ciで失敗したテストを再実行する

perlのmoduleを開発しているとき、travis ciでときどき失敗するテストがあり、失敗するたびにRestart buildボタンをポチっと押すという不毛なことをしていた。

もちろん失敗する原因をちゃんと特定し、テストをなおすのが一番だが、とりあえず失敗したテストを自動でリトライさせるなら下記のように書けばいいことを最近知った。

language: perl
perl:
  - '5.24'
  - '5.22'
  - '5.20'
script:
  - prove --state save -l t || prove --state failed -l
sudo: false

最初のproveで--state saveを指定しておき結果を.proveファイルに保存する。そして失敗したときは、--state failedのテストを対象にproveを再び走らせている。

実際cpmでこうしている。

forkを使うテストではTest2::IPCを使うといい

perlでforkを使うテストでは Test::SharedFork をuseしておくと安心なことが知られているが、最近その実装をみたところTest2がロードされていたら、そのIPC実装を使うように変わっていた。

よっていま、forkを使ったテストを新しく書くなら、直接Test2::IPCを使えばいいと思う。

use strict;
use warnings;
use Test2::IPC;
use Test::More;

my $pid = fork // die;
if ($pid == 0) {
    is 1 + 1, 2;
    exit;
}
waitpid $pid, 0;

done_testing;

実際、Mojo::IOLoop::Signalのテストでそうした。

pipeを他プロセスから読み書きする

長らくpipeは自プロセスもしくは 親子プロセスでしか読み書きできないものと思っていたが、 最近、他のプロセスからも読み書き可能なことを発見した。つまり/proc/pid/fdを使えばよい。

自分としてはかなりの驚きであった。

例えば、

#!/usr/bin/env perl
use strict;
use warnings;

pipe my $read, my $write or die $!;

while (my $line = <$read>) {
    warn "-> GOT: $line";
}

というのを用意したとき下記のように通信できる。

$ perl pipe.pl &
[1] 13801

$ ls -l /proc/13801/fd
total 0
lrwx------ 1 skaji skaji 64 Nov  6 15:30 0 -> /dev/pts/6
lrwx------ 1 skaji skaji 64 Nov  6 15:30 1 -> /dev/pts/6
lrwx------ 1 skaji skaji 64 Nov  6 15:30 2 -> /dev/pts/6
lr-x------ 1 skaji skaji 64 Nov  6 15:30 3 -> pipe:[4096813]
l-wx------ 1 skaji skaji 64 Nov  6 15:30 4 -> pipe:[4096813]

# filedescriptor4が書き込み用pipeなのでそこに書き込む。
$ perl -E 'open my $fh, ">", "/proc/13801/fd/4" or die $!; say {$fh} "hello from $$"'
-> GOT: hello from 13843

なお、同じやり方で例えば tmpfile(3)によってopen、すぐunlinkされたファイルも他プロセスから読み書き可能だ。

use Foo () としたときFoo->importが呼ばれないのはなぜか

perl5の話題。

use FooとするとFooをrequireしつつ、Foo->importが呼ばれることはよく知られているが、 use Foo ()としたときには、importは呼ばれない。

これをどういう風にして実現しているのか前から疑問に思っていた。 というのも普通の関数は「引数なし」と「空リストの引数」を区別できないからだ。

perlソースコードをみたところ、 parseのところで「引数なし」と「空リストの引数」を区別しているとわかった。

https://github.com/Perl/perl5/blob/v5.24.0/op.c#L6048

https://github.com/Perl/perl5/blob/v5.24.0/perly.y#L346-L354

追記

plenv-update

UPDATE Ooops, there already exists https://github.com/hfm/plenv-update . You should use it!


github.com

Are your plenv and its plugins up-to-date?
Make sure they are up-to-date with plenv-update.

plenv-update adds plenv update command that updates plenv and all installed plugins at one time.

f:id:shoichikaji:20161009120844p:plain

Remove all ads

plenv freeze

plenv のplugin、plenv freezeを作った。 github.com

たとえばCPAN moduleを作っている人は、テストのため あるperlのinstallationを コアモジュール以外何もインストールしていない状態に保っていたいことがあるかもしれない。 plenv freezeは、あるperlのinstallationをread only(ファイルは0444, ディレクトリは0555)にすることで、これを助けてくれる。

僕は、このアイデアをgotandapmでのSongmuさんの発表で知った。 http://songmu.github.io/slides/gotandapm4/#6

もともとはmiyagawaさんのアイデアとのこと。

またokinawapmにてpapixさんもこの話をされていた。

ということで、自分含めて少しは需要がありそうなのでpluginとしてまとめてみた。

Remove all ads