Common Lisp에 Clojure 바람의 네임스페이스 설치
이 기구는
in-pacakge
, import
, export
를 사용하여 기호의 명칭 공간을 관리하는 표를 조작한다.평소 Common Lisp
defpacakge
에 매크로를 사용하여 네임스페이스를 관리합니다.이것은 상술한 함수의 자물쇠로 동작하고 있다.
Common Lisp에는 이미 관리 공간이 있습니다.
나는 이곳에서 반드시 명공간 관리 시스템을 교육 목적으로 실시해야 한다고 생각한다.
언뜻 보면 이름 공간은 프로그래밍 언어의 기초를 구성하는 개념이다.
나는 사용자가 다시 낮은 수준의 조작을 실시할 수 있을지 의심할 수도 있다.
원래 네임스페이스를 사용하는 이유가 뭘까요?
기호 간의 기호 이름 충돌을 피하기 위해서다.
기호에 다른 접두사를 붙이면 충돌을 피할 수 있다는 것이다.
다음 코드는 함수를 덮어써서 이름 공간이 충돌합니다.
(defun hello () (print 'nihao))
(defun hello () (print 'konnichiwa))
따라서 접두사 추가를 피할 수 있습니다.(defun chinese/hello () (print 'nihao))
(defun japanese/hello () (print 'konnichiwa))
에서 기호를 정의할 때마다 접두사를 붙이면 해결됩니다.이것은 정말 지루한 규칙이며, 접두사를 붙이는 것은 원본 코드를 쓰는 사람의 책임이다.
따라서 명명 공간을 해결한다. 즉, 최근에 정의된 명명 공간에 기호를 붙이고 함수를 준비한다.
(defun resolve (stream char)
(declare (ignore char))
(read-char stream t nil t)
;; シンボルをストリームから取得する
(let ((sym (read stream t nil t)))
;; シンボルに`*package*`をプレフィックスとしてつける。
(intern (format nil "~a/~a" *package* sym))))
이것을 읽기 매크로로 읽기 매크로에 로그인하면 ~/hello
*package*/hello
로 처리됩니다.참고로 이것은 읽을 때 해결된 것이기 때문에 원본 코드로 실행할 때 이미 접두사를 붙였다
상징적인 장치입니다.
그러니까 아까 코드는 아래와 같다는 거야.
(defparameter *package* 'chinese)
(defun ~/hello () (print 'nihao))
(~/hello) ;; => nihao
(defparameter *package* 'japanese)
(defun ~/hello () (print 'konnichiwa))
(~/hello) ;; => konnichiwa
이것만으로도 상당히 포장 관리 스타일을 가진 구조가 형성되었다.그러나 이 시스템은 이름 공간 이외의 함수를 호출할 때 접두사를 붙여야 한다.
(japanese/hello) ;; => konnichiwa
(chinsese/hello) ;; => nihao
따라서 우리는 명명 공간 이외의 함수를 Import로 하는 메커니즘을 고려한다.다행히도 Common Lisp에서 코드
(setf (fdefinition 'f) #'g)
의 함수g
의 정의f
매크로 사용(defparameter *package* 'japanese)
(import-functions chinese hello)
전개(setf (fdefinition 'japanese/hello) #'chinese/hello)
를 고려하면 다음과 같다.(defmacro import (package &rest symbols)
(when symbols
`(progn
(setf (fdefinition ',(intern (format nil "~a/~a" spack/*package* (car symbols))))
#',(intern (format nil "~a/~a" package (car symbols))))
(import ,package ,@(cdr symbols)))))
간단한 네임스페이스 작업을 위한 패키지를 준비합니다.(deparameter spack/*package* 'spack)
(defmacro spack/defpackage (package)
`(defparameter spack/*package* ',package))
(defun spack/resolve (stream char)
(declare (ignore char))
(read-char stream t nil t)
(let ((sym (read stream t nil t)))
(intern (format nil "~a/~a" spack/*package* sym))))
(set-macro-character #\~ #'spack/resolve)
(defmacro spack/import (package &rest symbols)
(when symbols
`(progn
(setf (fdefinition ',(intern (format nil "~a/~a" spack/*package* (car symbols))))
#',(intern (format nil "~a/~a" package (car symbols))))
(spack/import ,package ,@(cdr symbols)))))
이걸 사용하면 다음과 같이 명명 공간을 분리한 소프트웨어를 개발할 수 있다.(spack/defpackage example-lib)
(defvar ~/pi 3.141592)
(defun ~/sayhello ()
(print ~/pi))
(spack/defpackage example-main)
(spack/import example-lib sayhello)
(~/sayhello)
이름 공간이라는 낮은 수준의 작업은 리더 매크로보다 낮은 수준의 API를 사용한다면쉽게 구현할 수 있는 프레젠테이션입니다.
Reference
이 문제에 관하여(Common Lisp에 Clojure 바람의 네임스페이스 설치), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/dog/articles/6a6ce081796fb6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)