Lisp Meta-Programming for C++ Developers: First Macros
deque.blog
deque.blog
If you look at the Servant library [1] for ClojureScript, they wrapped the callback-hell mess that is Javascript web workers (read: the only way to actually multi-thread on the web), into beautiful Go-style channels, via the use of macros.
This can be true in C++ as well, but those limits are quite high and are easily set to something else. Perhaps Clojure also allows you to reset what these limits are.
You can execute arbitrary code at macro-expansion time.
You can also recompile while the process is running, which would include re-macroexpanding.
This is how you get a REPL and other forms of runtime evaluation.
This is kind of the nub of being a dynamic programming language, if it can't do this, it isn't a dynamic programming language. Lisps are generally dynamic programming languages.
Clojure-script might be an exception because of how it is implemented, but Clojure proper on the JVM certainly supports this type of behavior.
I would expect to be able to do (eval `(defun ,function_name () (complicated_macro ,@args))) or (compile `(defun ,function_name () (complicated_macro ,@args)))) at runtime in Common Lisp, without even really considering the consequences beyond whether it is necessary.
It's supposed to work a little bit like if you had an implementation of GCC in the same process as your C program, and you could call GCC from a function to compile some new C code for you to add features or replace existing code. It's powerful + dangerous.
C++ obviously has a limit on template depths as well, but they are so high that rarely does anyone get close to the defaults. Clojure probably has very limited defaults (assuming that defaults are the cause).
In lisps you very typically have complete access to the compiler, though this is not universal. Resource limits on a running process are a separable issue.
In a very typical lisp system, for example, exactly the same resources would be available at runtime as your original compile (in fact, the boundary between these two is pretty fuzzy and often might be the same process anyway)
Likewise, C++ typically doesn't have any runtime access to compilers at all, so what resources are available to them or not is a bit moot.
If the point is that you might deploy on a different machine or configuration, well - that's true, but I can't see the relevance.
You might be pointing out some oddities of Clojure, I suppose, but that's not a great model for "typical lisp".
https://github.com/billsix/bug
http://www.lulu.com/shop/bill-six/computation-at-compile-tim...
The computing resources required to process the code (macros, and whatever) are usually unrelated to the computing resources used by that code when it runs.
The computing resources required to process the code (macros, and whatever) is usually unrelated to the computing resources of the application.
A program that works with gigabytes or data might need only megabytes during its compilation.
(It's not easy to imagine practical circumstances where it would be reversed, with those exact numbers. Some algorithms you might want to use at compile time do explode in memory size, I suppose.)
However, if you need gigabyte to expand your macros, it is likely you need megaseconds, too, and then, it is wise to use 'precompiled headers', and save your 'preprocessor output'.
It happens once ever blue moon, but every time I would kill for a proper syntax-case for CL. Racket's is fine, but I'd be happy with a one like the plain R6RS as well
See e.g. Alexandria[0] for with-gensyms (automatically binding your variables to gensyms) and once-only (similar, but ensures the value will be evaluated only once).
Also note that lack of hygiene is actually a useful feature - it allows macros to capture variables from code passed to it as well as the environment they expand it. Some cool stuff can be done that way (some uncool foot-shooting too, though).
--
[0] - https://common-lisp.net/project/alexandria/draft/alexandria....
Doug Hoyte's excellent book _Let Over Lambda_ has a lot of examples.