Lazy aKari:わぁいLazy K あかりLazyKインタプリタだいすき

Abstract

CPUのクロック数が頭打ちになり、1コアあたりの性能を向上させるよりもコア数を増やす事による並列性能向上が行われるようになった昨今では、並列化の行い易い純粋関数型プログラミング言語が注目されています。本研究で題材とするLazyKは、トークンが4つというシンプルさでありながら、チューリング完全な純粋関数型プログラミング言語です。

一方、近年のアニメシーンにおいて、アニメ本編よりもインターネット上での罵声の浴びせかけあいやステマばかりが着目され、アンチと信者のせめぎあいがより激しくなり荒廃が進んでいます。

7/2より放送されている「ゆるゆり♪♪」の主人公赤座あかりは、彼女の必殺技「\アッカリ~ン/」によって可視光における強い参照透過性を実現し、彼女のすべてを愛す性格によって、世界に愛をもたらしています。

本研究では、LazyKに赤座あかりの愛を組み合わせた独自言語「Lazy aKari」を実装することで、LazyKの啓蒙と世界に愛を広めました。

いつも通りの「トークン変えただけのゴミ言語のお時間」です。Brainfuckでやってる事が多い気がしますが、毎度毎度Brainfuckでやるのも流石に秋田ので別のにしました。トークンが4つで調度良かったのでLazyKです。で、毎度毎度手続き型で書くのも秋田ので今回はLISPで書いて見ました。ほとんどLISPの機能を使ったので随分楽ちんな実装となっております。

Scheme処理系の一つであるgaucheを使ってます。

Unlambdaスタイルのみに対応しております。トークンの対応は次の通り

  • わぁい⇨`
  • うすしお⇨s
  • あかり⇨k
  • だいすき⇨i
$ gosh akari.scm <ソースファイル>

として、入力を入れたらCtrl+D(WindowsではCtrl+Zらしい)を押して入力を確定すると、プログラムが実行されて結果が表示されます。

サンプル:echoプログラム

入力をそのまま返します。

大好き

これを保存してgosh akari.scm echo.txtとして実行し、入力したらCtrl+D(WindowsではCtrl+Z)を押してね。入力した結果がそのまま表示されます。

% gosh akari.scm echo.akari
yryr[Ctrl+D]
yryr

大好きはエコー…。そう、人と人との絆は、相互承認なのです(鼻で笑いながら

サンプル:Hello World

Hello Worldです。メッセージ変えたかったのですがLazyKは書ける気がしなかった()のでWikipediaのをそのまま使いました

わぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁいうすしおわぁい
 あかりわぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかり
 うすしおあかり大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいわぁいうすしおわぁい
 わぁいうすしお大好き大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁいうすしおわぁい
 わぁいうすしおわぁいあかりうすしおあかりわぁいわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかり
 うすしおあかり大好きわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁい
 あかりうすしおあかり大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁい
 わぁいわぁいうすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁい
 わぁいうすしおわぁいあかりわぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいわぁいうすしお大好き
 大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしお
 わぁいわぁいうすしお大好きわぁいあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいわぁい
 うすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 大好きわぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしお
 わぁいあかりうすしおあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしおわぁいあかりわぁい
 わぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいうすしおわぁい
 わぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいわぁいうすしお大好き
 大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしおわぁい
 わぁいうすしお大好きわぁいあかりわぁいわぁいわぁいわぁいうすしおわぁいわぁいうすしおわぁい
 あかりうすしおあかりわぁいわぁいわぁいうすしおわぁいわぁいうすしお大好き大好き大好き
 わぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいわぁいうすしお大好き大好き
 わぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしお
 わぁいわぁいうすしお大好きわぁいあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいわぁいうすしおわぁい
 わぁいうすしお大好き大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁい
 あかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好き
 わぁいあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお
 わぁいあかりうすしおあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしおわぁい
 わぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいうすしおわぁいわぁいうすしお
 わぁいあかりうすしおあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいわぁい
 うすしおわぁいわぁいうすしお大好き大好き大好きわぁいわぁいうすしおわぁいわぁいうすしお
 わぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好き
 わぁいあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしお
 わぁいあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしおわぁいあかりわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいわぁいうすしお大好き大好き
 わぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしおわぁいわぁい
 うすしおわぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好き
 わぁいあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしお
 あかり大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしお
 わぁいあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁいうすしおわぁいあかり
 わぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好き
 わぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしお
 あかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁい
 うすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁいわぁいうすしおわぁいわぁいうすしおわぁい
 あかりうすしおあかり大好きわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお
 わぁいあかりうすしおあかり大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり
 わぁいわぁいわぁいうすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうす
 しおあかり大好きわぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいうすしおわぁいあかりわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいわぁいうすしおわぁいわぁいうすしお
 大好き大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好き
 わぁいあかりわぁいわぁいうすしおわぁいわぁいうすしお大好きわぁいあかりわぁいわぁいうすしおわぁい
 あかりわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいわぁいうすしお
 わぁいわぁいうすしおわぁいあかりうすしおあかりわぁいわぁいわぁいうすしお大好き大好きわぁいわぁい
 うすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好きわぁいあかりわぁいわぁいうすしおわぁい
 わぁいうすしお大好きわぁいあかりわぁいわぁいわぁいうすしお大好き大好きわぁいわぁいわぁい
 うすしお大好き大好きわぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好き
 わぁいあかりわぁいわぁいわぁいうすしお大好き大好きわぁいわぁいわぁいうすしお大好き大好き
 わぁいわぁいうすしおわぁいわぁいうすしおわぁいあかりうすしおあかり大好き

どうしたあかり。たまにはのり塩も食べないと。

% gosh akari.scm hello.akari
[Ctrl+D]
Hello, world!

かんたんなかいせつ

LazyKは上にあるように、4つのトークン`skiをつかいます。で、そのうちskiの3つは関数です。LISPで書くとこんな関数。

(define (S x) (lambda (y) (lambda (z) ( (x z) (y z)))))
(define (K x) (lambda (y) x))
(define (I x) x)

で、`というのは関数呼び出しを表します。つまり、`ikは(I K)で、“skiは( (S K) I)のことで、`s`kiは(S (K I) )ということです。関数は必ず1つだけ引数を取ります。以下可読性を重視してLISP形式で書きます。

Iは引数をそのまま返す関数なので簡単ですね。

Kは関数を返す関数です。つまり、(K 1)の戻り値は (lambda (y) 1)という「関数」で、((K 1) 2)としてさらに戻ってきた関数を呼び出すと1(=x)という結果になります。なんでこんな面倒な事をするかというと、LazyKの世界では関数は引数を1つしか取れないのですが、Kという関数にはどうしても2つ引数を取らせたかったからです。LazyKでは関数は関数を返すことができるので、関数を返す関数を作ることで引数が1個しかとれない問題を回避しています。これをカリー化と言うそうです。

Sはちょっと厄介ですね。((S K) K)が関数Iと等しい関数であることを確かめると理解できると思います。

((S K) K) -> (lambda (z) ( (K z) (K z))) ;定義にしたがって、xとyをKに置き換えただけ
-> (lambda (z) ( (lambda (w) z) (K z))) ;最初の(K z)を展開した。内側のラムダ式でwは使われないことに注目。
-> (lambda (z) z)
-> これはIそのもの

…うーん、面倒ですね。

数字は?

LazyKは上記でみた3つの要素しかありません。数字というリテラルはありません。えっ、でも計算くらいできないと困るじゃん。

そこでLazyKでは、数をチャーチ数というので表します。数とありますがやっぱり関数で、この関数に別の関数fを渡すと、fをn回適用してくれる関数を返してくれる関数です。「関数」がゲシュタルト崩壊してきてはあ?って感じですね。たとえば、チャーチ数で3を表す関数をchurch-3は、引数として関数fをとり、「f(f(f(x)))を返す関数」を返してくれます。つまり、渡す関数を「引数に1を足して返す関数」にすると、

(define (adder x) (+1 x)) ;1を足した引数を返す
((church-3 adder) 0) -> 3

というわけです。ちなみに、チャーチ数の0は(K I)です。

リストは?

よくわからないんですけどこれも関数で表します。LISPのcar/cdrなリストと同じような構造で、具体的にはリストの関数を_LIST_とすると、(_LIST_ K)とするとcarが、(_LIST_ (K I))とするとcdrをしたことになるらしいです…。同様にconsも定義できるそうです。 終了条件がわからない(lispでのpair?はどうやるの?)ので誰か教えてください。

入出力は?

入出力は上で紹介したチャーチ数とリスト構造を使います。LazyKのプログラムは関数を組み合わせて作られる大きな大きなひとつの関数なので、これへ引数として入力値のASCIIコードをチャーチ数で表したもののリストを入れて実行されます。で、その戻り値(チャーチ数のリスト)が出力というわけです。

なので、「大好き」(=i)だけのプログラムは、入力値をそのまま返すechoプログラムになったわけですね。

というかですね

LazyKは情報がなさ過ぎます。あと実をいうと二期はまだ見てないです(

二期みた

こwwwwwねwwwwwこwwwwwwwちゃんwwwwwwwwwwwwwwwwwwwたちwwwwwwwwwwwwwwwwwww