"One of the nice things about getting older is that you come to understand that you can integrate multiple aspects of your life together. When you're young, you think everything has to be binary, as that's exactly how you feel at that age".
- Min Jin Lee

Ping 16/Oct/2020


ADT1만큼 만들어 쓰는 것은 아니지만, 그냥 Kotlin, Python의 dataclass 정도는 쓰고 싶어서 CommonLisp 매크로를 만들어봤다.2

equals 라이브러리를 써서 동치 비교와 CLOS의 print-object generic function을 구현해서 to-string 정도만 되도록 만들어 봤다.

macro body

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(defmacro define-data-class
    (class-name parent-classes slot-names
     &key (no-print-slot-names nil) (no-equals-slot-names nil))
  (flet ((accessor-symbol (slot-name)
           (alexandria:format-symbol *package*
                                     "~a-~a" class-name slot-name)))  
    (list 'progn          
          ;; defclass
          (let ((slot-defs (loop for slot-name in slot-names
                                 collecting `(,slot-name
                                              :initarg ,(alexandria:make-keyword slot-name)
                                              :accessor ,(accessor-symbol slot-name)))))
            `(defclass ,class-name ,parent-classes ,slot-defs))

          ;; defmethod print-object
          (let* ((print-slot-names (set-difference slot-names
                                                   no-print-slot-names))
                 (fmt-ctrl (format nil "~{~a=~~a~^, ~}" print-slot-names)))
            `(defmethod print-object ((obj ,class-name) stream)
               (print-unreadable-object (obj stream :type t)
                 (with-slots ,print-slot-names obj
                   (format stream ,fmt-ctrl ,@print-slot-names)))))

          ;; defmethod equals:equals
          (let* ((equals-slot-names (set-difference slot-names
                                                    no-equals-slot-names))
                 (equals-exprs (loop for equals-slot-name in equals-slot-names
                                     collecting `(equals:equals (slot-value lhs (quote ,equals-slot-name))
                                                                (slot-value rhs (quote ,equals-slot-name))))))
            `(defmethod equals:equals ((lhs ,class-name) (rhs ,class-name) &rest args)
               (declare (ignore args))
               (and t ,@equals-exprs)))
          )))

synopsis / usage

1
2
3
4
5
6
(define-data-class animal () (name age))

(define-data-class bird (animal) ())

(equals:equals (make-instance 'animal :name "foo" :age 18)
               (make-instance 'animal :name "foo" :age 18))

오랬만에 재밌었다.

Ping (2nd) 15/Oct/2020


… '田大'이라고 적혀 있었다.

다른 한문으로 쓰여 있어 읽지 못하는 각각의 수 많은 바램들과 이름들 사이로 삐뚤빼뚤한 어색한 글씨로 그렇게 적혀 있었었다.

너무 단순한 이름, 그리고 설명이 붙어 있었듯이, 다른 사람들처럼 많은 이야기를 적고 싶었지만, 아이여서 그랬는지, 아니면 글을 몰라 그랬는지, 이름만이라도 적어놓은 그 못그린 그림 같은 두 글자를 읽었다.

누군가 아주 오래 전에 그 사람도 아마도 나와 별로 다를 것도 없는 고민들을 하며 매일을 살았었던 것을 느꼈다.

아주 오랜 세월이 흐른 후에야 그렇게 만났었던 모르는 어떤 사람이 떠올랐다.

Ping 15/Oct/2020


예전에 다니던 회사의 소식을 뉴스로 봤다. 사고 자체는 그렇게 좋은 이야기는 아니어서 안타까웠었다.

그리고 나오기 이전에 팀의 문화나 프로세스, 방법론 같은 이야기를 대표와 많이 나누고 많은 글을 써서 전달한 것이, 관련 검색에 보이는 구인란에 잘 적혀있고 문화와 시스템에 반영된 것 같아서 기분이 정말 좋았다. 비록 그것에 대한 기여가 내 몫으로 내 이름을 빛나게 하거나 경제적 이익이 되지는 못했지만, 그래도 그런 내용들을 이해 해주고 반영한 사람에 대해서 다시금 애정과 존경의 마음이 들었다.

Ping 11/Oct/2020


어째서 더 잘 그럴 수 있을까

무엇인가를 만드는 일은 사실 두 가지 단계로 발전하는 것 같다.

단지 목적한 그것만을 만드는 일과, 또는 그것을 반복적으로 생산하고 또 더 나은 방법으로 추상화하여 내는 도구를 만들어내는 일으로 구분할 수 있는 것 같다.

직관적으로 생각했을 때에는, 목적이 명확하다면 당연히 그것 자체를 만드는 일을 이미 존재하는 도구들을 통해서 표현하고 만들면 그만인 것 같다.

그리고 더 나아가서 결과물을 그냥 직접 만드는 것이 아니라, 그 결과물을 만들기 위한 도구까지 같이 만들거나, 그 결과물이 그를 만들기 위해 고안된 도구를 통해서 만드는 경우가 비교할 수 없이 생산적이고 그 결과물 또한 훨씬 매끄럽고 완성도가 높은 경우가 오히려 보통인 것 같다.

Ping 10/Oct/2020


오래 써오던 맥북에어의 WIFI이 성능이 계속 안 좋아졌었던 것 같다.

모델명을 알아보니, 2012년 형이었다. 정말 오래 썼구나. 1

어차피 MacOS을 여러 가지 이유로 좋아하지 않아서 그냥 아치리눅스2를 설치하고 그대로 쓰고 있다.

최근에는 아예 WIFI을 USB-LAN으로 연결해주는 RPi을 만들어 쓰고 있었다. 물론 내장WIFI은 너무 느려서 nmcli r wifi off 을 기본으로 아예 S/W Disable시켜놓고 살았다.

어쩌다 계기가 있어서, USB-LAN연결용 RPi을 챙기지 못한 외부에서 어쩔 수 없이 쓰려고 시도해보니, 아예 조금 내장WIFI을 쓰면 조금 동작하다가 시스템이 뻗어버린다. …아예 맛이 갔나보다.