생각해 볼 질문
하나의 중앙 조건식을 다시 열지 않고 범용 시스템에 새 표현이나 연산을 어떻게 더할 수 있을까요? 프로시저를 명시적인 연산·타입 키 아래 저장하기 패키지 설치와 나중 범용 적용을 분리하기 표현별 메서드에는 태그를 벗긴 내용만 넘기기 apply-generic을 바꾸지 않고 두 번째 표현 추가하기 안정된 클라이언트 코드와 표의 성장으로 가산성 관찰하기 각 설치 프로시저는 한 표현의 세부를 소유하고 메서드 네 개를 등록합니다. apply-generic은 타입 태그를 읽고 메서드를 찾고 내용만 넘기는 방법만 압니다. rectangular 내용은 x 다음 y를 저장하고 swapped 내용은 y 다음 x를 저장합니다. 두 패키지는 같은 real-part, imag-part, magnitude-squared, 생성자 프로토콜을 만족합니다.
두 번째 프로그램은 integer 설명 메서드 하나로 시작합니다. rational 값은 처음에는 no-method를 만듭니다. 표 항목 하나를 더 설치하면 같은 describe 디스패처가 그 값을 받아들이며 디스패처나 integer 패키지는 수정하지 않습니다. 여기서 가산성은 새 키 아래 메서드를 등록하는 명시적이고 유한한 확장입니다.
SICP 코드 UTF-8 2,221 / 1,048,576바이트
( begin
( define operation-table ' ( ) )
( define ( put operation type procedure )
( set! operation-table
( cons ( list operation type procedure )
operation-table ) )
' ok )
( define ( get operation type )
( define ( scan records )
( cond ( ( null? records ) #f )
( ( and ( eq? operation ( car ( car records ) ) )
( eq? type ( cadr ( car records ) ) ) )
( caddr ( car records ) ) )
( else ( scan ( cdr records ) ) ) ) )
( scan operation-table ) )
( define ( attach-tag type contents ) ( cons type contents ) )
( define ( type-tag datum ) ( car datum ) )
( define ( contents datum ) ( cdr datum ) )
( define ( apply-generic operation datum )
( let ( ( method ( get operation ( type-tag datum ) ) ) )
( if method
( method ( contents datum ) )
' no-method ) ) )
( define ( make-from-real-imag type x y )
( ( get ' make-from-real-imag type ) x y ) )
( define ( install-rectangular-package )
( put ' real-part ' rectangular car )
( put ' imag-part ' rectangular cdr )
( put ' magnitude-squared ' rectangular
( lambda ( z )
( + ( * ( car z ) ( car z ) )
( * ( cdr z ) ( cdr z ) ) ) ) )
( put ' make-from-real-imag ' rectangular
( lambda ( x y )
( attach-tag ' rectangular ( cons x y ) ) ) )
' done )
( define ( install-swapped-package )
( put ' real-part ' swapped cdr )
( put ' imag-part ' swapped car )
( put ' magnitude-squared ' swapped
( lambda ( z )
( + ( * ( cdr z ) ( cdr z ) )
( * ( car z ) ( car z ) ) ) ) )
( put ' make-from-real-imag ' swapped
( lambda ( x y )
( attach-tag ' swapped ( cons y x ) ) ) )
' done )
( install-rectangular-package )
( define first-count ( length operation-table ) )
( install-swapped-package )
( define rectangular
( make-from-real-imag ' rectangular 3 4 ) )
( define swapped
( make-from-real-imag ' swapped 3 4 ) )
( list first-count
( length operation-table )
( type-tag rectangular )
( type-tag swapped )
( apply-generic ' real-part rectangular )
( apply-generic ' imag-part rectangular )
( apply-generic ' magnitude-squared rectangular )
( apply-generic ' real-part swapped )
( apply-generic ' imag-part swapped )
( apply-generic ' magnitude-squared swapped ) ) ) 코드 실행Ctrl/⌘ Enter 파일 열기 코드 저장 코드 복사 편집기 지우기
예제 하나의 범용 인터페이스 뒤에 표현 두 개 설치하기 디스패처를 고치지 않고 메서드 추가하기
실행은 브라우저 안에서 이루어지며 프로그램 결과와 실행 추적을 보여줍니다. 예상 결과 패키지 프로그램은 (4 8 rectangular swapped 3 4 25 3 4 25)를 반환합니다. 가산 확장 프로그램은 ((integer 7) no-method (fraction 3 2) 2)를 반환합니다.
실행 추적에서 볼 점 설치 시점의 put 호출과 나중 get·메서드 적용을 분리하세요. swapped를 설치할 때 apply-generic이 바뀌지 않는지 확인하세요. 두 번째 프로그램에서는 새 표 항목 하나가 생기기 전과 뒤의 rational 조회를 비교하세요.
직접 해보기 프로그램을 수정하고 결과를 비교해 보세요. 내용에 x+10과 y+10을 저장하는 translated 표현을 추가하세요. 변환을 되돌리는 선택자를 설치하고 기존 범용 클라이언트가 여전히 3, 4, 25를 관찰하는지 확인하세요.
힌트 보기 이동은 새 생성자와 메서드 안에만 두고 apply-generic에 타입 조건을 추가하지 마세요.