Perlã§Continuationãã¼ã¹ã®ã¦ã§ããµã¼ã
Continuationã£ã¦ããã®ã¯ããã°ã©ã ã®å®è¡éç¨ãéä¸ã§ããªã¼ãºãã¦å¥ã®ã¨ããããåã¹ã¿ã¼ããããããããã¨ãã§ããã¨ããé ã®çããªããããªæ©è½ã ãã¯ãã御æ¬å®¶ã¯scheme(call/cc)ã ãã©ä»ã®ãã¤ã¬ãã«è¨èªã§ãã§ãããã®ãããããã ã
ã¦ã§ããã¬ã¼ã ã¯ã¼ã¯ã¨ãã¦ã¯smalltalkã®seasideãcommon lispã®uwcãæåãRubyãPythonãGeneratorã使ã£ã¦å®è£ ãããã®ããããããããã¨ãã¢ããªã±ã¼ã·ã§ã³ã¨ãã¦ã¯Paul Grahamæ°ã®news.ycombinator.comãæåãããã¯å½¼ã®ã100å¹´è¨èªã(å®ã¯PLTã®ä¸ã«ãã¯ãã§ä½ã£ãLispã®æ¹è¨)ã«ãã£ã¦å®è£ ããã¦ããã
perlã«ã¯call/ccãgeneratorã®ãããªã³ã¼ã«ãç¡ãã®ã§Continuationãã¼ã¹ã®ãã¬ã¼ã ã¯ã¼ã¯ã¯ç¡ãã¨æã£ã¦ããããééã£ã¦ãããPerlã«ã§ããªããã®ã¯æ» å¤ã«ãªããããã§ãæ©éPerlã«ããContinuationã¦ã§ãã¢ããªã®Hello Worldããã£ã¦ã¿ãã
Continuationã®ããã¨ããã¯ã³ã¼ã«ããã¯ç¶ã«ããããååããããã¸ãã¯ãé常ã®ããã°ã©ã ã®ããã«ç´ç·çã«ä¸ã¤ã®é¢æ°ã§å®è£ ã§ãããã¨ã ããªã®ã§ãå¾å¾©åæ°ã®å¤ããã©ã¼ã ãªã©ã«ããã¿ãªãé ç®ãã§ãã¯ã®å¤ãã¦ã¼ã¶ç»é²ç»é¢ããã£ã¦ã¿ãã
以ä¸ãå®è¡å¯è½ãªPerlã«ããContinuationã¦ã§ãã¢ããªãã¤ã³ã¹ãã¼ã«ã¯ä¸ãåç §ã
#!/usr/local/bin/perl
use strict;
use Carp;
use Data::Dumper;# ããããã¼ã«ã§continuationãå¯è½ã«ããéæ³ã
# ã©ããã£ã¦ãããç¥ãããããªãã
use Continuity;# ãã¼ããè¨å®ãã¦ãµã¼ããèµ°ãããã
my $server = new Continuity(port=>3000);
$server->loop;# ãã£ãã©ã«ãã§mainã¨ããé¢æ°ãèµ°ãããã man 3 Continutiyãåç §ã
sub main
{
my ($request)=@_;# æä½éã®ã¡ã½ãããããã ãç¥ã£ã¦ããã°ããªãã®ãã¨ãã§ããã
# $request->print($html);
# $request->next;
# $request->param($_);
# $request->request->url->path# ã¡ã¤ã³é¢æ°ã®ä¸ãã¢ããªã±ã¼ã·ã§ã³ã®ãã¼ã¿ãæã¦ããã
# ãã®ç¶æ ã¯ãªã¯ã¨ã¹ããçµã¦ä¿ãããã
my %user_db=(tengu=>'5db05ef25fd0a77a6965b6696c5e4ad0');# ã¦ã¼ã¶ç»é²ãã©ã¼ã ãè¦ããã
my $html=<<__END__;
<html>
<body>
<div class="message">
%s
</div>
<form>
ã¦ã¼ã¶å<input type="text" name="user" value="%s"><br>
ãã¹ã¯ã¼ã<input type="password" name="passwd"><br>
ãã¹ã¯ã¼ã確èª<input type="password" name="passwd2"><br>
<input type="submit" name="reg" value="ç»é²ãã">
</form>
</body>
</html>
__END__
#
# ãã©ã¦ã¶ã«ç»é¢ãéãã
#
$request->print(sprintf($html, '', ''));
#
# ã¦ã¼ã¶åã¨ãã¹ã¯ã¼ãã®æ¤è¨¼ãéãã¾ã§ã°ã«ã°ã«ã¾ããã
#
my $user;
while(1) {
#
# ããã§æ¬¡ã®ãªã¯ã¨ã¹ãã¾ã§ãããã¯ããã
# ãããé常ã®ã¦ã§ãã¢ããªã¨æ¯ã¹ã¦éãã¨ããã
# åã®$request->printã¨ãã®nextã®éã§
# ã¯ã¢ã©ã¤ã¢ã³ãã¨ãä¸å¾å¾©ãããã
#
$request->next;
# ã¯ã©ã¤ã¢ã³ããã帰ã£ã¦ããã
# ãªã¯ã¨ã¹ããã©ã¡ã¿ã¯ããã§è¦ããã
# die Dumper $request->param;#
# åé¡ãããå ´åã¯ã¡ãã»ã¼ã¸ãå ãã¦ããã©ã¼ã ãæãç´ãã
#
my ($passwd, $passwd2);
($user, $passwd, $passwd2)=map { $request->param($_) } qw(user passwd passwd2);# æ¢åã®ã¦ã¼ã¶å?
if (exists $user_db{$user}) {
$request->print(sprintf($html, 'å¥ã®ã¦ã¼ã¶åãé¸ãã§ãã ããã', ''));
}
# ã¾ã¨ããªãã¹ã¯ã¼ããï¼
elsif (length($passwd)<4) {
$request->print(sprintf($html, 'ãã¹ã¯ã¼ãã¯4æå以ä¸ã«ãã¦ãã ããã', $user));
}
# ãã¹ã¯ã¼ãã¯ããããã¦ãããï¼
elsif ($passwd ne $passwd2) {
$request->print(sprintf($html, 'ãã¹ã¯ã¼ããããããã¦ãã¾ããã', $user));
}
# ä¸äºãªã¼ã±ã¼
else {
use Digest::MD5 qw(md5_hex);
# ã¦ã¼ã¶ãDBã«æ¿å ¥ãããããã
$user_db{$user}=md5_hex('hoge', $passwd);
# ã«ã¼ãçµãã
last;
}
}
#
# ç»é²æ¸ã®ã¦ã¼ã¶æ§ããµã¤ãã«å¾¡æ¡å ãã
#
$request->print("<html><body><center><h2>ããããã$useræ§");# ããããè½ã¡ãã¨ããµã¼ãã®ã«ã¼ãã«æ»ã£ã¦ã¾ãæåãããããªããã
}
ææ³
ã¦ã¼ã¶ã¨é »ç¹ã«è¡ãæ¥ãã¦ãã¼ã¿ãã¼ã¹ã«å ¥ããããªããããªè¤éãªãªãã¸ã§ã¯ããä½ã£ã¦ããã«ã¯ä¾¿å©ããªã¨æããã§ããé常ã®ã³ã¼ã«ããã¯ãã¼ã¹ã®ã¦ã§ãããã°ã©ãã³ã°ã«æ £ãã¦ããã¨ãContinuationãã¼ã¹ã®æµãã«ããã£ã¦æ¸æããã¨ã®æ¹ãå¤ãã®ã§ãæ £ããã¾ã§ã¯çç£æ§ã¯é«ããªãããªã
PGæ°ã¯ãããã°ã©ã ãçããããã¨ãã«å·å¿µããã ãã¦ããããnews.ycã®ç°¡æ½ãããã®continuationææ³ã«ãããã®ã大ããã¨æãã
Continuationãã¼ã¹ã®ãã¬ã¼ã ã¯ã¼ã¯ã¨ã¯æ£å対ã«ãã¦ã§ãããã°ã©ãã³ã°ã¯finite state machine ã ã¨èªèãã¦ãã¼ã«ããã¬ã¼ã ã¯ã¼ã¯ã使ã対å¿ãã¦ããã¨ããããæ¹ã«ãèå³ãããã
Continuationã®ã¢ããã¼ããFSMã®è¦³ç¹ã使ããã¨ããããã¨æãã®ã§ãåå¼·ãã¦ããããææ³ã ã
ã¤ã³ã¹ãã¼ã«
FreeBSDã ã¨(cd /usr/ports/www/p5-Continuity/; sudo make install)ã§ç°å¢ãæã£ãã¨æãã
Ubuntuã ã¨ãã¼ã«ã¢ã¸ã¥ã¼ã«ãããã±ã¼ã¸åããã¦ããªãã¿ãããªã®ã§ãcpanã³ãã³ãã使ã£ã¦ã¤ã³ã¹ã¼ãã¼ã«ããã
ä¾åã¢ã¸ã¥ã¼ã«ã¯ï¼Continuity, Guard, Coro, (ããããã¦Eventã)