我刚刚开始学习普通口唇症,并且正在尝试以一种使我的日常工作更轻松的方式进行锻炼。特别是,我试图创建一组函数和宏,它们使用最少的语法并输出一些我经常使用的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;"
知道我在做什么错吗?
答案 0 :(得分:2)
,(loop for e in contents collect `(conc output …))
这将返回一个列表:
((conc output …)
(conc output …)
…)
通过将运算符(即列表的第一个元素)应用于参数来评估列表。
有效运算符只是符号或lambda形式。 conc
表单作为运算符无效。您最有可能想要以下内容:
(progn
(conc output …)
…)
请注意,我不知道您的JavaScript输出真正应该做什么。它忽略ns
参数,并设置两个新的全局变量。这似乎没有用。