🪃

Uiua の基本的なスタック操作関数

2023/10/01に公開

https://zenn.dev/hatappo/articles/9a7f4e601df235

の続きでもあります。

Uiua はスタックベースのプログラミング言語[1]であり、スタックの基本的な操作の関数はそろっています。順に見ていきます。

· noop

何もせず与えられた値をそのまま返す関数。

· [10 20 30 40 50]
# ↓
[10 20 30 40 50]

∵ each (forEach みたいなの) のコールバック関数として渡せば対象の配列をそのまま返す。↑が配列自体をそのまま返しているのに対して↓は配列の各要素に noop して結果元の配列と同じ配列が返っている。

∵· [10 20 30 40 50]
# ↓
[10 20 30 40 50]

; pop

先頭要素を取り出す。 griph は一番上からピョンって飛び出してきたイメージだろうか。

[; 10 20 30 40 50]
# ↓
[20 30 40 50]
[;; 10 20 30 40 50]
# ↓
[30 40 50]

. duplicate

スタックの先頭要素をコピーしてスタックの先頭に積む

. [10 20 30 40 50] # Uiua は値を右から評価するので注意
# ↓
[10 20 30 40 50]
[10 20 30 40 50]

スタックの中間状態を残す目的で . を挿入する使い方は、説明的な記述のときにはよく見る。あと配列を操作するときにコピーした配列に対応する情報を作って、元の配列にあてるという操作でも目にする。

∶ flip

先頭2要素の位置を交換する

[10 20 30 40 50]
# ↓
[20 10 30 40 50]
[10 20 30 40 50]
# ↓
[20 10 30 40 50]

, over

先頭から2番目の値をコピーして先頭に追加する

[, 10 20 30 40 50]
# ↓
[20 10 20 30 40 50]

→ dip

先頭の値を一時的によけといて、その状態でスタックの残りに対して関数を適用し、よけといた元の先頭要素をまた先頭に戻す。

先頭の 10 をちょっと横に置いといて、その次の 20 と 30 に対して + (加算)を実行してその結果の50をスタックに積み、さらにどかしておいた 10 をスタックの先頭に戻している。

[→+ 10 20 30 40 50]
# ↓
[10 50 40 50]

面白いのは連続して重ねることでスタック内の任意の位置に対して関数適用できるようになること。

[+ 10 20 30 40 50]
[→+ 10 20 30 40 50]
[→→+ 10 20 30 40 50]
[→→→+ 10 20 30 40 50]
[→→→→+ 10 20 30 40 50] # Error: Stack was empty when evaluating argument 2

# ↓

[30 30 40 50]
[10 50 40 50]
[10 20 70 50]
[10 20 30 90]
Error: Stack was empty when evaluating argument 2

注意点
→ dip はこの記事を書いている数時間前(2023年10月1日 17:13) に commit されていました。自分の環境で dip が使えないな、と思ったら uiua を再ビルドしてください。

また dip の登場によって ↷ roll↶ unroll 関数が deprecated (非推奨)となりました。↷ roll↶ unroll の機能を十分に一般化しているから、なんですかね。

[+↷ 1 2 3]
[∶→+ 1 2 3]
[+↶ 1 2 3]
[∶→+∶ 1 2 3]

# ↓

[5 1]
[5 1]
[4 2]
[4 2]

~ trace

スタックの先頭要素を表示する。ただし pop のように消費はせず値は残る。その意味で一般的なスタック操作の peek に少し近い挙動。基本的にデバッグ用途。

main.ua
~ [10 20 30 40 50]
# ↓
main.ua:1:1 [10 20 30 40 50]
[10 20 30 40 50]

続きは

https://zenn.dev/hatappo/articles/a6dad4af411ecf

脚注
  1. ただしスタック指向ではなく、あくまでスタックを変数を保持するための便利なツールとして採用している。 ↩︎

Discussion