My Y2020 Bug | Tom Wyant [blogs.perl.org]
http://blogs.perl.org/users/tom_wyant/2020/01/my-y2020-bug.html
以下のコードを実行すると、1970-01-01が欲しい所に、2070-01-01が返ってくるという問題。
#!/usr/bin/perl use 5.028; use warnings; use POSIX qw(strftime); use Time::Local; my $t = timegm(0, 0, 0, 1, 0, 70); say strftime("%Y-%m-%d %H:%M:%S", gmtime($t));
2070-01-01 00:00:00
https://metacpan.org/pod/Time::Local#Year-Value-Interpretation
Years in the range 0..99 are interpreted as shorthand for years in the rolling "current century," defined as 50 years on either side of the current year.
(snip)
Whenever possible, use an absolute four digit year instead.
Time::Localの仕様として、年数に2桁の値を与えた場合、19xx年と20xx年、現在の時間から近い年を取るらしい。
何故、私はPerlを続けるのか - taro-nishino の日記
http://slashdot.jp/~taro-nishino/journal/475752
はてなブックマーク - Perlはもう終り? | | プログラマ2.0日報 | あすなろBLOG
http://b.hatena.ne.jp/entry/http://blog.pasonatech.co.jp/sugiura/9524.html
はてなもmixiもPerlでできてるようですが、PHPと比較して、「Perlの方が絶対つよいぜ」ということを教えてください。逆に「PHPの方がいいよ」「パフォーマンスも対して変わ.. - 人力検索はてな
スクリプト自体はほぼコピペなので、何の貢献もはたしてないんですが。
ActivePerlからネットワーク共有フォルダのファイル一覧が取得できて、びっくらこいたびっくらこいーたーってことで。
use strict; use warnings; use File::Find::Rule; use Data::Dumper; my $rule = File::Find::Rule->new; $rule->file; $rule->maxdepth(2); # ディレクトリ深さ(お好みで) my @files = $rule->in("//NeighborMachine/SharedFolder"); # \記号を使う場合"\\\\NeighborMachine\\SharedFolder" warn Dumper(\@files);
ActivePerl 5.8 Build 820で動作確認
俺がPerlを捨ててRubyに行った理由と同じ - ’(rubikitch wanna be (a . lisper))
[Ruby] Ruby >>>(越えられない壁)>>> perl (第一種臨界不測日記)
「Perlベストプラクティス」まとめ を読んでふと「Ruby使えばいいのに」と思った - World Wide Walker
「美しいコードを書けるからRubyを選んだ」---Ruby on Rails作者 David Heinemeier Hansson氏:ITpro
Ruby on Railsはすでに60万件以上ダウンロードされました。
またRailsについての書籍「Agile Web Development with Rails」は4万部になりました。
要するに社長になってみて初めて、
「手早く書けた方が効率が良い」という当たり前のことに気づきました。
Perl/10年前で止まっているperlから脱却する方法 - TOBY SOFT wiki
百万回繰り返された例の件について書いてみるよ。あ、タイトルは必要ないよね?このタグだけ見ればわかるものw
総評:とにかく微妙というか、中途半端につかいにくい。いまだにPerlが生きていたり、Rubyにキャッチアップされてるのも納得の出来。これがLL界を制覇したらPerlよりうっとうしい。
おれはもうMooseしかつかわねぇ。後にも先にもMooseMooseMooseMooseMoose!!!!!!!!!!!1111111
ってな人の為にいつでもどこでもMooseする。automooseを実装しますた。
package automoose; use strict; use warnings; sub import { strict->import; warnings->import; } package automoose::before; use Moose; no Moose; package automoose::after; use Moose; my @before = keys %automoose::before::; my @after = keys %automoose::after::; my @exports = do { my %u; @u{@before} = (); grep { !exists $u{$_} } @after }; package UNIVERSAL; use Moose; for my $func (@exports) { __PACKAGE__->meta->remove_method($func); __PACKAGE__->meta->add_method($func,sub { my $class = shift; my $auto = $class.'::__auto__'; no warnings 'redefine'; local *Moose::_get_caller = sub { return $class }; Moose->import( { into => $auto } ); my $code = $auto->can($func); $class->meta->add_method($func,sub { shift; goto $code; }); goto $code; }); } 1;
使い方はいたって簡単。useするだけ。
use automoose; my $obj = Foo->new;
いきなりnewが呼べちゃう。
他にも
use automoose; Foo->has( hoge => is => 'rw' ,default => 9999 ); Foo->has( muge => is => 'rw' ,default => 7777 ); print Foo->new->hoge; print Foo->new->muge; Bar->extends('Foo'); print Bar->new->hoge;
ょーかんたん。げーべんり。
しっかしこれ、automooseだけど実装するの結構めんどかったのよ。Moose-0.44をベースに作ったんだけどさ。
Moose内部で使用している$CALLERって変数がレキシカルなもんだから、どうやってそれを外から制御すればいいのかすんごい苦労したわけさね。
で結局importの引数にinto渡してさらにMoose::_get_caller関数を上書き無理矢理ハックしたってわけさ。
でもね。でもね。でもね。ちょっと聞いてよ。
ふと最新のMoose-0.50見てみたらさ、Moose::__CURRY_EXPORTS_FOR_CLASS__なんて関数が定義されてるわけよ。
外から明示的に$CLASSを変更できるインターフェイスなわけよ。おいおいおいおい、勘弁してくれよ。こっちゃ折角苦労してハックしたのにあっさり公式対応するなってばよ。メゲルヨ?ぼく。
まぢめげるよ。めげる。ってかもうめげたよ。もうMooseなんてつかわんね!つかわんね!
Mooseなんて大嫌いだー!
俺はMooooooooooseをやめるぞぉおおおおおおおおお、JOJOぉぉぉおおおおお!!!!11
ちょっとアレ見な Moooooooooooooooose!が通る
すぐれものゾと 街中騒ぐ
あいつの噂でNantoも走る
それにつけても俺達ゃなんだろう
アクセサ1つに キリキリまいさ
Moose, Moose, Moose, Test and Moose
いつかきめるぜ 稲妻トーク
そんとき俺も Perl Mongerさ
Moose, Moose, Moose, Test and Moose
最近Perl界隈ではMoose、MooseってなんかMooseってのが流行ってるらしい。
自分自身のブログでは、さもずっと前からMoose知ってたかのように振舞うために、増田で先に放出しておく。てへへ。
プログラマ層が限りなく低い増田にこんなこと書いてもだれも見てくれない気はするけど。
初めてのMoose - Mooseのすすめ - はてな#hide-k
meta object protocol について考えてみる - TokuLog 改めChumbyとどきました日記
YappoLogs: Moose のコードを探索して理解を深めた
Mooseってのは結局のところClass::MOPのラッパーみたいなもんだと。
で、Class::MOPってのは何だ?ってことだけど、メタなんとかプログラミング?え?プロトコル?まーどっちでもいい。
よくよく読んでいくとメタなんとかとか大層な名前が付いてるけど、結局のところPerlのpackageそのものの操作をオブジェクティブ扱えるようにしたものみたいだ。
つまりだな、例えばpackageに対して動的に(静的ではなく!)メソッドを追加したい場合、今までなら
package Foo; **Foo::method = sub { return 'hoge'; }; print Foo->method;
のように型グロブに関数のリファレンスを突っ込むということをしなければなかったが
use Class::MOP; my $class = Class::MOP::Class->create('Foo'); $class->add_method('method',sub { return 'hoge'; }); print Foo->method;
みたいな感じでかっこよく追加できるってわけさ。ま、これはほんの一例だけどな。(他にもメソッドを削除したりフックしたり色々できる。その辺は今回省略。)
本来なら「package Foo」とするところを「my $class = Class::MOP::Class->create('Foo');」と書ける。
これの何が良いのかというと、$classというオブジェクト経由でFooパッケージを色々操作できるところにつきる。
型グロブを使用したり「no (warnings|strict)」をしたりパッケージを操作する処理っていうのはPerlのキチャナイ構文が多かったのだが、Class::MOPのおかげでスッキリ綺麗に書けるようになったってこった。
で、次にMooseだが、これは結局のところClass::MOPのパッケージ管理の部分に+αしただけのラッパーだ。
でもその+αってのが結構凄かったりする。
もうこの辺の話はさんざん既出だが、例えばhasという関数を使ってアクセサや型定義が出来たり
package Foo; use Moose; has 'method' => ( is => 'rw', isa => 'Int' , default => '10' ); my $obj = Foo->new; print $obj->method; # 10 $obj->method(50); print $obj->method; # 50 $obj->method('hoge') # Int型じゃないのでエラー
Moose::Roleを使ってRubyのMixinみたいなことができたりする。
でも実はこれらの処理ってのは本当は別に凄くもなんとも無い。
アクセサ生成なんてClass::Accessorがあるし、関数の引数の型チェックなんてのもParams::Validate等昔から存在してるし、Mixinに関してはもともとPerlは多重継承できるので最初からできるし。
じゃあなんでみんなMoose、Moose言ってるのかっていうと、それはやはりClass::MOPの存在が大きいであろう。
綺麗且つ柔軟にパッケージの操作が出来るClass::MOPが土台にあって、今まで別々の役割として存在してきたモジュール達を統合し、よりわかりやすく、より柔軟に、そしてより強力なPerlのオブジェクト指向を構築できるようにした。それがMooseなのだ。
・・・しかし、小生。
Mooseについて調べていくうちに一つ残念に思ったことがある。
オブジェクトにメソッドを追加する機構がないのだ。
オブジェクトにメソッドを追加する、だ。パッケージにではなく、オブジェクトに、だ。
具体例をあげる。
package Foo; use Moose; my $obj = Foo->new; $obj->meta->add_method('hoge', sub { return 'hoge' }); print $obj->hoge; # hoge
ちなみに$obj->metaというのはFooパッケージを管理するClass::MOPへのアクセサだ。
ということは上記の処理はFooに対してhogeというメソッドを追加していることになる。
では次の例。
package Foo; use Moose; my $obj = Foo->new; $obj->meta->add_method('hoge', sub { return 'hoge' }); print $obj->hoge; # hoge my $obj_2 = Foo->new; print $obj_2->hoge; # hoge
$obj_2->hogeが呼べてしまうわけだ。
$obj->metaは結局のところFooパッケージなのだから、そこにメソッドを追加しているので当然の結果である。
$objだけにメソッドを追加することは、Mooseではできないのだ。
非常に残念である。ああ、残念だ。
・・・しかし、小生。
これでもプログラマの端くれである。こんなことでめげていてはMooserを名乗れないのである。(あ、MooserってのはMoose使いの人の俗称ね。今僕が考えたの)
なのでオブジェクトにメソッドを追加できるように拡張して見せよう。
package Foo; use Moose; use Class::Object; my $class_object = Class::Object->can('new'); override new => sub { ref($class_object->(shift))->SUPER::new(@_) }; my $obj = Foo->new; $obj->meta->add_method('hoge', sub { return 'hoge' }); print $obj->hoge; # hoge my $obj_2 = Foo->new; print $obj_2->hoge; # エラー
たった3行追加するだけで実現できる。さすがMoose。
ただし、Class::Objectを利用しているのでFoo->newで返ってくるパッケージがFoo::0といったようにFooではなくなってしまっているのでrefとかでパッケージ名の比較ができなくなってしまう問題が発生する。
でもこれも継承順をいじったりと本気で頑張れば、表向きに見せるパッケージ名をFooすることも可能だろう。
その添削の役目はどこかのハッカーに任せるとして、今日のところはこの辺で終了としたい。
Moooooooooooooose!と叫ぶのが流行ってるみたいなので、もっとも長くMooooooooooooooose!と叫んだ最初の男となるべく下記の処理を残しておく。
length q chdir uc and print chr ord uc q rmdir and do { print chr ord q xor x while $a++ < 0xffffffff } or print chr ord qw q sin q and print chr ord q ne sin and print chr hex length q q shift shmread bless q;
どうーでもいいーですよー。
どうでもいい話ー、聞いてください。
Perlというやつは一応内部的には数値か文字列かをちゃんと分けて変数の管理をしているのです。
でわ、現在ある変数が内部的に数値なのか?内部的に文字列なのか?判別しようと思ったらどうしますか?
こうしてみます。
my @data = ( 100, # 100は内部的に数値 '200' # 200は内部的に文字 ); foreach my $d ( @data ) { if( ($d ^ $d) eq '0' ){ print $d . " = It's numeric\n"; } else { print $d . " = It's string\n"; } }
同じ変数同士を排他的論理和(^)すると、その変数が数値の場合は0になり、その変数が文字列の場合は空文字になるのです。
なぜかって?そりゃ同じ値同士で排他的論理和したら必ず00000000になるでしょう?
で00000000は、数値なら数字の0だし、文字列なら制御コードのNUL文字になるので上記のような処理が成り立つというわけです。
あってますよね?
ってか判別できたからなんだというんだと問われたらぐうの音すら出ません。まったくもってどうでもいい話でした。
結論→一緒。
すまん嘘。
ほぼ同じ意味だって言いたかったの。カンマもイコールダイナリもほとんど同じ感覚で使用できる。
唯一つ違うのはイコールダイナリの左辺に置いた文字列は裸でも良いってところにある。
どういうことか?んー。
my @hoge = ( 'foo' , 'bar' );
これはカンマを使っているわけだが、当然文字列を指定する場合、シングルクォートでくくらねばならない。
しかしイコールダイナリを使えば左辺の値のみシングルクォートでくくらなくてもよくなる。
my @hoge = ( foo => 'bar' );
こういうことだ。当然こんな風にもかける(普通あまりこんな書き方はしないが)
my @hoge = ( foo => bar => baz => 'hoge' );
これらの書き方はハッシュに値を代入する際に良く使われる傾向がある。
my %hoge = ( foo => 1, bar => 2, );
しかし、気をつけなければならないこともある。いくらシングルクォートが必要ないとは言っても記号が混ざってるとその限りではない。
my %hoge = ( 10-1 => 'bar', );
これは引き算と見なされる。10引く1というわけだ。
ドットの扱いにも注意が必要だ。
my %hoge = ( foo.bar => 1 );
このように文字同士だとstrict環境下でエラーになる。だが数値同士ならエラーにならない。
my %hoge = ( 1.1 => 'foo' );
この場合、「1.1」というキーが生成される。
また、vの扱いにも気をつけなければならない。
my %hoge = ( v1 => 'foo' );
上記は「v1」というキーが生成されるが、
my %hoge = ( v1.1 => 'foo' );
上記はエラーになると思いきや、エラーにならずバージョン文字列に変換されてうまく動いてしまう。
標準関数等も文字列として扱われる。
my %hoge = ( rand => 'foo', undef => 'bar', );
関数を展開したくば()をつけると良い
my %hoge = ( rand() => 'foo', undef() => 'bar', );
アンダーバーの扱いにも注意する必要がある。
my %hoge = ( a_a => 'foo', );
これは「a_a」というキーが生成され、正しく動いてくれる。が、数値同士を繋いだ場合は話が別だ。
my %hoge = ( 1_1 => 'foo', );
これは「11」というキーになってしまう。この問題は1_1と11が等価であることに起因する。気をつけたし。
しっかし、「,」と「=>」はほぼ同じと言っておきながら「=>」を使う場合は裸の文字列の扱いに対する注意が多すぎて困る。
404 Blog Not Found:coders.each{|you| you.get(this) if you.langs[0] != 'ruby' } # - 書評 - 初めてのRuby
1章 ようこそ、Rubyのある生活へ
1.1 Rubyの特徴
1.1.1 オブジェクト指向言語
1.1.2 より良いPerl
ある研究によれば、生産性はそれぞれのプログラマでそれぞれ違う。
でも、あるプログラマに着目すれば、
そのプログラマが時間あたりに書けるコードの行数は、プログラミング言語によらず決まっている、
たとえば一年に50,000行なのだそうだ。
行数が決まっていたら、
どの言語で一番多くのことを達成できる?
そう、Rubyだよね。
例えば C のプログラムより 50 倍遅くなったとして、実行時間はどのくらい変わるだろうか?
もし C のプログラムが 0.01 秒で終わる としたら、
Ruby 版は 0.5 秒。あなたのプログラムは 0.49 秒速くす るために C で書く価値があるのか?
プログラムは開発の時間よりも保守の時間のほうがかかるというのはもはや常識だけども、
Ruby で書いてあれば例えば、
そういう点でも Ruby は非常にいい。
だいたい、スピードに対してごちゃごちゃ言うなら C じゃなくアセンブラで書けばいい。
それをなんで C で書いてるのかって言えば、
それはもちろん「コードがわかりやすい」とか、「早く書ける」って のが理由だろう。
そして、Ruby は C よりわかりやすいし速く書ける。
404 Blog Not Found:「PHPなめんな」と「(Perl|Python|Ruby)をなめんな」の違い
実行速度より実装速度(前編) - Object Station
最近perlの勉強してて、naoyaのはてなダイアリー - Web::ScraperでWeb::Scraperを知り、試しにはてブのAPIを真似してニフティクリップのコメントを吐くJSONを作った。
#!/usr/local/bin/perl -T # # use strict; use warnings; use URI; use Web::Scraper; use JSON::XS; use CGI; use Encode; my $q = new CGI; print $q->header( -type=>'text/plain', -charset=>'UTF-8'); my $path_info = $q->path_info; my $path = $path_info =~ m{^/?(nobracket/)?(http\w?)://?(.*)$}xms ? $2.'://'.$3 : undef ; exit if ! $path; my $is_nobracket = 'true' if $1; if ($q->query_string) { my $query_string = $q->query_string; $query_string =~ s/;/&/g; $path = $path.'?'.$query_string } $path =~ s/%23/#/; $path =~ s/([^\w ])/'%' . unpack('H2', $1)/eg; $path =~ tr/ /+/; my $entry_url = "http://clip.nifty.com/entry/?url=" . $path; my $bookmarks = scraper { process 'h4>a', 'user' => 'TEXT'; process 'li.dateAndTime', 'timestamp' => 'TEXT'; process 'a.tagtag', 'tags[]' => sub { my $text = $_->as_text or return; my $left = decode_utf8('??~P'); my $right = decode_utf8('??~Q'); return $text =~ /$left (.*?) $right/xms; }; process 'p.comment', 'comment' => 'TEXT'; result 'user', 'timestamp', 'tags', 'comment'; }; my $niftyclip_entry_info = scraper { process 'div.clipTitle>h3>a', 'title' => 'TEXT'; process 'div.clipTitle>p.url>a', 'url' => '@href'; process 'div.comments>div.commentsDetails', 'bookmarks[]' => $bookmarks; result 'title','url','bookmarks'; }; my $niftyclip = scraper { process 'div#content', 'niftyclip_entry' => $niftyclip_entry_info; result 'niftyclip_entry'; }->scrape(URI->new($entry_url)); exit if ! ($niftyclip->{'url'}); $niftyclip->{'entry_url'} = $entry_url; $niftyclip->{'count'} = @{$niftyclip->{'bookmarks'}}; my $json = JSON::XS->new->utf8->encode($niftyclip); $json = '('. $json. ')' if ! $is_nobracket; print $json;
取得方法は
http://monm.on.coocan.jp/niftyclip/json/entry/<取得したいURL>
ってすればいい。「#」は「%23」にエスケープしないとダメ。
作りながら「取得したいURLをURLエンコードするのは面倒だな」って思い、はてブのAPIみたいにpath_infoでアクセスできるようにしたわけだけど、その取得したいURLにquery_stringが付いてた場合にどうやってやって良いかわからず結構悩んだ。
結局、path_info+'&'+query_stringってやることで無理やり作ったけど、普通どうやるもんなんだろ?cpanに何か良いモジュールがあったりするのかな。
それと、はてブに合わせて出力の際に()を付けるようにしたけど、これだとYahoo!Pipesで使えなかったから、
http://monm.on.coocan.jp/niftyclip/json/entry/nobracket/<取得したいURL>
みたいに「nobracket」付きでアクセスした場合には()を付けないようにした。
コレ使うとニフティクリップとlivedoor クリプのコメント取ってくるAPIみたいなのが作れる。
RSSで取得する場合は
http://pipes.yahoo.com/pipes/pipe.run?_id=zECBJ_VY3BGtBw6B8ivLAg&_render=rss&URL=<URLエンコードしたURL>
で取得できるし、jsonで取得する場合は
http://pipes.yahoo.com/pipes/pipe.run?_id=zECBJ_VY3BGtBw6B8ivLAg&_render=json&URL=<URLエンコードしたURL>
ってなる。
とりあえずサクッと作ってみたけど、わざわざページからJSON作ってるからちょっと重い。
その頃にはJSON吐いてくれるようになるんじゃないかなと期待はしてるけど。
参考URL: