タグ

ブックマーク / gfx.hatenadiary.org (28)

  • bless($args, $class) is a bad practice - Islands in the byte stream (legacy)

    さいきん散見される以下のようなコードは悪いコードです。 # usage: Foo->new({ age => 42 }) sub new { my($class, $args) = @_; return bless $args, $class; } それは、ハッシュリファレンスと想定される$argsのそのままつかっているため、引数としてハッシュリテラル以外の何かを渡すと予期しない動作を引き起こすという点です。 たとえば、以下のような使い方は問題を引き起こします。 my %args = (age => 20); my $o1 = Foo->new(\%args); my $o2 = Foo->new(\%args); # ここで $o1 と $o2 は同じオブジェクトになってしまう このような場合、$argsはコピーすべきです*1。またついでにハッシュリファレンスではなくkey-value

    bless($args, $class) is a bad practice - Islands in the byte stream (legacy)
    kwry
    kwry 2013/08/19
  • overloadプラグマの使い方 - Islands in the byte stream (legacy)

    404 Blog Not Found:紹介 - Software Design 2013年06月号 呼ばれてないけど勝手に添削。 use overload '""' => 'toString', '_' => 'add', ; はないわー。そこは use overload '""' => \&toString, '_' => \&add, ; でしょうが。 いいえ、overloadプラグマの引数は文字列でいいんです。でないとサブクラスでオーバーライドできませんから。 つまり、overloadプラグマへ与えるメソッドの実体$methodは、$obj->$method()として与えられたかのように振舞うのです。コードリファレンスを与えると、メソッドのレシーバが何であろうとそのコードリファレンスが呼び出されてしまいます。文字列であれば、サブクラスでたとえばtoString()メソッドをオーバーラ

    overloadプラグマの使い方 - Islands in the byte stream (legacy)
    kwry
    kwry 2013/05/25
  • 環境変数にいろいろ突っ込み過ぎると危険があぶない - Islands in the byte stream (legacy)

    $ export FOO=`perl -E 'say "." x 1_000_000'` $ perl -v bash: /usr/bin/activeperl: Argument list too long 簡易的にIPCをする方法として環境変数にJSONを突っ込んでサブプロセスから参照する、みたいなことはたまにすると思いますが、ちょっと大きなデータを突っ込むとサブプロセスを起動できなくなります。データサイズが未知の場合は使ってはいけない方法ですね。 Max sizeはカーネル次第ですがだいたい128KiBくらいらしく意外と小さいです。 環境変数にJSONを突っ込むというのはxaicronメソッドによるTest::mysqldの永続化でやったりするのですが*1、以下のように他にもいろいろやりだしたりするとある日突然うごかなくなって危険があぶないのではないかと思った次第です。 make t

    環境変数にいろいろ突っ込み過ぎると危険があぶない - Islands in the byte stream (legacy)
    kwry
    kwry 2013/01/26
  • SYNOPSISの構文を自動でチェックする - Islands in the byte stream (legacy)

    新しいモジュールの使い方を調べるときに真っ先に目を通すのがPODのSYNOPSISセクションである。特に,英語が母語ではないPerlerにとってはPODの中で最も重要なセクションといっても過言ではない。それだけに,自らモジュールを書くときは細心の注意を払う。 ところで,その内容の構文チェックは今まで手動でやっていたのだが,Test::Weakenのテストファイルを眺めていると面白いテストがあった。synpsis.tというのがそれで,PODのSYNPISISセクションの中身を抜き出して実行するというものだ。考えてみれば,構文チェックで十分なら特別なモジュールのサポートを得なくても簡単に書くことができる。 そこで,一般化してModule::Setup用のテンプレートにしてみた。 #!perl -w use strict; use Test::More tests => 1; use [% mo

    SYNOPSISの構文を自動でチェックする - Islands in the byte stream (legacy)
  • PerlでAssert - Islands in the byte stream (legacy)

    Perl5.9の時点では,assersionsと-Aコマンドラインスイッチという仕組みでCのassert(3)のようなことができるようになるはずだったらしい。しかし,そのメカニズムはPerl5.10には結局採用されなかった。 開発中はassert()が欲しい,しかし,リリース後の実行時パフォーマンスは落としたくない,というのがAssertを考えるときのジレンマというわけだ。そんななかで,CPANのCapr::Assertは関数呼び出しを完全に消し去ることができるので悪くない方法だと思う。 use Carp::Assert; assert($x > 1) if DEBUG; DEBUGはCarp::Assertの提供する定数関数で,その値が偽ならばこの一文はコンパイル時に完全に削除される。 $ PERL_NDEBUG=0 perl -MO=Deparse -MCarp::Assert \ >

    PerlでAssert - Islands in the byte stream (legacy)
    kwry
    kwry 2012/01/12
  • Perlのメモリリークを見つける方法 - Islands in the byte stream (legacy)

    Perlではメモリリーク検出ツールがいくつか開発されているので、top(1)の結果を眺めるよりそういうツールを使うほうが楽である。 さて、メモリリークが発生しているとき、その可能性としてはだいたい以下の4つが挙げられる。 Perlレベルでの循環参照 グローバル変数に値をどんどん足しているとき*1 XSレベルでリファレンスカウントの管理ミス XSレベルでmalloc()したメモリの管理ミス この1-3についてはすべてPerlインタプリタ内の出来事であり、Test::LeakTraceを使って検出できる。4を検出するのは難しいが、Test::Valgrindが役に立つ。 Test::LeakTraceのSYNOPSISは歴史的経緯によりごちゃごちゃしているが、テストで使うべき関数はno_leaks_ok()とleaks_cmp_ok()だけである。 たとえば、以下のようにして使う*2。 #!p

    Perlのメモリリークを見つける方法 - Islands in the byte stream (legacy)
  • each()は遅い上に微妙な問題も起きやすい - Islands in the byte stream (legacy)

    特別な条件がないかぎり、each()は使うべきではありません。代わりにkeys()/values()を使うべきです。その理由は2つあります。 each()は遅い each()でハッシュ全体をループするのは遅いです。これは、keys()/values()がその内部の値をそのまま参照する*1のに対し、each()は代入しないとその値を使えないからです。 ベンチマーク: #!perl use strict; use warnings; use Benchmark qw(cmpthese); my %hash = map { $_ => $_ } ( 1 .. 10000 ); cmpthese -1, { each_k => sub { while(my $key = each %hash) { } }, each_kv => sub { while(my($key, $value) = eac

    each()は遅い上に微妙な問題も起きやすい - Islands in the byte stream (legacy)
    kwry
    kwry 2011/06/04
  • lib::xi - installs missing libraries on demand - Islands in the byte stream (legacy)

    gistなどで公開されているPerlスクリプトを実行する際、モジュールが足りないことがよくあります。そういう場合はCan't locate Foo.pm ...というエラーメッセージを見ながらモジュールをインストールするわけですが、決まりきった作業にうんざりしたので自動的にそれをするモジュールを書きました*1。 https://github.com/gfx/p5-lib-xi `perl -Mlib::xi script.pl`とするだけで、足りないモジュールをcpanmで適当にインストールしてくれます。 -Mlib::xi=extlibとすれば既存の環境を壊すことなくlocal::lib的にextlib/にインストールして実行できますし、-Mlib::xi=-L,extlib,-qなどとしてcpanmにオプションを渡すこともできます。 これで退屈なインストール作業をしなくてすむはずです。

    lib::xi - installs missing libraries on demand - Islands in the byte stream (legacy)
  • JavaScriptにおけるオブジェクトの定義 - Islands in the byte stream (legacy)

    JavaScriptで一番簡単にオブジェクト指向プログラミングを行う方法 (id:perlcodesample) 私は特にJavaScriptに詳しいわけではなく、オライリーの『JavaScript』、通称サイを読んだ程度なのですが、私の知るかぎりJavaScriptでオブジェクト*1を定義する方法には二つの軸があります。一つ目はオブジェクトの生成方法で、二つ目はメソッドの与え方です。すなわち: new演算子で生成する / オブジェクトリテラルで生成する prototypeによってメソッドを生やす*2 / プロパティを直接代入してメソッドを生やす これについて具体的に説明してほしいとのことでしたので、以下にこの二つの軸の組み合わせ、計4つの方法を示します。 (実行可能なコードはjsdo.itにて: http://jsdo.it/gfx/9LR3) var pointToString =

    JavaScriptにおけるオブジェクトの定義 - Islands in the byte stream (legacy)
    kwry
    kwry 2011/02/27
  • Tips on IEC (implicit encoding conversion) - Islands in the byte stream

    Perlにおいて日語のテキスト文字列とバイナリ文字列*1を結合すると激しく文字化けするのは誰もがつまづくトラップですが、これはPerlのデフォルトのIECが Latin-1 に基づいて行われるからです。UTF-8ではなくLatin-1なのは後方互換のために必要な決定なのですが、我々日人にとってはこのせいで文字化けに苦しまれることになってしまいました。 そこで、IECが発生したときに致命的エラーを発生させるプラグマを書いてみました。 https://github.com/gfx/p5-encoding-implicit `no encoding::implicit` によって、そのスクリプト全体でIECを禁止します。これはencoding::warningsプラグマとほとんど同じですが、デフォルトで警告ではなく致命的エラーであること、スクリプト全体に効果があることが異なります。これにより

    Tips on IEC (implicit encoding conversion) - Islands in the byte stream
  • Data::Validatorの凝った使い方 - Islands in the byte stream (legacy)

    https://github.com/gfx/p5-Data-Validatorが大体できたのでリリースしました。 基的には名前で引数を指定する関数向けですが、メソッド用に対応したりリストスタイルで引数を指定したりする拡張機能もあります。 まず、$validator->with('Method') でメソッド用になります。ただし、第一引数の型はいまのところ指定できません: use feature 'state'; use Data::Validator; sub Foo::add { state $rule = Data::Validator->new( a => 'Int', b => 'Int', )->with('Method'); my($self, $args) = $rule->validate(@_); return $args->{a} + $args->{b}; } p

    Data::Validatorの凝った使い方 - Islands in the byte stream (legacy)
    kwry
    kwry 2011/01/02
  • Re: バリデーションはどの位置で必要か - Islands in the byte stream (legacy)

    バリデーションはどの位置で必要か - サンプルコードによるPerl入門 バリデーションはアクセサメソッドの内部で行うのではなく、バリデーションの専用のモジュールを使用して、データを受け取った入り口で行うのがよいでしょう。 私はこれには反対です。アプリケーションにせよライブラリにせよ、原則としてすべての公開APIの入力値はバリデーションするのが望ましいと考えます。 すなわち、アクセサメソッドもそれがパブリックなAPIであればバリデーションをしたほうがいいと思います。 とはいえ以下の基的な考え方に異論があるわけではありません。 データのバリデーションを行う主要な目的は、外部から入力されるデータが正しい値かどうかをチェックするためのものです。 問題は、どこまでを「外部からの入力」とみなすかということでしょう。私は、そのプログラム/ライブラリのパブリックなAPIが受け取る値はすべて「外部からの入

    Re: バリデーションはどの位置で必要か - Islands in the byte stream (legacy)
    kwry
    kwry 2011/01/02
  • Don't use base.pm, use parent.pm instead! - Islands in the byte stream (legacy)

    「使っちゃいけない標準モジュール」*1の反響を見ていると、baseが非奨励ということに驚かれた方が少なくありませんでした。そこで、baseについて補足します。 まずbase.pmのドキュメントの最初の文は以下のようになっています。 Unless you are using the fields pragma, consider this module discouraged in favor of the lighter-weight parent. (拙訳: fieldsプラグマを使用しているのでないかぎり、このモジュールは勧められない。かわりに軽量なparent.pmを使う方がよい。) fieldsプラグマは、ハッシュリファレンスのキーを固定したオブジェクトを作成するための機能ですが、あまり一般的ではないためここでは解説しません。特に理由がない限り、ここは素直に忠告に従った方がいいでし

    Don't use base.pm, use parent.pm instead! - Islands in the byte stream (legacy)
  • Idea of Data::Validator - Islands in the byte stream (legacy)

    Smart::Argsは無駄がなくて使いやすいのですが、欠点はXSモジュール(PadWalker)への依存があることと、Perlの作法を完全に無視していることです。 そこで、試みにData::Validatorというモジュールを書いてみました。 https://github.com/gfx/p5-Data-Validator コンセプトは以下の通り: 機能的にはSmart::Args + X Pure Perlでも動く Perlの作法に則る 十分に速い 使い方は以下の通り #!perl -w use 5.010_00; use strict; use Data::Validator; sub request { state $rule = Data::Validator->new( url => { isa => 'Str', xor => [qw(schema host path_que

    Idea of Data::Validator - Islands in the byte stream (legacy)
  • Simple zcat(1) in Perl with Compress::Raw::Zlib - Islands in the byte stream (legacy)

    Perlのzlibインターフェイスは沢山あってよく分からないが、単純に圧縮/解凍をするだけならCompress::Raw::Zlibがシンプルで良さそうだ。 これでzcat(1)を実装すると以下のようになる。 #!perl -w use strict; use Compress::Raw::Zlib; my $z = Compress::Raw::Zlib::Inflate->new( -WindowBits => WANT_GZIP, ); foreach my $file(@ARGV) { open my $fh, '<', $file or die "Cannot open $file: $!"; while(read $fh, my $buf, 1024) { my $d; my $status = $z->inflate($buf, \$d, 1); ($status == Z_

    Simple zcat(1) in Perl with Compress::Raw::Zlib - Islands in the byte stream (legacy)
  • YAPC::Asia 2010 Tokyoで発表しました - Islands in the byte stream (legacy)

    至らない点は多々ありましたが無事発表を終えることができました!ありがとうございました! How Xslate WorksView more presentations from gorof.ちょっと捕捉します。 まず会場の質疑応答から(スライドにも簡単に追記しました)。 Q. テンプレートをPerlコードに落とし込んでperlに実行させるというモデルもあると思うが、敢えて独自VMを実装した理由は? A. たしかに、Perlコードに落とし込むテンプレートエンジンはあり、Template::ToolkitText::MicroTemplateなどはそうしています。しかしPerlは汎用のインタプリタであり、テンプレートのレンダリングに特化しているわけではりません。Xslateは汎用性を犠牲にし、高速化を図っています。特に、出力バッファに対する文字列の連結に大きな差があります。なので、独自VMの

    YAPC::Asia 2010 Tokyoで発表しました - Islands in the byte stream (legacy)
  • Let's use the /x modifier! - Islands in the byte stream (legacy)

    Perl ベストプラクティス』はクセの強いではあるが、私のプログラミングスタイルが受けた影響は少なくない。なかでも、PBPによってPerlの正規表現の/x修飾子のすばらしさを知ったことは大きい。これはPBP以前は使おうと思ったことがなかったが、今となってはこれなしに複雑な正規表現を書こうとは思わない。 /x修飾子は、正規表現中の空白を無視し、コメントを入れられるようにするための修飾子だ*1。 以下の正規表現は、Text::Xslateから抜粋したものだ。 In Text/Xslate/Util.pm: our $NUMBER = qr/ (?: (?: [0-9][0-9_]* (?: \. [0-9_]+)? \b) # decimal | (?: 0 (?: (?: [0-7_]+ ) # octal | (?: x [0-9a-fA-F_]+) # hex | (?: b [01

    Let's use the /x modifier! - Islands in the byte stream (legacy)
  • Xslateが特定の条件で落ちる件(fixed in 0.2009) - Islands in the byte stream (legacy)

    Xslateが特定の条件で落ちるという現象がいくつか確認されていました。 Xslateでテンプレート大きいと困った件 ←修正されました - pepponの日記 http://twitter.com/kaz_hosib/status/26527707914:twitter id:pepponさんの記事を参考に巨大なファイルを生成してrender()したところ、5.8.9でSEGV、5.12.2で致命的エラーとなって落ちることを確認したため、修正してXslate 0.2009をリリースしました。ご確認ください。 http://search.cpan.org/dist/Text-Xslate/ これは、Xslateではなくperlの正規表現エンジンのバグ(あるいは限界)であったようです。 5.12.2で出力されるエラーメッセージに対するperldiagのエントリは以下の通り: Complex r

    Xslateが特定の条件で落ちる件(fixed in 0.2009) - Islands in the byte stream (legacy)
    kwry
    kwry 2010/10/06
  • Data::MessagePackをXslateのキャッシュ保存用に使ってみる - Islands in the byte stream (legacy)

    Text::Xslateのコンパイル済みコードは今まで独自フォーマットで保存しており、これはこれでデバッグしやすくて便利だったが、CLIアプリケーションではこのコンパイル済みコードのロードにほとんどの時間を費やす羽目になっていたのだった。そこで、速度が売りのシリアライズフォーマットmessagepackを使ってコンパイル済みコードを保存するようにしてみた。計測には、自分用のpmsetupであるところのdimを使った。 version 0.2008 (original): $ time dim init --force Foo::Bar >/dev/null real 0m0.220s user 0m0.156s sys 0m0.019sversion 0.2008_01 (using Data::MessagePack): $ time dim init --force Foo::Bar>

    Data::MessagePackをXslateのキャッシュ保存用に使ってみる - Islands in the byte stream (legacy)
  • Re: Perlスクリプトの一行目には何と書くべきなのか - Islands in the byte stream (legacy)

    Re: Perlスクリプトの一行目には何と書くべきなのか もしCPAN形式でスクリプトを配布するなら、それは#!/usr/bin/perlないし#!perlとするべきで、env(1)を使うべきではないと思います。 CPAN形式のディストリビューションでは、インストールするスクリプトのshebang行をインストール直前に修正し、正しいパスに書き換えてくれます。ただし、このルーチン*1はいまのところenv(1)を認識してくれません。つまり、env(1)を使った場合、インストールに使用したperlと実際に実行されるperlが一致するとは限りません。perlを一つしかインストールしていないシステムなら、これでも問題なく動きます。しかし最近では、システムにインストールしてあるperlには触らず、アプリケーション用のperlを別途perlbrewなどでインストールしてそちらを使うということもよく行われ

    Re: Perlスクリプトの一行目には何と書くべきなのか - Islands in the byte stream (legacy)
    kwry
    kwry 2010/09/14