Type error when running a common lisp macro that tries to output Javascript code. Why?











up vote
0
down vote

favorite












I just started learning common lisp and I'm trying to exercise it in a way that makes my daily work easier. In particular, I'm trying to create a set of functions and macros that takes a minimal syntax and outputs some JavaScript that I'm using often.



This is the code that I have written:



;;;; 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))


The idea is to be able to write code like this:



(namespace "namespace"
(#'public-var "hello" "world")
(#'public-var "something" "else"))


and get this output:



(function(ns){
ns.hello = world;
ns.something = else;
}(window.namespace = window.namespace || {}));


I know that I still need to work on the indentation of the output and on the line breaks, but that's not the point yet (these should be the first building blocks to abstract away more complex logics). The problem is that I'm getting this error and I can't figure out why (seriously, I already spent hours researching and trying different things):



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--


I also tried the individual pieces. For example this:



 (let ((output ""))  (CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))))


works and gets me this output:



".ciao = mondo;"


Any idea what I'm doing wrong?










share|improve this question




















  • 1




    Use macroexpand-1 and pprint to look at the macroexpansion of your (namespace ...) example. Then you can see the error easily.
    – Rainer Joswig
    Nov 5 at 20:28















up vote
0
down vote

favorite












I just started learning common lisp and I'm trying to exercise it in a way that makes my daily work easier. In particular, I'm trying to create a set of functions and macros that takes a minimal syntax and outputs some JavaScript that I'm using often.



This is the code that I have written:



;;;; 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))


The idea is to be able to write code like this:



(namespace "namespace"
(#'public-var "hello" "world")
(#'public-var "something" "else"))


and get this output:



(function(ns){
ns.hello = world;
ns.something = else;
}(window.namespace = window.namespace || {}));


I know that I still need to work on the indentation of the output and on the line breaks, but that's not the point yet (these should be the first building blocks to abstract away more complex logics). The problem is that I'm getting this error and I can't figure out why (seriously, I already spent hours researching and trying different things):



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--


I also tried the individual pieces. For example this:



 (let ((output ""))  (CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))))


works and gets me this output:



".ciao = mondo;"


Any idea what I'm doing wrong?










share|improve this question




















  • 1




    Use macroexpand-1 and pprint to look at the macroexpansion of your (namespace ...) example. Then you can see the error easily.
    – Rainer Joswig
    Nov 5 at 20:28













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I just started learning common lisp and I'm trying to exercise it in a way that makes my daily work easier. In particular, I'm trying to create a set of functions and macros that takes a minimal syntax and outputs some JavaScript that I'm using often.



This is the code that I have written:



;;;; 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))


The idea is to be able to write code like this:



(namespace "namespace"
(#'public-var "hello" "world")
(#'public-var "something" "else"))


and get this output:



(function(ns){
ns.hello = world;
ns.something = else;
}(window.namespace = window.namespace || {}));


I know that I still need to work on the indentation of the output and on the line breaks, but that's not the point yet (these should be the first building blocks to abstract away more complex logics). The problem is that I'm getting this error and I can't figure out why (seriously, I already spent hours researching and trying different things):



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--


I also tried the individual pieces. For example this:



 (let ((output ""))  (CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))))


works and gets me this output:



".ciao = mondo;"


Any idea what I'm doing wrong?










share|improve this question















I just started learning common lisp and I'm trying to exercise it in a way that makes my daily work easier. In particular, I'm trying to create a set of functions and macros that takes a minimal syntax and outputs some JavaScript that I'm using often.



This is the code that I have written:



;;;; 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))


The idea is to be able to write code like this:



(namespace "namespace"
(#'public-var "hello" "world")
(#'public-var "something" "else"))


and get this output:



(function(ns){
ns.hello = world;
ns.something = else;
}(window.namespace = window.namespace || {}));


I know that I still need to work on the indentation of the output and on the line breaks, but that's not the point yet (these should be the first building blocks to abstract away more complex logics). The problem is that I'm getting this error and I can't figure out why (seriously, I already spent hours researching and trying different things):



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--


I also tried the individual pieces. For example this:



 (let ((output ""))  (CONC OUTPUT (APPLY #'PUBLIC-VAR (LIST "ciao" "mondo"))))


works and gets me this output:



".ciao = mondo;"


Any idea what I'm doing wrong?







common-lisp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 6 at 8:16

























asked Nov 5 at 18:04









roccobarbi

748




748








  • 1




    Use macroexpand-1 and pprint to look at the macroexpansion of your (namespace ...) example. Then you can see the error easily.
    – Rainer Joswig
    Nov 5 at 20:28














  • 1




    Use macroexpand-1 and pprint to look at the macroexpansion of your (namespace ...) example. Then you can see the error easily.
    – Rainer Joswig
    Nov 5 at 20:28








1




1




Use macroexpand-1 and pprint to look at the macroexpansion of your (namespace ...) example. Then you can see the error easily.
– Rainer Joswig
Nov 5 at 20:28




Use macroexpand-1 and pprint to look at the macroexpansion of your (namespace ...) example. Then you can see the error easily.
– Rainer Joswig
Nov 5 at 20:28












1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










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


This returns a list:



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


A list is evaluated by applying the operator, which is the first element of the list, to the arguments.



Valid operators are only symbols or lambda forms. A conc form is invalid as an operator. Most likely you wanted something like:



(progn
(conc output …)
…)


As a side note, I don't know what your JavaScript output is really supposed to do. It ignores the ns parameter and sets two new global vars. This does not seem useful.






share|improve this answer





















  • Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
    – roccobarbi
    Nov 6 at 5:55











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53159826%2ftype-error-when-running-a-common-lisp-macro-that-tries-to-output-javascript-code%23new-answer', 'question_page');
}
);

Post as a guest
































1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










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


This returns a list:



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


A list is evaluated by applying the operator, which is the first element of the list, to the arguments.



Valid operators are only symbols or lambda forms. A conc form is invalid as an operator. Most likely you wanted something like:



(progn
(conc output …)
…)


As a side note, I don't know what your JavaScript output is really supposed to do. It ignores the ns parameter and sets two new global vars. This does not seem useful.






share|improve this answer





















  • Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
    – roccobarbi
    Nov 6 at 5:55















up vote
2
down vote



accepted










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


This returns a list:



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


A list is evaluated by applying the operator, which is the first element of the list, to the arguments.



Valid operators are only symbols or lambda forms. A conc form is invalid as an operator. Most likely you wanted something like:



(progn
(conc output …)
…)


As a side note, I don't know what your JavaScript output is really supposed to do. It ignores the ns parameter and sets two new global vars. This does not seem useful.






share|improve this answer





















  • Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
    – roccobarbi
    Nov 6 at 5:55













up vote
2
down vote



accepted







up vote
2
down vote



accepted






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


This returns a list:



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


A list is evaluated by applying the operator, which is the first element of the list, to the arguments.



Valid operators are only symbols or lambda forms. A conc form is invalid as an operator. Most likely you wanted something like:



(progn
(conc output …)
…)


As a side note, I don't know what your JavaScript output is really supposed to do. It ignores the ns parameter and sets two new global vars. This does not seem useful.






share|improve this answer












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


This returns a list:



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


A list is evaluated by applying the operator, which is the first element of the list, to the arguments.



Valid operators are only symbols or lambda forms. A conc form is invalid as an operator. Most likely you wanted something like:



(progn
(conc output …)
…)


As a side note, I don't know what your JavaScript output is really supposed to do. It ignores the ns parameter and sets two new global vars. This does not seem useful.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 6 at 0:06









Svante

38.8k662109




38.8k662109












  • Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
    – roccobarbi
    Nov 6 at 5:55


















  • Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
    – roccobarbi
    Nov 6 at 5:55
















Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
– roccobarbi
Nov 6 at 5:55




Thanks a lot for explaining it. In fact, as a newbie, I would have had a hard time noticing it. About the Javascript, I'll correct it as soon as I'm in front of a computer for future reference. I forgot to add ns. before each variable in the example output.
– roccobarbi
Nov 6 at 5:55


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53159826%2ftype-error-when-running-a-common-lisp-macro-that-tries-to-output-javascript-code%23new-answer', 'question_page');
}
);

Post as a guest




















































































這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()