Lispと一緒(2) uLisp、Lispのリハビリその1、ループを回す

Joseph Halfmoon

組み込みマイコン向けのuLispを浮かれて始めたのは良いものの、元よりLisp素人、過去の記憶も忘却の彼方ということで、リハビリを行って少しずつ動けるようにいたしてまいりたいと存じます。折角グラフィックスが使えるWio Terminal機なので、動作が見た目に分かりやすいようにLispで描画してみると。

uLispの描画機能

描画可能なスクリーンを持つマイコン機種は限られるので、uLispの描画機能はextensionという扱いですが結構充実しています。ドキュメントは以下に。

Graphics extensions

Graphicsサポートの対象機種の中でも Wio Terminalは最大の画面サイズです。

320 x 240

最大とはいえパソコンの画面とは比べ物にならないサイズですが、描く内容は即座に観察できるのでプログラムの動作が目に見えやすいデス。

そこで、描画機能を動かしながら、Lispっぽいコードの書き方のリハビリをばいたして参りたいと思います。今回使用するのは、矩形の描画機能です。

(draw-rect x y w h [colour])

左上座標 x ,y に置かれた幅w、高さhの矩形をオプショナルなcolour色で描くもの。colourを指定しないと白になるようです。

3通りの方法でループしてみた

今回のリハビリ題材は以下のようなものです。

    1. 外部よりxposとsizを与える(整数)
    2. sizが1より大きい間以下を繰り返す
    3. 座標 xpos, xpos におかれた幅siz、高さsizの矩形を白で描く
    4. 繰り返しの中でxposは+3づつ増やす
    5. 繰り返しの中でsizは-2づつ減らす

作製した関数は以下です。3通りの方法で同じことをやってます。

(defun rectdemo (xpos siz)
    (if (> siz 1)
        (progn
            (draw-rect xpos xpos siz siz)
            (rectdemo (+ xpos 3) (- siz 2))))) 

(defun rectdemo2 (xpos siz)
    (loop
        (draw-rect xpos xpos siz siz)
        (setq xpos (+ xpos 3))
        (setq siz (- siz 2))
        (if (< siz 2) (return))))

(defun rectdemo3 (xpos siz)
    (dotimes (i (/ siz 2))
        (let ((x (+ xpos (* i 3)))
              (s (- siz (* i 2))))
            (draw-rect x x s s))))

第1の方法は、一番Lispっぽいじゃないかと思う、末尾再帰によるループです。明朗会計?で分かりやすいじゃないかと思います。

第2の方法は、真正面からloop関数よんでループしてみたもの。ループからの脱出にreturn使てます。ローカル変数を保持するのに setqしてるので何だかな~なコードっす。

第3の方法は、決まった回数ループするdotimes関数を呼んでいるもの。画面の大きさは有限なので、何回ループするのか事前にわかるやろ、というスタイル。ローカルな変数はlet関数でバインドしているので、アカラサマなsetqはないですが。。。

実験結果

上記のコードをVScodeの「ターミナル」からuLispに流し込んだ後、以下のように入力すれば 第1の方法を動かしてみれます。

(fill-screen)
(rectdemo 0 100)

fill-screenは引数(色)をとると、その色で画面を埋める関数です。何も引数を与えないと黒で埋めるので、画面クリアのために使ってます。

同様に第2の方法は以下です。

(fill-screen)
(rectdemo2 0 100)

第3の方法は以下で動作します。

(fill-screen)
(rectdemo3 0 100)

どれも結果は同じなので、第1の方法のみ実機写真を掲げます。

rectdemoDUT

こんなもんで、リハビリになるのか?

Lispと一緒(1) uLisp、Seeeduino Wio Terminal+VScodeで快適? へ戻る

Lispと一緒(3) uLisp、Wio Terminalのボタンをセンスする へ進む