I have a problem constructing a DSL in Clojure. This is the concrete problem I have isolated from everything else.
Let's say we hava a simple macro:
user> (defmacro m1 [x] `'~x)
#'user/m1
it just returns the literal supplied
user> (m1 toUpperCase)
toUpperCase
if we call java method for object everything works as expected
user> (. "a" toUpperCase)
"A"
but if we substitute method name for macro call that returns the methodname
user> (. "a" (m1 toUpperCase))
; Evaluation aborted.
Unable to resolve symbol: toUpperCase in this context
I want to use some java library that has fluent interface like a().b().c().
This maps to Clojure as:
(.. obj method1 method2 method3....etc)
I want to create macros that substitute some parts of this chain so my code should be like:
(.. obj method1 macro1)
and that should expand to
(.. obj method1 method2 method3)
definline also doesn't help. I tried that also
The reason you're running into this problem is that the . special form does not evaluate its second argument (the symbol specifying the method or field) in the way you expect: it sees it as a call of the METHOD m1, with the ARGUMENT toUppercase. Because of that, you cannot generate the symbol for the method dynamically just as an argument to . (dot) - even if you use a macro to specify that argument.
A way to work around that is to include the . in your macro:
(defmacro m1 [x y] `(. ~x (~y)))
(m1 "a" toUppercase)
user> "A"
Note that you need to wrap parentheses around ~y to indicate you want to call a method instead of reading a field.
Related
defmacro is documented at http://clhs.lisp.se/Body/m_defmac.htm but the documentation is not entirely clear on exactly when things happen. By experiment with Clisp, I have found the following (assuming all macros and functions defined at top level):
Straight top-level code can only call macros and functions that have been defined earlier.
Code within a macro or function, or generated by a macro, can call any function it likes, including one define later (as expected from the need to support mutual recursion).
Code within a macro can only call a macro defined earlier than the calling site of the first macro.
Code generated by a macro can call a macro defined later.
Is it the case that Clisp is just following the specification, or is there any variation between implementations in this regard?
Is the exact intended set of rules, and the rationale behind them, documented anywhere?
You are asking about macro expansion - but I'd like to clarify how functions are handled first.
Pay attention to when the calls and the defines actually happens. In your second point you say code within a function can call a function that is defined later. This isn't strictly true.
In languages like C++ you declare and define functions and then compile your app. Ignoring inlining, templates, lambdas and other magic..., when compiling a function, the declarations of all other functions used by that function need to be present - and at link time, the compiled definitions need to be present - all before the program starts running. Once the program starts running, all functions are already fully prepared and ready to be called.
Now in Lisp, things are different. Ignore compilation for now - let's just think about an interpreted environment. If you run:
;; time 1
(defun a () (b))
;; time 2
(defun b () 123)
;; time 3
(a)
At time 1 your program has no functions.
The first defun then creates a function (lambda () (b)), and associates it with the symbol a. This function contains a reference to the symbol b, but at this point in time it is not calling b. a will only call b when a itself gets called.
So, at time 2 your program has one function, associated with the symbol a, but it has not been executed yet.
Now the second defun creates a function (lambda () 123), and associates it with the symbol b.
At time 3 your program has two functions, associated with the symbols a and b, but neither has been called yet.
Now you call a. During its execution, it looks for the function associated with the symbol b, finds that such a function already exists at this point in time, and calls it. b executes and returns 123.
Let's add more code:
;; time 4
(defun b () 456)
;; time 5
(a)
After time 4, a new defun creates a function returning 456, and associates it with the symbol b. This replaces the reference b was holding to the function returning 123, which will then be garbage collected (or whatever you implementation does to take out the trash).
Calling a (or more correctly, the lambda referenced by the function attribute of the symbol a), will now result in a call to a function that returns 456.
If, instead, we had originally written:
;; time 1
(defun a () (b))
;; time 2
(a)
;; time 3
(defun b () 123)
... this would not have worked, because after time 2 when we call a, it can't find a function associated with the symbol b and so it will fail.
Now - compile, eval-when, optimisation and other magic can do all kinds of funky things different from what I've described above, but make sure you first have a grasp of these basics before worrying about that more advanced stuff.
Functions are only created at the time that defun is called. (The interpreter doesn't "look ahead in the file".)
One of the attributes of a symbol is a reference to a function. (The function itself doesn't actually have a name.)
Multiple symbols can reference the same function. ((setf (symbol-function 'd) (symbol-function 'b)))
Defining a function a that calls function b (speaking colloquially), is OK as long as the symbol b has an associated function by the time a is called. (It is not required at the time of defunning a.)
A symbol can refer to different functions at different times. This affects any functions "calling" that symbol.
The rules for macros are different (their expansions are static after "read" time), but many of the principles remain the same (Lisp doesn't "look ahead in the file" to find them). Understand that Lisp programs are far more dynamic and "run-time" than most (lesser ;-) ) languages you may be used to. Understand what happens when during execution of a Lisp program, and the rules governing macro expansion will start making sense.
I have a code-base for a graphics program in cljx that gets compiled to Clojure and ClojureScript.
I now want to introduce my first macro.
(defmacro optional-styled-primitive [args body]
(let [extra (conj args 'style)]
`(fn (~extra (->SShape ~'style ~body))
(~args (->SShape {} ~body))
)
)
)
The purpose of this macro is to take a list of arguments, and an expression that uses those arguments to generate a geometry. And to return a function with two arities : one of which takes an optional style parameter. This macro is then to be used within the file where it's defined, to make a number of other functions that optionally take styles. For example :
(def square (optional-styled-primitive [n] [[0 0] [0 n] [n n] [n 0]]))
But introducing this macro, obviously, breaks the ClojureScript stage of the compilation.
What I can't figure out is what to do about it. The online discussions talk about ClojureScript needing to use :require-macros but I never actually export or require this macro anywhere. I just want to use it where it's defined. So how can I, in the middle of a file, tell the compiler to use Clojure to expand this macro, before it gets to the ClojureScript compiler?
OK.
I've made some progress with this.
Here's what I did.
1) I refactored my macro definition out into a separate file called macros.cljx
2) In the file where I was using the macros, I did this. (A different require for clj and cljs)
(#+clj :require #+cljs :require-macros
[myapp.macros :refer [optional-styled-primitive]])
3) I updated my leiningen project.clj file :
:cljsbuild {:builds [{
:source-paths ["target/classes" "src-cljs" ] ...
The important thing here I added "target/classes", which is the output-path where cljx puts the clj files it creates, to the cljsbuild source-paths. This is where the cljsbuild process can find the clj file with the macro definition.
I'm not sure if this is the right or principled way to solve the problem. But it now seems to be working (unless I'm confused by something).
I have been trying to use Clojure tagged literals, and noticed that the reader does not evaluate the arguments, very much like a macro. This makes sense, but what is the appropriate solution for doing this? Explicit eval?
Example: given this function
(defn my-data
([[arg]]
(prn (symbol? arg))
:ok))
and this definition data_readers.clj
{myns/my-data my.ns/my-data}
The following behave differently:
> (let [x 1] (my.ns/my-data [x]))
false
:ok
So the x passed in is evaluated before being passed into my-data. On the other hand:
> (let [x 1] #myns/my-data [x])
true
:ok
So if I want to use the value of x inside my-data, the my-data function needs to do something about it, namely check that x is a symbol, and if so, use (eval x). That seems ugly. Is there a better approach?
Summary
There is no way to get at the value of the local x in your example, primarily because locals only get assigned values at runtime, whereas tagged literals are handled at read time. (There's also compile time in between; it is impossible to get at locals' values at compile time; therefore macros cannot get at locals' values either.)1
The better approach is to use a regular function at runtime, since after all you want to construct a value based on the runtime values of some parameters. Tagged literals really are literals and should be used as such.
Extended discussion
To illustrate the issue described above:
(binding [*data-readers* {'bar (fn [_] (java.util.Date.))}]
(eval (read-string "(defn foo [] #bar x)")))
foo will always return the same value, because the reader has only one opportunity to return a value for #bar x which is then baked into foo's bytecode.
Notice also that instead of passing it to eval directly, we could store the data structure returned by the call to read-string and compile it at an arbitrary point in the future; the value returned by foo would remain the same. Clearly there's no way for such a literal value to depend on the future values of any locals; in fact, during the reader's operation, it is not even clear which symbols will come to name locals -- that's for the compiler to determine and the result of that determination may be non-obvious in cases where macros are involved.
Of course the reader is free to return a form which looks like a function call, the name of a local etc. To show one example:
(binding [*data-readers* {'bar (fn [sym] (list sym 1 2 3 4 5))}]
(eval (read-string "#bar *")))
;= 120
;; substituting + for * in the string yields a value of 15
Here #bar f becomes equivalent to (f 1 2 3 4 5). Needless to say, this is an abuse of notation and doesn't really do what you asked for.
1 It's worth pointing out that eval has no access to locals (it always operates in the global scope), but the issue with locals not having values assigned before runtime is more fundamental.
I'd like to change the syntax of the following expression:
(> 2 1)
to something like:
(2 greater 1)
My first try is the following macro:
(define-syntax greater
(lambda (x)
(syntax-case x (greater)
[(a greater b)
(syntax (> a b))])))
Using this macro fails with: "bad syntax in: greater"
I've been surfing some Scheme docs, but I was not able to find the way to do it.
In Racket, there already exists a reader feature to allow for general infix notation: write a dot before and after the function or macro name: (2 . > . 1) It's a little verbose (the dots have to be surrounded by spaces), but I like it and use it a lot. See the documentation for more information.
The expression (2 greater 1) is an application. It expands to (#%app 2 greater 1). You must define your own version of #%app and call it, say, my-%app. If greater is present swap the first and second argument, otherwise just expand to the standard #%app.
To use your new application you must export it from the file (module) in which you define it, and then import it in the module where your want your special application syntax.
You might that the "curly-infix" notation is what you want. Just surround a list with {...}, and you can write the list contents in infix order instead of prefix order (the reader transforms it). So if you write {x + ,y} the reader maps it to (+ x ,y).
Curly-infix is defined in SRFI-105: http://srfi.schemers.org/srfi-105/
I know that the current version of GNU guile, at least, implements it.
The "sweet-expression" notation of SRFI-110 ( http://srfi.schemers.org/srfi-110/ ) builds on top of SRFI-105.
I want to write a macro that uses functions from the clj-time library. In one namespace I would like to call the macro like this:
(ns budget.account
(:require [budget.time]))
(budget.time/next-date interval frequency)
The next-date macro would be defined in another file like this:
(ns budget.time
(:require [clj-time.core :as date]))
(defmacro next-date [interval freq]
`(~interval ~freq))
If the macro were called with the following arguments (budget.time/next-date interval freq) and interval and freq where "weeks" and "2" repectively then the macro expand would look something like this (clj-time.core/weeks 2)
Whenever I try this from the REPL it cannot resolve the namespace.
Is there a way to force the macro to resolve interval to the arguments to the clj-time namespace? What is the best way to do this?
Thanks!
Macros return a list which is then evaluated in the namespace it is called from, not the namespace it is defined in. this is different than functions which evaluate in the namespace in which they where defined. This is because macros return the code to be run, instead of just running it.
if i go to another namespace, for instance hello.core and expand a call to next-date i get:
hello.core> (macroexpand-1 '(next-date weeks 2))
(weeks 2)
then after the expansion, weeks is resolved from hello.core, in which it is of course not defined. to fix this we need the returned symbol to carry the name-space information with it.
fortunately you can explicitly resolve a symbol in a namespace with ns-resolve. It takes a namespace and a symbol and tries to find it in the namespace returning nil if it's not found
(ns-resolve 'clj-time.core (symbol "weeks"))
#'clj-time.core/weeks
next your macro will be taking a symbol and a number so we can dispense with the explicit call to symbol
(ns-resolve 'clj-time.core 'weeks)
#'clj-time.core/weeks
so now you just need a function that resolves the function and then creates a list of the resolved function followed by the number,
(defmacro next-date [interval freq]
(list (ns-resolve 'clj-time.core interval) freq))
In the above macro all it does is make a function call which is immediatly called, so you don't even need a macro for this:
(defn next-date [interval freq]
((ns-resolve 'clj-time.core interval) freq))
(next-date 'weeks 2)
#<Weeks P2W>
the non-macro version requires you to quote the interval because it need it not to be evaluated before you can look it up. What the macro really buys you here is not having to include the quote, at the cost of requiring all the callers to require clj-time
of course you could also just require clj-time everywhere, but that's not really the point.