I am wondering how one writes macros in Common Lisp that allow him to part with Lisp forms in calls to the former.
For instance, suppose I have the following macro:
(defmacro define-route ((app uri method) &body body)
`(setf (ningle:route ,app ,uri :method ,method)
,#body))
A call to it would look something like this:
(define-route (*app* "/" :GET)
(print "Welcome to ningle using GET!"))
What if one wanted to write a macro that could be called like this:
#route(*app*, "/", :GET)
or like this:
route: *app*, "/", :GET
Is this possible? I have seen the #route syntax somewhere before but am not sure how to implement it, nor do I remember what it was called to look it up again.
We encounter this decorator syntax (or annotations in CL) in the Caveman or Lucerne web frameworks:
#route GET "/"
(defun index ()
(render #P"index.tmpl"))
I doubt you can do route: *app*, "/", :GET.
cl-annot is a general annotation library for CL.
It is a reader macro, more examples here: http://lisp-lang.org/wiki/article/reader-macros
ps: Snooze, by the author of Sly (and yasnippet), is a web frameworks that treats routes as usual functions, thus route parameters as usual function arguments. It also has built-in reporting of errors (in browser, in the debugger, with a custom 404 page). I liked it better than the two mentioned. No big experience with either of them.
Related
I want to make a macro, that when used in class definition creates a field, it's public setter, and an annotation. However, it'd seem the macro is not expanding, mostly because it's used inside other (class definition) macro.
Here is an example how to define a class with one field:
(define-simple-class test-class ()
(foo :: java.util.List ))
My macro (only defines field as of now):
(define-syntax autowire
(syntax-rules ()
((autowire class id)
(id :: class))))
However, if I try to use it:
(define-simple-class test-class ()
(autowire java.util.List foo))
and query fields of the new class via reflection, I can see that it creates a field named autowire, and foo is nowhere to be seen. Looks like an issue of the order the macros are expanded.
Yes, macros are expanded “from the outside in”. After expanding define-simple-class, the subform (autowire java.util.List foo) does not exist anymore.
If you want this kind of behaviour modification, you need to define your own define-not-so-simple-class macro, which might expand to a define-simple-class form.
However, please step back before making such a minor tweak to something that is standard, and ask yourself whether it is worth it. The upside might be syntax that is slightly better aligned to the way you think, but the downside is that it might be worse aligned to the way others think (who might need to understand your code). There is a maxim for maintainable and readable coding: “be conventional”.
Let us say I have a X.clojurescript and a X.clojure namespace. Everything in X.clojurescript is Clojurescript code, everything in X.clojure is Clojure code. Unfortunately, I cannot define macros directly in Clojurescript, I have to define them in Clojure and then bring them into a Clojurescript namespace using
(ns X.clojurescript.abc
(:require-macros [X.clojure.def :as clj]))
This is fine. However, what if the macro (defined in X.clojure) is going to need to reference something defined in a Clojurescript namespace (X.clojurescript)? The problem is that the Clojure compiler does not look in my Clojurescript namespace (a separate directory) when resolving other namespaces.
I have gotten around this problem by simply creating a namespace in my Clojure code that has the same namespace and needed definition as exist in Clojurescript, but this seems kind of stupid. So, for instance, if I need X.clojurescript.abc.y in my macro, I will just create an additional namespace on the Clojure side that defs a dummy y in my Clojure version of X.clojurescript.abc; kind of dumb.
How do I deal with a macro that needs to refer to something on the Clojurescript side?
The only time a macro needs a specific namespace at the time of definition is if the macro is using code from said namespace to generate the list of symbols it will return.
you can follow along with these examples in the repl:
(defmacro foo
[a]
`(bar/bar ~a))
the definition of foo will compile even though bar is not a defined namespace
(foo :a)
calling foo will now fail because you have not defined the bar namespace, or the function bar yet
(ns bar)
(defn bar
[x]
[x x])
defines bar in the bar namespace
(ns user)
(foo :a)
=> [:a :a]
Notice that bar does not need to exist at the time of foo's definition. In fact the namespace does not even need to exist at the time of foo's definition.
I need to add several methods to a Clojure defprotocol that I am writing for several identical Swing components:
(defprotocol view-methods
(ok-button-add-action-listener [this listener])
(ok-button-set-enabled [this enabled])
(ok-button-set-selected [this selected])
(cancel-button-add-action-listener [this listener])
(cancel-button-set-enabled [this enabled])
(cancel-button-set-selected [this selected])
(other-button-add-action-listener [this listener])
(other-button-set-enabled [this enabled])
(other-button-set-selected [this selected]))
Is there any way that I can write a macro that returns all three of the method signatures (xxx-button-add-action-listener, xxx-button-set-enabled, xxx-button-set-selected)?
(defprotocol view-methods
(add-methods ok)
(add-methods cancel)
(add-methods other))
This macro needs to add three items to the growing defprotocol with each invocation.
Can a macro return `~#a-list and expand "in place"?
Yes, you just need to have your macro expand in a (do ...), and the Clojure compiler will thread the do children as a sequence of top level forms.
I believe a macro must expand to a single form - so you can't do this in the exact way you are describing.
However, all is not lost because it would certainly be possible to write this with a macro at the top level that looks something like the following:
(defmacro build-button-protocol [name & method-specs]
....)
Which you could use as follows:
(build-button-protocol view-methods
(add-methods ok)
(add-methods cancel)
(add-methods other))
In common-lisp, I want to implement a kind of reference system like this:
Suppose that I have:
(defclass reference () ((host) (port) (file)))
and also I have:
(defun fetch-remote-value (reference) ...) which fetches and deserializes a lisp object.
How could I intervene in the evaluation process so as whenever a reference object is being evaluated, the remote value gets fetched and re-evaluated again to produce the final result?
EDIT:
A more elaborate description of what I want to accomplish:
Using cl-store I serialize lisp objects and send them to a remote file(or db or anything) to be saved. Upon successful storage I keep the host,port and file in a reference object. I would like, whenever eval gets called on a reference object, to first retrieve the object, and then call eval on the retrieved value. Since a reference can be also serialized in other (parent) objects or aggregate types, I can get free recursive remote reference resolution by modyfing eval so i dont have to traverse and resolve the loaded object's child references myself.
EDIT:
Since objects always evaluate to themselves, my question is a bit wrongly posed. Essentially what I would like to do is:
I would like intercept the evaluation of symbols so that when their value is an object of type REFERENCE then instead of returning the object as the result of the symbol evaluation, to return the result of (fetch-remote-value object) ?
In short: you cannot do this, except by rewriting the function eval and modifying your Lisp's compiler. The rules of evaluation are fixed Lisp standard.
Edit After reading the augmented question, I don't think, that you can achieve full transperency for your references here. In a scenario like
(defclass foo () (reference :accessor ref))
(ref some-foo)
The result of the call to ref is simply a value; it will not be considered for evaluation regardless of its type.
Of course, you could define your accessors in a way, which does the resolution transparently:
(defmacro defresolver (name class slot)
`(defmethod ,name ((inst ,class))
(fetch-remote-reference (slot-value inst ',slot))))
(defresolver foo-reference foo reference)
Edit You can (sort of) hook into the symbol resolution mechanism of Common Lisp using symbol macros:
(defmacro let-with-resolution (bindings &body body)
`(symbol-macrolet ,(mapcar #'(lambda (form) (list (car form) `(fetch-aux ,(cadr form)))) bindings) ,#body))
(defmethod fetch-aux ((any t)) any)
(defmethod fetch-aux ((any reference)) (fetch-remote-reference any))
However, now things become pretty arcane; and the variables are no longer variables, but magic symbols, which merely look like variables. For example, modifying the content of a variable "bound" by this macro is not possible. The best you can do with this approach is to provide a setf expansion for fetch-aux, which modifies the original place.
Although libraries for lazy evaluatione and object persistence bring you part of the way, Common Lisp does not provide a portable way to implement fully transparent persistent values. Lazy or persistent values still have to be explicitly forced.
MOP can be used to implement lazy or persistent objects though, with the slot values transparently forced. It would take a change in the internals of the Common Lisp implementations to provide general transparency, so you could do e.g. (+ p 5) with p potentially holding a persistent or lazy value.
It is not possible to directly change the evaluation mechanisms. You would need to write a compiler for your code to something else. Kind of an embedded language.
On the CLOS level there are several ways to deal with it:
Two examples:
write functions that dispatch on the reference object:
(defmethod move ((object reference) position)
(move (dereference reference) position))
(defmethod move ((object automobile) position)
...))
This gets ugly and might be automated with a macro.
CHANGE-CLASS
CLOS objects already have an indirection, because they can change their class. Even though they may change their class, they keep their identity. CHANGE-CLASS is destructively modifying the instance.
So that would make it possible to pass around reference objects and at some point load the data, change the reference object to some other class and set the slots accordingly. This changing the class needs to be triggered somewhere in the code.
One way to have it automagically triggered might be an error handler that catches some kinds of errors involving reference object.
I would add a layer on top of your deserialize mechanism that dispatches based on the type of the incoming data.
I'm running up against a problem in understanding the CLOS way of handling file access within a class. In c++ I would be able to do this:
class Foo {
Foo (string filename); // opens the file (my_file) requested by the filename
~Foo (); // close the file
FILE * my_file; // a persistent file-handle
DataStruct my_data; // some data
void ParseData (); // will perform some function on the file and populate my_data
DataStruct * GetData () { return &my_data; } // accessor to the data
};
What I'd like to point out is that PraseData() will be called multiple times, and each time a new block of data will be parsed from the file and my_data will be altered.
I'm trying to perform the same trick in CLOS - create all the generic methods to parse the data, load the file, read headers, etc. as well as the class definition which I have as:
(defclass data-file ()
((filename :initarg :filename :accessor filename)
(file :accessor file)
(frame :accessor frame)))
In the "constructor" (i.e. initialize-instance) I open the file just as my c++ idiom. Then I have access to the data and I can parse the data as before. However, I'm told that using a "destructor" or (finalize) method to close the file is not idiomatic CLOS for handling this type of situation where I need the file to be around so I can access it outside of my data-file methods.
I'm going to define a function that loads a data-file, and then performs a series of analyses with its data, and then hopefully close it. What's a way to go about doing this? (I'm assuming a macro or some type of closure would work in here, but I'm not familiar enough with the lisp way to decide what is needed or how to implement it).
One option is to have the stream as a slot instead of the filename, and then scope it with WITH-OPEN-FILE:
(with-open-file (stream file)
(let ((foo (make-instance 'foo :stream stream)))
(frob foo)
(...other processing of foo...)))
Then your stream will be closed automatically.
I think I would lean towards making classes only to store complete authoritative data (what you call DataStruct?).
You don't really need a special class for "loading + storage of another class". Plus, that way has the unspoken invariant that my_data holds the data of my_file up to the current seek position, which seems a bit strange to my eye.
Put another way: what does Foo do? Given a filename, it loads data, and gives you a DataStruct. That sounds like a function to me. If you need to be able to run it in a thread, or fire events between loading records, a class is the natural way to do it in C++, but you don't need a class for those things in Lisp.
Also, remember that you don't need to use DEFCLASS in order to use generic methods in CLOS.
I don't know what the structure of your data is, but in similar situations I've made a parse-one-chunk function that takes a stream and returns one record, and then create a complete Foo instance inside a loop in a with-open-file. If the stream is never needed outside the scope of a with-open-file expansion, you never need to worry about closing it.