32
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

「文言」(漢文プログラミング言語)の「獺祭」について

Last updated at Posted at 2020-07-22

いままでのあらすじ

プログラミング経験の無い友人と通話していたところ、彼は「文言」(漢文プログラミング言語)プログラミングを始めてしまいました。これは3割ぐらい私のせいなので、責任を取って私も始めることにしました。

公式サイトを見たところ、

wenyan currently compiles to JavaScript, Python, or Ruby, and will support more languages (e.g. C) in the future.

と書いてあったので、「よし、じゃあRustへのコンパイラを書くか。Rustで。」という気持ちになりました。ということでそれを書いています。GitHubリポジトリはこちら。2020年7月22日現在、愛おしい教科書の「算術第三」まではコンパイルできるようになっています。

内容

今回は、これを実装する上で「仕様を読まずに空気を読む」で組んだ結果だいぶ仕様の理解に苦労し、最終的に教科書(の「變數第二」)に答えの書いてあった仕様である、「獺祭」について解説していきたいと思います。

前提知識

はじめてのプログラミングを「文言」(漢文プログラミング言語)で 1日目』は読んできていることを前提とします。もしくは原文の明義第一

「獺祭」?

日本では酒の名前として有名ですね1。なぜそれが仕様の名前なのでしょうか。

実は「獺祭」または「獺祭魚」というのは礼記に出てくる言葉で、自分が捕まえた魚を並べるカワウソの習性を祭り供え物(Mag462さんご指摘ありがとうございます)に喩える用語だそうです。これから解説する仕様は「變數第二」の末尾に説明されているのですが、この「獺祭」の典故を知らないと意味が取れません。私に漢籍の教養がないことを恥じるばかりです。

教科書読解

さて、読んでいきましょう。文脈としては、

加一以三。加六以九。名之曰「甲」。曰「乙」。

と書くことによって変数「甲」に1+3、「乙」に6+9が入る、という説明がされた後で、

凡未名之變數。皆如獺祭然。言者。取至近之魚而棄其餘。言書之者。盡書之。言名之者。取若干而名之。曰。然也。善哉此比。

問曰。每有未名者。輒祭如是。豈非終累累然焉。今欲盡棄其魚。復當作何書。曰。當書者。嘆辭也。所以嘆彼之盡棄也。

という記述があります。先程の典故を踏まえると意味を取ることができて、

  • 名前のついていない変数は、カワウソが魚を並べるように並んでいる。
  • は、最も近くの魚(=名前のついていない変数)を取って残りを捨てる。
  • 書之は、これ(=並んでいる魚)を全て書く。
  • 名之は、何個かを取ってこれを名付ける。
  • 魚を捨てたいときには、と書け

ということが書いてあります。

先程の例を見ると、

加一以三。加六以九。名之曰「甲」。曰「乙」。

加一以三。で魚4が並べられ、加六以九。で魚15が並べられ、名之曰「甲」。曰「乙」。で魚2匹が消費され変数「甲」と変数「乙」に値が代入される、ということです。

せっかくなので、幾つか例を見ていきましょう。

例1

加二以三。加一以三。加三以三。書之。書之。

魚が546の順に並べられ、最初の書之がこれらを全て消費し五 四 六を出力。次の書之は消費すべき変数がないので空文字列を出力する。

例2

加二以三。加一以八。減其以七。書之。

魚が59の順に並べられ、次の減其以七にあるは川岸から9を取得して5を捨てる。よって9から7が引かれた2のみが川岸に置かれるので、書之によりが出力される、

例3

加二以三。加一以三。加三以三。名之曰「甲」。曰「乙」。書之

これは、魚が546の順に並べられ、次の名之曰「甲」。曰「乙」。によって最も近くの二つである46がそれぞれ「甲」と「乙」に。川岸にはまだ5が残っているので、それを書之が出力する。

例4

加一以三。加六以九。名之曰「甲」。名之曰「乙」。

これは先程見た 加一以三。加六以九。名之曰「甲」。曰「乙」。非常に似ているが、なんと挙動が異なる。今回は魚4と魚15が並べられたあと、名之曰「甲」。最も近くの魚を一つ消費するので、「甲」には15が入り、次の名之曰「乙」で「乙」に4が入る。

紛らわしい。私はこれで1回バグらせた。

例5

加一以三。加二以三。減其以其。書之。

これは45が川岸に置かれたあと、減其以其の最初の5を取得し、同時に魚を全部捨てる。よって次のは何も取得できない2。結果として計算は上手く行かず、不可算數かなんかが出力される。

例6

吾有一言。曰「「天地。」」。
為是三遍。
	書之。
	吾有一言。曰「「問天地好在。」」。書之。
云云。

まず文字列「「天地。」」を川岸に置いたあと、ループが始まり、直後に書之がある。これは川岸に置かれた列「「天地。」」を指し、これを指し続ける。結果、出力されるのは

天地。
問天地好在。
天地。
問天地好在。
天地。
問天地好在。

となる。

余談(というか愚痴)

JavaScriptくんで自由に使える undefined とかいうものの意味論をRustに移すのがわりとつらいです。ReferenceErrorが実行時にcatchできるのもつらそうです。吾有一言。名之曰三。を本家実装くんが平気でvar 3 = "";とかコード生成してくれるのもつらいです。issue・プルリクお待ちしています

  1. 私は酒を一切飲まないので詳しいことは知りません。

  2. 本家実装は 加一於三。減其於其加一於三。減其以其 も共に const _ans1 = 3 + 1; const _ans2 = _ans1 - undefined; にコンパイルされるのだけど、厳密にいうと意味論的には片方は undefined - _ans1 であるべき……だけどまあ必ずNaNになるんだし、まあ、うーん

32
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?