Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Likewise in Common Lisp, arguably much more easily.



Well LISP has no distinction between meta-programming and programming. so as long as you like parens, you can do anything


There is no macro needed here. You just write the code, then execute it at compile time. This is designed properly, it's not any where near as hacky as C++'s constexpr


No need for macros, eval-when is a special operator designed for this:

    (eval-when (:compile-toplevel)
       ...)
You can also have read-time macros or load-time values, depending on what you need.


how ... macros?


Macros, or (eval-when (:compile-toplevel) [your code here]). Caveats apply.


Vanilla macros are one option.

  (defmacro html (string)
    (some-html-parser-library:parse string))
Or you could use a function and a compiler macro to make it more of an optimization -- if the argument is known at compile-time just parse it then, otherwise wait til runtime:

  (defun html (string)
    (some-html-parser-library:parse string))

  (define-compiler-macro html (&whole form string)
    (if (constantp string)
      `',(some-html-parser-library:parse string)
      form))
Actual example, using `string-upcase` to stand in for an HTML parsing library:

  (defun html (string)
    (string-upcase string))
  
  (define-compiler-macro html (&whole form string)
    (if (constantp string)
      `',(string-upcase string)
      form))
  
  (defun foo (arg)
    (print (html arg))
    (print (html "compile-time"))
    nil)

  (foo "run-time")
  ; "RUN-TIME"
  ; "COMPILE-TIME"
  
  (disassemble 'foo)

  ; disassembly for FOO
  ; Size: 128 bytes. Origin: #x10106A207D
  ; 7D:       498B4C2460       MOV RCX, [R12+96]                ; thread.binding-stack-pointer
                                                                ; no-arg-parsing entry point
  ; 82:       48894DF8         MOV [RBP-8], RCX
  ; 86:       488D5C24F0       LEA RBX, [RSP-16]
  ; 8B:       4883EC18         SUB RSP, 24
  ; 8F:       488B55F0         MOV RDX, [RBP-16]
  ; 93:       488B0576FFFFFF   MOV RAX, [RIP-138]               ; #<SB-KERNEL:FDEFN HTML>
  ; 9A:       B902000000       MOV ECX, 2
  ; 9F:       48892B           MOV [RBX], RBP
  ; A2:       488BEB           MOV RBP, RBX
  ; A5:       FF5009           CALL QWORD PTR [RAX+9]
  ; A8:       480F42E3         CMOVB RSP, RBX
  ; AC:       488D5C24F0       LEA RBX, [RSP-16]
  ; B1:       4883EC18         SUB RSP, 24
  ; B5:       488B055CFFFFFF   MOV RAX, [RIP-164]               ; #<SB-KERNEL:FDEFN COMMON-LISP:PRINT>
  ; BC:       B902000000       MOV ECX, 2
  ; C1:       48892B           MOV [RBX], RBP
  ; C4:       488BEB           MOV RBP, RBX
  ; C7:       FF5009           CALL QWORD PTR [RAX+9]
  ; CA:       488D5C24F0       LEA RBX, [RSP-16]
  ; CF:       4883EC18         SUB RSP, 24
  ; D3:       488B1546FFFFFF   MOV RDX, [RIP-186]               ; "COMPILE-TIME"
  ; DA:       488B0537FFFFFF   MOV RAX, [RIP-201]               ; #<SB-KERNEL:FDEFN COMMON-LISP:PRINT>
  ; E1:       B902000000       MOV ECX, 2
  ; E6:       48892B           MOV [RBX], RBP
  ; E9:       488BEB           MOV RBP, RBX
  ; EC:       FF5009           CALL QWORD PTR [RAX+9]
  ; EF:       BA17001020       MOV EDX, 537919511
  ; F4:       488BE5           MOV RSP, RBP
  ; F7:       F8               CLC
  ; F8:       5D               POP RBP
  ; F9:       C3               RET
  ; FA:       0F0B10           BREAK 16                         ; Invalid argument count trap
`html` is only called once, to handle the call that isn't known at compile time.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: