CL: Odczytuje komunikaty na podstawie tabeli czytelnej związanej z CL: * READTABLE * w momencie uruchomienia wywołania READ. Pod maską ENABLE-INTERPOL-SYNTAX tworzy nowy readtable, ustawiając CL: * READTABLE *, aby go zatrzymać, i przechowuje starą wartość CL: * READTABLE *. DISABLE-INTERPOL-SYNTAX anuluje poprzedni odczyt i ustawia CL: * READTABLE * aby ponownie go przytrzymać. Minimalnie zmienia swoją pierwotną konfigurację, można zorganizować dla zachowania chciałeś brzmienie:
(in-package :cl-user)
(eval-when (:compile-toplevel :load-toplevel :execute)
(require :cl-interpol))
(cl-interpol:enable-interpol-syntax)
(defvar *interpol-reader* *readtable*)
(cl-interpol:disable-interpol-syntax)
(defun read-and-eval (s)
(let ((*readtable* *interpol-reader*))
(eval (read-from-string s))))
wywołanie wyłączyć składni może być umieszczony w dowolnym miejscu po defvar i odczytu i eval będzie nadal działać, ale jeśli chcesz bezpośrednio wprowadzić składnię interpolacji w pliku, którą składnia będzie musiała zostać umieszczona między włączaniem i wyłączaniem wywołań. W tym ostatnim celu ważne jest, że wywołania interpolowe rozszerzają się na KIERDĘ EVAL, z tego samego powodu, dla którego twoje wezwanie do POWTARZANIA musi znajdować się w punkcie GŁÓWNY; to znaczy, efekty muszą się już zdarzyć, gdy te ostatnie formularze są READ. Interfejs
CL-Interpolu abstrakty, co się dzieje, więc pokażę wam jak można ręcznie tworzyć i zmieniać readtable:
;; Create a fresh readtable with standard syntax
(defvar *not-readtable* (copy-readtable nil))
;; A simple reader function
(defun not-reader (stream char &optional count)
"Like ' but for (not ...) instead of (quote ...)"
(declare (ignore count char))
`(not ,(read stream t nil t)))
;; Mutate that readtable so that the dispatch character you want
;; calls the function you want
(set-macro-character #\! 'not-reader nil *not-readtable*)
;; Try it out
(let ((*readtable* *not-readtable*))
(read-from-string "(if !foo bar baz)"))
=>
(IF (NOT FOO)
BAR
BAZ)