Emmental言語の紹介と記録
http://esolangs.org/wiki/Emmental
良い言語である。 (面倒なだけの部分を機械に投げ付けてしまえば)けっこう書き易い。 grassとsedを足して割った感じ。
introduction
状態としては、stackとqueueをそれぞれ持ち、動的に操作できる関数空間を持つ。
命令は使い易さと簡潔さを意識して選ばれており、条件分岐は縮約命令 $\lfloor log x \rfloor$ ~
とeval ?
を主に用い、関数を呼び分ける形で行う。
関数定義のためのquoteによる特徴的な見ためを持つ。
詳細に関してはwiki等を見て。
examples
drop命令
準備として、; #0 !
として$0$番目の関数をnopにする。
: -
としてstack topを$0$にし、?
により$0$番目の関数を呼ぶことでこれを消費し、全体としてdrop操作となる。
not命令
例えば~ #8 + ~ #3 -
とする。
$256$種類の値を$0,1$の$2$種類に分ける必要があるが、非可逆操作でこの用途に使えるのは実質的に$log x$ ~
のみであり、これを使う。
$0, 1, \dots, 255$をまず$8 = [0], 0 = [1] = [2], \dots, 7 = [128] = \dots = [255]$の$8$種の同値類に分割し、これをずらして再度分割することにより、$0, 1$のみに潰す。
if文
分岐が可能な命令はeval ?
のみである。
例えば、上で示したnot等を使い$0,1$を作り、関数$0$と関数$1$をそれぞれ分岐先として定義し、?
により呼び分けることで実現できる。
while文
末尾再帰のようにすればよい。if文で直接制御してもよいが、再帰関数自体を動的にnopで塗り替えることもできる。
criticism
if文やwhile文の分だけ関数定義がnestすることになる。 この際、toplevelとそれ以外で諸々の挙動に差があり、綺麗でない。 具体的には、
;
命令はtoplevelでのみ使える';
$=$#59
と;
は同値であるので、ひとつ内側では'';
と#35#53#57
とする必要がある
?
を介さない直接の関数呼び出しが不透明- その関数内で動的に定義された関数を呼ぶには
?
が必要 !
命令により定義された関数が実際の環境に反映されるのが、そのscopeを抜けた時点であるのが原因
- その関数内で動的に定義された関数を呼ぶには
fizzbuzz
書いた。
quoted
wikiのそれと同様のquoteによる記法で書いて翻訳させた。以下のような規則。
'A
$\to$#65
''A
$=$'#'6'5
$\to$#35#54#53
'''A
$\to$#35#51#53#35#53#52#35#53#51
中規模のものを書きたいなら、例えば以下のような拡張されたquotationと、commentの記法を定めるとよさそう。
'(ABC)
$=$'A'B'C
$\to$#65#66#67
'(A'(BC)D)
$=$'A''B''C'D
$\to$#65#35#54#54#35#54#55#68
; #32! NOP
; ':'-'3'2'? '$ ! DROP
; '~'#'8'+'~'#'3'- 'c ! NEGATE LOGICALLY
; '#'1'0'. 'a ! PRINT NEWLINE
; ''f'.''i'.''z'.''z'. 'f ! PRINT FIZZ
; ''b'.''u'.''z'.''z'. 'b ! PRINT BUZZ
; ''0'+'. 'p ! PRINT DIGIT
; 'v'^'$ 'r ! ROTATE QUEUE
MEMORY ON QUEUE
#1^$ FIZZ
#1^$ BUZZ
#0^$ TEN
#1^$ ONE
#1^$ COUNT
;
MEMORY ON FUNCTION AREA
''; '''p''? ''n '!
''; '''; '''n ''! ''N '!
FIZZ
'v
''; ''f''N ''$''#''1 '#'1 '!
''; ''#''1''+ '#'0 '!
':'#'3'-'c'? '^'$
BUZZ
'v
''; ''b''N ''$''#''1 '#'1 '!
''; ''#''1''+ '#'0 '!
':'#'5'-'c'? '^'$
TEN
'v
''; '#'1 '! SKIP IF ZERO
''; '':'''n''? '#'0 '!
':'c'? '^'$
ONE
'v
':''n'?
''; ''$''#''0 ''r''r''r''v ''#''1''+ ''^''$ '#'1 '! CARRY
''; ''#''1''+ '#'0 '!
':'#'9'-'c'? '^'$
'a NEWLINE
'v
''; ''';'''l''! '#'1 '! REMOVE FUNCTION L
''; ''#''1''+ '#'0 '!
':'#'1'0'0'-'c'? '^'$
''l'? NEXT LOOP
'l!
l BEGIN LOOP
raw
組込みでない関数がdefaultでは何もしない関数として扱われる(仕様?処理系依存?)ようなので、大文字で書いたCOMMENT
はそのままにしていてもよい。
; #32!
; #58#45#51#50#63 #36 !
; #126#35#56#43#126#35#51#45 #99 !
; #35#49#48#46 #97 !
; #35#49#48#50#46#35#49#48#53#46#35#49#50#50#46#35#49#50#50#46 #102 !
; #35#57#56#46#35#49#49#55#46#35#49#50#50#46#35#49#50#50#46 #98 !
; #35#52#56#43#46 #112 !
; #118#94#36 #114 !
#1^$
#1^$
#0^$
#1^$
#1^$
;
#35#53#57 #35#51#53#35#52#57#35#52#57#35#53#48#35#54#51 #35#49#49#48 #33
#35#53#57 #35#51#53#35#53#51#35#53#55 #35#51#53#35#52#57#35#52#57#35#52#56 #35#51#51 #35#55#56 #33
#118
#35#53#57 #35#49#48#50#35#55#56 #35#51#54#35#51#53#35#52#57 #35#49 #33
#35#53#57 #35#51#53#35#52#57#35#52#51 #35#48 #33
#58#35#51#45#99#63 #94#36
#118
#35#53#57 #35#57#56#35#55#56 #35#51#54#35#51#53#35#52#57 #35#49 #33
#35#53#57 #35#51#53#35#52#57#35#52#51 #35#48 #33
#58#35#53#45#99#63 #94#36
#118
#35#53#57 #35#49 #33
#35#53#57 #35#53#56#35#51#53#35#52#57#35#52#57#35#52#56#35#54#51 #35#48 #33
#58#99#63 #94#36
#118
#58#35#49#49#48#63
#35#53#57 #35#51#54#35#51#53#35#52#56 #35#49#49#52#35#49#49#52#35#49#49#52#35#49#49#56 #35#51#53#35#52#57#35#52#51 #35#57#52#35#51#54 #35#49 #33
#35#53#57 #35#51#53#35#52#57#35#52#51 #35#48 #33
#58#35#57#45#99#63 #94#36
#97
#118
#35#53#57 #35#51#53#35#53#51#35#53#55#35#51#53#35#52#57#35#52#56#35#53#54#35#51#51 #35#49 #33
#35#53#57 #35#51#53#35#52#57#35#52#51 #35#48 #33
#58#35#49#48#48#45#99#63 #94#36
#35#49#48#56#63
#108!
l
Emmental言語の紹介と記録
書き易いから上記でもって満足してしまっているが、漏らしている面白さがあれば教えてほしい。