[perl]Readonlyやめてdlockにします。

Posted under perl by uechoco on 土曜日 14 4月 2012 at 12 : 15 : 28

最近はphpを触ってもいなくて、もっぱらPerlしか触っていないうえちょこです。

Perlは初心者(と言い続けるのもアレなんですが。。。)なので、まだまだプログラムの"イイ形"を見つけている最中です。今回は定数の定義方法についてのお話です。私はReadonly派だったのですが、後述の記事でReadonlyの弱点を知ったので、本格的にdlock関数に乗り移ろうと決めました。

Perlの定数定義(constant編)

本題に入る前に、王道から学んでいきます。perlの標準的な定数の定義方法は、constantモジュールを使用して

PERL:
  1. use constant FLAG_ON => 1;

といったように記述します。ただこの方法には面倒な問題がいくつもあって、この定数は定数もどきで実は単なる関数だったりします。定数なので上書きしようとするとコンパイルエラーが通るのは素晴らしいのですが、関数なので文字列内で展開できなかったりハッシュや配列がリファレンスでないと定義できなかったりします。

Perlの定数定義(Readonly編)

とまぁConstantモジュールには使いづらい点が幾つもあったわけですが、そんなことは全く知らずに、私はReadonlyモジュールという方を使用していました。Readonlyモジュールで定数を定義する場合は

PERL:
  1. use Readonly;
  2. Readonly my $FLAG_ON => 1;

というように記述します。Readonlyモジュールを使用すれば配列やハッシュも普通に定義できますし、文字列内で展開もできます。ちょっとやっかいなのは、定数を上書きしようとする場合はコンパイル時ではなく実行時にしか検出できないという点です。これは慣れればいいですし、エラーが出ることには変わりないので我慢します。

ですが、もう1つReadonlyには欠点がありました。

Readonlyの欠点

Perlにおける定数宣言(constant or Readonly or Attribute::Constant) - Unknown::Programmingという記事に詳しくまとまっていますが、Readonlyはとにかく遅いようです。記事の末尾にベンチマークが貼ってありますので見てみると、明らかにReadonlyだけが遅いです。

Readonlyが何故遅いのかというと、tieを使用しているからだそうです。tieというのは変数を内部的にオブジェクトに結びつけるperlの仕組みです。Dan先生がだいぶ前にブログ記事にしているのを見つけたので、そちらを参照してください。(404 Blog Not Found:perl - tie()って何をtieするの?

Data::Lock dlockという選択肢

Readonlyは遅いし、constantは使いづらいわけですが、もう1つ定数系モジュールがあります。Attribute::Constantとそのコア部分であるData::Lockです。Data::Lockにはdlockとdunlockという関数が含まれていて、変数をロックすなわち上書きできないようにしてしまうものと、そのロックを解除してしまうものです。定数なのに定数じゃなくせるというのが気持ち悪いという気持ちはありますが、規約でdunlockは使っちゃダメとか決めておけば大した問題にはなりません。

dlockはtieを使っていないのでReadonlyよりも速いですし、使い勝手はReadonlyみたいなものです。詳しくは前述のブログ記事を見てみてください。またdlockについては作者であるDan先生の記事を参照してください(404 Blog Not Found:perl - Attribute::Constant - Another Way to Make Read-only Variables)。

実際のところ

仕事で書いているコードはいろんな人がメンテナンスをしていますが、比較的最近書かれたコードはdlockを使用していることが多いです。ただ、スカラー変数にだけdlockを使用していて配列やハッシュにはReadonlyを使用している箇所が結構ありました。私はそれらのコードを読んで学習しているため、てっきりdlockはスカラー変数だけしか使用できないものかと勘違いしていたのですが、全然そんなことはなく、Readonlyと同等のことができてReadonlyよりも速いモジュールという認識でよさそうです(というところが気になったのでdlockの仕様を調べていたのがこの記事を書くきっかけでした)。

ではでは。


[perl]Google::API::Clientを使ってみた

Posted under perl by uechoco on 日曜日 5 2月 2012 at 16 : 11 : 24

perl歴はそろそろ1週間はすぎてるくらいのうえちょこです。初めてのPerlと続・初めてのPerlは読みましたが、リファレンスとオブジェクトの当たりから全然理解できてないです。なれるまでには暫く時間がかかりそうです。

さて、そうはいっても書かなきゃ慣れないので、前職でも使っていた日報クリエイターというWebアプリのPerl版をつくろうかなーと思っています。機能としては、Google Calendarから指定のカレンダーの指定の期間のイベントを取得し、整形して出力するだけのものです。前のはCakePHPで作ったんですがソースコードは会社に寄付しちゃってるんで、また1から作り直します。

最近のGoogle Data APIはバージョンが新しくなったらしく、GoogleからClient Libraryという形でライブラリが提供されています。PHP、Ruby、Python、Java、.NET、JavaScript、Objective-Cなどがあります。Perlのはありませんww が、perl版のClient Libraryを作っている方がいました。

Google APIs Client Library for Perl
モジュール構造で言うとGoogle::API::Clientです。

インストールログを貼っておきます。

そういえば、以下のインストール手順だと、本家のgithubから取ってきているんだけれど、今のバージョンだと、calendar APIに対するOAuth用URLが間違って出力されてしまうので、実際はforkしてoauth2_scope_delimiterというブランチ切ったものを使用しました。pull request投げたら、ローカルでは直してあるけどまだpushしてないバグだったって返答が来たので、そのうち本家も更新されると思います。

Bash:
  1. ## 環境はperlbrewでインストールしたperl 5.14.2とcpanm
  2.  
  3. ######################
  4. # ライブラリのDL
  5. ######################
  6. $ mkdir _libs
  7. $ cd _libs
  8. $ git clone https://github.com/comewalk/google-api-perl-client
  9. $ cd google-api-perl-client
  10.  
  11. ######################
  12. # 1回目のMakefile.PL … 失敗
  13. ######################
  14. $ perl Makefile.PL
  15.  
  16. ### Can't locate inc/Module/Install.pm in @INC (@INC contains: …… ) at Makefile.PL line 1.
  17. ### BEGIN failed--compilation aborted at Makefile.PL line 1.
  18.  
  19. ### (おそらく Module::Install がないのか?インストールしてみる)
  20. $ cpanm Module::Install
  21.  
  22. ######################
  23. # 2回目のMakefile.PL … 失敗
  24. ######################
  25. $ perl Makefile.PL
  26.  
  27. ### Unknown function is found at Makefile.PL line 3.
  28. ### Execution of Makefile.PL aborted due to runtime errors.
  29.  
  30. ### (readme_fromがないようなので、 Module::Install::ReadmeFromPod をインストールしてみる)
  31. $ cpamn Module::Install::ReadmeFromPod
  32.  
  33. ######################
  34. # 3回目のMakefile.PL … 失敗
  35. ######################
  36. $ perl Makefile.PL
  37.  
  38. ### Writing README from lib/Google/API/Client.pm
  39. ### Unknown function is found at Makefile.PL line 6.
  40. ### Execution of Makefile.PL aborted due to runtime errors.
  41.  
  42. ### (auto_set_repositoryがないようなので、 Module::Install::Repository をインストールしてみる)
  43.  
  44. ######################
  45. # 4回目のMakefile.PL … 成功
  46. ######################
  47. $ perl Makefile.PL
  48.  
  49. ######################
  50. # 1回目のmake … 成功
  51. ######################
  52. $ make
  53.  
  54. ######################
  55. # 1回目のmake test … 失敗
  56. ######################
  57. $ make test
  58.  
  59. ### (いろんなモノが足りない。エラーメッセージで分かるものからインストール)
  60. $ cpanm LWP::Protocol::https Test::Pod Test::Pod::Coverage
  61.  
  62. ######################
  63. # 2回目のmake test … 失敗
  64. ######################
  65. $ make test
  66.  
  67. ### (おそらくテストは通らないんじゃない?とりあえず先進む)
  68.  
  69. ######################
  70. # 1回目のmake install … 成功
  71. ######################
  72. $ make install
  73.  
  74. ### (サンプルプログラムでインストール確認)
  75. perl eg/urlshortener/cli_public_access.pl
  76.  
  77. ### $VAR1 = {
  78. ### 'kind' => 'urlshortener#url',
  79. ### 'longUrl' => 'http://code.google.com/apis/urlshortener/',
  80. ### 'id' => 'http://goo.gl/BwA5N'
  81. ### };
  82. ###
  83. ### $VAR1 = {
  84. ### 'kind' => 'urlshortener#url',
  85. ### 'status' => 'OK',
  86. ### 'longUrl' => 'http://code.google.com/apis/urlshortener/',
  87. ### 'id' => 'http://goo.gl/BwA5N'
  88. ### };

ちなみに、こんな感じのコードで、calendarList.listが取得出来ました。<CLIENT ID>とかはGoogle APIs Consoleで取得してください。

PERL:
  1. use strict;
  2. use warnings;
  3. use lib "/path/to/libs/google-api-perl-client/lib";
  4. use feature qw/say/;
  5.  
  6. use Data::Dumper;
  7.  
  8. use Encode;
  9. use Google::API::Client;
  10. use OAuth2::Client;
  11.  
  12. my $client = {
  13. id => '<client id>',
  14. secret => '<client secret>',
  15. redirect_url => '<client redirect url>',
  16. };
  17. my $service = Google::API::Client->new->build('calendar', 'v3');
  18.  
  19. my $auth_driver = OAuth2::Client->new({
  20. auth_uri => Google::API::Client->AUTH_URI,
  21. token_uri => Google::API::Client->TOKEN_URI,
  22. client_id => $client->{id},
  23. client_secret => $client->{secret},
  24. redirect_uri => $client->{redirect_url},
  25. auth_doc => $service->{auth_doc},
  26. });
  27.  
  28. say $auth_driver->authorize_uri;
  29.  
  30. say 'Enter verification code:';
  31. my $code = ;
  32. chomp $code;
  33.  
  34. my $token_obj = $auth_driver->exchange($code);
  35.  
  36. my $res = $service->calendarList->list->execute({ auth_driver => $auth_driver });
  37. #say Dumper($res);
  38.  
  39. my @calendar_list;
  40. for my $item (@{$res->{items}}) {
  41. push @calendar_list, $item;
  42. }
  43. for my $calendar (@calendar_list) {
  44. print "## Calendar Info: \n";
  45. print "$_ : $calendar->{$_}\n" for keys $calendar;
  46. print "\n";
  47. }


=>とか->とかの名前

Posted under perl by uechoco on 木曜日 26 1月 2012 at 16 : 29 : 36

phpで=>のことはダブルアローって呼んでます。そして->のことはシングルアローって呼んでます。見た目そのままですね。実は公式にもダブルアローは正しいという裏付けがあって、それはphpのパーサートークンでは「=>」が「T_DOUBLE_ARROW」と定義されているんです。ちなみに「->」は「T_OBJECT_OPERATOR」です。

Perlでは、=>のことはfat commaって呼ばれています。なぜかというと、ハッシュのリスト定義でカンマ(,)の代用として使用されるからです(言語上の正確な定義はよく知りませんが)。

PERL:
  1. my %hash = ("key1", "value1", "key2", "value2");

と同じ意味になるのが

PERL:
  1. my %hash = ("key1" =&gt; "value1", "key2" =&gt; "value2");

なんですね。

ちょっと調べきれていないですが、言語によってはfat allowとか、hash rocketとか、呼び方があるみたいです。

参考:Fat comma - Wikipedia, the free encyclopedia


[perl]「Perl」は元々何かの略称ではない

Posted under perl by uechoco on 日曜日 1 1月 2012 at 22 : 54 : 02

新年明けましておめでとうございます。2012年の抱負などは別途書きます。

さて、2012年はしょっぱなから新しい言語を習得しています。それが・・・Perl!!なんで今さらって言わないでください。覚えたいから覚えるんです。え?「phpはどうしたの?」って?ちょっと休憩です。

しょっぱなの記事は小ネタから。

Perlって名前が先に決まって、後から略称をこじつけたらしいですw 一応、公式の正式名称は「Practical Extraction and Report Language(実用データ取得レポート作成言語)」の略または「Pathologically Eclectic Rubbish Lister(病的折衷主義のがらくた出力機)」の略となっています。

なんだかもう、名前からしてハッカー臭い感じがしてきました。ちなみに以下の2冊が最初の教科書です。さーって、レッツPerl!


[perl]scalar=$calar、array=@rray、hash=%演算?

Posted under perl by uechoco on 土曜日 24 12月 2011 at 16 : 10 : 27

ふと、perlのスカラ変数、配列、ハッシュの記号について思ったのが、

  • scalar = $calar(ドル記号がSに似ている)
  • array=@array(アットマーク記号がaに似ている)
  • hash=%演算(ハッシュを求める代表的な演算は、%記号で余りを求める方法)

なんじゃないかなーっと。Perlなんて時々スクリプトを見る程度だけど、昔(8年前くらいに)CGIゲームとかyybbsとか弄ってたときは、それぞれの記号が何を示しているのか、理解してなかったよなーって懐かしむ。

モイッチョおまけに、配列の最後の添字を取得する$#arrっていう書き方もあった気がするけど、

  • $#arr = arrという変数の#(番号=ここでは添字)を$(スカラー値)で返す
  • $#arr = arrという変数の$#(添字番号)を返す

という感じで#が番号っていう意味を知っていれば、すんなり受け入れらるよなーって。

ついでに配列やハッシュが@や%記号で扱ったり$記号で扱ったりしてこんがらがっていた時代もあったけど、これも簡単で、その時点でのコンテキスト(文脈)でどう扱っているかを記号で表しているだけじゃないかと。

ちなみに、ここで書いたのは勝手な想像であって、どこかで調べたわけじゃなくて、もしかしたら間違っているかもしれません。(それでも覚えやすいからいいかなっとw)

プログラミング歴が遊びも含めて10年を超えてくると、いろいろな知識も増えてきて、昔分からなかったことをすんなり分かるようになったりしてきます。自分の成長を実感できた瞬間でしたw

 

P.S. (2012/01/02 13:40):

今、初めてのPerl 第5版(通称:リャマ本)を読んでいるのですが、p53の脚注に、「Larryは、それぞれ$calar(scalar)と@rray(array)だから、ドル記号とアットマークを選んだと主張しています。」ということが書いてあり、公式見解として正しいようです。


Copyright © 2012 うえちょこ@ぼろぐ. WP Theme created by Web Top.