読者です 読者をやめる 読者になる 読者になる

Common Lispで初めて実装

夏休みに入ってからM.Hiroi's Home Page / xyzzy Lisp ProgrammingとPAIPでCommon Lispの勉強をしている。
基本的には例題のコードを写して、実際に動かすといった具合だ。

夏休みも終わるなーと思っていた先日、「もし大学4年間が24時間だったら、現在は何時何分だろうか」と思った。
プログラムを書こうと思ったときに頭に浮かぶものはC言語C言語以外でプログラムについて考えたいと思って、Common Lispを始めたので、
「いかん、いかん、Common Lispで考えろ!」と自分に言い聞かせながら、一通り書いてみた。

(defconstant *hour* 24 "A day is 24 hours")
(defconstant *minute* 60 "A hour is 60 minutes")
(defconstant *second* 60 "A minute is 60 seconds")
(defconstant *day* 365 "A year is 365 days")
(defconstant *school-year* 4 "University is 4 years") 
(defvar *each-month-days* '(30 31 30 31 31 30 31 30 31 31 28 31) "Days of each months(April start)")

(defun StudentDays (year date day)
       "Days of student life"
	   (let ((days (* 365 (1- year)))
		 (date2 (mod (+ date 8) 12)))
	     (if (or (> day (elt *each-month-days* date2)) (< year 1) (> year 4)) (return-from StudentDays -1))
	     (dotimes (i date2 days)
	       (setf days (+ days (elt *each-month-days* i))))
	     (setf days (+ days day))))

(defun PrintTime (second)
       "Print 'hour:minute:second'"
           (if (< second 0)
               (format nil "error")
	       (progn (format nil "~s:~s:~,2F" (truncate (/ second 3600)) (truncate (mod (/ second 60) 60)) (float (mod second 60))))))

(defun StudenTtime (year data day)
       "Total seconds of student life"
       (let ((seconds (/ (* *hour* *minute* *second*) (* *day* *school-year*))))
	     (printtime
	      (* seconds (studentdays year data day)))))
(StudentTime 3 10 3)
"15:6:24.66"
(StudentTime 3 3 3)
"17:32:23.01"
(StudentTime 5 10 3)
"error"
(StudentTime 5 10 32)
"error"

しかし、初めて関数型言語で書いたので、関数型言語のスタイルが分からない。Common Lispも多くのコードに触れていないので、Common Lispのスタイルも分からない。そこで、今後のために現在の疑問を挙げようと思う。

・大域変数は"*変数名*"というスタイルであるが、定数の場合はどうなるのであろう?(今回はとりあえず、大域変数と同じスタイルにした。)
=>アスタリスクは付けないようだ。(2015/10/02)

スペシャル変数の名前は、最初と最後にアスタリスクを付けるのが慣習だが、定数の場合は通常この慣習に従わない。理由は、アスタリスクを付けると、「要注意!このレキシカルスコープの外側で何かによって変更されるかもしれない」と解釈されるからだ。もちろん、定数は変更されない。


Peter Norvig(2010) 「実用Common Lsip」翔泳社 149pp.


・計算結果を出力する際にPrintTimeで出力をしたが(1)、PrintTimeでは出力文字列を返すだけにして、呼び出し元(StudentTime)で表示するべきか(2)?

(1)

(defun foo ()
  (hoge))

(defun hoge ()
  (format nil "hoge"))

(2)

(defun foo ()
  (format nil "~S" (hoge)))

(defun hoge ()
  'print)

・Lispboxでは日本語が対応していないのでコメントも英語で書いてみたが、正しいか分からない。コメントの英語が正しいかチェツクする方法はあるのか?(とりあえずは英語のコメントにたくさん触れ、その中で身に付けていこうかな)


C言語取得の際は多くのコードに触れたことと例題のコードばかり写してないで、自分で一から創り上げたことが良かったと思うから、Common Lispでもそうしたい。また、人工知能にも興味があるから、その辺を絡めていけばよいのではないかと思っている。