As Sloth As Possible

可能な限りナマケモノでありたい

タグ:ネタ

なんでなのかと聞かれても「なんか暇だったから…」としか。

いや元々はこう周期的に来る「なんか仕事と全然関係ないコード書きたい」期だっただけなんだけど、Goとかで遊んでる最中にひょんなことからRustを見付けてしまってへー面白そうとか手を出してみることになり、「慣れない言語を使うときはとりあえずWhitespaceの処理系を作ってみるとなんか慣れたような気分になる」という癖でですね。なんか出来ちゃった。

記事書いてる時点の最新のnightly(v0.12.0-pre)ではコンパイル通るのを確認済み(というか多分0.12.0でしかビルドできない。流石いつβが出るとも分からないα言語、0.10.0と0.11.0と0.12.0で互換性無いし、ドキュメント見に行ったら標準ライブラリを含むほとんどのAPIがexperimentalだった)。rust-albinoの方をcloneしたら最新のrustcと対応するcargoをrustupかなんかで入れて、

cargo build
するとビルドできる。homebrewでも入れられるけどバイナリだと0.11.0、ソースからのビルドだとかなり時間かかるので大人しくnightlyのバイナリ使うがよろし。

Albinoがコマンドラインツールで、こいつがWhitespaceを実行したり逆アセンブルしたりしてくれる。最初は普通にインタプリタ作ってたんだけど、例のごとくWhitespace読めないし書けないからアセンブリ言語でもでっちあげよう、あとその昔書いたDTとかも動かしたいよねー、とかやってたらいつの間にかVMとパーサが分離して副産物として何故かライブラリになっちゃったのがWhitebase

厳密に言うと本体はWhitebaceの方でAlbinoはただのインターフェースだったりするけど細かいことは気にしない。先に名前が決まったのはWhitebaseの方で、Whitespaceの命令セットを持ったVMとパーサのライブラリなので「白地」というのが由来であって決して某19歳に見えない艦長率いる連邦の戦艦ではない。合わせてツールの方はWhitedevilにしようかなーとか一瞬考えたけどコマンド名としては長すぎるしrx78とかエイリアスするはめになるのでアルビノにした。VMとパーサが分離した結果どういうわけかBrainf*ck派生の言語をWhitespaceの命令セットに変換できるようになったので、「本来白くないものまで白くなっている」からアルビノなんです。

得られたもの。Rustがなかなか触っていて楽しいということが分かった。いまどきっぽいサブコマンド型のコマンドどうやって作ってるのかなーってのが分かった。WhitespaceもしくはBrainf*ckのトークンの内部表現を返すイテレータさえ実装できれば簡単にオレオレ言語が作れるライブラリが出来たので、今後さっと言語を作ってドヤリングしたいときは一瞬で出来るようになった。Brainf*ckの任意のプログラムからWhitespaceのコードが生成できるようになった。

失なったもの。時間。結構な無駄な時間。

ゴールデンウィークを利用して久々にろくでもないものができたので晒しておく。

「ごっこじゃないよ、兄ちゃん!」「才能の無駄遣いじゃなくて、無駄そのものだよ、お兄ちゃん。」

前のと何が違うの?

そもそもの発端についてはプログラミング言語「DT」という記事を、実際の言語仕様についてはREADMEでも読んでもらうとして、何で再実装したのかという話。

3年前に作ったのは「Whitespaceのトークンを置換した処理系をインタプリタとしてRubyで実装」したものなんだけど、何を思ったかコンパイルしてみたいと思い立ってしまい、んでそれ自体はLLVMが良く分かんなかったとか、llvmruby自体がプロジェクトとして大分アレな感じになってしまっていたとか、そういう事情で挫折してたんだけど、時は流れ、なんか見返してみたら普通にLLVMアセンブリ読み書きできるようになってたし、ruby-llvmがちゃんと動くようになってるみたいだし、ということで再実装してみることにした。

そんで作り直す過程で「Whitespaceの置換ってのもなんだか面白くないな」と思ってVMのアーキテクチャと言語仕様を見直すことにした(ぱっと見だと全然分かんないけど、旧DTと新DTの間に互換性は無い)。そのせいで実際にはチューリング完全じゃなくなってると思うし、そもそもちゃんと出来てるのかどうか怪しいものだけど、とりあえず「Hi!」って出力するのとフィボナッチ数を出すのは動いたので良しとする。

当初の目標だった「DTコードをネイティブのバイナリにまでコンパイルして高速に実行」ってのも実現して、DTインタプリタで250msくらいかかるfib.dtをコンパイルすると4msくらいで結果が出るようになった。似たようなRubyのコードだと大体100msくらいだったので素敵に速い。まぁ、コンパイル自体はLLVMとコンパイラに任せているので大して威張れるあれでもないのだけども。そして高速に動いたからなんだという話なのだけども。

ぶっちゃけDTよりLLVMアセンブリの方が遥かに記述力高いし書きやすい。当たり前のように構造体とか関数ポインタとか使えるのな。Cの関数呼べるし。最初Cで書いてたVMを途中でLLVMアセンブリ直接書くようにしたけど、大して変わらない。DTで書くくらいならLLVMアセンブリ書いた方がいいです。LLVMの無駄遣いタグを付けていただきたい。

DTの存在意義については疑問を差し挟む余地もなく皆無だと言っていいけど、その過程でレジスタマシンについて色々調べて、はー、こんぴゅーたーってこうやってうごいてるのかー、と勉強になったのでそれはそれで良かった。よくこんなの考えられるよなぁ。CPUとかコンパイラとか作ってる人達、本当に俺と同じ種類の生き物なのだろうか。凄い。

「RubyKaigiが終わったら真面目にやろう」とか言ってたくせに、中々やる暇無くて放置してたら大変に分かりやすい作り方講座が出てしまった上、弾さんまで乗ってきてしまって完全にタイミングを逃したfaultierですこんばんは。

悔しいので対抗してみる

うどんげが出たならてゐもいてもいいだろう、ということでてゐ。AAは上記の記事同様こちらを使わせてもらった。初春もいいなーと思ったんだけど表示してみたら大き過ぎて自分のターミナルで表示できなかったのでやめといた。コードはこんな感じ。

# tewi.rb
eval$s=%w't=true;e="eval($s=join("<<34<<34<<",qw{$t=1;$s=~/"<<92<<"[[0-9,]+"<<92<
<"]/;$n=eval($&);$e=          "<<39<<"eval$s=%w"<<39<<    ".chr(39)."<<39<<($s+(
($s.length>1756)?"   ":"#"<<$    s.gsub(/[^0-9a-zA-   Z]/,      "")[0,(1755-$s.l
ength)]));e[-312,  311]=""<<39<<   ";$e.=          ("<<39<<"#"<   <39<<".substr(
join("<<39<<39<<  ",split(/[^0-9a-z              A-Z]/,$s)),0,(200  9-length($s)
))).chr(39)."<<  39<<".join"<<39<<";@o   =       map{$t=!$t;split(//  ,((!$t)?su
bstr($e,0,$_,"< <39<<39<<"):chr(32)x$_)         )}@$n;for(1..34){spli  ce(@o,$_*
81,0,chr(10))}  ;print(join("<<39<<39<<         ",@o).chr(10      )    )}))";o=[
101,10,24,4,40 ,3,8,4,18,3,4,6,33,2,13           ,3,6,10,1            2,3,30,2,1
7,14,17,2,27,  2,21,3,1,7,19    ,2                     ,              25,1,23,9,
21,2,23,2,23,  9,12,6,1,                           4                   ,23,1,23,
11,9,12,23,2, 13,4,2,2                   1                             ,1,14,23,
2,9,27,1,19   ,22,1,8         ,                  1    9   ,             1,29,20,
3,7,9,1,      18,1,4      ,         1        ,          3           ,    1,13,16
,6,6,6,      1,9,1,8                          ,1           ,    1    0,    1,11,
1,4,14,      6,7,26,                   2,1     1,1,4   ,1              ,4,   2,4
,12,6,7     ,19,3,5,             5,  3,2,14,3  ,3,1   0,5               ,8,13  ,
2,2,8,    2,4,3,3,15,          5,2    ,7    ,  4,11 ,10,3,              4,2,4,1,
2,4,    1,6,14,12,4,1      3  ,   6,1,     2,1,3,4,5,18,3,1,3   ,   1   ,3,12,3,
12,1   3,5,1,2,4,15             ,1,1, 11    ,10,3,14,12,6,1 ,           2,5,13,2
,1   ,1,1,6,12,2,16            ,11,7, 8,     13,2,1,7,13,1  , 1      8,10,8,6,14
,  1,2,10,10,1,20,1           2,5,3,1        2,1,6,13,7,2,  1       9,13,26,14,7
, 2,16,16,11,1,13,14          ,8,2,14,      16,13,7,5,15,1 0,          3,8,10,1,
8 ,25,10,1,4,13,27,23,            12,4,   2,12,5,1,1,1 ,8,1,1             3,17,1
0  ,1,3,5,1,12,14,4,8,             4,10,2,13,25,2,3,9,4,2,1,3              ,15,1
3,  33,4,5,1,4,3,20,                8,182].map{ |i|t=!t;((!t)              ?e.sl
ice  !(0,i):32.chr*                i)}.join;1.up       to(35               ){|i|
o[(i*   81)-1,0]          =        10.chr};puts(o)#ttrueeeva          l    sjoin
3434qwt1                           s920992nevale39evalsw39            chr3  939s
slength1     7 5        6             sgsub09azAZ01755s          l   ength e3123
1139e39              39su        bstr          jo             #t1s09nevaleevalsw
chr39tt  rue         eeva  l   sjoin3434qwt1s9             20992nevale39evalsw39
chr3939sslen    gth17 56sg   sub09azAZ01755slengt        he31231139e3939substrjo
in3939split09azAZs02009lengthschr3939join39omapttsplittsubstre03939chr32xnfor134
spliceo810chr10printjoin3939ochr10o10110244403841834633213361012330217141'.join

Gistにも置いてあります。はい。

Quineじゃない件

上のコードをコピペしてRubyに実行させると何やらコードを吐くので、それをさらにRubyに流し込んで実行させてやると…なんということでしょう!エラーを吐くではありませんか!Quineになってねぇじゃねーか、このド低能が!

# tewi.pl(tewi.rbの出力結果)
eval($s=join("",qw{$t=1;$s=~/\[[0-9,]+\]/;$n=eval($&);$e='eval$s=%w'.chr(39).'t=
true;e="eval($s=join(          "<<34<<34<<",qw{$t=1;$s=    ~/"<<92<<"[[0-9,]+"<<
92<<"]/;$n=eval($&)   ;$e="<<3    9<<"eval$s=%w"<<39   <<".      chr(39)."<<39<<
($s+(($s.length>17  56)?"":"#"<<$   s.gsub          (/[^0-9a-zA-   Z]/,"")[0,(17
55-$s.length)]));  e[-312,311]=""<<3              9<<";$e.=("<<39<<  "#"<<39<<".
substr(join("<<3  9<<39<<",split(/[^0-9   a       -zA-Z]/,$s)),0,(200  9-length(
$s)))).chr(39)." <<39<<".join"<<39<<";@o         =map{$t=!$t;split(//,  ((!$t)?s
ubstr($e,0,$_,"  <<39<<39<<"):chr(32)x$_         ))}@$n;for(1      .    .34){spl
ice(@o,$_*81,0, chr(10))};print(join("<           <39<<39<<            ",@o).chr
(10))}))";o=[1  01,10,24,4,40    ,3                     ,              8,4,18,3,
4,6,33,2,13,3,  6,10,12,3                           ,                   30,2,17,
14,17,2,27,2,2 1,3,1,7,                   1                             9,2,25,1
,23,9,21,2,2   3,2,23,         9                  ,    1   2             ,6,1,4,
23,1,23,1      1,9,12      ,         2        3          ,           2    ,13,4,
2,21,1,1      4,23,2,                          9,           2    7    ,1    ,19,
22,1,8,1      9,1,29,                   20,     3,7,9   ,1              ,18   ,1
,4,1,3,1     ,13,16,6             ,6  ,6,1,9,1  ,8,1   ,10               ,1,11  
,1,4,14    ,6,7,26,2,1          1,1    ,4    ,  1,4, 2,4,12              ,6,7,19
,3,5,    5,3,2,14,3,3,      1  0   ,5,8     ,13,2,2,8,2,4,3,3,   1   5   ,5,2,7,
4,11,   10,3,4,2,4,1             ,2,4, 1,    6,14,12,4,13,6, 1           ,2,1,3,
4,5   ,18,3,1,3,1,3,            12,3,1 2,     13,5,1,2,4,15  , 1      ,1,11,10,3
,1  4,12,6,1,2,5,13,           2,1,1,1        ,6,12,2,16,11  ,       7,8,13,2,1,
7, 13,1,18,10,8,6,14,          1,2,10,1      0,1,20,12,5,3, 12          ,1,6,13,
7, 2,19,13,26,14,7,2,16            ,16,1   1,1,13,14,8, 2,14,1             6,13,
7,  5,15,10,3,8,10,1,8,             25,10,1,4,13,27,23,12,4,2,              12,5
,1,  1,1,8,1,13,17,10                ,1,3,5,1,12 ,14,4,8,4,10,              2,13
,25,  2,3,9,4,2,1,3,                15,13,33,4,5,       1,4,3               ,20,
8,182]   .map{|i|          t        =!t;((!t)?e.slice!(0,i):3          2    .chr
*i)}.join                           ;1.upto(35){|i|o[(i*81)            -1,0  ]=1
0.chr};pu     t s        (             o)#ttrueeevalsjoi          n   3434q wt1s
920992ne              vale        39ev          al             sw39chr3939ssleng
th1756sg  sub         09az  A   Z01755slengthe3             1231139e3939substrjo
';$e.=('#'.su    bstr( join   ('',split(/[^0-9a-zA        -Z]/,$s)),0,(2009-leng
th($s)))).chr(39).'.join';@o=map{$t=!$t;split(//,((!$t)?substr($e,0,$_,''):chr(3
2)x$_))}@$n;for(1..34){splice(@o,$_*81,0,chr(10))};print(join('',@o).chr(10))}))

ええはい。良く見てもらえると分かると思うけど、実はこのコードは自分自身を出力してない。何を出力してるかと言うと、Perlのコードを出力している。んで、そのPerlのコードは何をするかというと、最初のRubyのコードを出力する。つまり、最初のコードは「『このRubyのコードを出力するPerlのコード』を出力するRubyのコード」で、後のコードは「『このPerlのコードを出力するRubyのコード』を出力するPerl」のコードになっていて、お互いがお互いの自分自身を相手に出力させるという、「人は一人では生きて行けないんだ」というメッセージ性を持った難読コードなわけです。まぁ嘘です。RubyもPerlもやられちゃったので、そのまま真似してもつまらなかっただけです。こんな感じで遊んでみるといいよ!

$ cat tewi.rb | ruby | perl | ruby | perl | ruby

何をしたの?

実のところ別になんということはなくて、やってることは基本的にはうどんげQuineと一緒。配列リテラルとjoinとevalを使ったQuineはPerlでもRubyでも全く同じ要領でできるので、自分自身を吐く代わりに相手のコードを吐くように書き換えると簡単に行ったり来たりできるようになる。

# 任意に加工できるRubyコードを出力する、
# 任意に加工できるPerlコードを出力する、
# 任意に加工できるRubyコードの例
eval$s=%w'puts("eval(join("<<39<<39<<",qw{print("<
<39<<"eval$s=%w"<<
39<<".chr(39)."<<39<
<$s<<39<<".chr(39)."<<39<<".join"<<39<
<")}))")'.join

あとは、二言語分のコードが一つのAAの中に入ることになるし、PerlとRubyだとリテラルがそっくりなのでデータ部は共有したいので生のデータを書きたい、となると流石に元のAAデータだと文字数の制限がキツいから、反転して白抜きのAAにした。ちなみに、てゐの方はうどんげのとはAAデータ持ち方は換えてる(元記事のロジックをPerlで実装するのが面倒だっただけ)。

あとはまぁ、出力時に尻尾に適当なゴミを付けて文字数調整してるんだけど、文字列リテラルの入れ子が簡単に崩れるので面倒臭いとかそんな程度。chr(39)濫用しまくり。あとドットがRubyのドットなのかPerlのドットなのか良くわかんなくなったりします。

まとめ

途中で「俺は一体何をやってるんだ」と思ったら多分負けなんだと思います。一度ベースができちゃうと後はデバッグと文字数の調整が面倒なだけで、割と簡単にできます。あと段々哲学的な気分になります。

最近ブログ更新してないなーと思ってふと最終更新日見たら3ヶ月も前の日付になっていた。良くない。ブログ書いてないということはブログに書けるような馬鹿なことをしてないということで、3ヶ月間一日も休まず馬鹿であったにもかかわらず馬鹿なことをしてないというのはとても良くない。これはアイデンティティの危機である。

ということで久々に馬鹿なことをしないとと思い立ったわけでは全然なくて、ただただ単純に八九寺が可愛過ぎるので、八九寺に名前を噛みまみたしてもらえるモジュールを作ってみた。結果的にだいぶ馬鹿になった。

faultier's kamimamize at master - GitHub

こんな風にして使います。

$ cat kamimamizer.rb
#!/usr/bin/env ruby
# coding: utf-8
require 'kamimamize'

mayoi = Kamimamize::Coverter.new({
    :pattern => { :priority => 10 },
    :repeat  => { :priority => 5, :through => 0.4 },
    :swap    => { :through => 0.05, :appid => 'APPID' },
    :default => { :class => 'Kamimamize::Plugin::Random' }
})

puts mayoi.kamimamize('阿良々木', 'あららぎ')
puts mayoi.kamimamize('羽川', 'はねかわ')

$ ./kamimamizer.rb
阿良々々々木さん
骨川さん (ほねかわさん)

名前とその読みを入れるとカミママイズされた名前が出てきます。カミママイズだなんていやらしいです。それだけです。それだけですが、何か?

一応ちょっとだけ解説すると、引数にプラグインの設定を入れてKamimamize::Converterをnewすると、kamimamizeするときにそのプラグインのどれかを使って名前を変換します。priorityが高い奴から順に処理されて、自分が処理できない名前のときは次のプラグインに任せます。throughが設定されてると大体それぐらいの割合で答えられるときでもスルーして次に渡します。上の例だとrepeatプラグインは4割くらいの確率で処理できるときでもスルーします。全部のプラグインがスルーすると最後にdefaultのプラグインが拾います。何も設定されてないとrandomプラグインがdefaultで、ランダムで八九寺にひどいことを言われます。

プラグインはとりあえず4つ作ってあって、

  • HashかYAMLファイルのパスで名前とそれに対応する変換結果のリストを渡すと、対応する名前が来たとき変換結果リストの中からランダムで返すpatternプラグイン。何もリストを渡さないと「八九寺」にだけ反応する。
  • 同じ文字が続く名前、もしくは「々」が含まれる名前のときにその数を増やしたり減らしたりして噛むrepeatプラグイン。
  • 名前の読みの母音や子音を適当に置き換えるswapプラグイン。Yahoo!のテキスト解析APIを使うのでアプリケーションIDが必要。ちなみに、名前の字面を見ているわけではなく読みを適当に置き換えるだけなので、そんなに上手いことは言わない。
  • 返答リストからランダムに返すだけのrandomプラグイン。返答リストは初期化時に設定できるけど、しないと八九寺にひどいことを言われる。Converterをnewするときに明示的にdefaultを設定しない場合、このプラグインがthrough=0で一番後ろに設定される(つまり上の例ではdefaultの設定は意味ない)。

がある。上の例だと阿良々々々木さんはrepeatプラグインで、骨川さんはswapプラグインの変換結果。何かと適当なので多分そんなに面白い結果は出ないと思うけど(例えば戦場が原とか入れると意味不明すぎて噛んだのかどうかすら怪しいのが出てくるとか、阿良々木さんをカミママイズすると木が消えちゃうとか)、個人的には羽川が骨川とか花沢に変換されたのが面白かったので満足です。ひらがなの音を置き換えるのって結構面倒なのよ。というか八九寺の神懸ったセンスに勝てる気がしない。

あとは類義語に置き換えるとか、名前の中の語彙の分割を真面目にやるとか、specくらい書くとかしたいけど、多分飽きてやんないだろう気配がします。自分で言うな。なんというか、カミママイズするためだけにY!のAPIを使うという無駄遣いをしたかっただけだったりする。Y!のAPI面白かった。途中で形態素解析とかして遊んでた。どうせならもっと盛大に無駄遣いしてみたいなあ。

ねんどろいどぷち 化物語セット 其ノ貮 (ノンスケールABS&amp;PVC塗装済み可動フィギュア)
ねんどろいどぷち 化物語セット 其ノ貮 (ノンスケールABS&amp;PVC塗装済み可動フィギュア)
クチコミを見る
ねんどろいどぷち 化物語セット 其ノ壹 (ノンスケールABS&amp;PVC塗装済み可動フィギュア)
ねんどろいどぷち 化物語セット 其ノ壹 (ノンスケールABS&amp;PVC塗装済み可動フィギュア)
クチコミを見る

余談

上のねんぷちの化物語セット、これを書いてる時点ではAmazonでは受付終了しちゃってるんですが、それを今更気付いてものすごく落ち込んでたら、twitterで

と八九寺が教えてくれるという素敵展開が。@mayoi_hachikujiには足を向けて寝れそうにないと思いながらどこにいるか知らないので普通に寝ました。ありがとう八九寺。大好きだ八九寺。

今日は秋らしいよいお天気だったので、それとは特に関係なく今日も今日とてぼーっとディスプレイに向かっていたところ、こんな記事を見付けた。

勇気を出して告白! その返事で覚えるHTTPステータス・コード

あらあらまあまあ。なんだか俺、この記者の方にシンパシーを覚えるよ。

この手のネタは大好物なのだけど、404はお断りの返事ちゃうやん、てか断り方だけでも何パターンもあるんやで、とうずうずしてきたので便乗して考えてみることにした。例によって400系レスポンスに偏ってるのはお約束。しかたないよねー。告白のレスポンスなんて受けとる方でも返す方でも400系しか知らないもん。ごめん嘘だ。503(「お前本当にタイミング悪いな」)返したことある。再リクエストはありませんでした。200?ああ、そんなステータスコードもありましたね。おいしいのかな。使ってみたいです。

(予想外に反響があったので追記)見ての通り全部のステータスコードについては書いてないです。100系一切書いてないし、201とか下ネタしか思い付かなかったし、300とか305とかも結構面白いなと今気付いたりしたし、400系はWebDAVとかでしか使ってないようなマニアックなステータスコードとか一杯あるんだけどスルーしてるし、500系は元記事のネタで個人的には満足してたので良いかなと思ったりしました。や、思い付きで書いてるから、これ割と適当なんでちゃんとみんなRFCとか読むといいよ。

200系レスポンス

200 OK
「好きです、付き合ってください」「はい…」だって。よかったね。あーほんとよかったね。なんだよ。別に羨しくないし。
202 Accepted
「好きです、付き合ってください」「…受理されました」「え、あの…」「只今処理中です。お待ち下さい」。とりあえず、告白は聞いてはもらえたらしい。待てばいいんだろうか。

300系レスポンス

303 See Other
「好きです」に対して「…あなたには、もっとふさわしい人がいると思うの…」と返すときに使う。ちなみに、この返事をするときに、多くの人が302(「今は私じゃなくて、あの子の方が素敵だと思うの」)を返すが、実は正しくないことがある。302を返されたら(一時的ではあるが)基本的には誰であれその人とは付き合えず、紹介された別な人に行くべきであるが、303の場合は「あなたにはもっとふさわしい人がいると思うの」なので、誰からのどんな要求かによってはOKが返っている可能性がある。
304 Not Modified
「まだあなたに対する気持ちは変わってないの」。最初に断わられたのかOKだったのかによって全然意味が違ってくるが、要するに「この前言ったのと同じだから、もう一度答えるまでもない」ということ。違う返事が欲しければしばらく待つ必要がある。
305 Use Proxy
「話ならマネージャーを通して聞きます」。その連絡先では直接会話することが許されていないので、しかるべき人に伝言をお願いすることになる。

400系レスポンス

400 Bad Request
「好きです」に対して「何言ってるかわかんない」「理解に苦しむ」という返事をするときに使う。告白の仕方が遠回しすぎて伝わらない、何か手順を間違えた、言語や文化の壁で相手に意図が通じてない、等の可能性がある。あるいは、「お前が告白してくる、ということ自体が不正なリクエストである」ということを婉曲に表現している可能性も考慮した方がいい。
401 Unauthorized
交際を要求されたが、「そもそも私とあなたは知り合いですらないんですけど」「誰が話しかけていいって言ったよ」などの返事をするときに使う。告白するまえにまずは会話する許可を貰いましょう。
402 Payment Required
「付き合ってもいいけど、お金払って下さい」
403 Forbidden
「半径1km以内に近付いてはいけないと、裁判所で言われたのをお忘れですか?」
404 Not Found
文字通りに受けとるならば「その人はいない」。家に行ったら留守だった、実家にかけたら「そんな子はうちにはいません」って言われた、などのときにはこのステータスが返っていると思われる。ただ、拒否したいんだけど、丁度いい理由がない、あるいは理由を言いたくない場合に使うことも多いので、居留守である可能性もある。
406 Not Acceptable
交際の要求に対し、相手が求めているものと違うものしか返せない場合に使う。拒否ではなく一応レスポンスが返ってくることもある。「そう言ってくれるのは嬉しいけど、私、多分あなたの思ってるような子じゃないよ…?本当の私、見てくれる…?」と言われた場合、受け入れる側に覚悟が求められる。実際は好みの子じゃなかった、程度であればいいが、異性だと思ったら同性だった、そもそも人間じゃなかった、などの可能性も考慮する必要がある。
408 Request Timeout
「もーーーー、トロい!言いたいことがあるんならさっさと言ってくれない!?」という言葉とともに返す。言われた通りもう一回繰り返しても構わないが、さっさと言わないと怒られる。
410 Gone
「その人はいない、そして二度と戻ってはこない」。404と似ているが、こっちのがより強く「もう、いくら望んでも手に入らない」ことを意味する。いいですか、いい加減忘れて下さい。もうあの人はいないんです。新しい恋を探して下さい。
413 Request Entity Too Large
「長編小説一本分になるほどの超大作のラブレターを送ってこないで下さい、重すぎます」
418 I'm a teapot
「私は人間ではなくティーポットです」。ティーポットに対して交際を要求するあらゆる行為は、このステータスコードで終わる。なお、RFCとして定義されてはいるものの、これは正式なHTTP Status Codeではなく基本的にはエイプリルフールの冗談である。
423 Locked
ちょっと束縛してしまう癖のある恋人と付き合っている人に対して告白してしまったときに返される。恋人の束縛が解けるまでは何度リクエストしても付き合ってくれる可能性はないと思う。

500系レスポンス

500 Internal Server Error
告白された側が予期せぬ事態にテンパってしまっている時に返す。思考回路はショート寸前、だって純情どうしよう。
501 Not Implemented
「付き合うってなんですか?」「多分、私それ、できないし、よくわからない」などの返事とともに使われる。要求している側は、「相手が幼児でないか」「相手がロボットでないか」などを確認する必要がある。
502 Bad Gateway
ああ、お前に頼んだ俺が馬鹿だったよ。余計なことしやがって。お前のせいで台無しだ。
503 Service Unavailable
「ちょっと今…返事できないの」。沢山の人に言い寄られていてすぐには返事すらできない場合や、前回の失恋からまだ立ち直れずそういう話をする気分ではないときに使う。ちなみに、このステータスだからと言って必ずしも過負荷であったり立ち直る最中とは限らない。単純に告白に対して返答する気がないだけの場合もあり、とにかく分かることは「今聞いても返事が返ってこない」ということである。親切な相手であれば「ちょっと今」が「いつまで」なのかを教えてくれることもあるが、そうでなければ告白した側にから見れば500の場合と大差ない。

400系多くない?

やっぱり人間断わるときの方があれこれ考えるものなんだろうか。色々理由付けられても「ダメ」なことに変わりはないんだけど、ダメと返されたときに「諦める」「何度でも言う」以外にパターン毎に適切な対応をした方が相手の態度も変わってくるんじゃないかと思うんだ。なんだそのまとめ。

追記

400系のネタだけでにするつもりだったけど結局他のも入れたので、「告白を断わるときの…」ってタイトルは変えた。

あと、400系は基本的にクライアントからのリクエストに問題があるときに使うものなのに、告白された方の問題のような書き方をしてるとこは直した。告白される方や仲介してくれる人に問題があるのは500系。まぁ、幼児や機械に交際を求めるリクエストはどっちかというと403 Forbiddenな気もしないでもないけども。

彼女のステータスを返す」のソースが読みたいというリクエストがあったので、少し書き直してgistに上げてみた。

gist: 112607 - GitHub

一応上の状態でrackupすれば動きます。hamlとrackの最新版が必要な他は特に何も要らないはず。ちなみに1.8.6、1.8.7、1.9.1では動くのを確認済み。んでPassengerで動かすときには、「PassengerでRackアプリを動かす」で書いたように、config.ruと同じ階層にpublicとtmpってディレクトリを作ってやって、コメントアウトしてあるRewindableInputWrapperを有効にしてやればいいはず。

ついでにRack::Testを使って書いたspecと、実際にGETしたりPOSTしたりしてどんなレスポンス返してるのか見るスクリプトも置いといたので、参考までに。

ぶっちゃけRackとHaml(とあとPassenger)で遊びたかっただけなので、「Sinatraのが楽じゃね?」「ってかそれApacheの設定だけでなんとかなりそうな…」とかいうツッコミは無しの方向で。ちなみにRackでオレオレWAFもどき作りにはそろそろ飽きてきたので、今はRamazeさんで遊んでたり。Ramazeさんいいな、気に入った。とはいえこのRackいじりは無駄ではなくて、こういうことやってからRamazeのソース読んでたら案外流れが掴めて良かった。

あとLast-Modifiedの日付とかもうほんと冗談なのでそういう小ネタに食いつくとか無しの方向で。食いつくなよ。絶対に食いつくなよ。絶対だかんな!

大分出遅れたけど乗ってみた。

上の方は日常的に使ってて下に行くほど怪しくなってくる感じで。

  • Ruby
  • Objective-C
  • Perl
  • HTML
  • JavaScript
  • CSS
  • XML
  • SQL
  • C
  • PHP
  • Java
  • C#
  • ActionScript
  • Haskell
  • LLVM asm
  • Brainf*ck
  • DT
  • Whitespace
  • XSLT
  • てってってー
  • VB
  • YARV opcode
  • Curry
  • Schema
  • Erlang
  • SmallTalk
  • Python
  • C++
  • D
  • Io
  • Grass

思ったよりはあったけど、Low Layerなのが全然入ってなくて残念な感じ。あとなんか変なの入ってるな。なんだよDTって。ちなみにASあたりまでは一応仕事で書いたことのあるもの、Schemaより下はそれこそHello, worldくらいしかやったことないもの。そういやC++使ったことない。なんでだろ。ObjCばっかり書いてるからかな。うん。

日々着実にバカな方にバカな方に向かってるのを実感してるfaultierです、みなさんお久しぶり。

一昨日あたりに見かけた「彼女がいないことをステータスコード404で表わす」ってのが大変ツボに入ったので、今日はせっかくだから実際にそれを実装してみたよ。なんと以下のURLをGETすると「faultierの彼女」ってリソースがいまどんなステータスなのか返してくれるんだ。

http://faultier.jp/resource/kanojo

…まぁ俺に彼女がいるかどうかなんて瑣末なことはどうでも良くて、一応これGET/POST/PUT/DELETEに対応してて、それぞれ違うレスポンスを返すように作ってあるので、生まれついてのHTTPクライアントな感じの少年少女紳士淑女な方々はいろんなリクエストを送って「リソース:faultierの彼女」をいじってみるといいと思うんだ。まぁどう操作しようが何も起きませんが。何、あんま使わないからってサボってGETとPOSTしか実装してない?しょうがないやつだな、GETするときにURLの末尾に/putとか/deleteとか入れてみなよ。それっぽい動きするから。

みごとに400系のステータスコードばっかりになっちゃったけど、せっかく作ったので、そのうち「418 I'm a teapot」とかも実装する予定。ってそれも400系か。あ、あとちなみに、GETするときにmode=prevとかmode=nextってクエリを付けると「前の彼女」「未来の彼女」についての情報も返ってくる。どうでもいいですね。

追記:418も実装した。ついでに多少ステータスコードをいじった。そのリクエストにそのレスポンスは普通無いだろ、みたいのがあるとあれなので。あと、HEADを忘れてたのでHEADも対応した。

Rack可愛いよRack

ネタはネタとして置いとくとして、今回はこれをRackHamlを使って作ってみた。何でかというと、今Ruby版Atompub::Serverみたいの作ってて、RailsやMerbのプラグインもそのうち書くつもりではいるんだけど、まず単体でサクっと動くの作りたいなと思っていろいろいじってるところだったから。Hamlは興味はあったんだけど中々触る機会がなかったので、ついで。

なんというか、Rackは素敵だなぁ。この程度のものを作るのにちゃんとしたWAFを使うのもなんだかゴキブリ退治に対戦車ミサイル持ち出すみたいで気がひけるんだけど、かといってCGIってのもねぇ、みたいなときにもとても良い。簡単な認証とかロギングとかセッションとかは添付のミドルウェア使えば実現できちゃうし、WEBrickとかで簡単にローカル環境で開発サーバ作れちゃうのも魅力的。そんでもって深く考えなくてもWEBrik、thin、mongrel、fcgi、Passengerと色んな環境に対応できちゃうのも素敵だ(というかそれは話が逆で、そのためのインターフェースライブラリなんだけども)。なによりRack::Testが便利すぎる。こんなしょうもないアプリでもちゃんとSpec書いたんだぜ、あんまり簡単だったから。

ハムは食べたいけども

Hamlの方は、なんというか、結構微妙。いやまぁ、確かにすっきりシンプルなテンプレートが書けるんだけど、普段見なれてるHTMLから乖離しすぎててちょっと抵抗あるかも。正直学習コスト考えたら素のHTMLとRubyをそのまま書けるerbやその派生/改善版のテンプレートエンジンのがよっぽどとっつきやすい気がする。一人でやってるときはともかく、デザイナーやマークアッパーとの分業で仕事してると、これ出力がどうなるか想像しながらやんなきゃならなくて作業しづらいんじゃないのかなーとか思ってしまう。

とは言え不思議な魅力もあるのも確かで、文句言いながら書いてたけど数分後にはなんとなく慣れてしまった。趣味でなんか作るときにはしばらく使ってみようかなと思ってたりする。

ところで

一応言っとくけど、あそこからエントリーしても別にデータとか保存してないしメール送ったりもしないので、安心して彼女の名乗りを上げるといいよ!まぁ本当に名乗りたければあんなとこで慎しやかに名乗られても困るけど、いないよねそんな人。

このブログへのアクセスを見て、どんな人が見に来てくれてるんだろうなーと想像するのは結構面白い。例えば、このブログの6、7割はリーダー経由で来てるとか、IE6の倍以上Mac Safariのアクセスが来るとか、大体がリピーターだけど大概の人が1セッションにつき1~2ページしか読まずに帰るとか、それだけでも「ああ、このブログ読んでるのはやっぱ俺と同種の人達なんだろうな」と推測できてニヤニヤできる。というか、おかしいよねその比率。ここで書いてる内容から言うとまぁそうかなという気がするけど。

ところで、面白いのが、「どんなキーワードで検索してこのブログに来たか」。ちなみにGoogle Analyticsで取れたキーワードの上位10位がこれ。

検索キーワード

なんだこれ。いや、LLVMとかDataMapperとかは、実際書いてるし、わかる。というかLLVMやらDataMapperやらMacRubyで検索してほぼ上位のページに出てることの方が驚き。ごめんなさいごめんなさい。せっかく来てくれてるのにDTのことばっかり書いててごめんなさい。

それはいいんだけど、「あきばふみっ娘学園」とか「第501統合戦闘航空団 秘め声CD」って何。俺、それについて一言も言及したことないし、そもそもどっちも一体どんなものなのかも良く知らないんですが。いや、名前は知ってる。でもどっちも、明らかにもっと相応しいページがあるよね…?ってか、どうやっても俺のブログになんか辿り着けないんだけど…なんでこれが一定数居るんだよ…。先生、怒らないから正直に言いなさい。どうやってここに辿り着いたんだ。それだけが気になる。

そして良く考えたら、今までは本当に一切言及してなかったから謎のキーワードだったんだけど、この記事を書いたせいでそのワードで検索引っかかるようになるねこれ。そう言えば以前「兄貴と私 ボディービル」なんてのでこのブログ引っかかるようになっちゃった前例があるし…。ひゃー。うっかり上記のワードでここに来てしまうであろう人に申し訳ない。ちゃんと言っとこう。当ブログはフィクションではありませんが、実在のふみっ娘とも秘め声CDとも一切関係ありません。ついでに言うとfaultierはボディービルダーではありません。

あー、どうせ無関係な単語で飛んでくるんなら、せめて「御坂美琴 感電したい」とか「萩原雪歩 一緒に埋まってますぅ」とかで検索してくれたらもっといいんじゃないかなぁ、って何を言ってるんだろう俺は。

追記

美琴に感電したい

Google先生、反応速すぎやしないですか…。本当に捕捉されてしまった…。

こないだ作ったesotericがあろうことか0.0.2にバージョンアップしました。主な変更点は以下の通り。

  • 各言語をコンパイルしてできる中間コードが、前のバージョンでは似非アセンブラ的な何かだったものを、ParseTreeなんかで作るようなRubyの抽象構文木(AST)的な何かに変わった。VMでの実行前に生成されたコードを最適化するとかできるようになるとか、他のRubyライブラリにEsoteric Languageパーサが埋め込めるようになるとか、無駄に夢が広がる感じで。
  • もちろん似非VMでは動かなくなったので、作り直さなきゃいけないんだけど、ちょっと時間かかりそうなので似非VM殺した。そのかわり、ASTはRuby2RubyとかでRubyコードに変換できるように作ってあるので、とりあえずRuby2Rubyを使うようにして誤魔化すことにした。
  • 副産物としてDTやWhitespaceのコードを実行可能なRubyスクリプトに変換するコンパイラもどきのツールが出来た。Cへのトランスレータもあるみたいだし、そういうの使えば本当にコンパイルしてバイナリも作れたりしますね。DTでコマンドとか作れるようになるね。まったくやりたくないけどね。
  • Brainf*ckのパーサを追加
  • てってってーのパーサを追加。一応一通りの仕様は満たしてると思うけど、「「\xAB」「\uABCD」「\d00000」:エスケープシーケンスとして、それ全体で1文字と扱われる。(予定)」ってのはまだ実装してない。あと「ててー」と「てっー」が微妙な動きをするのを解決してないけど、まぁそのうちなんとかする。

とまぁ、そんな感じ。次はまず、VMの再実装と、あとSpec書く。それ終わったらRubyで作る奇妙なプログラミング言語 ~Esoteric Language~に載ってたStarryやBolicでも実装しようかな。あとはとかやってみようかしら。

大分楽しくなってきたところだけどアイマスSP買ってきてしまったので、一回休み。そしたら来月ぐらいから仕事が忙しくなるに違いないのでまた一回休み。一段落ついたら多分飽きてるだろうからまた(ry。まぁまったりもったりやりますかねぇ。

プログラミング言語DTを作ったところ「いいからソースを晒せコラ」と言われたので、DT処理系のソースコードをgithubに上げてみた。

faultier's esoteric at master - GitHub

正確に言うと、DTの処理系と言うか、似非VMとそれで実行できる中間言語を吐くコンパイラ群のセット。その中にDTコンパイラとサンプルも入ってます。構成整理して無駄にgemspecを作ってあるので、

$ sudo gem install faultier-esoteric --source http://gems.github.com

とかやるとesotericがインストールできる…はず。なにしろgem作るのも初めてだしそれをgithubで自動ビルドさせるのも初めてなので、なんかしくじったかもしれない。てか、初めてのgemがこれか。それでいいのか、俺。まぁいいや。あ、できた。ちゃんとできてた。一応1.8.6-p287、1.8.7-p72、1.9.1-p0では動作確認済み。大したことやってないのでまぁ動くはず。

ちなみに、esotericに含まれてるコンパイラはWhitespaceとDTだけです。HRKは白紙に戻して、Nonowaと改称した上で言語仕様から考え直すため、Decadeはfaultierが某特撮番組を観てないので、ファンの人から怒られそうなため、今バージョンでのリリースは見送りました。今バージョン、てことは、esotericはバージョンアップするものらしい。何のために。誰が得するんだ。多分次のリリースあたりではBrainf*ckとかてってってーとかが取り込まれてて、その次のリリースあたりではNonowaが実装されたりしてるんだと思う。気が向いたら。飽きてなかったら。

あ、で、使い方だけど、インストールするとesm、whitespace、dtの三つのコマンドが使えるようになるので、

$ dt -v
esoteric 0.0.1, dt 0.0.1
$ dt hi.dt
Hi!

などとすると前の記事のコードが実行できたりする。これであなたも今日からDTer。

まさかそんな馬鹿いないとは思うけど、これ一緒にいじりたい、って人がいたら「べ、別にあなたのために手伝ってあげるんじゃないんだから、ただの興味よ、興味」とかメールで送ってください。別になにもしないけど。俺がニヤニヤします。…まぁ、githubにあるものなので好きにいじってください。あ、あとVMのこととか教えてくれる人がいたらすごく喜びます。

最近「Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~」を読んで、ついカッとなって言語処理系を作ってみた。それも、チューリング完全な、本物の(ry まぁ、Whitespaceのトークンを置き換えただけだけど。

一応、上記の本に習って、ソースコードをWhitespaceの命令セットを持つ中間言語にコンパイルしてVMで実行する形にしてみた。あとはパースする部分を適当に置き換えたコンパイラを作ればそれっぽいのが簡単に作れる。んで、いくつかネタ言語を作ってみたんだけど、その中でも一番しょーもないのがDT。DTでは次のようなソースを実行することができます。("Hi!\n"を出力する)

「○○くんて、もしかして童貞?」
「どどど童貞ちゃうわっ!どど童貞ちゃうわっ!どどど…童貞ちゃうわっ!」
「えー。その慌てっぷりが余計怪しなぁw」
「…どどどどど童貞ちゃうわっ!童貞ちゃうわっ!ど童貞ちゃうわっ!どど童貞ちゃうわっ!…童貞ちゃうわっ!」
「はいはい、わ、わかったってば。そんなにムキになんないでよ。」
「…どどどどど童貞ちゃうわっ!どどどど童貞ちゃうわっ!…童貞ちゃうわっ!」
「だから、わかったってば。もう言わないから。」
「…どどどどど童貞ちゃうわっ!ど童貞ちゃうわっ!ど…童貞ちゃうわっ!」
「いやその、なんか、ほんとごめんね。そんなに気にしてると思わなかったから、あの…」
「どど…」
「(ほんとキモいなぁ…)」
「…」

バレンタインだと言うのに一体何をしてるんですかね、僕は。ちなみに「ど」「童貞ちゃうわっ!」「…」以外の文字は全て無視するので、それらの順番と数さえあってればどんなコメントを挟んでも問題ない。コメント記法とかも特にない。ちなみに上記のコードから有効な部分を抜き出すとこんな感じ。一応読みやすくするために改行は入れてある。

どどど童貞ちゃうわっ!どど童貞ちゃうわっ!どどど…
童貞ちゃうわっ!…どど
どどど童貞ちゃうわっ!童貞ちゃうわっ!ど童貞ちゃうわっ!どど童貞ちゃうわっ!…
童貞ちゃうわっ!…どど
どどど童貞ちゃうわっ!どどどど童貞ちゃうわっ!…
童貞ちゃうわっ!…どど
どどど童貞ちゃうわっ!ど童貞ちゃうわっ!ど…
童貞ちゃうわっ!…どど
………

あと他に「アイドルが機嫌良さげに踊るののワ型言語HRK」とか、「9つの世界を巡る変身ヒーロー型言語Decade」とか作ったけど、どれも今のところただのWhitespaceなのでどんなソースになるかは想像つきますね。てことで割愛。もちろんどれも入出力や四則演算やジャンプ命令を備えてますので、フィボナッチ数列を無限に出力するとか余裕だし、その気になればきっとWebアプリぐらい書けますね。やりたかないけど。ていうかどれも書くことを全く考慮してないので、俺もうざくなって似非中間言語書いてそれを置換してソースコードにするっていう本末転倒なことしないと書けない。まぁそんなもん。

そろそろWhitespaceにも飽きたので、次は何しよう。Ruby分は十分補充できたので、Objective-CでVM書くとか、Parrotの上で処理系作るとかしようかな、とか。関数型言語もまだやってないので、それを実装するのもいいし、処理系をHaskelで書いてみるとかもしたい。しょーもない見た目の「まともな」言語仕様を考えるとかもしたいなー。やってみると結構面白い。ハマる。十分脳味噌ほぐれたらちゃんとした言語処理系のソースでも読んでみよう。

と、そんな現実逃避をして過した休日。うーん、充実した土日だった。え?何?何でDTなんか作ったのって?もしかしてfaultierって童…いいいいいやいやいや。どどどどど童貞ちゃうわっ!

注意

上の言語はほんとしょーもないですが、Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~の方はちゃんと面白い本なので誤解のなきよう。変な言語も色々紹介されてるし、Rubyでサクっと言語処理系つくるやりかたも書いてあるので、オススメです。

Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~
著者:原 悠
販売元:毎日コミュニケーションズ
発売日:2008-12-20
おすすめ度:4.0
クチコミを見る

追記

これ書いた後にクチコミを見たら弾さんがてってってーとかやってて、その記事のさらに元記事が結構なブクマ数だったりして、今頃それに気付いてなんか負けた気分。ぬぅ…。いいもん、ちゃんとののワさん言語完成させるから。もうなんかiPhoneで動くようにしちゃうから。配布できないけど(インタプリタは規約でAppStoreに登録できなかったはず)。

↑このページのトップヘ