[JavaScript] 猿でもわかるクロージャ超入門という記事が好評だったので、今回はPerl編です。
上記のJavaScript版の記事を読んだという前提で解説させていただきます。
JS版とそっくりですね~。
関数のリファレンスを使っているので、呼び出し方法が$f->()のような形になっちゃいますが、そこはご愛嬌ということで。
これを利用すると、さらに短く書けます。
他にもいろいろ書き方があると思います。
Perlってサイコー!!
これらのモジュールでは、クロージャを使うことによってアクセサを実現しています。
上記のJavaScript版の記事を読んだという前提で解説させていただきます。
問題
呼び出すたびに、1,2,3,...を返すような関数f( )を定義せよ。f(); // 1
f(); // 2
f(); // 3
クロージャ その1
JS版のクロージャに似せて書くとこうなります。#!/usr/bin/perl
use strict;
use warnings;
sub outer {
my $i = 1;
return sub {
print "$i\n";
$i++;
};
}
my $f = outer();
$f->(); # 1
$f->(); # 2
$f->(); # 3
JS版とそっくりですね~。
関数のリファレンスを使っているので、呼び出し方法が$f->()のような形になっちゃいますが、そこはご愛嬌ということで。
クロージャ その2
JSと違ってPerlでは中カッコ{}でスコープを作ることができるので、より簡潔に書けます。#!/usr/bin/perl
use strict;
use warnings;
my $f;
{
my $i = 1;
$f = sub {
print "$i\n";
$i++;
};
}
$f->(); # 1
$f->(); # 2
$f->(); # 3
クロージャ その3
Perlではローカルスコープ内で宣言した関数を、スコープ外から参照することができます。これを利用すると、さらに短く書けます。
#!/usr/bin/perl
use strict;
use warnings;
{
my $i = 1;
sub f {
print "$i\n";
$i++;
}
}
f();
f();
f();
以上、Perlでのクロージャの作り方でした。他にもいろいろ書き方があると思います。
Perlってサイコー!!
クロージャの使われどころ
PerlにはClass::AccessorやClass::Data::Inheritablenaといった、オブジェクト指向をより便利にするための定番モジュールがあります。これらのモジュールでは、クロージャを使うことによってアクセサを実現しています。
参考
-
はてな匿名ダイアリー:PerlのClass::Data::Inheritableの解析
軽妙な語り口でClass::Data::Inheritableの実装を解説してくれる。もはやこれは文学だ。
Perl のクロージャ - naoyaのはてなダイアリー
クロージャの応用方法について深堀したい方はこちら。
PerlでDBIモジュールを使ってDB操作を行うためのかんたんなサンプルコードです。
「都道府県マスタ」テーブルを作って、CRUD(レコード追加、読み取り、変更、削除)を行います。
注:
「都道府県マスタ」テーブルを作って、CRUD(レコード追加、読み取り、変更、削除)を行います。
注:
- コマンドラインから実行することを想定しています。
- ユーザ名、パスワード、DB接続情報などは環境に合わせて変更してくださいね。
- サンプルではMySQLを使用していますが、他のRDBMSにも使えると思います。
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $user = 'username';
my $passwd = 'pass';
my $host = 'localhost';
my $dbname = 'mysample';
my $dbh = DBI->connect("DBI:mysql:$dbname:".$host, $user, $passwd);
my $sql;
my $sth;
# CREATE TABLE
$sql = "CREATE TABLE prefmaster ( id INT , name VARCHAR(255) ) ";
$dbh->do($sql);
# INSERT
$sql = " INSERT INTO prefmaster (id,name) values (1, 'hokkaido') ";
$dbh->do($sql);
$sql = " INSERT INTO prefmaster (id,name) values (2, 'akita') ";
$dbh->do($sql);
# SELECT
$sql = "SELECT * FROM prefmaster";
$sth = $dbh->prepare($sql);
$sth->execute;
print "SELECT\n";
while(my @a = $sth->fetchrow_array){
print "@a\n";
}
print "\n";
# UPDATE
$sql = " UPDATE prefmaster SET name = 'iwate' WHERE id = 2 ";
$dbh->do($sql);
# DELETE
$sql = " DELETE FROM prefmaster WHERE id = 1 ";
$dbh->do($sql);
# SELECT AGAIN
$sql = "SELECT * FROM prefmaster";
$sth = $dbh->prepare($sql);
$sth->execute;
print "SELECT\n";
while(my @a = $sth->fetchrow_array){
print "@a\n";
}
print "\n";
# DROP TABLE
$sql = " DROP TABLE prefmaster ";
$dbh->do($sql);
$sth->finish;
$dbh->disconnect;
Ubuntu9.04のPECL版memcachedクライアントを入れようとしたらphpizeでエラーが出ます。
この場合は、php5-devをインストールすればOK。
userdqn@colinux:~$ sudo pecl install memcached
downloading memcached-1.0.0.tgz ...
Starting to download memcached-1.0.0.tgz (22,281 bytes)
........done: 22,281 bytes
4 source files, building
running: phpize
sh: phpize: not found
ERROR: `phpize' failed
この場合は、php5-devをインストールすればOK。
$ sudo apt-get install php5-dev
みなさん要注意ですよ!!
CoLinux(0.7.4) 上の Ubuntu9.04をUbuntu9.10にアップグレードしたら、このようなエラーメッセージを吐いてお亡くなりになりました。
CoLinuxが悪いんじゃないんです。
Ubuntuが悪いんじゃないんです。
バックアップをとっておかなかった私が悪いんです。
というわけで、みなさんもUbuntuをアップグレードする際はバックアップをとりましょう!!
Ubuntu公式サイトにもちゃんとそう書いてあります。
アップグレードの前に
- Ubuntu 9.04からUbuntu 9.10へは直接アップグレードができます(UpgradeNotes(英語)を見てください)
- アップグレードの前にUbuntu 9.04における全パッケージのアップデートを必ず実施してください。
追記
同じ目に会った人が何人かいるようです。。。
今のところ解決策は見つかっていません。
私はあきらめて、Ubuntu9.04をインストールしなおしました。
秀丸を使っていて、今開いているのファイルのフルパス名を取得したいことがよくあります。
コマンドからやる方法がわからなかったので、マクロを作りました。
(他の場所でもOKです。)メニュー>マクロ>マクロ登録
で、タイトル名に「フルパス取得」など入力。ファイル名の欄で、"getFullPath.mac"を選択すればOKです。
コマンドからやる方法がわからなかったので、マクロを作りました。
- 下記の内容のテキストファイルを作って、"getFullPath.mac"というファイル名で、秀丸本体と同じ場所に保存してください。
setclipboard filename;
WindowsXPの場合は"C:¥program Files¥Hidemaru¥"になります。(他の場所でもOKです。)
で、タイトル名に「フルパス取得」など入力。ファイル名の欄で、"getFullPath.mac"を選択すればOKです。