EmacsでLispの覚え直し(その8)

EmacsでLispのプログラミング学習しているおかげで、Emacsの操作も覚えてきているようです。
各ツールも、GUIのメニューからではなく、M-xで直接実行できるようになりました。
特にLispでお世話になっている、M-x ielm は、これが何をするツールなのかは、一生忘れない自信があります。でも、Mキーがどこのキーのことをいってるのかってことに関しては、忘れる自信しかありません。

今回は、seqコマンドのようなことを、Lispでもやってみます。
(いつも、新しく言語を覚えるときは、seqコマンドって必ず作るので)

コマンドラインでseqはこのように、1から指定した数値までの整数の数列を生成してくれますね。

takk@deb9:~/tmp$ seq 10
1
2
3
4
5
6
7
8
9
10
takk@deb9:~/tmp$ 

カウントダウン、つまり、10から下がっていく方は、すでにやりましたので、簡単ですね。

ELISP> (defun count (n)
(if (> n 0) (progn (princ n)
                   (count (- n 1))) ))
count
ELISP> 
ELISP> (count 10)
10987654321
nil
ELISP> 

これをリストにするだけなので、consを使ってリストにします。

ELISP> (defun count (n)
(if (> n 0) (cons n (count (- n 1))) ))
count
ELISP> 
ELISP> (count 10)
(10 9 8 7 6 5 4 3 2 1)

ELISP> 

しかし、リストが逆になってしまいます。

リストを逆順にする関数、reverseを使うとseqと同じ並びになります。

ELISP> (reverse (count 10))
(1 2 3 4 5 6 7 8 9 10)

ELISP> 

しかし、reverseを使ってseq関数を作るとなると、関数内にの、別の関数を作らないといけません。 つまり、2つ関数が必要となります。

LISP> (defun seq (n)
(reverse (count-down n)))
seq
ELISP> (defun count-down (n)
(if (> n 0) (cons n (count (- n 1))) ))
count-down
ELISP> 
ELISP> (seq 10)
(1 2 3 4 5 6 7 8 9 10)
ELISP> 

まだ、学び直して日が浅いので、Lispプログラミングにおいて、このように関数内に別関数を作ることが、
良いことなのか分かりません。(悪いことなら、別の方法があるはず)

なので、reverseを使わずに、正順の数列を作るため、
関数のパラメータを2つにして完成したことにしました。

ELISP> (defun seq (now max)
(if (<= now max) (cons now (seq (+ now 1) max)) ))
seq
ELISP> 
ELISP> (seq 1 10)
(1 2 3 4 5 6 7 8 9 10)

ELISP> 

コメント

タイトルとURLをコピーしました