Expanding nested macro calls during code compilation/evaluation





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I have a next piece of code:



(in-package :cl-user)

(defmacro test0 (form)
(format t "test0: Expander phase: ~s" form)
`(format t "test0: Expansion phase: ~s" ,form))

(defmacro test1 (form)
(format t "test1: Expander phase: ~s" form)
(test0 form)
`(format t "test1: Expansion phase: ~s" ,form))


Common Lisp implementation: "SBCL 1.3.16".




  1. Results of (compile-file "source.lisp"):

    ; compiling (IN-PACKAGE :CL-USER)
    ; compiling (DEFMACRO TEST0 ...)
    ; compiling (DEFMACRO TEST1 ...)test0: Expander phase: FORMtest0: Expander phase: FORM


  2. Results of (load "source.lisp"):

    ; #<PACKAGE "COMMON-LISP-USER">
    ; TEST0
    test0: Expander phase: FORM
    ; TEST1



And I just can't understand next things:




  1. Why is nested subform (test0 form) expanded and processed in the definition of test1 macro? Why isn't it processed in the macro call instead?


  2. Where is Common Lisp standard specify such a behavior? eval-when? Files compilation? Forms evaluation?


  3. Finally, why is "test0: Expander phase: FORM" printed twice during compilation(compile-file) and only once during evaluation(load)?



I think the answers are pretty obvious but I can't find them out.










share|improve this question































    0















    I have a next piece of code:



    (in-package :cl-user)

    (defmacro test0 (form)
    (format t "test0: Expander phase: ~s" form)
    `(format t "test0: Expansion phase: ~s" ,form))

    (defmacro test1 (form)
    (format t "test1: Expander phase: ~s" form)
    (test0 form)
    `(format t "test1: Expansion phase: ~s" ,form))


    Common Lisp implementation: "SBCL 1.3.16".




    1. Results of (compile-file "source.lisp"):

      ; compiling (IN-PACKAGE :CL-USER)
      ; compiling (DEFMACRO TEST0 ...)
      ; compiling (DEFMACRO TEST1 ...)test0: Expander phase: FORMtest0: Expander phase: FORM


    2. Results of (load "source.lisp"):

      ; #<PACKAGE "COMMON-LISP-USER">
      ; TEST0
      test0: Expander phase: FORM
      ; TEST1



    And I just can't understand next things:




    1. Why is nested subform (test0 form) expanded and processed in the definition of test1 macro? Why isn't it processed in the macro call instead?


    2. Where is Common Lisp standard specify such a behavior? eval-when? Files compilation? Forms evaluation?


    3. Finally, why is "test0: Expander phase: FORM" printed twice during compilation(compile-file) and only once during evaluation(load)?



    I think the answers are pretty obvious but I can't find them out.










    share|improve this question



























      0












      0








      0








      I have a next piece of code:



      (in-package :cl-user)

      (defmacro test0 (form)
      (format t "test0: Expander phase: ~s" form)
      `(format t "test0: Expansion phase: ~s" ,form))

      (defmacro test1 (form)
      (format t "test1: Expander phase: ~s" form)
      (test0 form)
      `(format t "test1: Expansion phase: ~s" ,form))


      Common Lisp implementation: "SBCL 1.3.16".




      1. Results of (compile-file "source.lisp"):

        ; compiling (IN-PACKAGE :CL-USER)
        ; compiling (DEFMACRO TEST0 ...)
        ; compiling (DEFMACRO TEST1 ...)test0: Expander phase: FORMtest0: Expander phase: FORM


      2. Results of (load "source.lisp"):

        ; #<PACKAGE "COMMON-LISP-USER">
        ; TEST0
        test0: Expander phase: FORM
        ; TEST1



      And I just can't understand next things:




      1. Why is nested subform (test0 form) expanded and processed in the definition of test1 macro? Why isn't it processed in the macro call instead?


      2. Where is Common Lisp standard specify such a behavior? eval-when? Files compilation? Forms evaluation?


      3. Finally, why is "test0: Expander phase: FORM" printed twice during compilation(compile-file) and only once during evaluation(load)?



      I think the answers are pretty obvious but I can't find them out.










      share|improve this question
















      I have a next piece of code:



      (in-package :cl-user)

      (defmacro test0 (form)
      (format t "test0: Expander phase: ~s" form)
      `(format t "test0: Expansion phase: ~s" ,form))

      (defmacro test1 (form)
      (format t "test1: Expander phase: ~s" form)
      (test0 form)
      `(format t "test1: Expansion phase: ~s" ,form))


      Common Lisp implementation: "SBCL 1.3.16".




      1. Results of (compile-file "source.lisp"):

        ; compiling (IN-PACKAGE :CL-USER)
        ; compiling (DEFMACRO TEST0 ...)
        ; compiling (DEFMACRO TEST1 ...)test0: Expander phase: FORMtest0: Expander phase: FORM


      2. Results of (load "source.lisp"):

        ; #<PACKAGE "COMMON-LISP-USER">
        ; TEST0
        test0: Expander phase: FORM
        ; TEST1



      And I just can't understand next things:




      1. Why is nested subform (test0 form) expanded and processed in the definition of test1 macro? Why isn't it processed in the macro call instead?


      2. Where is Common Lisp standard specify such a behavior? eval-when? Files compilation? Forms evaluation?


      3. Finally, why is "test0: Expander phase: FORM" printed twice during compilation(compile-file) and only once during evaluation(load)?



      I think the answers are pretty obvious but I can't find them out.







      common-lisp






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 16 '18 at 14:32









      sds

      40.4k1498177




      40.4k1498177










      asked Nov 16 '18 at 13:13









      Андрій ТимчукАндрій Тимчук

      33




      33
























          1 Answer
          1






          active

          oldest

          votes


















          5














          A macro is a function which operates on code.
          Since in Lisp code is just a
          list,
          macro functions look like ordinary functions.



          Your defmacro test1 is treated as a definition of a function, so all the code is processed appropriately and (test0 form) is macroexpanded when the SBCL compiles defmacro test1. This answers q1.



          load "sequentially executes
          each form it encounters", so to answer your q2, you need to read 3.1
          Evaluation, specifically,
          3.1.2.1.2.2 Macro Forms.



          As for how many times a macro is expanded, this is not specified by the
          standard (an implementation can expand it on every call of the user
          function!), and this is a reason why it is not a good idea for a macro
          to have side effects (e.g., to do output).
          In your case, loading requires expansion when test1 is defined.
          Compilation expands when it defines test1 and then again when it
          compiles it.
          Remember, defmacro arranges that the macro can be used in the
          following code (including in itself recursively), so is has to be defined immediately.






          share|improve this answer
























          • Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

            – Андрій Тимчук
            Nov 19 '18 at 13:19













          • 3.1.2.1.2.3 Function Forms

            – sds
            Nov 19 '18 at 13:26











          • I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

            – sds
            Nov 19 '18 at 13:59












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


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53338637%2fexpanding-nested-macro-calls-during-code-compilation-evaluation%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









          5














          A macro is a function which operates on code.
          Since in Lisp code is just a
          list,
          macro functions look like ordinary functions.



          Your defmacro test1 is treated as a definition of a function, so all the code is processed appropriately and (test0 form) is macroexpanded when the SBCL compiles defmacro test1. This answers q1.



          load "sequentially executes
          each form it encounters", so to answer your q2, you need to read 3.1
          Evaluation, specifically,
          3.1.2.1.2.2 Macro Forms.



          As for how many times a macro is expanded, this is not specified by the
          standard (an implementation can expand it on every call of the user
          function!), and this is a reason why it is not a good idea for a macro
          to have side effects (e.g., to do output).
          In your case, loading requires expansion when test1 is defined.
          Compilation expands when it defines test1 and then again when it
          compiles it.
          Remember, defmacro arranges that the macro can be used in the
          following code (including in itself recursively), so is has to be defined immediately.






          share|improve this answer
























          • Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

            – Андрій Тимчук
            Nov 19 '18 at 13:19













          • 3.1.2.1.2.3 Function Forms

            – sds
            Nov 19 '18 at 13:26











          • I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

            – sds
            Nov 19 '18 at 13:59
















          5














          A macro is a function which operates on code.
          Since in Lisp code is just a
          list,
          macro functions look like ordinary functions.



          Your defmacro test1 is treated as a definition of a function, so all the code is processed appropriately and (test0 form) is macroexpanded when the SBCL compiles defmacro test1. This answers q1.



          load "sequentially executes
          each form it encounters", so to answer your q2, you need to read 3.1
          Evaluation, specifically,
          3.1.2.1.2.2 Macro Forms.



          As for how many times a macro is expanded, this is not specified by the
          standard (an implementation can expand it on every call of the user
          function!), and this is a reason why it is not a good idea for a macro
          to have side effects (e.g., to do output).
          In your case, loading requires expansion when test1 is defined.
          Compilation expands when it defines test1 and then again when it
          compiles it.
          Remember, defmacro arranges that the macro can be used in the
          following code (including in itself recursively), so is has to be defined immediately.






          share|improve this answer
























          • Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

            – Андрій Тимчук
            Nov 19 '18 at 13:19













          • 3.1.2.1.2.3 Function Forms

            – sds
            Nov 19 '18 at 13:26











          • I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

            – sds
            Nov 19 '18 at 13:59














          5












          5








          5







          A macro is a function which operates on code.
          Since in Lisp code is just a
          list,
          macro functions look like ordinary functions.



          Your defmacro test1 is treated as a definition of a function, so all the code is processed appropriately and (test0 form) is macroexpanded when the SBCL compiles defmacro test1. This answers q1.



          load "sequentially executes
          each form it encounters", so to answer your q2, you need to read 3.1
          Evaluation, specifically,
          3.1.2.1.2.2 Macro Forms.



          As for how many times a macro is expanded, this is not specified by the
          standard (an implementation can expand it on every call of the user
          function!), and this is a reason why it is not a good idea for a macro
          to have side effects (e.g., to do output).
          In your case, loading requires expansion when test1 is defined.
          Compilation expands when it defines test1 and then again when it
          compiles it.
          Remember, defmacro arranges that the macro can be used in the
          following code (including in itself recursively), so is has to be defined immediately.






          share|improve this answer













          A macro is a function which operates on code.
          Since in Lisp code is just a
          list,
          macro functions look like ordinary functions.



          Your defmacro test1 is treated as a definition of a function, so all the code is processed appropriately and (test0 form) is macroexpanded when the SBCL compiles defmacro test1. This answers q1.



          load "sequentially executes
          each form it encounters", so to answer your q2, you need to read 3.1
          Evaluation, specifically,
          3.1.2.1.2.2 Macro Forms.



          As for how many times a macro is expanded, this is not specified by the
          standard (an implementation can expand it on every call of the user
          function!), and this is a reason why it is not a good idea for a macro
          to have side effects (e.g., to do output).
          In your case, loading requires expansion when test1 is defined.
          Compilation expands when it defines test1 and then again when it
          compiles it.
          Remember, defmacro arranges that the macro can be used in the
          following code (including in itself recursively), so is has to be defined immediately.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 16 '18 at 14:31









          sdssds

          40.4k1498177




          40.4k1498177













          • Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

            – Андрій Тимчук
            Nov 19 '18 at 13:19













          • 3.1.2.1.2.3 Function Forms

            – sds
            Nov 19 '18 at 13:26











          • I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

            – sds
            Nov 19 '18 at 13:59



















          • Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

            – Андрій Тимчук
            Nov 19 '18 at 13:19













          • 3.1.2.1.2.3 Function Forms

            – sds
            Nov 19 '18 at 13:26











          • I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

            – sds
            Nov 19 '18 at 13:59

















          Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

          – Андрій Тимчук
          Nov 19 '18 at 13:19







          Thank you for your response, it helps me a lot. But some points are still unclear to me. "sequentially executes each form it encounters" - for macro form it means "expand and evaluate result". But how is function forms executed? I mean, the function evaluate subforms(body) when it's called. But what is done during load or compile-file? As I understand, compiler can optimize calls somehow, for example, inline function. But where is specified in the standard how function forms is executed?

          – Андрій Тимчук
          Nov 19 '18 at 13:19















          3.1.2.1.2.3 Function Forms

          – sds
          Nov 19 '18 at 13:26





          3.1.2.1.2.3 Function Forms

          – sds
          Nov 19 '18 at 13:26













          I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

          – sds
          Nov 19 '18 at 13:59





          I suggest that you ask a separate question about "top level forms". Comments is not the right place for new questions.

          – sds
          Nov 19 '18 at 13:59




















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53338637%2fexpanding-nested-macro-calls-during-code-compilation-evaluation%23new-answer', 'question_page');
          }
          );

          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







          Popular posts from this blog

          Xamarin.iOS Cant Deploy on Iphone

          Glorious Revolution

          Dulmage-Mendelsohn matrix decomposition in Python