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))
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”.
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.
I'm currently following the book Learn You Some Erlang for Great Good by Fred Herbert and one of the sections is regarding Macros.
I understand using macros for variables (constant values, mainly), however, I don't understand the use case for macros as functions. For example, Herbert writes:
Defining a "function" macro is similar. Here's a simple macro used to subtract one number from another:
-define(sub(X, Y), X-Y).
Why not just define this as a function elsewhere? Why use a macro? Is there some sort of performance advantage from the compiler or is this merely just a "this function is so simple, let's just define it in one line" type of thing?
I'm not trying to start a debate or preference argument, but after seeing some production Erlang code, I've started noticing lots of macros function usage.
In this case, the one obvious advantage of the macro not being a function (-define(sub(X, Y), X-Y), which would be safer as -define(sub(X, Y), (X-Y))) is that it can be used as a guard since custom function calls are forbidden.
In many cases it would otherwise be safer to define the function as an inlined one.
On the other hand, there are other interesting cases, such as assertions in tests or shortcuts where what you want is to keep some local context in the final place.
For example, let's say I want to make a generic call for a test where the objective is 'match a given pattern and return a given value, or fail after M milliseconds'.
I cannot make this generic with code since patterns are not data structures you are allowed to carry around. However, with macros:
-define(wait_for(PAT, Timeout),
receive
PAT -> VAL
after Timeout ->
error(timeout)
end).
This macro can then be used as:
my_test() ->
Pid = start_whatever(),
%% ...
?wait_for({'EXIT', Pid, Reason}, 5000),
?assertMatch(shutdown, Reason).
By doing this, I'm able to simplify the form of text in some tests without needing a bunch of nesting, and in a way that is not possible with functions.
Do note that the assertion itself as defined by eunit is using a function macro, and does something akin to
-define(assertMatch(PAT, TERM),
%% funs to avoid leaking bindings into parent scope
(fun() ->
try
PAT = TERM,
true
catch _:_ ->
error({assertion_failed, ?LINE, ...})
end
end)()).
This similarly lets you carry patterns and bindings and do fancy forms that couldn't be possible otherwise.
In this last case, you'll notice I used the ?LINE macro. That's another advantage of macros: you preserve information and locality about the call site, such as its module name, line number, and so on. This is useful when such metadata is required, such as when you're reporting test failures.
If you're looking at old code, there might be macros used as a way of inlining small functions under the assumption that function calls are very expensive. I'm not sure if that was ever true, but it's not something you need to worry about today.
Macros can be used to define constants, like
-define(MAX_TIMEOUT, 30 * 1000).
%% ...
gen_server:call(my_server, {do_stuff, Data}, ?MAX_TIMEOUT),
%% ...
I mostly prefer to pass in environment variables for this job, but it's more work to read them on startup and stash them somewhere and write accessors.
Finally, you can do some simple metaprogramming:
-define(MAKE_REQUEST_FUN(Method),
Method(Request, HTTPOptions, Options) ->
httpc:request(Method, Request, HTTPOptions, Options)).
?MAKE_REQUEST_FUN(get).
?MAKE_REQUEST_FUN(put).
%% Now we've defined a get/3 that can be called as
%% get(Request, [], []).
I am writing a macro in Scala, but when I call it I get an error message saying "Double does not take parameters". Clearly there is something wrong with how the macro builds the AST. So how can I see the expanded macro? Is there a way to call the macro implementation at runtime?
Provide -Ymacro-debug-lite or -Ymacro-debug-verbose option to the compiler.
Off the top of my head, detalization of printed ASTs is governed by -Yshow-trees-compact, -Yshow-trees-stringified, -Xprint-types, -uniqid and -Yshow-symkinds. You can find other gems by running scala -X and scala -Y (or inspecting the sources of scala settings at https://github.com/scala/scala/blob/2.10.x/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala).
Also, despite being essentially a macro, reification has its own tracing mechanism that can be configured by -Yreify-copypaste and -Yreify-debug.
There is Macrocosm's desugar which can show how your source code, including, but no limited to macros, is transformed into.
println("TRANSFORMATION:\n"+ desugar{
println("a string")
MY_MACRO("something")
})
defrecord in clojure allows for defining simple data containers with custom fields.
e.g.
user=> (defrecord Book [author title ISBN])
user.Book
The minimal constructor that results takes only positional arguments with no additional functionality such as defaulting of fields, field validation etc.
user=> (Book. "J.R.R Tolkien" "The Lord of the Rings" 9780618517657)
#:user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657}
It is always possible to write functions wrapping the default constructor to get more complex construction semantics - using keyword arguments, supplying defaults and so on.
This seems like the ideal scenario for a macro to provide expanded semantics. What macros have people written and/or recommend for richer defrecord construction?
Examples of support for full and partial record constructor functions and support for eval-able print and pprint forms:
http://david-mcneil.com/post/765563763/enhanced-clojure-records
http://github.com/david-mcneil/defrecord2
David is a colleague of mine and we are using this defrecord2 extensively in our project. I think something like this should really be part of Clojure core (details might vary considerably of course).
The things we've found to be important are:
Ability to construct a record with named (possibly partial) parameters: (new-foo {:a 1})
Ability to construct a record by copying an existing record and making modifications: (new-foo old-foo {:a 10})
Field validation - if you pass a field outside the declared record fields, throw an error. Of course, this is actually legal and potentially useful, so there are ways to make it optional. Since it would be rare in our usage, it's far more likely to be an error.
Default values - these would be very useful but we haven't implemented it. Chas Emerick has written about adding support for default values here: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
Print and pprint support - we find it very useful to have records print and pprint in a form that is eval-able back to the original record. For example, this allows you to run a test, swipe the actual output, verify it, and use it as the expected output. Or to swipe output from a debug trace and get a real eval-able form.
Here is one that defines a record with default values and invariants. It creates a ctor that can take keyword args to set the values of the fields.
(defconstrainedrecord Foo [a 1 b 2]
[(every? number? [a b])])
(new-Foo)
;=> #user.Foo{:a 1, :b 2}
(new-Foo :a 42)
; #user.Foo{:a 42, :b 2}
And like I said... invariants:
(new-Foo :a "bad")
; AssertionError
But they only make sense in the context of Trammel.
Here is one approach: http://david-mcneil.com/post/765563763/enhanced-clojure-records