运行试图输出Javascript代码的公共lisp宏时,键入错误.为什么



我刚开始学习通用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;"

知道我做错了什么吗?

,(loop for e in contents collect `(conc output …))

这会返回一个列表:

((conc output …)
(conc output …)
…)

通过将运算符(列表的第一个元素(应用于参数来计算列表。

有效的运算符仅为符号或lambda形式。conc表单作为运算符无效。很可能你想要这样的东西:

(progn
(conc output …)
…)

顺便说一句,我不知道你的JavaScript输出到底应该做什么。它忽略了ns参数,并设置了两个新的全局变量。这似乎没有用。

最新更新