別枠でやっているトークが非常に面白そうですが、途中で抜けられると悲しみ。(僕も行きたい)
ベストスピーカーの投票だけは何卒…
ちなみにトークの最後に驚きの発表が…?
いろいろな仕事・いろいろな技術を使ってきたけど、Webの仕事をしたかったのとPerlが書きたくてカヤックに転職(2011年)。
それからPerlをたくさん書くように。
2番目!
I love and hate all languages.
~ Go Conference 2014 spring
言語には良し悪しがあるし、Perlには古臭い部分があるのも事実だろう。
でも、自分よりはるかに総合力の高いエンジニアの中にPerlを好んで使う人がいるという 事実から学ぶべきところもあると考えた方が良いのではないだろうか。
PerlをdisりたいならPerlを学んでから来てください。(Uzullaさんインスパイア)
if (my $prop = $obj->prop) {
...
}
ところでgolangだとこう書けるの良い
if prop := obj.Prop(); prop != nil {
...
}
sub sub_name {
my ($arg1, $arg2) = @_;
# <- ここが揃うのが好き(但し4スペに限る)
}
package Class::Name; # クラスを定義(名前空間がクラスになる)
sub new {
my ($class, %args) = @_; # 第一引数はクラス名(Class::Name)
my $obj = bless {%args}, $class;
return $obj;
}
# my $obj = Class::Name->new(%args); とか呼び出す
bless
を使って、単なるデータ構造(この場合ハッシュ)をオブジェクトに昇格させる。
(僕は昔JavaとかやってたけどPerlでオブジェクト指向がわかった(かも))
sub prop {
my $self = shift; # 第一引数からオブジェクトを取り出す
return $self->{prop}; # ハッシュrefのフィールドから読み出す
}
# `$obj->prop()` でアクセス `$obj->prop` と()を省略可能
sub prop {
my $self = shift; # 第一引数からオブジェクトを取り出す
$self->{prop} = shift if @_; # 引数が残っていたら値をセット
return $self->{prop};
}
# `$obj->prop()` でアクセス `$obj->prop` と()を省略可能
# `$obj->prop(10)` で値をセット
あくまでも実装の一例
$obj->prop = 'hoge'
とか出来ないのはちょっとカッコ悪い(:lvalue使う手はあるけどやらない)$obj->{prop}
に外部から直接アクセスするのはマナー違反基本的には素のオブジェクト指向を別の書き方で実現できるようにしているだけ。
Scalar::Util::weaken()
で対処するTest::LeakTrace
で確かめるmy $hoge = 'hoge';
{
my $obj = Hoge::Fuga->new;
say $hoge; # hoge
}
# $objはここでは参照不可能
ということを利用したテクニック。終了処理を確実にやりたいときなどに重宝する。
デストラクタを利用しているので、循環参照に注意。シグナルにも注意が必要。
use Scope::Guard;
{
my $guard = Scope::Guard->new(sub {
say 'ya!';
});
say 'say'
} # say\n ya! の順に出力される
# 以下のシンタックスシュガーも提供されている
{
my $guard = scope_guard {
say 'ya';
}
}
スコープを抜けた時に確実に実行させたい処理を記述しておく。golangで言うところのdefer
use Test::Mock::Guard;
{
my $guard = Test::Mock::Guard->new('ClassName', {
method1 => sub {
...
},
})
}
スコープの中でクラスの挙動を差し替える。スコープを抜けると元に戻る
use Test::mysqld;
my $mysqld = Test::mysqld->new(my_cnf => {'skip-networking' => ''});
my $dbh = DBI->connect($mysqld->dsn);
テスト用にサラのmysqldを起動する。$mysqldはガードオブジェクトにもなっていて、オブジェクトが破棄されるときにちゃんとMySQLのプロセスを落とすようになっている。
Proc::Guard
っていう汎用的な別モジュールも。
Test::mysqld大好き。
ファイル一気読みの例
my $content = do {
local $/;
open my $fh, '<:encoding(UTF-8)', 'filename' or die $!;
<$fh>
};
# この例は以下で良い :p
use Path::Tiny
my $content = path('filename')->slurp_utf8;
ref. 複雑なデータ構造の中にうまっているデータのパスをさがす方法
再帰的に呼び出しをする場合にダイナミックスコープを活用することによってスッキリ書くことができる。(静的スコープしか活用できない言語の場合は、引数で頑張って引き回す形になる)
Tengの例。
sub get_userhash_by_id {
my ($teng, $id) = @_;
# row objectを作成をスコープ内で抑制
local $teng->{suppress_row_objects} = 1;
return $teng->single(user => {id => $id});
}
ガードオブジェクトパターンを使ったTeng::Plugin::RowObjectCreationSwitcherもある。
sub hoge($) {
my $scalar = shift;
}
sub run(&) {
my $sub = shift;
$sub->();
}
sub CONST() { 'CONST' } # 定数 (定数扱いにならないこともある)
sub名の後にparenを付けて引数の型を指定することができる機能だが、今はほとんど使われない。DSLを作るときに活用されるという本来の目的とはちょっと違う用途に使われることがある。
requires 'Plack::Request';
on test => sub {
requires 'Test::More';
};
namespace db => sub {
desc 'データベースをmigrateします';
task migrate => sub {
sh 'tools/db/migrate';
};
};
desc 'テスト回します';
task test => sub {
my ($task, @args) = @_;
sh qw(prove -lr), @args;
};
desc 'CPANモジュールをインストールします';
task install => sub {
my ($task, @args) = @_;
sh qw(cpanm --quiet --with-develop --notest --installdeps .), @args;
};
create_table book => columns {
integer 'id', primary_key, auto_increment;
varchar 'name', null;
integer 'author_id', not_null;
decimal 'price', 'size' => [4,2];
add_index 'author_id_idx' => ['author_id'];
belongs_to 'author';
};
Perlは記号が多いとは何だったのか。(多いこともありますね…)
my @array
(1, 2, 3)
Perlではサブルーチン(含メソッド)の引数は、@_
にフラットに格納されているので委譲が簡単に書ける。
sub method {
my ($self, @args) = @_;
$self->obj->method(@args);
}
# 以下も同じ
sub method {
shift->obj->method(@_); # shift は shift(@_) と同じ
}
javascriptだとapplyとかを使う。
ClassB.prototype = {
obj: new ClassA(),
method: function() {
this.obj.method.apply(this, arguments);
}
};
use List::MoreUtils qw/uniq/;
say for uniq sort map {
split /-/, $_ # splitで分割された複数の結果がフラットに返される
} qw/1-2-44-58 3-33-15-1/;
逆順に考えないといけないのでそこは分りづらい。
Rubyだとこういうふうに順番に書ける。flattenが必要になる(と思う)。
%w(1-2-44-58 3-33-15-1).map {|v| v.split(/-/)}.flatten.sort.uniq.each{|v| puts v}
よくある無知な人の思考停止テンプレdisなので、どうでもいいんですが、
Sigil($hogeの$)があるから、記号が多いってのはちょっと違うと思っていて、変数にSigilがあるから、関数やメソッドの括弧を省略しても違和感がない部分があると思っていて、例えば、Rubyなんかだと、関数と変数の区別がつかず、優先順位の問題でこの場合は括弧が必要とかそういうのがある。
JavaScriptとかGolangみたいにメソッド呼び出しは括弧が必須で、括弧がない場合はFunction型が返るってのはいいなとか思います。関数呼び出しに括弧が必須だとDSLとかがちょっとかっこ悪くなっちゃうけど、括弧が必須ならsigilは無くても良いんだろうな、という感じはします。
デリファレンスとかその辺は、まあ、ぱっと見は汚く見えてしまうだろうなーとは思う。慣れの問題ではあるけど。
http://hatenacorp.jp/recruit/career/