feat: SDF wiki 컴파일 — 챕터별 한국어 소스 페이지 8개
Software Design for Flexibility (Hanson & Sussman 2021) 전문을 wiki/sources/ 아래 챕터별 한국어 wiki 페이지로 컴파일 - SDF-overview: 전체 개요, 챕터 관계도, 공통 테마 - SDF-ch1: 가산적 프로그래밍 철학, 퇴화성, 유연성 비용 - SDF-ch2: 컴비네이터, DSL, 래퍼, 도메인 모델 - SDF-ch3: 제네릭 프로시저, 자동 미분, 트라이 디스패치 - SDF-ch4: 패턴 매칭, 항 재작성, 단일화, 타입 추론 - SDF-ch5: eval/apply, lazy eval, amb, call/cc - SDF-ch6: 레이어드 데이텀/프로시저, 단위 산술, 의존성 추적 - SDF-ch7: 전파 모델, 부분 정보 결합, 의존성 지향 백트래킹 wiki/index.md Sources 섹션 등록, wiki/log.md 기록 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,14 @@ updated: 2026-04-30
|
|||||||
|
|
||||||
<!-- 항목 형식: - [[페이지명]] — 저자, 출처 유형, 한 줄 설명 -->
|
<!-- 항목 형식: - [[페이지명]] — 저자, 출처 유형, 한 줄 설명 -->
|
||||||
|
|
||||||
(비어 있음)
|
- [[SDF-overview]] — Hanson & Sussman (2021), 책, "Software Design for Flexibility" 전체 개요 및 챕터 관계도
|
||||||
|
- [[SDF-ch1-flexibility]] — Hanson & Sussman, Ch1, 가산적 프로그래밍 철학·퇴화성·탐색적 행동 원칙
|
||||||
|
- [[SDF-ch2-dsl]] — Hanson & Sussman, Ch2, 컴비네이터·래퍼·도메인 모델로 DSL 구축
|
||||||
|
- [[SDF-ch3-generic-procedures]] — Hanson & Sussman, Ch3, 술어-디스패치 제네릭 프로시저·자동 미분·어드벤처 게임
|
||||||
|
- [[SDF-ch4-pattern-matching]] — Hanson & Sussman, Ch4, 패턴 매칭·항 재작성·단일화·타입 추론
|
||||||
|
- [[SDF-ch5-evaluation]] — Hanson & Sussman, Ch5, 제네릭 인터프리터·lazy eval·amb·call/cc
|
||||||
|
- [[SDF-ch6-layering]] — Hanson & Sussman, Ch6, 레이어드 데이터/프로시저로 단위·의존성 추적
|
||||||
|
- [[SDF-ch7-propagation]] — Hanson & Sussman, Ch7, 전파 모델·부분 정보 결합·의존성 지향 백트래킹
|
||||||
|
|
||||||
## Patterns — 설계 패턴
|
## Patterns — 설계 패턴
|
||||||
|
|
||||||
|
|||||||
10
wiki/log.md
10
wiki/log.md
@@ -15,3 +15,13 @@ title: Wiki Operation Log
|
|||||||
- `raw/` CLAUDE.md 추가, articles/, repos/, notes/ 폴더 생성
|
- `raw/` CLAUDE.md 추가, articles/, repos/, notes/ 폴더 생성
|
||||||
- `output/` 폴더 및 CLAUDE.md 생성
|
- `output/` 폴더 및 CLAUDE.md 생성
|
||||||
- 메인 CLAUDE.md에 볼트 구조 및 위키 운영 규칙 추가
|
- 메인 CLAUDE.md에 볼트 구조 및 위키 운영 규칙 추가
|
||||||
|
- [SDF wiki 일괄 생성] "Software Design for Flexibility" (Hanson & Sussman 2021) 챕터별 wiki 페이지 8개 생성
|
||||||
|
- `wiki/sources/SDF-overview.md` — 전체 책 개요, 챕터 관계도, 공통 테마
|
||||||
|
- `wiki/sources/SDF-ch1-flexibility.md` — 가산적 프로그래밍, 퇴화성, 탐색적 행동, 유연성 비용
|
||||||
|
- `wiki/sources/SDF-ch2-dsl.md` — 컴비네이터 시스템, 정규표현식 DSL, 래퍼, 보드게임 도메인 모델
|
||||||
|
- `wiki/sources/SDF-ch3-generic-procedures.md` — 제네릭 프로시저, 자동 미분, 트라이 디스패치, 어드벤처 게임
|
||||||
|
- `wiki/sources/SDF-ch4-pattern-matching.md` — 패턴 언어, 항 재작성, 매처 컴비네이터, 단일화
|
||||||
|
- `wiki/sources/SDF-ch5-evaluation.md` — eval/apply 인터프리터, lazy eval, 분석/실행 분리, amb, call/cc
|
||||||
|
- `wiki/sources/SDF-ch6-layering.md` — 레이어드 데이텀/프로시저, 단위 산술, 의존성 추적
|
||||||
|
- `wiki/sources/SDF-ch7-propagation.md` — 전파 모델, 셀/전파기, 부분 정보, 의존성 지향 백트래킹
|
||||||
|
- `wiki/index.md` Sources 섹션에 생성된 8개 페이지 등록
|
||||||
|
|||||||
66
wiki/sources/SDF-ch1-flexibility.md
Normal file
66
wiki/sources/SDF-ch1-flexibility.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
title: "Ch1: Flexibility in Nature and in Design"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 1
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch1: Flexibility in Nature and in Design
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
소프트웨어는 요구사항 변화에 취약하게 설계되는 경향이 있으며, 이를 극복하기 위한 철학으로 **가산적 프로그래밍(additive programming)**을 제안한다. 기존 코드를 수정하지 않고 추가만으로 새 기능을 구현할 수 있는 시스템 설계 원칙을 생물학적 시스템의 적응성에서 도출한다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 가산적 프로그래밍 (Additive Programming)
|
||||||
|
|
||||||
|
동작하는 프로그램을 수정하지 않고 코드를 *추가*함으로써 새로운 기능을 구현하거나 기존 기능을 새 요구사항에 맞추는 프로그래밍 스타일. 이를 위한 전제조건:
|
||||||
|
|
||||||
|
- 프로그램이 어떻게 작동하고 어떻게 사용될지에 대한 가정을 최소화
|
||||||
|
- just-in-time 결정: 가정을 미리 굳히지 않고 실행 환경에 기반해 결정
|
||||||
|
- 부분들이 관심사를 명확히 분리하여 의도치 않은 상호작용 최소화
|
||||||
|
|
||||||
|
### 아키텍처의 parti 유추
|
||||||
|
|
||||||
|
건축의 *parti*(설계 조직 원리)와 유사하게, 프로그램의 추상적 골격(skeleton plan)이 분석·비판·실험 가능한 형태로 존재해야 한다. Java처럼 "served spaces"(실제 동작 코드)와 "servant spaces"(타입 선언, 클래스 선언 등)가 혼재하는 언어보다, Lisp처럼 parti를 드러내는 언어가 유리하다.
|
||||||
|
|
||||||
|
### 스마트 파츠 (Smart Parts)
|
||||||
|
|
||||||
|
생물학적 세포가 맥락 신호를 읽어 스스로 역할을 결정하듯, 소프트웨어 컴포넌트도 명령적(imperative) 제어 대신 **맥락 반응적(context-responsive)**으로 설계되어야 한다. 이를 통해 변화에 대한 적응이 전체 제어 구조를 수정하지 않고 영향을 받는 부분만의 변경으로 이루어진다.
|
||||||
|
|
||||||
|
### 중복성과 퇴화성 (Redundancy and Degeneracy)
|
||||||
|
|
||||||
|
- **중복성(redundancy)**: 동일한 기능의 여분 용량 (신장이 두 개인 것처럼)
|
||||||
|
- **퇴화성(degeneracy)**: 동일한 목적을 달성하는 *서로 다른* 복수의 메커니즘
|
||||||
|
|
||||||
|
퇴화성은 단순 중복성보다 강력하다. 한 방식이 실패해도 다른 방식이 작동하며, 서로 다른 메커니즘이므로 동일한 버그를 공유하지 않는다. 부분 정보들을 결합하면 개별 결과보다 더 정확한 결과를 얻을 수 있다 (예: 항법 시스템의 다중 위치 추정 결합).
|
||||||
|
|
||||||
|
### 탐색적 행동 (Exploratory Behavior)
|
||||||
|
|
||||||
|
생성-검증(generate-and-test) 메커니즘: 생성기는 제안을 내놓고, 검증기는 수락 또는 거부한다. 두 부분이 독립적으로 발전 가능하므로 한쪽의 변화가 다른 쪽의 변화를 요구하지 않는다. 백트래킹이 이 메커니즘의 계산적 구현이며, Chapter 4(패턴 매칭), Chapter 5(인터프리터의 amb), Chapter 7(의존성 지향 백트래킹)에서 순차적으로 발전시킨다.
|
||||||
|
|
||||||
|
### 유연성의 비용
|
||||||
|
|
||||||
|
유연성은 공간, 계산 시간, 프로그래머 시간에서 일정한 오버헤드를 수반한다. 그러나 소프트웨어의 주된 비용은 프로그래머가 생애주기 동안 소비하는 시간이다. 적응성이 높은 설계는 재작성·리팩토링 비용을 줄이므로 장기적으로 비용이 가산적(additive)이 된다.
|
||||||
|
|
||||||
|
### 정확성 요구의 문제
|
||||||
|
|
||||||
|
모든 것을 증명 가능하게 만들라는 규율은 오히려 시스템을 취약하게 만든다. 일반적인 메커니즘의 일반적 속성을 증명하기는 특수 메커니즘의 특수 속성을 증명하기보다 어렵기 때문에, 증명 요구는 부품을 가능한 한 특수하게 만들도록 유도한다. 특수화된 부품의 결합은 변화의 여지가 없어 취약하다.
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "One should not have to modify a working program. One should be able to add to it to implement new functionality or to adjust old functions for new requirements. We call this *additive programming*."
|
||||||
|
|
||||||
|
> "Be conservative in what you do, be liberal in what you accept from others." (Postel's Law, RFC760)
|
||||||
|
|
||||||
|
> "In order for additive programming to be possible, it is necessary to minimize the assumptions about how a program works and how it will be used."
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch2-dsl]] — 가산적 프로그래밍의 첫 번째 구체적 도구: 컴비네이터와 DSL
|
||||||
|
- [[SDF-ch3-generic-procedures]] — 제네릭 프로시저를 통한 기능 확장
|
||||||
|
- [[SDF-ch6-layering]] — 레이어링으로 기존 코드를 수정 없이 메타데이터 추가
|
||||||
|
- [[SDF-ch7-propagation]] — 퇴화성과 부분 정보 결합의 완성형
|
||||||
|
- [[SDF-overview]] — 책 전체 구조
|
||||||
126
wiki/sources/SDF-ch2-dsl.md
Normal file
126
wiki/sources/SDF-ch2-dsl.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
title: "Ch2: Domain-Specific Languages"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 2
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch2: Domain-Specific Languages
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
유연한 시스템을 구축하는 핵심 전략은 도메인 특화 언어(DSL)를 만드는 것이다. DSL은 문제 도메인의 개념 구조를 직접 반영하는 언어로, **컴비네이터 시스템**, **래퍼**, **도메인 모델 추상화** 세 가지 기법으로 구성된다. 모든 조합이 유효한 프로그램을 만들어내는 믹스앤매치(mix-and-match) 부품 체계가 핵심이다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 2.1 컴비네이터 시스템 (Combinator Systems)
|
||||||
|
|
||||||
|
**컴비네이터 언어**의 정의: 원시 부품(primitives)과 조합 수단(combinators)의 집합으로, 조합의 인터페이스 명세가 원시 부품의 인터페이스 명세와 동일한 것.
|
||||||
|
|
||||||
|
핵심 성질:
|
||||||
|
- 임의의 믹스앤매치 가능
|
||||||
|
- 어떤 조합도 유효한 프로그램 생성 (법적으로 유효, legally correct)
|
||||||
|
- 부품의 동작은 컨텍스트에 독립적
|
||||||
|
- 새 부품이나 컴비네이터 추가가 기존 프로그램에 영향 없음
|
||||||
|
|
||||||
|
**기본 함수 컴비네이터들:**
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; compose: f ∘ g
|
||||||
|
(define (compose f g)
|
||||||
|
(define (the-composition . args)
|
||||||
|
(call-with-values (lambda () (apply g args)) f))
|
||||||
|
(restrict-arity the-composition (get-arity g)))
|
||||||
|
|
||||||
|
;; parallel-combine: h(f(args), g(args))
|
||||||
|
(define (parallel-combine h f g)
|
||||||
|
(define (the-combination . args)
|
||||||
|
(h (apply f args) (apply g args)))
|
||||||
|
the-combination)
|
||||||
|
|
||||||
|
;; spread-combine: h(f(첫 n개 인수), g(나머지 인수))
|
||||||
|
(define (spread-combine h f g)
|
||||||
|
(compose h (spread-apply f g)))
|
||||||
|
```
|
||||||
|
|
||||||
|
**기타 유용한 컴비네이터:**
|
||||||
|
- `discard-argument i` — i번째 인수를 무시하는 함수 생성
|
||||||
|
- `curry-argument i` — i번째 인수를 고정하는 커링
|
||||||
|
- `permute-arguments` — 인수 순서 재배열
|
||||||
|
|
||||||
|
**아리티(Arity) 관리**: 컴비네이터가 올바르게 작동하려면 각 함수의 인수 개수를 추적해야 한다. `restrict-arity`와 `get-arity`로 함수에 아리티를 "스티키 노트"처럼 첨부한다 (해시 테이블 사용).
|
||||||
|
|
||||||
|
### 2.2 정규 표현식 DSL
|
||||||
|
|
||||||
|
정규 표현식은 DSL의 **나쁜 예시**: 조각들이 독립적으로 조합되지 않으며, 컨텍스트에 따라 의미가 달라진다. 이를 개선하기 위해 컴비네이터 기반 DSL을 만들고 POSIX BRE 문법으로 컴파일한다.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 기본 패턴 프리미티브
|
||||||
|
(r:dot) ; 임의의 문자
|
||||||
|
(r:bol) ; 줄 시작
|
||||||
|
(r:eol) ; 줄 끝
|
||||||
|
(r:quote string) ; 문자열 그대로 매칭
|
||||||
|
(r:char-from string) ; 집합에서 한 문자
|
||||||
|
|
||||||
|
;; 컴비네이터
|
||||||
|
(r:seq pat ...) ; 순서대로 매칭
|
||||||
|
(r:alt pat ...) ; 하나라도 매칭
|
||||||
|
(r:repeat min max pat) ; 반복 매칭
|
||||||
|
```
|
||||||
|
|
||||||
|
교훈: 조합 가능한 부품과 컴비네이터로 만든 DSL이 전통적 정규 표현식보다 단순하고 견고하다.
|
||||||
|
|
||||||
|
### 2.3 래퍼 (Wrappers)
|
||||||
|
|
||||||
|
기존 프로그램을 재작성하지 않고 **감싸서(wrapping)** 새 컨텍스트에서 사용하는 전략.
|
||||||
|
|
||||||
|
단위 변환 예시: `gas-law-volume`(SI 단위 기준)을 화씨/PSI/인치로 사용하고 싶을 때, 프로시저 자체를 수정하지 않고 `unit-specializer`로 래퍼를 생성:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define make-specialized-gas-law-volume
|
||||||
|
(unit-specializer gas-law-volume
|
||||||
|
'(expt meter 3) ; 출력 단위
|
||||||
|
'(/ newton (expt meter 2)) ; 압력
|
||||||
|
'kelvin ; 온도
|
||||||
|
'mole)) ; 양
|
||||||
|
|
||||||
|
(define conventional-gas-law-volume
|
||||||
|
(make-specialized-gas-law-volume
|
||||||
|
'(expt inch 3) '(/ pound (expt inch 2))
|
||||||
|
'fahrenheit 'mole))
|
||||||
|
```
|
||||||
|
|
||||||
|
원칙: 기본 프로그램은 단순하고 일반적으로 유지하고, 특수화는 래퍼로 감싸서 수행. 세 부분(기본 프로그램, 래퍼, 단위 특수화기)이 느슨하게 결합되어 각각 독립적으로 일반화 가능.
|
||||||
|
|
||||||
|
### 2.4 도메인 추상화 (Abstracting a Domain)
|
||||||
|
|
||||||
|
체커 게임 심판 구현을 통해 DSL 레이어 구축 과정을 보여준다.
|
||||||
|
|
||||||
|
**1단계 — 모놀리식 구현**: 도메인 모델이 체커 특화적이며, 규칙이 코드 전체에 분산됨.
|
||||||
|
|
||||||
|
**2단계 — 도메인 모델 분리**:
|
||||||
|
- 게임 특화 요소(킹, 점프 등)를 추상적 타입(심볼 타입, change 플래그)으로 교체
|
||||||
|
- `partial-move(pmove)` 추상화로 이동 경로 표현
|
||||||
|
- **룰 익스큐티브(rule executive)**: 제어 구조를 규칙에서 분리
|
||||||
|
- **진화 규칙(evolution rules)**: pmove를 새 pmove들로 변환
|
||||||
|
- **집합 규칙(aggregate rules)**: 완료된 pmove 집합에 작용
|
||||||
|
- 각 체커 규칙이 단일 프로시저로 표현됨
|
||||||
|
|
||||||
|
도메인 모델 = 도메인 언어의 프리미티브 + 조합 수단 + 추상화 수단.
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "A *system of combinators* is a set of primitive parts and a set of means of combining parts such that the interface specifications of the combinations are the same as those of the primitives."
|
||||||
|
|
||||||
|
> "Rather than rewriting a program to adapt it to a new purpose, it's preferable to start with a simple and general base program and wrap it to specialize it for a particular purpose."
|
||||||
|
|
||||||
|
> "The moral of this story is that regular expressions are a beautiful example of how *not* to build a system. Using composable parts and combinators to make new parts by combining others leads to simpler and more robust implementations."
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch1-flexibility]] — 가산적 프로그래밍의 철학적 기반
|
||||||
|
- [[SDF-ch3-generic-procedures]] — 컴비네이터 한계를 극복하는 제네릭 프로시저
|
||||||
|
- [[SDF-ch4-pattern-matching]] — 패턴 매칭 컴비네이터
|
||||||
|
- [[SDF-ch5-evaluation]] — 인터프리터로 언어에 완전한 의미 부여
|
||||||
|
- [[SDF-ch6-layering]] — 래퍼 개념의 확장인 레이어링
|
||||||
156
wiki/sources/SDF-ch3-generic-procedures.md
Normal file
156
wiki/sources/SDF-ch3-generic-procedures.md
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
---
|
||||||
|
title: "Ch3: Variations on an Arithmetic Theme"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 3
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch3: Variations on an Arithmetic Theme
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
**술어-디스패치 제네릭 프로시저(predicate-dispatched generic procedures)**를 중심으로, 기존 프로그램의 동작을 확장하는 강력하지만 위험한 기법을 다룬다. 산술 연산의 의미를 수치에서 기호, 함수, 미분 객체로 확장하는 과정을 통해 제네릭 시스템의 설계 원칙을 보여준다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 3.1 산술 패키지 컴비네이터
|
||||||
|
|
||||||
|
**산술 패키지(arithmetic package)**: 연산자 이름에서 구현으로의 매핑. `install-arithmetic!`으로 사용자 환경에 설치.
|
||||||
|
|
||||||
|
**적용 가능성 명세(applicability specification)**: 술어 리스트의 리스트. 인수들이 케이스 중 하나를 만족하면 해당 핸들러 적용.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 수치 산술: (number? number?) 케이스만 적용
|
||||||
|
;; 기호 산술: (number? symbolic?), (symbolic? number?),
|
||||||
|
;; (symbolic? symbolic?) 케이스에 적용
|
||||||
|
|
||||||
|
(define combined-arithmetic
|
||||||
|
(extend-arithmetic symbolic-extender numeric-arithmetic))
|
||||||
|
```
|
||||||
|
|
||||||
|
`add-arithmetics` 컴비네이터로 산술들을 결합. 그러나 컴비네이터 방식은 한계가 있다:
|
||||||
|
- 부품의 형태를 미리 결정해야 함
|
||||||
|
- 계층화된 구조(예: 함수 산술)를 나중에 확장하기 어려움
|
||||||
|
- 자기 참조 구조 불가
|
||||||
|
|
||||||
|
### 3.2 확장 가능한 제네릭 프로시저
|
||||||
|
|
||||||
|
컴비네이터의 한계를 극복하기 위해 **동적으로 확장 가능한 제네릭 프로시저** 도입.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 생성
|
||||||
|
(define plus (simple-generic-procedure 'plus 2 #f))
|
||||||
|
|
||||||
|
;; 핸들러 추가
|
||||||
|
(define-generic-procedure-handler plus
|
||||||
|
(all-args 2 number?)
|
||||||
|
(lambda (a b) (+ a b)))
|
||||||
|
|
||||||
|
(define-generic-procedure-handler plus
|
||||||
|
(any-arg 2 symbolic? number?)
|
||||||
|
(lambda (a b) (list '+ a b)))
|
||||||
|
```
|
||||||
|
|
||||||
|
**구현 메커니즘**:
|
||||||
|
1. `generic-procedure-constructor`: 디스패치 전략을 인자로 받아 제네릭 프로시저 생성기 반환
|
||||||
|
2. `dispatch-store`: 핸들러 저장/검색 전략 캡슐화
|
||||||
|
3. 메타데이터 테이블: 제네릭 프로시저에 "스티키 노트"로 규칙 목록 첨부
|
||||||
|
|
||||||
|
**제네릭 산술의 폐쇄성(closure)**: 모든 확장을 제네릭 산술 자체를 기반으로 만들면 자기 참조 구조가 가능하다.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(let ((g (make-generic-arithmetic make-simple-dispatch-store)))
|
||||||
|
(add-to-generic-arithmetic! g numeric-arithmetic)
|
||||||
|
(extend-generic-arithmetic! g symbolic-extender)
|
||||||
|
(extend-generic-arithmetic! g function-extender)
|
||||||
|
(install-arithmetic! g))
|
||||||
|
```
|
||||||
|
|
||||||
|
**주의**: 핸들러 추가 순서에 의존성이 생길 수 있다. 적용 가능성이 겹치는 규칙들의 순서에 따라 결과가 달라짐.
|
||||||
|
|
||||||
|
### 3.3 자동 미분 (Automatic Differentiation)
|
||||||
|
|
||||||
|
제네릭 프로시저의 탁월한 응용 예시. **미분 객체(differential object)** `[x, δx]`를 새 데이터 타입으로 도입:
|
||||||
|
|
||||||
|
$$[x, \delta x] \xrightarrow{f} [f(x), Df(x)\delta x]$$
|
||||||
|
|
||||||
|
각 산술 연산에 미분 객체 처리 핸들러를 추가하기만 하면, 함수의 합성을 통해 연쇄 법칙이 자동으로 적용된다.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define (derivative f)
|
||||||
|
(define (the-derivative x)
|
||||||
|
(let* ((dx (make-new-dx))
|
||||||
|
(value (f (d:+ x (make-infinitesimal dx)))))
|
||||||
|
(extract-dx-part value dx)))
|
||||||
|
the-derivative)
|
||||||
|
|
||||||
|
;; sqrt의 미분 핸들러
|
||||||
|
(define diff:sqrt
|
||||||
|
(diff:unary-proc sqrt (lambda (x) (/ 1 (* 2 (sqrt x))))))
|
||||||
|
```
|
||||||
|
|
||||||
|
고차 함수(함수를 반환하는 함수)에서의 미분은 기술적 복잡성이 있다: dx 태그 충돌 문제를 `replace-dx` 메커니즘으로 해결.
|
||||||
|
|
||||||
|
### 3.4 효율적인 디스패치
|
||||||
|
|
||||||
|
**단순 선형 스캔의 문제**: 많은 규칙에서 동일한 술어를 반복 호출.
|
||||||
|
|
||||||
|
**트라이(Trie) 기반 디스패치**:
|
||||||
|
- 인수 시퀀스를 트라이로 인덱싱
|
||||||
|
- 첫 번째 인수의 타입으로 후보 규칙 집합을 좁힘
|
||||||
|
- 중복 술어 평가 제거
|
||||||
|
|
||||||
|
**캐싱**:
|
||||||
|
- 인수의 구현 타입 태그를 키로 사용
|
||||||
|
- 이전 디스패치 결과를 해시 테이블에 캐시
|
||||||
|
- `cache-wrapped-dispatch-store`로 임의의 디스패치 전략에 캐싱 추가
|
||||||
|
|
||||||
|
### 3.5 사용자 정의 타입
|
||||||
|
|
||||||
|
**추상 술어(abstract predicate)**: 비용이 높은 술어 평가를 메모이즈. 객체에 태그를 붙여 이후 디스패치에서 비싼 술어 재평가 불필요.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define prime-number?
|
||||||
|
(simple-abstract-predicate 'prime-number slow-prime?))
|
||||||
|
|
||||||
|
(set-predicate<=! prime-number? exact-integer?)
|
||||||
|
;; 이후 exact-integer? 도 prime-number 객체를 인식
|
||||||
|
```
|
||||||
|
|
||||||
|
**서브타입 관계 선언**: `set-predicate<=!`로 부분집합 관계 명시. 가장 특수적인 핸들러가 선택됨.
|
||||||
|
|
||||||
|
### 3.5.4 어드벤처 게임
|
||||||
|
|
||||||
|
제네릭 프로시저와 사용자 정의 타입의 실용적 응용 예시.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 이동 행동이 4개 인수 타입의 조합에 따라 달라짐
|
||||||
|
(define generic-move!
|
||||||
|
(most-specific-generic-procedure 'generic-move! 4 #f))
|
||||||
|
|
||||||
|
(define-generic-procedure-handler generic-move!
|
||||||
|
(match-args mobile-thing? place? bag? person?) ...)
|
||||||
|
(define-generic-procedure-handler generic-move!
|
||||||
|
(match-args mobile-thing? bag? place? person?) ...)
|
||||||
|
(define-generic-procedure-handler generic-move!
|
||||||
|
(match-args person? place? place? person?) ...)
|
||||||
|
```
|
||||||
|
|
||||||
|
단일 디스패치 OOP와 달리, 모든 인수 타입의 조합에 따라 행동이 결정되므로 더 자연스러운 분해가 가능하다.
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "Systems built by combinators, as in section 3.1, result in beautiful diamond-like systems. This is sometimes the right idea... but it is very hard to add to a diamond. If a system is built as a ball of mud, it is easy to add more mud."
|
||||||
|
|
||||||
|
> "Construction of a system on a substrate of extensible generic procedures is a powerful idea... a user may extend them to support arithmetic on quaternions, vectors, matrices, integers modulo a prime, functions, tensors, differential forms..."
|
||||||
|
|
||||||
|
> "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." (Alan Perlis)
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch2-dsl]] — 컴비네이터 기반 접근의 한계에서 제네릭 프로시저로 이행
|
||||||
|
- [[SDF-ch4-pattern-matching]] — 제네릭 프로시저의 패턴 기반 확장
|
||||||
|
- [[SDF-ch6-layering]] — 제네릭 프로시저와 밀접한 레이어링
|
||||||
|
- [[SDF-ch7-propagation]] — 타입 태그와 의존성 추적의 결합
|
||||||
|
- [[SDF-overview]]
|
||||||
133
wiki/sources/SDF-ch4-pattern-matching.md
Normal file
133
wiki/sources/SDF-ch4-pattern-matching.md
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
title: "Ch4: Pattern Matching"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 4
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch4: Pattern Matching
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
패턴 매칭은 등호 검사의 일반화로, 구조와 내용의 일부를 미지수(패턴 변수)로 남겨둔 채 데이터와 비교하는 기술이다. 이를 통해 **항 재작성(term-rewriting) 시스템**, **단일화(unification) 기반 타입 추론**, **패턴 지향 호출(pattern-directed invocation)**을 구현한다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 4.1 패턴 언어
|
||||||
|
|
||||||
|
**패턴 구문**:
|
||||||
|
- `(? a)` — 단일 요소 변수
|
||||||
|
- `(?? t)` — 세그먼트 변수 (0개 이상의 연속 요소 매칭)
|
||||||
|
- `(? a ,number?)` — 제약 있는 변수 (number?를 만족하는 요소만 매칭)
|
||||||
|
- 나머지 요소 — 패턴 상수 (정확히 일치)
|
||||||
|
|
||||||
|
**세그먼트 변수의 중요성**: 세그먼트 변수는 매칭 시 **탐색**이 필요하다. 동일한 패턴 변수가 두 위치에 나타나면 양쪽이 같은 길이여야 한다.
|
||||||
|
|
||||||
|
예: 패턴 `(a (?? x) (?? y) (?? x) c)`는 `(a b b b b b b c)`를 4가지 방식으로 매칭 가능.
|
||||||
|
|
||||||
|
### 4.2 항 재작성 시스템
|
||||||
|
|
||||||
|
**규칙(rule)**: 패턴 + 귀결(consequent). 패턴이 매칭되면 귀결을 평가해 매칭된 부분식을 교체.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define algebra-1
|
||||||
|
(rule-simplifier
|
||||||
|
(list
|
||||||
|
(rule '(+ (? a) (+ (? b) (? c)))
|
||||||
|
'(+ (+ ,a ,b) ,c)) ; 결합 법칙
|
||||||
|
(rule '(* (? b) (? a))
|
||||||
|
(and (expr<? a b) ; 교환 법칙 (순환 방지)
|
||||||
|
'(* ,a ,b)))
|
||||||
|
(rule '(* (? a) (+ (? b) (? c)))
|
||||||
|
'(+ (* ,a ,b) (* ,a ,c)))))) ; 분배 법칙
|
||||||
|
```
|
||||||
|
|
||||||
|
`rule-simplifier`는 고정점(fixed point)에 도달할 때까지 반복 적용하는 단순화기를 반환.
|
||||||
|
|
||||||
|
**세그먼트 변수를 사용하는 algebra-2**: n항 덧셈/곱셈을 직접 표현:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(rule '(+ (?? a) (+ (?? b)) (?? c))
|
||||||
|
'(+ ,@a ,@b ,@c)) ; 결합 법칙 (n항)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2.2 매처 구현
|
||||||
|
|
||||||
|
**매처(matcher)**의 인터페이스:
|
||||||
|
- 인수: `data`, `dictionary`, `succeed` 연속(continuation)
|
||||||
|
- 성공 시 `succeed`를 `(새 사전, 소비된 요소 수)`로 호출
|
||||||
|
- 실패 시 `#f` 반환
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 패턴 상수 매처
|
||||||
|
(define (match:eqv pattern-constant)
|
||||||
|
(define (eqv-match data dictionary succeed)
|
||||||
|
(and (pair? data)
|
||||||
|
(eqv? (car data) pattern-constant)
|
||||||
|
(succeed dictionary 1)))
|
||||||
|
eqv-match)
|
||||||
|
|
||||||
|
;; 요소 변수 매처
|
||||||
|
(define (match:element variable)
|
||||||
|
(define (element-match data dictionary succeed)
|
||||||
|
(and (pair? data)
|
||||||
|
(let ((binding (match:lookup variable dictionary)))
|
||||||
|
(if binding
|
||||||
|
(and (equal? (match:binding-value binding)
|
||||||
|
(car data))
|
||||||
|
(succeed dictionary 1))
|
||||||
|
(succeed (match:extend-dict variable
|
||||||
|
(car data)
|
||||||
|
dictionary)
|
||||||
|
1)))))
|
||||||
|
element-match)
|
||||||
|
```
|
||||||
|
|
||||||
|
컴파일된 패턴은 이런 매처들의 컴비네이터 조합이다. 세그먼트 변수 매처는 가능한 분할을 백트래킹하며 시도한다.
|
||||||
|
|
||||||
|
### 4.2.4 패턴 지향 호출 (Pattern-Directed Invocation)
|
||||||
|
|
||||||
|
패턴 연산자(pattern operator): 입력을 패턴으로 디스패치하여 처리.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define factorial
|
||||||
|
(make-pattern-operator
|
||||||
|
(rule '(0) 1)
|
||||||
|
(rule '((? n ,positive?))
|
||||||
|
(* n (factorial (- n 1))))))
|
||||||
|
```
|
||||||
|
|
||||||
|
`attach-rule!`로 나중에 규칙을 동적 추가 가능. 컴파일러의 피프홀 최적화처럼, 관련 코드와 규칙을 함께 위치시킬 수 있다.
|
||||||
|
|
||||||
|
### 4.4 단일화 (Unification)
|
||||||
|
|
||||||
|
일반 패턴 매칭: 한 쪽은 패턴(변수 포함), 다른 쪽은 데이터.
|
||||||
|
**단일화**: 양쪽 모두 변수를 포함할 수 있으며, 두 패턴을 동시에 만족하는 가장 일반적인 변수 할당을 찾는다.
|
||||||
|
|
||||||
|
타입 추론 응용: 각 식에서 국소적으로 유추되는 타입 제약들을 단일화로 결합하여 비국소적 타입 제약 도출.
|
||||||
|
|
||||||
|
예:
|
||||||
|
- `(+ a b)` → `a: number, b: number`를 요구
|
||||||
|
- `(> a 0)` → `a: number`를 요구
|
||||||
|
- 단일화 결과: `a: number`로 확정
|
||||||
|
|
||||||
|
### 4.5 그래프 패턴 매칭
|
||||||
|
|
||||||
|
트리(S-표현식)를 넘어 임의의 그래프에 대한 패턴 매칭으로 확장. 체스 이동 규칙을 그래프 패턴으로 표현하는 예시.
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "Pattern matching is a generalization of equality testing. In equality testing we compare two objects to determine that they have the same structure and contents. In pattern matching, we generalize equality testing to allow some parts of the structure and contents to be unspecified."
|
||||||
|
|
||||||
|
> "A pattern can be matched to a part of a larger datum; the context of the match is unspecified. The ability to work with partial information means that only the specified parts of the pattern are assumptions about the data matched; there are few or no assumptions about the unspecified parts."
|
||||||
|
|
||||||
|
> "Besides the use of patterns to match data that meets a partial specification, patterns can themselves represent partially known information. Merging such patterns (*unification*) can generate more specific information than the individual patterns contribute."
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch2-dsl]] — 컴비네이터 패턴으로 매처 구현
|
||||||
|
- [[SDF-ch3-generic-procedures]] — 제네릭 프로시저의 패턴 기반 확장으로서의 패턴 지향 호출
|
||||||
|
- [[SDF-ch5-evaluation]] — 매처를 이용한 언어 구현
|
||||||
|
- [[SDF-ch7-propagation]] — 부분 정보 결합의 다른 형태
|
||||||
|
- [[SDF-overview]]
|
||||||
151
wiki/sources/SDF-ch5-evaluation.md
Normal file
151
wiki/sources/SDF-ch5-evaluation.md
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
---
|
||||||
|
title: "Ch5: Evaluation"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 5
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch5: Evaluation
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
문제 해결의 가장 강력한 방법 중 하나는 그 해법을 쉽게 표현할 수 있는 도메인 특화 언어를 만드는 것이다. 이 장은 인터프리터를 점진적으로 발전시키면서 **lazy evaluation**, **컴파일(분석/실행 분리)**, **비결정적 평가(amb)**, **연속(continuations)** 등 언어 설계의 핵심 기법을 보여준다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 5.1 제네릭 eval/apply 인터프리터
|
||||||
|
|
||||||
|
인터프리터의 핵심: `eval`과 `apply`의 상호 재귀.
|
||||||
|
|
||||||
|
- `eval`: 표현식 + 환경 → 값 (표현식의 타입별로 제네릭 프로시저로 처리)
|
||||||
|
- `apply`: 프로시저 + 인수 → 값 (프로시저 본문을 새 환경에서 eval)
|
||||||
|
|
||||||
|
**g:eval을 제네릭 프로시저로 구현**하는 이유: 새 표현식 타입을 핸들러 추가만으로 도입 가능.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define g:eval
|
||||||
|
(simple-generic-procedure 'eval 2 default-eval))
|
||||||
|
|
||||||
|
;; 기본 케이스: 적용(application)
|
||||||
|
(define (default-eval expression environment)
|
||||||
|
(cond ((application? expression)
|
||||||
|
(g:apply (g:advance (g:eval (operator expression)
|
||||||
|
environment))
|
||||||
|
(operands expression)
|
||||||
|
environment))
|
||||||
|
(else (error "Unknown expression type" expression))))
|
||||||
|
```
|
||||||
|
|
||||||
|
**g:advance**: 지연된 평가를 재개하는 제네릭 프로시저. 기본적으로 항등함수이나, lazy evaluation 도입 시 활성화됨.
|
||||||
|
|
||||||
|
**비평가 피연산자(unevaluated operands)를 apply에 전달**: applicative-order와 normal-order 평가 모두를 나중에 지원할 수 있게 하는 유연한 설계 결정.
|
||||||
|
|
||||||
|
각 표현식 타입에 대한 핸들러:
|
||||||
|
- 자기 평가 표현식(숫자, 불리언, 문자열): 그대로 반환
|
||||||
|
- 인용(quote): 보호된 부분식 반환
|
||||||
|
- 변수: 환경에서 조회
|
||||||
|
- if: 술어 평가 후 귀결 또는 대안 평가
|
||||||
|
- lambda: 프로시저 객체 생성 (환경 포함)
|
||||||
|
- define, set!: 환경 수정
|
||||||
|
|
||||||
|
### 5.2 Lazy Evaluation (지연 평가)
|
||||||
|
|
||||||
|
형식 매개변수에 **선언(declaration)**을 추가하여 평가 전략을 지정:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(lambda ((lazy x) y) ; x는 필요할 때만 평가
|
||||||
|
...)
|
||||||
|
|
||||||
|
(lambda ((lazy-memo x) y) ; x는 필요할 때 평가하고 결과를 메모이즈
|
||||||
|
...)
|
||||||
|
```
|
||||||
|
|
||||||
|
**thunk**: 아직 평가되지 않은 표현식 + 환경의 묶음. g:advance가 필요 시 강제 평가.
|
||||||
|
|
||||||
|
선언은 타입, 단위 등 다른 정보에도 활용 가능.
|
||||||
|
|
||||||
|
### 5.3 분석/실행 분리 (Analysis/Execution Separation)
|
||||||
|
|
||||||
|
인터프리터의 비효율: 동일한 표현식을 만날 때마다 반복 분석.
|
||||||
|
|
||||||
|
해결책: 해석을 두 단계로 분리:
|
||||||
|
1. **분석 단계**: 표현식을 검사하여 **실행 프로시저** 생성
|
||||||
|
2. **실행 단계**: 실행 프로시저를 환경에 적용
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 분석: 표현식 → 실행 프로시저
|
||||||
|
(define (analyze-if expression)
|
||||||
|
(let ((p (analyze (if-predicate expression)))
|
||||||
|
(c (analyze (if-consequent expression)))
|
||||||
|
(a (analyze (if-alternative expression))))
|
||||||
|
(lambda (env succeed fail) ; 실행 프로시저
|
||||||
|
...)))
|
||||||
|
```
|
||||||
|
|
||||||
|
실행 프로시저들은 모두 동일한 형태를 가지며, **컴비네이터 시스템**을 이룬다.
|
||||||
|
|
||||||
|
### 5.4 비결정적 평가 (Nondeterministic Evaluation, amb)
|
||||||
|
|
||||||
|
**amb 연산자**: 여러 선택지 중 하나를 비결정적으로 선택. 선택이 실패하면 자동으로 다음 선택지로 백트래킹.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 피타고라스 세 쌍 찾기
|
||||||
|
(let ((a (amb 1 2 3 4 5))
|
||||||
|
(b (amb 1 2 3 4 5)))
|
||||||
|
(require (= (* a a) (+ (* b b) 1)))
|
||||||
|
(list a b))
|
||||||
|
```
|
||||||
|
|
||||||
|
**구현**: 실행 프로시저를 **연속 전달 스타일(CPS, continuation-passing style)**로 재표현.
|
||||||
|
|
||||||
|
분석 단계는 변경 없음. 실행 프로시저가 `succeed`와 `fail` 두 연속을 인수로 받음:
|
||||||
|
- `succeed(value, fail-again)`: 값이 있을 때 성공 연속 호출
|
||||||
|
- `fail()`: 실패 시 실패 연속 호출로 백트래킹
|
||||||
|
|
||||||
|
**amb 분석**:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define (analyze-amb expression)
|
||||||
|
(let ((cfns (map analyze (amb-choices expression))))
|
||||||
|
(lambda (env succeed fail)
|
||||||
|
(let loop ((cfns cfns))
|
||||||
|
(if (null? cfns)
|
||||||
|
(fail)
|
||||||
|
((car cfns) env succeed
|
||||||
|
(lambda () (loop (cdr cfns)))))))))
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.5 연속의 노출 (call/cc)
|
||||||
|
|
||||||
|
CPS 구조는 연속을 명시적으로 사용하게 만든다. Scheme의 `call/cc`(call-with-current-continuation)는 현재 연속을 캡처하여 제공한다.
|
||||||
|
|
||||||
|
`call/cc`만으로 amb를 직접 Scheme에서 구현 가능:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define (amb . choices)
|
||||||
|
(call/cc
|
||||||
|
(lambda (k)
|
||||||
|
(for-each (lambda (choice)
|
||||||
|
(call/cc (lambda (next)
|
||||||
|
(set! *fail* next)
|
||||||
|
(k choice))))
|
||||||
|
choices)
|
||||||
|
(*fail*))))
|
||||||
|
```
|
||||||
|
|
||||||
|
이는 인터프리터/컴파일러 시스템 없이 Scheme 자체 기능으로 amb의 능력을 얻는 방법이다.
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "One of the best ways to attack a problem is to make up a domain-specific language in which the solution is easily expressed... We believe that programmers should know how to escape the confines of whatever programming language they must use by making an interpreter for a language that is more appropriate for expressing the solution to the current problem."
|
||||||
|
|
||||||
|
> "Remarkably, [adding amb] requires no change to the analysis part of the evaluator. The only change required is in the format of the execution procedures, which are re-expressed in continuation-passing style."
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch2-dsl]] — DSL 구축의 궁극적 도구로서의 인터프리터
|
||||||
|
- [[SDF-ch3-generic-procedures]] — g:eval이 제네릭 프로시저로 구현됨
|
||||||
|
- [[SDF-ch4-pattern-matching]] — 패턴 매처가 인터프리터 분석 단계에 활용
|
||||||
|
- [[SDF-ch7-propagation]] — amb의 의존성 지향 백트래킹으로 발전
|
||||||
|
- [[SDF-overview]]
|
||||||
107
wiki/sources/SDF-ch6-layering.md
Normal file
107
wiki/sources/SDF-ch6-layering.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
title: "Ch6: Layering"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 6
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch6: Layering
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
**레이어링(layering)**은 데이터와 프로시저 모두를 여러 계층으로 구성하여, 기존 프로그램을 수정하지 않고 메타데이터를 병렬로 처리하는 기법이다. 수치 데이터에 단위(units)를 첨부하거나, 결과에 출처(provenance) 정보를 추적하는 것처럼, 기본 계층의 계산에 영향을 주지 않으면서 부가 계층을 독립적으로 처리할 수 있다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 6.1 레이어링 사용
|
||||||
|
|
||||||
|
각 데이터 항목은 여러 계층의 정보를 담은 **레이어드 데이텀(layered datum)**이다:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define G
|
||||||
|
(layered-datum 6.67408e-11
|
||||||
|
unit-layer (unit 'meter 3 'kilogram -1 'second -2)
|
||||||
|
support-layer (support-set 'CODATA-2018)))
|
||||||
|
```
|
||||||
|
|
||||||
|
`F = G * m1 * m2 / r^2`를 계산할 때:
|
||||||
|
- 기본 계층: 수치 계산 수행
|
||||||
|
- 단위 계층: 단위 자동 검사 및 전파
|
||||||
|
- 지원 계층: 사용된 데이터 출처 자동 수집
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(pp (F M-earth M-Moon a-moon))
|
||||||
|
; (base-layer 1.9805035857209e20)
|
||||||
|
; (unit-layer (unit kilogram 1 meter 1 second -2))
|
||||||
|
; (support-layer (support-set Wieczorek-2006 NASA-2006 ...))
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 레이어링 구현
|
||||||
|
|
||||||
|
**두 핵심 컴포넌트**:
|
||||||
|
|
||||||
|
1. **레이어드 데이텀**: 계층 이름 → 값의 연관 구조. 특수 이름으로 기본 계층을 식별.
|
||||||
|
|
||||||
|
2. **레이어드 프로시저**: 각 계층을 (다소) 독립적으로 처리하는 향상된 프로시저.
|
||||||
|
|
||||||
|
**레이어 이름**: 변수로 레이어를 참조하여 사용자 인터페이스를 구현 세부사항에서 분리.
|
||||||
|
|
||||||
|
**제네릭 프로시저와의 관계**: 레이어링은 제네릭 프로시저와 밀접하게 관련되나 새로운 관점을 더한다. 각 레이어는 해당 레이어의 데이터에 대한 자체 프로시저를 가지며, 기본 계층의 코드는 다른 레이어의 존재를 전혀 모른다.
|
||||||
|
|
||||||
|
### 6.3 단위 레이어
|
||||||
|
|
||||||
|
**단위 산술**: SI 단위를 차원(dimension)으로 표현하고, 연산 시 단위를 자동으로 결합/검사.
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(unit 'meter 3 'kilogram -1 'second -2) ; m³/(kg·s²)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 곱셈: 각 차원의 지수를 더함
|
||||||
|
- 나눗셈: 각 차원의 지수를 뺌
|
||||||
|
- 덧셈: 단위가 동일한지 검사 (불일치 시 오류)
|
||||||
|
|
||||||
|
기본 계층의 수치 프로시저(`F = G*m1*m2/r²`)는 단위를 전혀 알지 못하지만, 레이어드 프로시저는 단위 계층을 자동으로 처리한다.
|
||||||
|
|
||||||
|
### 6.4 의존성 추적 레이어
|
||||||
|
|
||||||
|
**출처/의존성(support) 레이어**: 각 값이 어떤 원시 소스에서 파생되었는지 추적.
|
||||||
|
|
||||||
|
- 연산의 결과 의존성 = 모든 피연산자의 의존성의 합집합
|
||||||
|
- 값의 출처를 자동으로 추적하여 설명(explanation)과 디버깅에 활용
|
||||||
|
|
||||||
|
이 레이어는 Chapter 7의 의존성 지향 백트래킹(dependency-directed backtracking)의 기반이 된다.
|
||||||
|
|
||||||
|
### 6.5 레이어링의 설계 원칙
|
||||||
|
|
||||||
|
**관심사의 분리**: 아키텍처의 "served spaces"(기본 계산)와 "servant spaces"(단위, 의존성 등 메타데이터)를 분리.
|
||||||
|
|
||||||
|
- 기본 코드: 원래의 수치 계산만 담당
|
||||||
|
- 레이어 처리 코드: 기본 코드와 무관하게 독립적으로 개발
|
||||||
|
- 새 레이어 추가: 기존 코드 변경 없음
|
||||||
|
|
||||||
|
**aspect-oriented programming과의 비교**: AOP(관점 지향 프로그래밍)는 "횡단 관심사(cross-cutting concerns)"를 분리하려는 시도. 레이어링은 더 구조적인 방법으로 동일한 목표를 달성.
|
||||||
|
|
||||||
|
**레이어링이 가능한 것들**:
|
||||||
|
- 수치 정밀도 선언
|
||||||
|
- 타입 정보 (컴파일러용)
|
||||||
|
- 단언(assertions)/사전조건/사후조건
|
||||||
|
- 대안 구현 제안 (퇴화성 지원)
|
||||||
|
- 의존성/출처 추적
|
||||||
|
- 로깅
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "Both the data and the procedures that process it will be made up of multiple layers that enable additive annotation without introducing clutter."
|
||||||
|
|
||||||
|
> "The processing of the underlying data is not affected by the metadata, and the code for processing the underlying data does not even know about or reference the metadata. However, the metadata is processed by its own procedures, effectively in parallel with the data."
|
||||||
|
|
||||||
|
> "The decoration of a value is a generalization of the tagging used to support extensible generic operations."
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch1-flexibility]] — 관심사 분리 원칙 (served/servant spaces)
|
||||||
|
- [[SDF-ch2-dsl]] — 래퍼 개념의 확장
|
||||||
|
- [[SDF-ch3-generic-procedures]] — 레이어링의 기술적 기반
|
||||||
|
- [[SDF-ch7-propagation]] — 의존성 레이어가 전파 시스템의 핵심 재료
|
||||||
|
- [[SDF-overview]]
|
||||||
122
wiki/sources/SDF-ch7-propagation.md
Normal file
122
wiki/sources/SDF-ch7-propagation.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
---
|
||||||
|
title: "Ch7: Propagation"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: 7
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ch7: Propagation
|
||||||
|
|
||||||
|
## 핵심 아이디어
|
||||||
|
|
||||||
|
**전파 모델(propagator model)**은 폰 노이만 순차적·방향성 계산 패러다임에서 벗어나, 공유 셀(cells)로 연결된 자율적 전파기(propagators)들이 부분 정보를 축적하고 전파하는 다방향 계산 모델이다. 레이어링을 통한 의존성 추적과 결합하면 **의존성 지향 백트래킹(dependency-directed backtracking)**이 가능해져 대규모·복잡한 시스템의 탐색 공간을 크게 줄인다.
|
||||||
|
|
||||||
|
## 주요 개념
|
||||||
|
|
||||||
|
### 전파 모델의 핵심 구조
|
||||||
|
|
||||||
|
- **셀(cell)**: 정보를 축적하는 공유 저장소. 새 정보가 추가되면 기존 정보와 병합.
|
||||||
|
- **전파기(propagator)**: 셀에서 정보를 읽고, 계산하여, 다른 셀에 정보를 추가하는 자율 기계.
|
||||||
|
- 전파기들은 **독립적**이며, 연결된 셀에 정보가 변경될 때마다 활성화.
|
||||||
|
|
||||||
|
기존 언어: 값이 표현식 트리를 통해 위쪽으로 스며오름(percolating up).
|
||||||
|
전파 모델: 값이 **배선도(wiring diagram)**를 통해 다방향으로 전파.
|
||||||
|
|
||||||
|
### 7.1 응용 예시: 별까지의 거리
|
||||||
|
|
||||||
|
시차(parallax)와 거리 간의 쌍방향 제약:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(define-c:prop (c:parallax<->distance parallax distance)
|
||||||
|
(let-cells (t (AU AU-in-parsecs))
|
||||||
|
(c:tan parallax t)
|
||||||
|
(c:* t distance AU)))
|
||||||
|
```
|
||||||
|
|
||||||
|
`c:*`은 세 셀 사이의 곱셈 제약을 강제하는 양방향 전파기를 구성한다:
|
||||||
|
- `p:*`: product = factor1 * factor2
|
||||||
|
- `p:/`: factor1 = product / factor2 (역방향)
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; 별까지의 거리 계산
|
||||||
|
(define-cell Vega-parallax-distance)
|
||||||
|
(define-cell Vega-parallax)
|
||||||
|
(c:parallax<->distance Vega-parallax Vega-parallax-distance)
|
||||||
|
|
||||||
|
;; 두 가지 독립적 측정값 제공
|
||||||
|
(tell! Vega-parallax (+->interval ...) 'FGWvonStruve1837)
|
||||||
|
(tell! Vega-parallax-distance (+->interval ...) 'HipparcosSatellite)
|
||||||
|
|
||||||
|
;; 시스템이 두 값을 결합하여 더 정확한 추정치 계산
|
||||||
|
```
|
||||||
|
|
||||||
|
### 부분 정보와 구간 산술
|
||||||
|
|
||||||
|
셀은 구간(interval)을 값으로 가질 수 있으며, 새 정보가 추가될 때 구간의 교집합을 취함:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(make-interval lower upper)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 두 독립적 추정값의 구간을 교집합 취함 → 더 좁은 구간 (더 정확한 추정)
|
||||||
|
- 구간이 비어 있으면 모순 감지
|
||||||
|
|
||||||
|
### 의존성 추적과 전제 (Premises)
|
||||||
|
|
||||||
|
레이어링의 의존성 레이어를 전파 모델에 통합. 각 값은 그것을 지지하는 **전제(premises)**의 집합을 동반:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(tell! Vega-parallax interval 'FGWvonStruve1837)
|
||||||
|
;; 'FGWvonStruve1837 이 전제(premise)
|
||||||
|
```
|
||||||
|
|
||||||
|
파생된 값은 그것의 전제들의 합집합을 전제 집합으로 가짐. 이를 통해:
|
||||||
|
- 어떤 소스가 특정 결론에 기여했는지 추적
|
||||||
|
- 모순(contradiction)이 발생하면 어떤 전제가 문제인지 특정
|
||||||
|
|
||||||
|
### 의존성 지향 백트래킹 (Dependency-Directed Backtracking)
|
||||||
|
|
||||||
|
**amb 기반 탐색의 문제**: 실패가 발생하면 무작정 직전 선택지로 돌아감 (연대기적 백트래킹). 이미 탐색한 공간을 다시 탐색하는 비효율.
|
||||||
|
|
||||||
|
**의존성 지향 백트래킹**:
|
||||||
|
1. 각 값이 의존하는 전제(가설)들을 추적
|
||||||
|
2. 모순 발생 시 모순의 원인이 된 전제들을 파악
|
||||||
|
3. 해당 전제들을 포함하는 선택지만 건너뜀 (다른 선택지는 재탐색 불필요)
|
||||||
|
|
||||||
|
이는 Chapter 5의 amb와 Chapter 6의 의존성 레이어링이 결합된 결과.
|
||||||
|
|
||||||
|
### 퇴화성과 다중 소스 (Degeneracy)
|
||||||
|
|
||||||
|
전파 모델은 **여러 독립적인 방법**으로 동일한 값을 추정하고 결합하는 것을 자연스럽게 지원한다 (Chapter 1의 퇴화성 원칙):
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
;; Vega까지의 거리를 두 가지 방법으로 추정:
|
||||||
|
;; 1. 시차 측정 (Struve)
|
||||||
|
;; 2. Hipparcos 위성 데이터
|
||||||
|
;; 전파 시스템이 두 추정값을 자동으로 결합
|
||||||
|
```
|
||||||
|
|
||||||
|
새 추정 방법을 추가하는 것은 새 전파기를 배선도에 추가하는 것으로, 기존 구성 요소를 변경하지 않는 **가산적(additive)** 확장이다.
|
||||||
|
|
||||||
|
### 배선도 언어의 특성
|
||||||
|
|
||||||
|
- 표현식 트리 대신 **배선도**로 계산 구조를 표현
|
||||||
|
- 부분 결과가 즉시 사용 가능 (최종 결과를 기다릴 필요 없음)
|
||||||
|
- 본질적으로 **병렬적, 분산적, 확장 가능**
|
||||||
|
- 강한 격리(isolation)와 병렬 계산 내장
|
||||||
|
|
||||||
|
## 핵심 인용
|
||||||
|
|
||||||
|
> "The propagator model is built on the idea that the basic computational elements are propagators, autonomous independent machines interconnected by shared cells through which they communicate. Each propagator machine continuously examines the cells it is connected to, and adds information to some cells based on computations it can make from information it can get from others."
|
||||||
|
|
||||||
|
> "The structure is additive: new ways to contribute information can be included just by adding new parts to a network, whether simple propagators or entire subnetworks."
|
||||||
|
|
||||||
|
> "Using layering, we incorporate dependencies into the propagator infrastructure in a natural and efficient way... Dependency tracking also provides a substrate for debugging."
|
||||||
|
|
||||||
|
## 관련 개념
|
||||||
|
|
||||||
|
- [[SDF-ch1-flexibility]] — 퇴화성 원칙과 부분 정보 결합의 완성형
|
||||||
|
- [[SDF-ch5-evaluation]] — amb의 의존성 지향 업그레이드
|
||||||
|
- [[SDF-ch6-layering]] — 의존성 레이어가 전파 시스템의 핵심
|
||||||
|
- [[SDF-overview]]
|
||||||
112
wiki/sources/SDF-overview.md
Normal file
112
wiki/sources/SDF-overview.md
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
title: "SDF: Software Design for Flexibility — 전체 개요"
|
||||||
|
tags: [source, SDF]
|
||||||
|
source: "Software Design for Flexibility, Hanson & Sussman (2021)"
|
||||||
|
chapter: overview
|
||||||
|
updated: 2026-04-30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Software Design for Flexibility — 전체 개요
|
||||||
|
|
||||||
|
## 서지 정보
|
||||||
|
|
||||||
|
- **저자**: Chris Hanson, Gerald Jay Sussman
|
||||||
|
- **출판**: MIT Press, 2021
|
||||||
|
- **부제**: How to Avoid Programming Yourself into a Corner
|
||||||
|
- **라이선스**: CC BY-SA 4.0
|
||||||
|
- **관련**: SICP의 고급 후속편으로 볼 수 있음
|
||||||
|
|
||||||
|
## 책의 핵심 주장
|
||||||
|
|
||||||
|
> "It would be nice if all we had to do to add a new feature to a program was to add some code, without changing the existing code base."
|
||||||
|
|
||||||
|
대부분의 소프트웨어는 요구사항 변화에 취약하게 설계된다. 이 책은 이 문제에 대한 대안으로 **가산적 프로그래밍(additive programming)**: 기존 코드를 수정하지 않고 코드를 추가해서 기능을 확장하는 스타일을 제안한다.
|
||||||
|
|
||||||
|
생물학적 시스템(진화적 적응성, 퇴화성, 탐색적 행동)에서 영감을 받은 설계 원칙들을 Scheme 코드로 구체화한다.
|
||||||
|
|
||||||
|
## 챕터별 핵심 주제
|
||||||
|
|
||||||
|
| 챕터 | 제목 | 핵심 기법 | 가산성 기여 |
|
||||||
|
|------|------|-----------|------------|
|
||||||
|
| 1 | Flexibility in Nature and in Design | 철학·원칙 | 전체 프레임워크 |
|
||||||
|
| 2 | Domain-Specific Languages | 컴비네이터, 래퍼, 도메인 모델 | 믹스앤매치 부품 |
|
||||||
|
| 3 | Variations on an Arithmetic Theme | 제네릭 프로시저, 자동 미분 | 핸들러 추가로 확장 |
|
||||||
|
| 4 | Pattern Matching | 패턴 매처, 단일화, 항 재작성 | 규칙 추가로 확장 |
|
||||||
|
| 5 | Evaluation | 인터프리터, lazy eval, amb, call/cc | 언어 자체를 확장 |
|
||||||
|
| 6 | Layering | 레이어드 데이터/프로시저 | 수정 없이 메타데이터 추가 |
|
||||||
|
| 7 | Propagation | 전파기, 의존성 백트래킹 | 배선도에 전파기 추가 |
|
||||||
|
|
||||||
|
## 기법들의 관계
|
||||||
|
|
||||||
|
```
|
||||||
|
가산적 프로그래밍 (Ch1 철학)
|
||||||
|
│
|
||||||
|
├── 컴비네이터/DSL (Ch2) ──────── 도메인 특화 언어의 기반
|
||||||
|
│ │
|
||||||
|
│ └── 컴비네이터 한계 → 제네릭 프로시저 (Ch3)
|
||||||
|
│ │
|
||||||
|
│ 자동 미분 (Ch3.3)
|
||||||
|
│
|
||||||
|
├── 패턴 매칭 (Ch4) ──────────── 항 재작성, 타입 추론
|
||||||
|
│ │
|
||||||
|
│ └── 단일화 → 부분 정보 결합
|
||||||
|
│
|
||||||
|
├── 인터프리터 (Ch5) ──────────── 언어 설계의 완전한 자유
|
||||||
|
│ │
|
||||||
|
│ └── amb → 비결정적 탐색
|
||||||
|
│
|
||||||
|
├── 레이어링 (Ch6) ─────────────── 수정 없는 메타데이터 추가
|
||||||
|
│ │
|
||||||
|
│ └── 의존성 레이어
|
||||||
|
│ │
|
||||||
|
└── 전파 모델 (Ch7) ─────────────── 다방향 제약 + 의존성 백트래킹
|
||||||
|
```
|
||||||
|
|
||||||
|
## 공통 테마
|
||||||
|
|
||||||
|
### 가산성 (Additivity)
|
||||||
|
모든 기법은 기존 코드를 수정하지 않고 새 기능을 추가하는 방식을 제공:
|
||||||
|
- Ch2: 컴비네이터에 새 부품 추가
|
||||||
|
- Ch3: 제네릭 프로시저에 새 핸들러 추가
|
||||||
|
- Ch4: 규칙 시스템에 새 규칙 추가
|
||||||
|
- Ch5: 인터프리터에 새 표현식 타입 추가
|
||||||
|
- Ch6: 데이터에 새 레이어 추가
|
||||||
|
- Ch7: 배선도에 새 전파기 추가
|
||||||
|
|
||||||
|
### 부분 정보 (Partial Information)
|
||||||
|
여러 챕터에서 부분적으로 알려진 정보를 결합하여 더 완전한 답을 얻는 패턴이 반복된다:
|
||||||
|
- Ch4: 단일화로 타입 제약 결합
|
||||||
|
- Ch7: 구간 값과 전제를 가진 값들의 결합
|
||||||
|
|
||||||
|
### 관심사의 분리 (Separation of Concerns)
|
||||||
|
- Ch1: served spaces vs. servant spaces (아키텍처 유추)
|
||||||
|
- Ch2: 도메인 모델 / 제어 구조 / 게임 규칙 분리
|
||||||
|
- Ch3: 디스패치 전략을 dispatch-store로 분리
|
||||||
|
- Ch6: 기본 계산과 메타데이터 처리 분리
|
||||||
|
|
||||||
|
## 사용 언어: Scheme
|
||||||
|
|
||||||
|
Scheme을 선택한 이유:
|
||||||
|
1. 최소한의 문법 (자연스러운 파스 트리 표현)
|
||||||
|
2. 허용적(permissive) 언어 — 산술 연산자의 동적 재정의 가능
|
||||||
|
3. first-class 프로시저, 렉시컬 스코핑
|
||||||
|
4. reified continuations (call/cc)
|
||||||
|
5. 동적 바인딩
|
||||||
|
|
||||||
|
정적 타입 시스템은 의도적으로 배제 — 유연성 전략의 지적 탐색을 저해하기 때문.
|
||||||
|
|
||||||
|
## 저자들의 배경
|
||||||
|
|
||||||
|
- Gerald Jay Sussman: Scheme 공동 창시자, MIT 교수, SICP 공저자
|
||||||
|
- Chris Hanson: MIT/GNU Scheme 주요 개발자, Google/Datera 경력
|
||||||
|
- 합산 100년 이상의 프로그래밍 경험
|
||||||
|
|
||||||
|
## 챕터별 wiki 페이지
|
||||||
|
|
||||||
|
- [[SDF-ch1-flexibility]] — Ch1: Flexibility in Nature and in Design
|
||||||
|
- [[SDF-ch2-dsl]] — Ch2: Domain-Specific Languages
|
||||||
|
- [[SDF-ch3-generic-procedures]] — Ch3: Variations on an Arithmetic Theme
|
||||||
|
- [[SDF-ch4-pattern-matching]] — Ch4: Pattern Matching
|
||||||
|
- [[SDF-ch5-evaluation]] — Ch5: Evaluation
|
||||||
|
- [[SDF-ch6-layering]] — Ch6: Layering
|
||||||
|
- [[SDF-ch7-propagation]] — Ch7: Propagation
|
||||||
Reference in New Issue
Block a user