2018年6月17日日曜日

あっ、ぷらい

 cl-dbiで返ってきたデータにはめんくらってしまったのだけど
 こんなデータ。

(:|date| 3281472000 :|place| "A7")

 DBのカラム名と値が交互にならんでいる。
 きっと何か、うまくやる方法があるんだとは思っていた。値をひっぱりだすのにgetfを使うというのは了解した。

CL-USER> (setq wrk '(:|date| 3281472000 :|place| "A7"))
(:|date| 3281472000 :|place| "A7")
CL-USER> wrk
(:|date| 3281472000 :|place| "A7")
CL-USER> (getf wrk :|date|)
3281472000

 きっとkeyとしても使えるにちがいない。それがよくわからなかった。applyかな、とは思っていたのだけど、うまく動かない。

CL-USER> (defclass <wrk> ()
    ((date :initarg :date)
     (place :initarg :place)))

#<STANDARD-CLASS COMMON-LISP-USER::<WRK>>
CL-USER> (apply #'make-instance '<wrk> wrk)
; Evaluation aborted on #<SB-PCL::INITARG-ERROR {10048A9723}>.
CL-USER>

 ふと気づく。

CL-USER> (defclass <wrk> ()
    ((date :initarg :|date|)
     (place :initarg :|place|)))

#<STANDARD-CLASS COMMON-LISP-USER::<WRK>>
CL-USER> (apply #'make-instance '<wrk> wrk)
#<<WRK> {1004641BE3}>
CL-USER>

 そっか。
 defclassの定義で「:date」としていたのが、まちがいだったのだ。
 CommonLispのsymbol名は基本、大文字小文字の区別がないのだけれど、「|」付の場合は区別しているという意味だった(それは一応は知っていた)。「|」付で定義すると、区別あり、と定義できるのだった(これには気づいてなかった)。DBのカラム名は普通、大文字小文字の区別があるのでこうなっているのだろう。

 これでcl-dbiからの返却値を一気にクラスに流しこむことができる。
 この「apply」を使うやり方に気づいてから一気にコード量が減った。ちまちまと値を設定しているところがごっそりなくなったので。
 applyって凄い1

 それにしても「:」付のsymbolってどうやってつくるんだろう?
 単純にinternしてもだめなんだよなぁ。

CL-USER> (intern "date")
|date|
:INTERNAL
CL-USER>

Footnotes:

1

いや、listが凄いのかも。