A Gentle Introduction To Symbolic Computation: http://www.cs.cmu.edu/~dst/LispBook/

읽으면서 정리해보자

== 서문 ==
 * 리스프는 인공지능 연구의 주요 언어로 유명하다
 * 염두에 둔 독자: 프로그래밍 입문하는 학생 / 심리학자, 언어학자, 컴퓨터 과학자 등 인공지능에 관심 있는 사람들 / 취미로 컴퓨터 하는 사람
 * 책의 구성
  * 1, 2장: 상자, 화살표 표기로 기초적인 함수, 함수 합성 설명
  * 3장: EVAL 표기
  * 8장까지는 부수효과 없는 프로그래밍
  * 9장: 입출력
  * 10장: ordinary variables, generalized variables, destructive sequence operations.
  * 11장: 반복(DO, DO*)
  * 12장: 구조
  * 13장: 배열, 해시테이블, property list
  * 14장: 매크로, 컴파일, lexical scoping과 dynamic scoping의 차이
 * 간략화
  * Common Lisp는 복잡한 언어라 적당히 간략화한 것들이 있다
  * 1+와 1-는 이름이 혼란스러워 뺐다
  * EQUAL을 주로 사용. EQ, EQL, EQUALP, =는 고급 주제에서 논의
  * 잘 알려지지 않은 PUSHNEW 같은 원시형을 사용하느니 함수를 좀 더 풀어쓴 것이 몇 군데 있다
  * 가장 고급 주제인 multiple value나 package system은 다루지 않는다

PDF 파일에 목차가 없어 ㅡㅡ

== 1장. 함수와 데이터 ==
=== 1장 요약 ===
 * 산술 함수: +, -, *, /, ABS, SQRT
 * 숫자형: 정수(integer), 부동소수점수(floating number), 비율수(ratio)
  * 정수로 산술 연산을 하면 결과는 정수 또는 비율수다.
  * 3/6 = '''1/2''' <- 이게 ratio
  * 3/6.0 = 0.5
 * 심볼: 숫자 이외의 또다른 자료형
  * 특수 심볼: T는 참 또는 긍정, NIL은 거짓 또는 부정
  * T 또는 NIL을 반환하는 함수는 술어식(predicate)
 * 기본적인 내장 함수들
  * NUMBERP: 데이터가 숫자형인가?
  * SYMBOLP: 데이터가 심볼인가?
  * 숫자형 전용 술어식들: ZEROP(영), ODDP(홀수), EVENP(짝수)
  * 크기 비교: <. >
  * 항등 비교: EQUAL
  * 내장 함수들은 원시 함수(primitive function) 또는 그냥 primitive라고 부른다
  * 입력에서 1을 더하거나 빼는 1+, 1- 함수가 있지만 이 책에선 쓰지 않겠다. 헷갈림
  * 부정: NOT(NIL은 T로, '''NIL이 아닌 모든 것은 NIL으로''')
   * 그럼 NOT(NOT(5))는 5가 아니라 T인가?
 * 함수의 인자 개수
  * ODDP의 인자는 딱 1개, EQUAL은 2개
  * +, -, *, /의 인자 개수는 여러 개
   * +의 인자가 2, 3, 4면 2랑 3부터 더하고 여기에 4를 더한다
   * -, /의 인자가 하나인 경우
    * -의 인자가 n이면 결과는 0에서 n 뺀 거
    * /의 인자가 n이면 결과는 1에서 n 나눈 거
   * 타 언어는 산술 연산이 이항 연산이고 2+3+4는 단순히 (2+3)+4로 처리되는데
   * 리스프는 + 자체가 n항 연산이 될 수 있다는 건가???
 * 오류: 3이랑 FRED를 더할 수 없고, EQUAL의 인자를 한 개만 넘기면 안 되고, 0으로 나누면 안 되고.
=== 1장 고급 주제 ===
 * 리스프의 역사
  * 1956년 Dartmouth 대학에서 여름에 열린 인공지능 관련 연구 모임에서 존 매카시가 "list processing"이란 기법을 배웠다
   * 1950년대에는 어셈블리어로 프로그래밍을 했지
   * "list processing"을 발표한 사람들은 심볼과 리스트를 다루는 보다 추상적인 IPL이란 언어를 만들었다
   * 그 문법이 어셈블리어에 가까워서 괴상했다
  * 한편 수치적 계산에 특화된 FORTRAN이 개발되고 있었다
   * 어셈블리어는 Y = (X + 5) * 10 하려면 LOAD Y, X -> ADD Y, 5 -> MULT Y, 10 라고 써야 하는데
   * FORTRAN은 그냥 Y = (X + 5) * 10 이라고 쓰면 된다. 표현식(expression)의 작성이 가능하다는 뜻
   * 그 당시에는 이 개념이 혁명이였다더라
   * 존 매카시: 나도... 나도 이런 거 만들 거야!
    * FORTRAN에 리스트 조작을 위한 특별한 하위루틴들을 추가하면 어떨까?
    * IBM의 Herbert Gelerntner와 Carl Gerberich가 이 아이디어를 따와 FLPL을 만듦
    * 매카시는 IPL, FORTRAN, FLPL을 토대로 LISP를 설계
  * Lisp 1.5는 처음으로 널리 퍼진 리스프 방언
  * 1960년대 중반부터 온갖 리스프 방언이 생기기 시작
   * MacLisp, Interlisp, Stanford Lisp 1.6, UCI Lisp...
   * 모두 Lisp 1.5을 확장한 것. 하지만 서로 호환이 하나도 안 된다
  * 1970년대: ALGOL계 언어의 특징들과 리스프의 문법을 결합한 Scheme이 나왔어요
   * 그리고 또다시 Scheme의 방언들이 우후죽순 생겨나기 시작했다
  * 1980년대: 널리 쓰이는 리스프 방언만 해도 수두룩한데... 뭘 써야 하지?
   * 만국공용어를 만들자!!!
   * 1984년 Common Lisp 초안 발표
   * 학술계에서도 산업계에서도 빠르게 주류로 성장
   * 지금은 Common Lisp 때문에 Scheme 빼고 거진 다 죽었지렁
 * 많은 프로그래밍 아이디어가 리스프에서 출발할 것
  * 인터프리터 함수와 컴파일 함수의 결합
  * 함수 재귀 호출
  * 소스 수준 추적 & 디버깅
  * 문법 지향 편집기
  * 오늘날의 리스프는 함수형, 객체지향, 병렬 프로그래밍 연구의 선두 주자

== 2장. 리스트 ==
=== 2장 요약 ===
 * Lisp는 List Processor라는 뜻
 * 리스트는 가장 다재다능한(versatile) 타입이다
  * 집합, 테이블, 그래프, 영어 문장 등 뭐든지 표현 가능
  * 함수도 리스트로 표현 가능
 * 모든 리스트는 두 가지 형태를 가진다
  * printed representation
   * 사람이 키보드로 쓰기 편한 형식
  * internal representation
   * 실제로 메모리에 거주하는 형식
  * 리스트의 예: {{{(RED GREEN BLUE)}}}, {{{(AARDVARK)}}}, {{{(2 3 5 7 11 13 17)}}}
  * 메모리에서의 실제 형태: 셀(cell)마다 원소를 가리키는 포인터, 다음 셀을 가리키는 포인터를 가진다
  * 마지막 셀은 NIL을 가리킨다
  * attachment:Figure_2.1.png
  * 포인터는 대개 4바이트이므로 셀은 8바이트
  * 중첩 리스트
   * {{{((BLUE SKY) (GREEN GRASS) (BROWN EARTH))}}}
   * attachment:Figure_2.2.png
  * 리스트의 길이: 원시 함수 LENGTH를 이용
  * 빈 리스트는 NIL로 표현
  * 사실 NIL은 ()다. NIL과 빈 리스트는 동치
  * NIL은 심볼이자 리스트인 유일한 존재
  * 리스트의 원소 얻기
   * FIRST, SECOND, THIRD 함수: 첫 번째, 두 번째, 세 번째 원소
   * REST 함수: 첫 번째를 제외한 나머지 리스트
   * FIRST는 CAR와 같고 REST는 CDR과 같다.
    * CAR, CDR이라는 이름은 리스프가 처음에 트랜지스터도 없어서 진공관 쓰는 컴퓨터에서 작동할 때 쓴 말
    * CAR: Contents of Address portion of Register
    * CDR: Contents of Decrement portion of Register (''카우더cou-der''라고 발음)
    * 요즘 컴퓨터에는 맞지 않지만 아직도 쓴단다
    * CADR: CDR 다음에 CAR (kae-der라고 발음)
    * CDAR: CAR 다음에 CDR (cou-dar)
    * CADDR: CDR 다음에 CDR 다음에 CAR (ka-dhi-der)
    * 이게 뭐야 ㅡㅡ
    * attachment:Figure_2.3.png
    * CAR와 CDR에 NIL을 입력하면 NIL이 출력된다
     * 에러가 아니구요???
     * 이게 더 좋대
  * 리스트 생성
   * CONS는 한 데이터와 리스트를 받아서 그 데이터를 첫 번째 원소로 끼워넣은 리스트를 반환한다
   * x = CONS of (CAR of x) and (CDR of x)
   * LIST는 임의 개수의 원소를 받아 그것들의 리스트를 생성한다
  * 리스트 술어식
   * LISTP: 입력이 리스트인가?
   * CONSP: 입력이 cons cell인가?
    * LISTP와 비슷하지만, NIL은 리스트인 반면 cons cell이 아니다
   * ATOM: 입력이 cons cell이 아닌가? (CONSP의 부정)
   * NULL: 입력이 NIL이면 T 반환. NOT과 동치.
    * 논리 연산에는 NOT을, 리스트 연산에는 NULL을 사용하는 관례가 있다
=== 2장 고급 주제 ===
 * 리스트를 이용한 1진법 산술
  * 0 =  NIL, (X) =  1, (X X) = 2, (X X X) = 3...
  * REST는 1 빼기. 단 0 빼기 1은 0
  * LENGTH는 실제 숫자로 변환
  * 이걸 어따 써먹죠
 * 진리스트(proper list)는 NIL로 끝나는 리스트
  * NIL로 안 끝나는 리스트는? dotted list
  * A와 B의 CONS : {{{(A . B)}}} <- dotted pair
  * LIST는 진리스트만 생성 가능. CONS는 Dotted list를 만들 수 있다
 * 순환 리스트(circular list)도 있다
  * 원소 A, B, C가 있는데 C를 포함하는 cell이 다시 A를 포함하는 cell을 가리키면?
  * sharp-equal notation: {{{#1=(A B C . #1#)}}} 라고 표기한다
 * (A B C . D)의 LENGTH는 4가 아니라 3
 * 순환 리스트의 LENGTH는 무한 루프

하루에 한 챕터씩 읽을려고 했는데 이상한 거 코딩하다가 못 했네 ㅡㅡ 3장은 내일

== 3장 EVAL 표기 ==
=== 3장 요약 ===
 * 함수를 그림으로 그리지 말고 리스트로 표현하자
 * 리스프에서 함수는 데이터다
 * EVAL 표기를 정복했으면 리스프를 통해 컴퓨터와 대화하는 데 필요한 건 대부분 알게 된 셈
 * EVAL 함수는 리스프의 핵심이다
  * 리스프 '''표현식'''을 평가해서 결과값을 내놓는다
  * 함수 뒤에 입력값들이 따라오는 형식
  * 표현식 {{{(+ 2 3)}}}는 5로 평가된다
  * {{{(+ 1 6) => 7}}}
  * {{{(oddp (+ 1 6)) => t}}}
  * {{{(* 3 (+ 1 6)) => 21}}}
  * {{{(/ (* 2 11) (+ 1 6)) => 22/7}}}
 * EVAL의 동작을 정의하는 평가 규칙들
  * 숫자형, T, NIL은 그 자신으로 평가된다
  * 리스트의 첫 원소는 함수, 나머지는 그 함수에 전달되는 아직 평가되지 않은 인자다
   * 인자들은 왼쪽에서 오른쪽으로 평가된다
  * 심볼은 그 심볼이 가리키는 변수의 값으로 평가된다
  * {{{(ODDP (+ 1 6))}}}의 evaltrace diagram(평가추적도표?)
    attachment:Figure_3.1_evaltrace_diagram.png
 * EVAL 표기로 함수 정의하기
  * 두 수의 평균을 구하는 AVERAGE 함수: {{{(defun average (x y) (/ (+ x y) 2.0))}}}
   * defun은 '''매크로 함수'''로서 그 인자를 평가하지 않는다
   * defun은 함수를 정의하기 위한 함수다
    * 첫 번째 인자는 함수 이름
    * 두 번째 인자는 인자 목록
    * 세 번째 인자는 함수 몸체
   * 이제 (AVERAGE 6 8) 처럼 쓸 수 있다
  * T와 NIL을 제외한 거의 모든 심볼을 인자 이름으로 쓸 수 있다
 * 변수: 데이터가 저장되는 공간
  * {{{(defun average (x y) (/ (+ x y) 2.0))}}}에서 x와 y가 변수
  * 변수는 심볼이 아니다
  * 심볼을 가지고 변수에 이름을 붙인 것
   * 리스프 프로그래머들이 "어떤 변수가 어떤 값으로 평가된다"고 말할 때
   * 사실은 "심볼이 그 심볼이 가리키는 변수의 값으로 평가된다"고 말하는 것
  * average란 심볼을 가지고 함수에 이름을 붙인 것
  * x, y 변수는 average 함수 안에서만 사용 가능
   * 머 흔히 말하는 스코프 개념이겠지
  * 전역 변수: 어떤 함수와도 엮이지 않은 변수
   * 예: PI = 3.14159
  * 값이 할당되지 않은 변수의 값을 요구하면 "미할당 변수 오류(unassigned variable error)"가 발생한다
   * "unbound variable error"라고 하는 사람들도 있지만 이건 역사적인 용어라 Common Lisp에 맞지 않음
   * 그럼 CAR니 CDR은 왜 쓰는 건데 ㅡㅡ
   * Common Lisp에는 EGGPLANT라는 내장 변수가 없으며 EGGPLANT 심볼을 평가하면 오류가 발생한다
   * {{{{color:#ff0000} 심볼이 왜 자꾸 문단에선 대문자로 나왔다 코드에선 소문자로 나왔다 하는 거야 뭐가 맞는 거야}}}
 * 심볼과 리스트를 데이터로 활용하기
  * 심볼 KIRK과 SPOCK이 같은 지 비교하고 싶어요
  * (equal kirk spock) 라고 쓰면 되지
  * 아니, KIRK이라는 심볼과 SPOCK이라는 심볼 자체를 비교하고 싶다니까요
  * 아ㅋ {{{(equal ’kirk ’spock)}}} 따옴표를 붙여
   * T와 NIL은 그 자신으로 평가되기 때문에 따옴표를 붙일 필요가 없다
  * Quoted Object의 평가 규칙: 따옴표를 뗀 자신으로 평가된다
  * (third (my aunt mary)) => Error! MY undefined function.
    (third ’(my aunt mary)) => mary
  * {{{{color:#ff0000}그러니까 따옴표는 평가되는 걸 막는다는 뜻인가}}}
  * 리스트를 만드는 세 가지 방법
   * ’(foo bar baz) => (foo bar baz)
   * (list ’foo ’bar ’baz) Þ (foo bar baz)
   * (cons ’foo ’(bar baz)) Þ (foo bar baz)
  * 이런 건 오류
   * (list foo bar baz) => Error! FOO unassigned variable.
   * (foo bar baz) => Error! FOO undefined function.
   * (’foo ’bar ’baz) => Error! ’FOO undefined function.
   * 슬슬 멘붕온다 겁나 헷갈린다
 * READ-EVAL-PRINT LOOP(REPL)
  * 그냥 콘솔에 뭐 치면 읽고 평가하고 출력 많이 하던 거네
 * 리스프 프로그래밍 환경
  * 코드 에디터: 괄호 오류 잘 찾아주는 거
   * 딱 봐도 괄호 땜에 오류 겁나 쏟아지게 생길 언어네
=== 3장 고급 주제 ===
 * 인자 없는 함수
  * 85에 97을 곱하는 함수를 정의하고 싶은데요
   * {{{(defun test () (* 85 97))}}}
 * 특수 함수 QUOTE
  * QUOTE의 인자는 평가되지 않는다
  * (quote foo) => foo
  * 따옴표랑 같은 거 아냐
   * (cons ’up ’(down sideways))
   * (cons (quote up) (quote (down sideways)))
 * 심볼의 내부 구조
  * CONS 심볼은 자신의 function cell에 함수 포인터를 가진다
  attachment:Figure_3.2_Symbol_Internal_Structure.png
  * (EQUAL 3 5)를 cons cell 연쇄로 표현
  attachment:Figure_3.3_EQUAL_cons_cell_chain.png
  * 더 자세히 표현하면?
  attachment:Figure_3.4_EQUAL_cons_cell_chain_detailed.png
  * 내장 함수 SYMBOL-NAME과 SYMBOL-FUNCTION
 * 람다 표기
  * 프린스턴 대학의 수학 교수 처치가 창안
  * 리스프의 원작자 존 매카시는 처치의 학생이여따
  * x + 3을 람다로 표현하면 {{{(lambda (x) (+ 3 x))}}}
  * DEFUN이랑 비슷한데?
   * LAMBDA는 함수가 아니다 --뭐라구요
   * EVAL이 특별 취급하는 마커,,marker,,
  * DEFUN의 역할은 이름과 함수를 엮어주는 것
   * HALF라는 새로운 함수를 정의할 때
    * 문자열 "HALF"는 심볼의 이름
    * 심볼 HALF는 함수의 이름
    attachment:Figure_3.5_LAMBDA_STRUCTURE.png
 * 원시 함수 EVAL
  * (eval ’(+ 2 2)) => 4
  * ’(list ’* 9 6)) => (list ’* 9 6)
    (eval ’(list ’* 9 6)) => (* 9 6)
    (eval (eval ’(list ’* 9 6))) => 54
 * 원시 함수 APPLY
  * 함수와 인자 목록을 인자로 취해서
  * 그 인자 목록을 가지고 함수를 호출한다
  * (apply #’+ ’(2 3)) => 5
   * 함수를 다른 함수의 인자로 넘길 때는 '가 아니라 #'를 써야 한다
   * 7장에서 알려줄게

== 4장. 조건문 ==
=== 4장 요약 ===
 * 조건문은 모두 특수 함수 또는 매크로이기 때문에 인자들이 자동 평가되지 않는다
  * 3장에서 본 DEFUN, QUOTE 함수도 그런 성질을 가진다
  * +, CONS 같은 함수는 항상 인자를 평가한다
 * 특수 함수 IF
  * 문법: {{{(if (test) (true-part) (false-part))}}}
  * 절댓값 함수: {{{(defun my-abs (x) (if (< x 0) (- x) x))}}}
  * 세 번째 인자 즉 false-part는 생략할 수 있다. 이 경우 NIL로 처리된다.
 * COND 매크로
  * 간략한 형태
        (COND (test-1 consequent-1)
        (test-2 consequent-2)
        (test-3 consequent-3)
        ....
        (test-n consequent-n))
  * test-1이 참이면 consequent-1로 평가됨
  * 아니면 test-2를 확인해보고 참이면 consequent-2로 평가됨
  * ... 그렇게 test-n까지 반복
  * test-n까지 거짓이면 NIL로 평가됨
  * (defun compare (x y) (cond ((equal x y) ’numbers-are-the-same) ((< x y) ’first-is-smaller) ((> x y) ’first-is-bigger)))
  * test-n에 T를 넣으면 consequent-n이 무조건 실행됨을 보장
  * (IF test true-part false-part) = (COND (test true-part) (T false-part))
 * AND 매크로와 OR 매크로
  * (and clause-1 clause-2 ... clause-n)
   * clause-1이 NIL이면 NIL로 종료. 아니면 계속
   * clause-2이 NIL이면 NIL로 종료. 아니면 계속...
   * clause-n이 NIL이면 NIL로 종료. 아니면 clause-n의 값 반환
   * (and 1 2 3 4 5) => 5
  * (or clause-1 clause-2 ... clause-n)
   * clause-1이 NIL이 아니면 clause-1의 값 반환. NIL이면 계속
   * clause-2이 NIL이 아니면 clause-2의 값 반환. NIL이면 계속
   * ...
   * clause-n이 NIL이 아니면 clause-n의 값 반환. NIL이면 NIL 반환
   * (or ’george ’fred ’harry) => george
   * (or nil ’fred ’harry) => fred
  * '''clause-x에서 평가가 끝나면 그 뒤의 clause들은 평가되지 않는다'''
   * (defun posnump (x) (and (numberp x) (plusp x)))
   * (numberp x)가 NIL이면 plusp는 실행되지 않는다
   * 만약 부수효과가 있는 코드라면... 신중해야 할 것
   * 리스프에서 부수효과를 어떻게 일으키는지 아직은 모르지만
   * 참고로 PLUSP는 숫자가 양수인지 확인하는 술어식
 * 리스프 도구: STEP
  * 리스프 표현식의 평가 과정을 단계별로 보여준다. 디버깅용
=== 4장 고급 주제 ===
 * 불리언 함수
  * (defun logical-and (x y) (and x y t))
   * (logical-and ’tweet ’woof) => t
   * (and ’tweet ’woof) => woof
 * 드 모르강의 법칙
  * (and x y) = (not (or (not x) (not y)))
  * (or x y) = (not (and (not x) (not y)))
  * 난 법칙이라고 배웠는데 영어로는 theorem이네... theorem은 정리 아닌감
  * T, NIL에 대한 논리 연산일 때만 성립
   * (not (not fred))는 fred가 아니라 T다

짧네 ㅋ 내일 5장

== 5장. 변수와 부수효과 ==
=== 5장 요약 ===