(Lispex)sicp.io
2.7 · 데이터 지향 디스패치

타입 태그가 표현에 맞는 연산을 고른다.

범용 인터페이스는 연산 이름과 데이터 타입을 하나의 키로 묶어 호출하는 곳마다 분기하지 않고 표에서 맞는 프로시저를 찾을 수 있습니다.

생각해 볼 질문

연산 표는 서로 다른 표현에서도 하나의 인터페이스를 어떻게 유지할까요?

  • 표현 내용에 명시적인 타입 태그 붙이기
  • 연산과 타입 순서쌍을 디스패치 키로 사용하기
  • 직교형과 극형의 magnitude 공식을 따로 두기
  • 두 표현에 같은 범용 magnitude 인터페이스 호출하기

표의 각 항목은 (magnitude type) 키와 그 타입의 내용만 이해하는 프로시저를 짝지어 둡니다. 직교형 프로시저는 x²+y²의 제곱근을 계산하고 극형 프로시저는 저장된 반지름을 읽습니다.

apply-generic은 get이 맞는 프로시저를 고른 뒤에야 태그를 떼고 내용만 넘깁니다. 사용하는 코드는 magnitude와 태그가 붙은 데이터만 주면 되며 어떤 표현인지 직접 묻지 않습니다. 새 표현을 더할 때 바뀌는 곳은 범용 인터페이스가 아니라 표입니다.

리스펙스 · SICP 코드SICP에 필요한 Scheme 호환 문법을 리스펙스 SICP 프로필로 실행합니다.
(begin
  (define operation-table
    (list
      (cons (list 'magnitude 'rectangular)
            (lambda (contents)
              (sqrt (+ (* (car contents) (car contents))
                       (* (cadr contents) (cadr contents))))))
      (cons (list 'magnitude 'polar)
            (lambda (contents) (car contents)))))
  (define (get operation type table)
    (cond ((null? table) #f)
          ((and (eq? operation (car (car (car table))))
                (eq? type (cadr (car (car table)))))
           (cdr (car table)))
          (else (get operation type (cdr table)))))
  (define (attach-tag type contents) (cons type contents))
  (define (apply-generic operation object)
    (let ((procedure (get operation (car object) operation-table)))
      (procedure (cdr object))))
  (list
    (apply-generic 'magnitude
                   (attach-tag 'rectangular (list 3.0 4.0)))
    (apply-generic 'magnitude
                   (attach-tag 'polar (list 5.0 0.0)))))
리스펙스 학습용 런타임리스펙스 SICP 프로필 1.0.0
리스펙스 SICP 런타임 불러오는 중
리스펙스 · SICP 코드UTF-8 969 / 1,048,576바이트
예제
결과
출력
진단
보이는 실행 흐름0 / 0 개의 실행 이벤트
    이 브라우저 결과는 리스펙스 바우치나 권한이 아닙니다.wasm —
    예상 관찰

    첫 프로그램은 (5.0 5.0)을 반환합니다. 두 번째 프로그램은 (13.0 13.0)을 반환합니다.

    실행 흐름에서 볼 점

    apply-generic이 선택한 프로시저에 내용만 넘기기 전에 get이 연산과 타입 키를 비교하는 과정을 따라가세요. 직교형 실행은 sqrt에 닿고 극형 실행은 첫 내용 필드를 반환합니다. 제한된 실행 흐름은 선택한 이번 실행만 설명하며 리스펙스 바우치나 권한이 아닙니다.

    직접 해보기

    힌트를 보기 전에 프로그램을 바꿔 보세요.

    linear라는 1차원 표현의 magnitude 항목을 추가한 뒤 기존 apply-generic을 바꾸지 않고 저장 길이 9.0을 실행하세요.

    힌트 하나 보기

    새 키는 (magnitude linear)입니다. 프로시저는 내용의 첫 필드를 반환하면 됩니다.