Dynamic macros in common-lisp - when and how to use
In my previous question, which @sds answered very nicely,
How to wrap and execute a lisp s-expression by another s-expression?
We came to the topic of dynamic and static macros.
The static solution of my with-open-files
macro problem by @sds was:
(defmacro with-open-files ((streams file-names &rest options &key &allow-other-keys) &body body)
(if (and streams file-names)
`(with-open-file (,(pop streams) ,(pop file-names) ,@options)
(with-open-files (,streams ,file-names ,@options)
,@body))
`(progn ,@body)))
And his dynamic solution:
(defmacro with-open-files-d ((streams file-names &rest options &key &allow-other-keys) &body body)
(let ((sv (gensym "STREAMS-"))
(ab (gensym "ABORT-"))
(op (gensym "OPTIONS-")))
`(let ((,sv ,streams)
(,ab t)
(,op (list ,@options)))
(progv ,sv (mapcar (lambda (fn) (apply #'open fn op)) ,file-names)
(unwind-protect (multiple-value-prog1 (progn ,@body) (setq ,ab nil))
(dolist (s ,sv)
(when s
(close s :abort ,ab))))))))
My question is: Does using a macro in a macro automatically prohibits it to be dynamic? (I guess yes ..., since the macro call in the macro definition has to be executed before compilation, isn't it? Or not?).
And when to use a static or dynamic macro solution? - Sure, if the data are only known at runtime, one would need a dynamic macro, isn't it?
What are best practices?
dynamic static macros common-lisp
add a comment |
In my previous question, which @sds answered very nicely,
How to wrap and execute a lisp s-expression by another s-expression?
We came to the topic of dynamic and static macros.
The static solution of my with-open-files
macro problem by @sds was:
(defmacro with-open-files ((streams file-names &rest options &key &allow-other-keys) &body body)
(if (and streams file-names)
`(with-open-file (,(pop streams) ,(pop file-names) ,@options)
(with-open-files (,streams ,file-names ,@options)
,@body))
`(progn ,@body)))
And his dynamic solution:
(defmacro with-open-files-d ((streams file-names &rest options &key &allow-other-keys) &body body)
(let ((sv (gensym "STREAMS-"))
(ab (gensym "ABORT-"))
(op (gensym "OPTIONS-")))
`(let ((,sv ,streams)
(,ab t)
(,op (list ,@options)))
(progv ,sv (mapcar (lambda (fn) (apply #'open fn op)) ,file-names)
(unwind-protect (multiple-value-prog1 (progn ,@body) (setq ,ab nil))
(dolist (s ,sv)
(when s
(close s :abort ,ab))))))))
My question is: Does using a macro in a macro automatically prohibits it to be dynamic? (I guess yes ..., since the macro call in the macro definition has to be executed before compilation, isn't it? Or not?).
And when to use a static or dynamic macro solution? - Sure, if the data are only known at runtime, one would need a dynamic macro, isn't it?
What are best practices?
dynamic static macros common-lisp
1
DOLIST
is a macro, you're using that in the dynamic version. So obviously it doesn't prohibit it.
– Barmar
Nov 12 '18 at 19:57
You should use whichever form produces the clearest code that solves the problem.
– Barmar
Nov 12 '18 at 19:58
@Barmar true ... but with-open-files prohibits it ... maybe because it takes an argument which is used literally? (e.g. the stream variable?) ...
– Gwang-Jin Kim
Nov 12 '18 at 20:01
Right. You can't use a macro that requires a compile-time literal when you're calculating the value at runtime.
– Barmar
Nov 12 '18 at 20:05
add a comment |
In my previous question, which @sds answered very nicely,
How to wrap and execute a lisp s-expression by another s-expression?
We came to the topic of dynamic and static macros.
The static solution of my with-open-files
macro problem by @sds was:
(defmacro with-open-files ((streams file-names &rest options &key &allow-other-keys) &body body)
(if (and streams file-names)
`(with-open-file (,(pop streams) ,(pop file-names) ,@options)
(with-open-files (,streams ,file-names ,@options)
,@body))
`(progn ,@body)))
And his dynamic solution:
(defmacro with-open-files-d ((streams file-names &rest options &key &allow-other-keys) &body body)
(let ((sv (gensym "STREAMS-"))
(ab (gensym "ABORT-"))
(op (gensym "OPTIONS-")))
`(let ((,sv ,streams)
(,ab t)
(,op (list ,@options)))
(progv ,sv (mapcar (lambda (fn) (apply #'open fn op)) ,file-names)
(unwind-protect (multiple-value-prog1 (progn ,@body) (setq ,ab nil))
(dolist (s ,sv)
(when s
(close s :abort ,ab))))))))
My question is: Does using a macro in a macro automatically prohibits it to be dynamic? (I guess yes ..., since the macro call in the macro definition has to be executed before compilation, isn't it? Or not?).
And when to use a static or dynamic macro solution? - Sure, if the data are only known at runtime, one would need a dynamic macro, isn't it?
What are best practices?
dynamic static macros common-lisp
In my previous question, which @sds answered very nicely,
How to wrap and execute a lisp s-expression by another s-expression?
We came to the topic of dynamic and static macros.
The static solution of my with-open-files
macro problem by @sds was:
(defmacro with-open-files ((streams file-names &rest options &key &allow-other-keys) &body body)
(if (and streams file-names)
`(with-open-file (,(pop streams) ,(pop file-names) ,@options)
(with-open-files (,streams ,file-names ,@options)
,@body))
`(progn ,@body)))
And his dynamic solution:
(defmacro with-open-files-d ((streams file-names &rest options &key &allow-other-keys) &body body)
(let ((sv (gensym "STREAMS-"))
(ab (gensym "ABORT-"))
(op (gensym "OPTIONS-")))
`(let ((,sv ,streams)
(,ab t)
(,op (list ,@options)))
(progv ,sv (mapcar (lambda (fn) (apply #'open fn op)) ,file-names)
(unwind-protect (multiple-value-prog1 (progn ,@body) (setq ,ab nil))
(dolist (s ,sv)
(when s
(close s :abort ,ab))))))))
My question is: Does using a macro in a macro automatically prohibits it to be dynamic? (I guess yes ..., since the macro call in the macro definition has to be executed before compilation, isn't it? Or not?).
And when to use a static or dynamic macro solution? - Sure, if the data are only known at runtime, one would need a dynamic macro, isn't it?
What are best practices?
dynamic static macros common-lisp
dynamic static macros common-lisp
asked Nov 12 '18 at 19:26
Gwang-Jin Kim
2,396116
2,396116
1
DOLIST
is a macro, you're using that in the dynamic version. So obviously it doesn't prohibit it.
– Barmar
Nov 12 '18 at 19:57
You should use whichever form produces the clearest code that solves the problem.
– Barmar
Nov 12 '18 at 19:58
@Barmar true ... but with-open-files prohibits it ... maybe because it takes an argument which is used literally? (e.g. the stream variable?) ...
– Gwang-Jin Kim
Nov 12 '18 at 20:01
Right. You can't use a macro that requires a compile-time literal when you're calculating the value at runtime.
– Barmar
Nov 12 '18 at 20:05
add a comment |
1
DOLIST
is a macro, you're using that in the dynamic version. So obviously it doesn't prohibit it.
– Barmar
Nov 12 '18 at 19:57
You should use whichever form produces the clearest code that solves the problem.
– Barmar
Nov 12 '18 at 19:58
@Barmar true ... but with-open-files prohibits it ... maybe because it takes an argument which is used literally? (e.g. the stream variable?) ...
– Gwang-Jin Kim
Nov 12 '18 at 20:01
Right. You can't use a macro that requires a compile-time literal when you're calculating the value at runtime.
– Barmar
Nov 12 '18 at 20:05
1
1
DOLIST
is a macro, you're using that in the dynamic version. So obviously it doesn't prohibit it.– Barmar
Nov 12 '18 at 19:57
DOLIST
is a macro, you're using that in the dynamic version. So obviously it doesn't prohibit it.– Barmar
Nov 12 '18 at 19:57
You should use whichever form produces the clearest code that solves the problem.
– Barmar
Nov 12 '18 at 19:58
You should use whichever form produces the clearest code that solves the problem.
– Barmar
Nov 12 '18 at 19:58
@Barmar true ... but with-open-files prohibits it ... maybe because it takes an argument which is used literally? (e.g. the stream variable?) ...
– Gwang-Jin Kim
Nov 12 '18 at 20:01
@Barmar true ... but with-open-files prohibits it ... maybe because it takes an argument which is used literally? (e.g. the stream variable?) ...
– Gwang-Jin Kim
Nov 12 '18 at 20:01
Right. You can't use a macro that requires a compile-time literal when you're calculating the value at runtime.
– Barmar
Nov 12 '18 at 20:05
Right. You can't use a macro that requires a compile-time literal when you're calculating the value at runtime.
– Barmar
Nov 12 '18 at 20:05
add a comment |
1 Answer
1
active
oldest
votes
You misunderstood me.
When I said "static" vs "dynamic" I was talking about whether variables bound by the macro are known at compile time ("static") or only at run time ("dynamic").
Generally speaking, one should stick with "static" because it produces more readable code. The only situation when "dynamic" is needed is when creating a DSL ("domain-specific language").
Using "macro in macro" is a completely orthogonal issue.
One can always do that (when done correctly).
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
1
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
add a comment |
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',
autoActivateHeartbeat: false,
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268823%2fdynamic-macros-in-common-lisp-when-and-how-to-use%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You misunderstood me.
When I said "static" vs "dynamic" I was talking about whether variables bound by the macro are known at compile time ("static") or only at run time ("dynamic").
Generally speaking, one should stick with "static" because it produces more readable code. The only situation when "dynamic" is needed is when creating a DSL ("domain-specific language").
Using "macro in macro" is a completely orthogonal issue.
One can always do that (when done correctly).
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
1
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
add a comment |
You misunderstood me.
When I said "static" vs "dynamic" I was talking about whether variables bound by the macro are known at compile time ("static") or only at run time ("dynamic").
Generally speaking, one should stick with "static" because it produces more readable code. The only situation when "dynamic" is needed is when creating a DSL ("domain-specific language").
Using "macro in macro" is a completely orthogonal issue.
One can always do that (when done correctly).
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
1
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
add a comment |
You misunderstood me.
When I said "static" vs "dynamic" I was talking about whether variables bound by the macro are known at compile time ("static") or only at run time ("dynamic").
Generally speaking, one should stick with "static" because it produces more readable code. The only situation when "dynamic" is needed is when creating a DSL ("domain-specific language").
Using "macro in macro" is a completely orthogonal issue.
One can always do that (when done correctly).
You misunderstood me.
When I said "static" vs "dynamic" I was talking about whether variables bound by the macro are known at compile time ("static") or only at run time ("dynamic").
Generally speaking, one should stick with "static" because it produces more readable code. The only situation when "dynamic" is needed is when creating a DSL ("domain-specific language").
Using "macro in macro" is a completely orthogonal issue.
One can always do that (when done correctly).
answered Nov 12 '18 at 20:09
sds
38.7k1493168
38.7k1493168
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
1
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
add a comment |
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
1
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
Which kind of mistakes do you know of "macro in macro" which are frequently done by beginners, then?
– Gwang-Jin Kim
Nov 12 '18 at 20:36
1
1
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
@Gwang-JinKim: The main mistake is debugging using execution rather than macroexpansion.
– sds
Nov 12 '18 at 20:37
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
thanks! And when did you feel "you got it" - did you ever had such a moment?
– Gwang-Jin Kim
Nov 12 '18 at 21:02
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268823%2fdynamic-macros-in-common-lisp-when-and-how-to-use%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
DOLIST
is a macro, you're using that in the dynamic version. So obviously it doesn't prohibit it.– Barmar
Nov 12 '18 at 19:57
You should use whichever form produces the clearest code that solves the problem.
– Barmar
Nov 12 '18 at 19:58
@Barmar true ... but with-open-files prohibits it ... maybe because it takes an argument which is used literally? (e.g. the stream variable?) ...
– Gwang-Jin Kim
Nov 12 '18 at 20:01
Right. You can't use a macro that requires a compile-time literal when you're calculating the value at runtime.
– Barmar
Nov 12 '18 at 20:05