Я только начал изучать общий lisp, и я пытаюсь использовать его так, чтобы облегчить мою повседневную работу. В частности, я пытаюсь создать набор функций и макросов, который использует минимальный синтаксис и выводит некоторый JavaScript, который я часто использую.
Это код, который я написал:
;;;; This program is aimed at creating a very high level language that writes
;;;; complex and formally correct Javascript with minimal code.
(defvar *namespace* nil)
(defmacro conc (var &body body)
`(setf ,var (concatenate 'string output ,@body)))
(defun public-var (name value)
(let ((output ""))
(conc output *namespace* "." name " = " value ";")
output))
(defmacro namespace (ns &rest contents)
`(let ((*namespace* (concatenate 'string "window." ,ns)) (output ""))
(conc output "(function(ns){")
(let ((*namespace* "ns"))
,(loop for e in contents collect `(conc output (apply ,(first e) (list ,@(rest e))))))
(conc output "}(" *namespace* " = " *namespace* " || {}));")
output))
Идея состоит в том, чтобы иметь возможность писать такой код:
(namespace "namespace"
(#'public-var "hello" "world")
(#'public-var "something" "else"))
и получить этот вывод:
(function(ns){
ns.hello = world;
ns.something = else;
}(window.namespace = window.namespace || {}));
Я знаю, что мне все еще нужно поработать над отступом вывода и разрывами строк, но это еще не главное (это должны быть первые строительные блоки для абстрагирования более сложной логики). Проблема в том, что я получаю эту ошибку, и я не могу понять, почему (серьезно, я уже часами исследовал и пробовал разные вещи):
Illegal function object:
(CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))).
[Condition of type TYPE-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [ABORT] Abort entirely from this (lisp) process.
Backtrace:
0: (IDE.BASE::IDE-INVOKE-DEBUGGER-FROM-NON-CG-PROCESS "Error" #<TYPE-ERROR @ #x22de54b2> T NIL NIL)
1: (ERROR TYPE-ERROR :DATUM (CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))) :EXPECTED-TYPE (OR SYMBOL FUNCTION) ...)
2: ((CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))))
3: (LET ((*NAMESPACE* "ns")) ((CONC OUTPUT (APPLY #'PUBLIC-VAR #))))
4: (LET ((*NAMESPACE* (CONCATENATE 'STRING "window." "webtrekk_dl")) (OUTPUT "")) ..)
5: (EVAL (NAMESPACE "webtrekk_dl" (#'PUBLIC-VAR "ciao" "mondo")))
--more--
Я также пробовал отдельные части. Например это:
(let ((output "")) (CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))))
работает и дает мне этот вывод:
".ciao = mondo;"
Любая идея, что я делаю неправильно?
macroexpand-1
иpprint
для просмотра макрорасширения вашего примера(namespace ...)
. Тогда вы легко увидите ошибку. - person Rainer Joswig   schedule 05.11.2018