I have the following code in a clj (clojure) namespace.
(ns project.clojure.clojurescript-macros)
(def trace-history (atom []))
; hmm, you could run out of memory on recursive functions here?
; Fortunately functions aren't actually recursive in clojure. :]
(defmacro push-args [name args]
`(swap! trace-history
(fn [stack#]
(conj stack# [~name (zipmap ~(vec (map str args)) ~args)]))))
(push-args :hello [:a :b :c])
within another cljs (clojurescript) namespace, I have the following
(ns project.clojurescript.user
(:require-macros [project.clojure.clojurescript-macros :as c]))
(c/push-args :hello [:a :b :c])
I compile my clojurescript code, and open it in my browser, Unfortunately, I get the following error.
Uncaught TypeError: Cannot read property 'trace_history' of undefined main.js:22348
(anonymous function) main.js:22348
Looking at line 22348 in my compiled clojurescipt code, I see the following.
cljs.core.swap_BANG_.call(null, project.clojure.trace_history, function(stack__6402__auto__) {
return cljs.core.conj.call(null, stack__6402__auto__,
cljs.core.PersistentVector.fromArray(["\ufdd0'hello",
cljs.core.zipmap.call(null,
cljs.core.PersistentVector.fromArray([":a", ":b", ":c"], true),
cljs.core.PersistentVector.fromArray(["\ufdd0'a", "\ufdd0'b", "\ufdd0'c"],
true))],
true))
});
The problem is that project.clojure.trace_history has not been defined anywhere in main.js . I understand what is wrong, but I am unsure as to how I might fix it. I have tried out other solutions, such as putting trace-history in a shared clojure file and putting trace history in a cljs file itself. None seem to work. Given that I want to have a shared global atom between all compilations of this macro, how can I do so in Clojurescript?
An atom is run-time data, a macro is a compile-time construct. It doesn't really make sense for a macro to have a "shared global atom" - what your macro there does is compile to code which simply expects there to be a symbol called trace-history in the current NS.
If you simply want to write common code which can use an atom, then you should write it such that can take the atom as an argument rather than assuming its existence via a hardcoded symbol name.
If you mean you want the same atom's value to be available to you on both the client and server of a Clojure+ClojureScript application, you'll need to write your own code to coordinate the value via Ajax calls... that's not something built in to the language.
Related
In Lisp, a function's arguments are evaluated first before entering the function body. Macro arguments stay not evaluated.
But sometimes, one wants to inject code pieces stored in variables into a macro. This means evaluating the argument for the macro first, and then apply the macro-of-choice on this evaluated result.
One has to resort to
(eval `(macro ,arg))
To achieve this - but eval does not behave correctly in different environments.
The best thing would be, if one could do:
(apply macro (list arg))
or
(funcall macro arg)
But since the macro is not a function this doesn't work.
Is it possible to achieve something like this? - To circumvent that problem oder to make the macro available in the functions namespace?
Or am I missing some other ways to solve such problems?
I came to this question while trying to answer How to produce HTML from a list. but also in Generate TYPECASE with macro in common lisp, Evaluate arguments passed to a macro that generates functions in lisp, and How to convert a list to code/lambda in scheme?. But I always thought while answering them it would be good to have an apply or funcall-like function which can take macros.
It is not clear what you are trying to do, although it is almost certain that you are confused about something. In particular if you are calling eval inside macroexpansions then in almost all cases you are doing something both seriously wrong and seriously dangerous. I can't ever think of a case where I've wanted macros which expand to things including eval and I have written Lisp for a very very long time.
That being said, here is how you call the function associated with a macro, and why it is very seldom what you want to do.
Macros are simply functions whose domain and range is source code: they are compilers from a language to another language. It is perfectly possible to call the function associated with a macro, but what that function will return is source code, and what you will then need to do with that source code is evaluate it. If you want a function which deals with run-time data which is not source code, then you need that function, and you can't turn a macro into that function by some magic trick which seems to be what you want to do: that magic trick does not, and can not, exist.
So for instance if I have a macro
(defmacro with-x (&body forms)
`(let ((x 1))
,#forms))
Then I can call its macro function on a bit of source code:
> (funcall (macro-function 'with-x)
'(with-x (print "foo")) nil)
(let ((x 1)) (print "foo"))
But the result of this is another bit of source code: I need to compile or evaluate it, and nothing I can do will get around this.
Indeed in (almost?) all cases this is just the same as macroexpand-1):
> (macroexpand-1 '(with-x (print "foo")))
(let ((x 1)) (print "foo"))
t
And you can probably write macroexpand-1 in terms of macro-function:
(defun macroexpand-1/equivalent (form &optional (env nil))
(if (and (consp form)
(symbolp (first form))
(macro-function (first form)))
(values (funcall (macro-function (first form)) form env)
t)
(values form nil)))
So, if the result of calling a macro is source code, what do you do with that source code to get a result which is not source code? Well, you must evaluate it. And then, well, since the evaluator expands macros for you anyway, you might as well just write something like
(defun evaluate-with-x (code)
(funcall (compile nil `(lambda ()
(with-x ,#code)))))
So you didn't need to call the macro's function in any case. And this is not the magic trick which turns macros into functions dealing with data which is not source code: it is a terrible horror which is entirely made of exploding parts.
A concrete example: CL-WHO
It looks like this question might have its origins in this one and the underlying problem there is that that's not what CL-WHO does. In particular it is a confusion to think that something like CL-WHO is a tool for taking some kind of list and turning it into HTML. It's not: it's a tool for taking the source code of a language which is built on CL but includes a way of expressing HTML output mingled with CL code, and compiles it into CL code which will do the same thing. It happens to be the case that CL source code is expressed as lists & symbols, but CL-WHO isn't really about that: it's a compiler from, if you like, 'the CL-WHO language' to CL.
So, let's try the trick we tried above and see why it's a disaster:
(defun form->html/insane (form)
(funcall
(compile nil `(lambda ()
(with-html-output-to-string (,(make-symbol "O"))
,#form)))))
And you might, if you did not look at this too closely, think that this function does in fact do the magic trick:
> (form->html/insane '(:p ((:a :href "foo") "the foo")))
"<p></p><a href='foo'>the foo</a>"
But it doesn't. What happens if we call form->html/insane on this perfectly innocuous list:
(:p (uiop/run-program:run-program "rm -rf $HOME" :output t))
Hint: don't call form->html/insane on this list if you don't have very good backups.
CL-WHO is an implementation of a programming language which is a strict superset of CL: if you try to turn it into a function to turn lists into HTML you end up with something involving the same nuclear weapon you tinker with every time you call eval, except that nuclear weapon is hidden inside a locked cupboard where you can't see it. But it doesn't care about that: if you set it off it will still reduce everything within a few miles to radioactive ash and rubble.
So if you want a tool which will turn lists – lists which aren't source code – into HTML then write that tool. CL-WHO might have the guts of such a tool in its implemenentation, but you can't use it as it is.
And this is the same problem you face whenever you are trying to abuse macros this way: the result of calling a macro's function is Lisp source code, and to evaluate that source code you need eval or an equivalent of eval. And eval is not only not a terrible solution to almost any problem: it's also a nuclear weapon. There are, perhaps problems for which nuclear weapons are good solutions, but they are few and far between.
The function find-data-from-command works fine when I run it without first doing the 'quickload' of the package. If I load the package it gives the error that split-sequence is undefined.
I have tried to reload split-sequence after loading the custom package. Doesn't work
(ql:quickload :<a-custom-package>)
(defun find-data-from-command (x desired-command)
(setq desired-data ())
(loop for line = (read-line x nil)
while (and line (not desired-data)) do
(progn
(setq commands (first (split-sequence ":" line)))
(setq data (split-sequence "," (first (rest (split-sequence ":" line)))))
(print (cons "command:" commands))
(cond
((equal commands desired-command) (return-from find-data-from-command data))))))
FIND-DATA-FROM-COMMAND
SIGMA 24 >
(setq obj-type (find-data-from-command (open "log.txt") "types"))
Error: Undefined operator SPLIT-SEQUENCE in form (SPLIT-SEQUENCE ":" LINE).
The problem is nothing to do with Quicklisp, it's to do with a package you've defined somewhere called SIGMA. In particular somewhere in your code is a form which looks like:
(defpackage "SIGMA" ;or :sigma or :SIGMA or #:sigma or ...
...
(:use ...)
...)
And then later
(in-package "SIGMA")
And the problem with this is that your package definition has an explicit (:use ...) clause.
defpackage, and the underlying function make-package has slightly interesting behaviour for the :use clause (or keyword argument in the case of make-package):
if none is given then there is an implementation-defined default;
if one is given then it overrides the default.
The idea, I think, is that implementations may want to provide a bunch of additional functionality which is available by default, and this functionality can't be in the CL package since the contents of that package is defined in the standard. So if you just say
(defpackage "FOO")
Then the implementation is allowed (and, perhaps, encouraged), to make the use-list of FOO have some useful packages in it. These packages might be the same ones that are in the default use-list of CL-USER, but I'm not sure that's required: the whole thing is somewhat under-specified.
The end result of this is that if you want to define packages which both make use of implementation-defined functionality and have explicit use-lists you have to resort to some slight trickery. How you do this is slightly up to you, but since you are by definition writing implementation-dependent code where you are defining packages like this, you probably want to make it clear that what you are doing is implementation-dependent, by some form like
(defpackage :foo
(:use ...)
#+LispWorks
(:use :lispworks :harlequin-common-lisp :cl)
...)
Or, if you just want some particular set of symbols
(defpackage :foo
(:use ...)
#+LispWorks
(:import-from :lispworks #:split-sequence))
Note that this is not quite the same thing as using a package containing the symbol.
In all these cases if your code has pretensions to be portable then there should be appropriate clauses for other implementations and a way of knowing when you're trying to run on an implemention you haven't yet seen: how to do this is outwith the scope of this answer I think.
Solved it.
The quickloading of the custom package was taking me into the package. I did not realize that. So I had to specify split-sequence is from outside. So, I replaced all occurrences of split-sequence in the function definition with
LISPWORKS:split-sequence
Then it worked.
If any one has a better solution, please do let me know. Thanks
Assume the following code
(defmacro sdef [sname]
`(def ~sname 3))
(defmacro sinc [sname]
(inc ... we want to access sname's value here...))
In ClojureScript we'd use it like this
(sdef sfoo)
(sinc sfoo) ; => 4
In our case it is mandatory that sinc is evaluated at compile time.
We managed to achieve this in Clojure using resolve, which didn't work in ClojureScript. We are aware, that especially in ClojureScript the macro evaluation is strictly separated from ClojureScript code execution.
However, is there a way to achieve the above?
Is it possible to expand a macro at run time in a compiled lisp executable? I would expect it to be impossible as macro expansion can only happen pre-compilation yet when i call macroexpand in compiled code i get output.
A macro is a function that's normally called automatically during compilation or evaluation, and whose return value is then compiled or evaluated in place of the original expression.
But since it's just a function, there's nothing preventing it from being called explicitly during run time as well, and that's what MACROEXPAND and MACROEXPAND-1 do.
It's roughly equivalent to:
(defun macroexpand-1 (form &optional env)
(if (and (listp form) (car form)) ;; list expression
(let ((macfun (macro-function (car form)))
(if macfun
(funcall macfun form env)
form))
form))
(Note that this definition doesn't handle symbol macros or use *MACROEXPAND-HOOK*, to keep it simple.)
It's possible to use EVAL-WHEN when defining the macro to make the macro definition only available in the compilation environment. If you do that, trying to expand at run time will fail.
In Lisp, the terms "run time" and "compile time" are situations in which a particular piece of code is being processed, not absolutes like in some static languages. If we evaluate (compile nil '(lambda ())), this is the compile function's run-time, but the lambda form's compile time: both times are happening at the same time.
The entire language is available in all situations. When you build a self-contained executable, that image contains not only support for expanding macros, but for compiling code. Your Lisp application can call compile-file to compile Lisp source to object form, and load to load the resulting object code.
The process of removing garbage, and unused functionality from a Lisp application image to make it smaller is called "tree shaking". If you don't want the compiler or macro expander in your application, find out whether/how they can be removed with your implementation's tree shaking support.
Here's the setup:
(defun square (x)
(* x x))
;; square
(symbol-function 'square)
;; (lambda (x) (* x x))
(byte-compile 'square)
;; #[(x) "\211_\207" [x] 2]
(symbol-function 'square)
;; #[(x) "\211_\207" [x] 2]
Is there a way to get the source (lambda (x) (* x x)) after square has been byte-compiled?
The two uses that I can think of are inlining the current function call
and doing a debug-step-in.
I've tried messing with find-definition-noselect to get the source,
but I wonder if there's a better way, because it sometimes raises
(error "Don't know where ... is defined")
Emacs keeps track of which function name is defined in which file (this info is kept in load-history). To find the definition, Emacs looks in load-history and if the function is listed there, it looks for the corresponding source file and then in that file looks for something that looks like a likely definition of the function (using regexps). That's what find-definition-noselect does.
As for the source code, no in general Emacs does not keep the source definition. If you define the function with cl-defsubst, then the source is kept around, but otherwise it isn't. For Edebugging, having the source wouldn't help anyway (because Edebug needs not just the source cod but also the precise location of each sub-expression); for plain debugging the source is not really needed either (you can always click on the function's name to jump to the source); for inlining the source is not needed either (the byte-compiler can inline at the source-code level, indeed, but it can just as well inline at the byte-code level).
There is no way to obtain the source of a function object. Byte compilation is no injective function, so you cannot revert it. Even disregarding macro expansion, there is no direct mapping from opcodes to Lisp expressions.
I do not see use cases for this anyway.
Debugging
To step into functions for debugging, navigate to its definition (i.e. find-definition) and instrument the definition for debugging (e.g. with edebug). That's the only way to reasonably debug Emacs Lisp functions. You can't use the contents of the function cell for debugging, because it's subject to macro expansion.
As such, the function cell may look completely different from the actual definition. If you find a bug in the function cell, you'll struggle to find the same bug in the actual function definition.
Inlining
For inlining, use macros or defsubst to define inline functions in Emacs Lisp. However, be careful to not accidentally expose these on the public interface of your library, since compile time inline functions impose a compile time dependency onto your library, so a dependent library needs to be recompiled for every release of your library. And since package.el doesn't support that yet, macros and substitutions can easily cause havoc.