1分でわかる記号だけのErlangプログラミング

takesako
2010-12-19

4回連続でそろそろネタ切れなid:TAKESAKOです。

みなさんが普段の業務でよく使っていると思われるErlangシェルで記号プログラミングをしてみましょう。

Erlangとは

Erlang(アーラン)は分散環境での並列処理をサポートした実用的な関数型言語です。

  • 1986年に誕生、1998年にオープンソースとして公開
  • 変数名の先頭は英大文字かアンダースコアで始まる
  • 変数への代入は1回しか行えない(再代入不可)
  • 式の終わりは.(ピリオド)で表す
  • 「変数=値.」で変数宣言と代入が行われる

などといった特徴があります。

.(ピリオド)が必ず文末に出てくるなど、COBOL時代を彷彿させる言語仕様の古臭さは否めません。

数学者のアグナー・アーラン (Agner Erlang) から名前をとった説、エリクソン社内で開発された言語(ERicsson LANGuage)なのでErlangと呼ぶ説があります。

Erlangのインストール

Ubuntuではapt-getで簡単にインストールできます。

$ sudo apt-get install erlang

Windows環境ではhttp://www.erlang.org/download.htmlのバイナリをダウンロードできます。

erlコマンド

Erlangシェルを起動するにはerlコマンドを実行します。
(Pが抜けたPerlコマンド=erlコマンドと覚えておけばよいでしょう)

$ erl
Erlang (BEAM) emulator version 5.6.5 

Eshell V5.6.5  (abort with ^G)
1>
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
a

Erlangシェルを終了するには、Ctrl+Cを入力し、a(abort)を押して改行を入力します。

Erlangシェルでこんにちは!

Erlangシェルを起動して、[1].を入力すると[1]が返りますが、[11]を入力すると文字列"\v"が返ります。

$ erl
Erlang (BEAM) emulator version 5.6.5

Eshell V5.6.5  (abort with ^G)
1> [1].
[1]
2> [11].
"\v"

怪しいですね。これは一体どういう仕様なのでしょうか?

なぜだかわかりませんが、リストの要素に表示可能文字に該当するASCIIコードの数値が指定されている場合、Erlangシェル上では文字列として表示されるようです。

3> [111].
"o"
4> [111,112,113].
"opq"

カンマ区切りでリスト指定すると複数文字も連結して表示できます。

記号だけで任意の数値を作る方法

実はErlangで「$a」と書くと'a'のASCIIコード97の数値が返ります。$の右側には印字可能な文字であれば何でも書けて、「$b」は98、「$c」は99の数値を意味します。
ということは、$の右側に記号も書くことができて「$!」と書くと'!'のASCIIコード33が返るのです。これらのASCIIコードは普通に数値として解釈されるため「$!+$!」のように足し算を行うことができ66の数値が生成できます。
これを応用して足し算や引き算を組み合わせると、すべての数値を記号だけで表現することができます。

NUL: ($!-$!) == 0
SOH: ($"-$!) == 1
STX: ($#-$!) == 2
ETX: ($$-$!) == 3
EOT: ($%-$!) == 4
ENQ: ($&-$!) == 5
ACK: ($'-$!) == 6
\a : ($(-$!) == 7
\b : ($)-$!) == 8
\t : ($*-$!) == 9
\n : ($+-$!) == 10
\v : ($,-$!) == 11
\f : ($--$!) == 12
\r : ($.-$!) == 13
SO: ($/-$!) == 14
SI : ($:-$+) == 15
DLE: ($:-$*) == 16
DC1: ($:-$)) == 17
DC2: ($:-$() == 18
DC3: ($:-$') == 19
DC4: ($:-$&) == 20
NAK: ($:-$%) == 21
SYN: ($:-$$) == 22
ETB: ($:-$#) == 23
CAN: ($:-$") == 24
EM : ($:-$!) == 25
SUB: ($;-$!) == 26
ESC: ($<-$!) == 27
FS : ($=-$!) == 28
GS : ($>-$!) == 29
RS : ($?-$!) == 30
US : ($@-$!) == 31
   : ($[-$;) == 32
 ! : ($!) == 33
 " : ($") == 34
 # : ($#) == 35
 $ : ($$) == 36
 % : ($%) == 37
 & : ($&) == 38
 ' : ($') == 39
 ( : ($() == 40
 ) : ($)) == 41
 * : ($*) == 42
 + : ($+) == 43
 , : ($,) == 44
 - : ($-) == 45
 . : ($.) == 46
 / : ($/) == 47
 0 : ($[-$+) == 48
 1 : ($[-$*) == 49
 2 : ($[-$)) == 50
 3 : ($[-$() == 51
 4 : ($[-$') == 52
 5 : ($[-$&) == 53
 6 : ($[-$%) == 54
 7 : ($[-$$) == 55
 8 : ($[-$#) == 56
 9 : ($[-$") == 57
 : : ($:) == 58
 ; : ($;) == 59
 < : ($<) == 60
 = : ($=) == 61
 > : ($>) == 62
 ? : ($?) == 63
 @ : ($@) == 64
 A : (${-$:) == 65
 B : ($!+$!) == 66
 C : ($!+$") == 67
 D : ($!+$#) == 68
 E : ($!+$$) == 69
 F : ($!+$%) == 70
 G : ($!+$&) == 71
 H : ($!+$') == 72
 I : ($!+$() == 73
 J : ($!+$)) == 74
 K : ($!+$*) == 75
 L : ($!+$+) == 76
 M : ($!+$,) == 77
 N : ($!+$-) == 78
 O : ($!+$.) == 79
 P : ($!+$/) == 80
 Q : ($"+$/) == 81
 R : ($#+$/) == 82
 S : ($$+$/) == 83
 T : ($%+$/) == 84
 U : ($&+$/) == 85
 V : ($'+$/) == 86
 W : ($(+$/) == 87
 X : ($)+$/) == 88
 Y : ($*+$/) == 89
 Z : ($++$/) == 90
 [ : ($[) == 91
 \ : ($\) == 92
 ] : ($]) == 93
 ^ : ($^) == 94
 _ : ($_) == 95
 ` : ($`) == 96
 a : ($!+$@) == 97
 b : ($"+$@) == 98
 c : ($#+$@) == 99
 d : ($$+$@) == 100
 e : ($%+$@) == 101
 f : ($&+$@) == 102
 g : ($'+$@) == 103
 h : ($(+$@) == 104
 i : ($)+$@) == 105
 j : ($*+$@) == 106
 k : ($++$@) == 107
 l : ($,+$@) == 108
 m : ($-+$@) == 109
 n : ($.+$@) == 110
 o : ($/+$@) == 111
 p : ($!+$!+$.) == 112
 q : ($!+$!+$/) == 113
 r : ($!+$"+$/) == 114
 s : ($!+$#+$/) == 115
 t : ($:+$:) == 116
 u : ($:+$;) == 117
 v : ($:+$<) == 118
 w : ($:+$=) == 119
 x : ($:+$>) == 120
 y : ($:+$?) == 121
 z : ($:+$@) == 122
 { : (${) == 123
 | : ($|) == 124
 } : ($}) == 125
 ~ : ($~) == 126
DEL: ($!+$^) == 127

Ruby1.8で記号プログラミングするときとやり方は一緒ですね。

記号だけで「Hello, world!\n」

あとは「Hello, world!\n」の文字列をASCIIコードの数値リストに変換してあげます。

5> [72,101,108,108,111,44,32,119,111,114,108,100,33,10].
"Hello, world!\n"

これを記号だけで書き直すと以下になります。

6> [$!+$',$%+$@,$,+$@,$,+$@,$/+$@,$,,$[-$;,$:+$=,$/+$@,$!+$"+$/,$,+$@,$$+$@,$!,$+-$!].
"Hello, world!\n"

ね、簡単でしょ?