Common Lispでは、時間は4つの方法で表現されます。ここではそのうちの2つを取り上げます。
1900-01-01T00:00:00Zからの経過秒数を表す整数です(これはUTCにおける1900年1月1日の真夜中です)。現在のユニバーサル時間を取得するには、get-universal-timeまたはget-decoded-timeを使います。
前者は1900-01-01T00:00Zからの現在の経過秒数を返し、後者は同じデータをデコードされた形式で返します。
時間を扱う主要な関数は、decode-universal-timeとencode-universal-timeです。
前者はユニバーサル時間を受け取り、複数の値としてデコードされた時間の値を返します。後者はデコードされた時間の値を引数として受け取り、ユニバーサル時間を返します。
どちらも省略可能なタイムゾーンの引数を取ります。 タイムゾーンの形式については、後述します。
デコードされた時間は、次の値の組です。
1/3600の倍数でなければなりません。(encode-universal-time 1 2 3 4 5 2000 0) ; => 3166398121
(decode-universal-time 3166398121) ; => 1
; 2
; 3
; 4
; 5
; 2000
; 3 (Thursday)
; NIL
; 0
(decode-universal-time 2208988800) ; => 0
; 0
; 0
; 1
; 1
; 1970
; 3
; NIL
; 0
Common Lispでは、関数は1つの値だけでなく、複数の値を返すことができます。
たとえば、ゼロに向かって切り捨てるfloorは2つの値を返します。1つ目は切り捨てられた値、2つ目は余りです。
(floor 3.5) ; => 3
; 0.5
(複数の値が返されるときは、出力の行を分けて示します。)
関数に複数の値を返させたいときは、valuesアクセサーを使います。
(defun three-numbers () (values 1 2 3))
(three-numbers) ; => 1
; 2
; 3
1つ目の値だけが必要なら、特別なことをする必要はありません。言語がうまく処理してくれます。
(+ (values 1 2 3) (values 10 20 30)) ; => 11
ただし、それ以外の値にアクセスしたい場合は、いくつかの関数を使う必要があります。
主なマクロはmultiple-value-listとmultiple-value-bindの2つです。
これらは、複数の値を返すものを包み込んで、すべての値を取り出します。
前者はすべての値からなるリストを作ります。
後者は個々の値に変数を束縛できます。
(multiple-value-list (values 1 2 3)) ; => (1 2 3)
(multiple-value-bind (a b c) (values 1 2 3)
(+ a b c)) ; => 6
もう1つ便利な関数がnth-valueです。
Lisp星人は記念日を祝うのが好きです。 彼らにとって大切な記念日が、ギガ秒です。 つまり、出来事から1,000,000,000秒後です。
year、month、day、hour、min、secという6つの入力を受け取り、ギガ秒の記念日の日時を計算する関数fromを書いてください。
この関数は、入力と同じ順序と意味を持つ配列として日付を返すようにしてください。
(from 2000 1 1 0 0 0) ; => (2031 9 9 1 46 40)
Exercismに登録すれば、27個のコンセプト92個の演習、そして本物の人間によるメンタリングとともに、Common Lispを学んでマスターできます。すべて無料です。