Naomi's notebook

Naomi's notebook

Railメモ

Esolangのメモ第二弾
esolangs.org

レール一覧

$ 'main'を実行する(必須)
'|-/\'で道を作った順にプログラムが動く
道が途切れたらクラッシュ
ただし繋げられる組み合わせは限られている。

'|' connects to itself and '\' and '/'
'-' connects to itself and '\' and '/'
'/' connects to itself and '|' and '-'
'\' connects to itself and '|' and '-'

よって、例えば

\
/

で垂直に移動することはできない
また、ある文字からそれ自身とその他の可能な線路が両方繋がっている場合、それ自身が優先される
その他の可能な路線が二種類繋がっているとエラー。

'$' 関数の始まりを表す。方向的には\と同じ
'#', 終了を表す。
'@' は進行方向の反転を表す。例えば下のようにすると@を経由してから#で終了する。

$
 \
#--@

'*','+', 'x',はそれぞれ入った時の進行方向を継続して移動する。

条件分岐

'>

  • 1なら右に
  • 0なら左に
  • スタックが空、またはどちらでもないならクラッシュする
\
 >-
/

どの方向にも足はないといけない(ないとエラー?)

標準入出力

'[' と ']'(順不同)に囲まれた全ての定数をスタックに積む。 'o'は直前に積まれたものを出力

$ 'main'
 \
  |
#--[star][s]o-@

output:sstar

変数

Variables
built-inコマンドは全てスタック上の値に対して操作しているので、変数は全て不変である。
'(!' と '!)' (同じく')!'と'!('でも可能)に囲まれた名前に、スタックの一番上の値が取り出され代入される。

名前が値に紐づけられたあとは、'('と')'に囲んでその名前を呼び出すと、その変数の値がスタックにコピーされpushされる。

$ 'main'
 \
  \-[2](!s!)(s)(s)oo#

output:22

変数名は'{', '}', '!', '(', ')', or a single quote 'でなければなんでもいい。スコープは関数。名前空間は関数と同じ。

関数

関数同士をつなぐことはできない、移動方法は呼び出しのみ。
コミュニケーションはスタックで行う(引数を指定できないっぽい?よくわからなかった)

$ 'main'
 \
  \-[bottom]-[middle]-[top]-{print-second}-#

$ 'print-second' (a b -- b), a gets printed.
 \
  \-(!b!)o(b)-#

lambda
&は反射板と同じ働きをするが、stackにlambdaをpushする。
stackにlambdaがあるときは{}を、が呼び出された時はその場所に飛び、そのあと反射しなかった時の方向に進行する。

$ 'main' (--):
 \
  \-[hello ](!h!)-[world\n\](!w!)-\
                                  |
   /------------------------------/
   |
   \
  /--&-(w)o-#
  |
  \-(!l!)-(h)o-(l){}#

システム

'b' スタックに積まれている文字列を出力して終了
'e' 標準入力をチェックしてあればtなければfを積む
'i' 標準入力をチェックして文字列を積むが、ないとクラッシュ
'o' 標準出力にスタックのtopを出力
'u' スタック内の要素数を読み取ってから、それをスタックに積む(つまり+1)
'?' スタックのトップの要素のタイプを'string' or 'nil' or 'list' or 'lambda'でスタックに積む

スタックのトップを使うものはそれを使ったあとは消えてしまう。

数学

演算に使った数字はスタックから取り除かれ、演算の結果はスタックにpushされる。
スタックの数は入れた順にa,bとすると、
'a' スタックのtop2個を加算(a+b)
'd' (a/b)
'm' (a*b)
'r' (a%b)
's' (a-b)
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9' それぞれをスタックに加算

基本的に二文字をpushできない感じかな(10をpushしたかったら[10]52mする)

文字

以下、(スタックの元々の要素入れた順 -- スタックに入る要素入れる順)と表す

'c' 切り取り(a b -- c d)  文字列aをc=[0,b)とd=[b, size(a)) に切り取る b=0なら空文字列
'p' 連結 (a b -- c) cはaとbをこの順に連結したもの
'z' サイズ (a -- b) bはsize(a)

systemと同様に文字列の長さを調べようとしたらその文字列自体がなくなってしまうので、コピー、というより変数を設定しないといけないですね…

リスト

'n' 空のリストnilをpush
':' Cons (a b -- c) aとbをこの順に連結したものを返す (注)原文のcdrは大まかにいうと一番左端、 carは残りをさす(誤謬あるかも)
'~' topの空でないリストaのcdr(a)とcar(a)をこの順にpushする

条件

'f' 0をpushする(false=fは0として表現される)
't' 1をpushする(true=tは1として表現される)
'g' >(a b -- c) a>bをpush
'q' ==(a b -- c) 文字や数字なら一致しているか、リストなら全てが一致していればtを返す。両者のtypeが違えばf

tips

使われていない文字

h,j,k,l,w,y
と思ったけど別に命名はすでに使われている文字を使ってもいい

その他

(kurgmさんのコードゴルフ大会のコードをとても参考にしました)
ループをRailで書くのめんどいので定義しちゃったほうがいい(再帰も使う)
変数名が 0 文字でも良いので、一つだけなら(!!) で定義して() で呼び出せる
引き算の結果が負になると-が含まれ、そのあと演算するときに型がintとして認められないことがわかった(ええ…)

  -@
<
  - @ 

とすると空白をうまく使ってコーディングできる
改行を読み込んじゃうけどpopがないので辛い?(思い違いでなければ)