Clojureの練習

Clojure - Sequences
ここにある関数をもういっぺん、ざっくり見直しておこう

L-99

L-99: Ninety-Nine Lisp Problems
Common Lispを勉強してたときにやっていた。Scalaを勉強したときもS-99というのをやっていた。どちらも全部やったわけじゃないけど。Clojureのリスト処理になれるために、何問か解いてみよう。

P01

A01.clj

(defn my-last [lst] 
    (if (empty? lst) 
        nil
        (if (empty? (rest lst)) 
            lst
            (my-last (rest lst)))))


user=> (load-file "C:\\Users\\Eiichi\\Desktop\\A01.clj")
#'user/my-last
user=> (my-last '(a b c d))
(d)
user=> (my-last '(a))
(a)
user=> (my-last '())
nil

うーん、期待通りに動いているかな。

この1問を解いただけで、気づかなかったことに気づいた。

  • firstとrestはおなじみのやつだ!
  • nil?とempty?は挙動が違う。
  • ファイルの読み込みは、load-file関数。なぜかフルパスじゃないとだめっぽい。コンソール起動時に作業ディレクトリに移動してるんだが効いてないのか?
  • しょせん、(....)だらけになるな!おなじみだ!


user=> (nil? '(a))
false
user=> (nil? '())
false
user=> (nil? nil)
true
user=> (empty? '(a))
false
user=> (empty? '())
true
user=> (empty? nil)
true
user=>

中でも、


user=> (nil? '())
false

この挙動が「おや?」だった。

Common Lisp(実行環境は、Windows版のclispを使った。CLISP - an ANSI Common Lisp download | SourceForge.net)の挙動は


[5]> (null '(a))
NIL
[6]> (null '())
T
[7]> (null nil)
T
だった。

P02


(defn my-but-last [lst]
(if (empty? lst)
nil
(if (empty? (rest lst))
lst
(if (empty? (rest (rest lst)))
lst
(my-but-last (rest lst))))))

もう少し、なんとかならんものか。


(defn my-but-last [lst]
(if (empty? lst)
nil
(if (<= (count lst) 2)
lst
(my-but-last (rest lst)))))

おっと、ここでまた、「おや?」が

  • lengthはなくて、countを使う

Clojure lengthで検索してもどうりでパッとヒットしなかった。

関数を活用しちゃえば、


(defn my-but-last [lst]
(reverse (take 2 (reverse lst))))
lengthはなかったのに、reverseやtakeは、当然のように使えるなー。
関数型言語は、リスト処理の基本の関数に関しては、どの言語も似たりよったりで助かるなー。

Practical Common Lisp

Practical Common Lisp
無料の英語版があるけど

実践Common Lisp

実践Common Lisp

日本語版も買っちゃってる。英和辞書いらないし!

3章と9章が好きなので、Clojureの練習でそのうちやってみたい。

Blog | PCL -> Clojure | Relevance
このひと、Practical Common LispにでてくるソースコードClojureでやっているらしい。なるほど。