Redefining "def" in Clojure - clojure

Is there anyway to define a new macro under the name def in Clojure? I defmacroed a new one after trying to :refer-clojure :exclude the original, but it used the built-in definition anyway.
I was trying to enable Scheme-style function definitions ((def (f x y) ...) as (defn f [x y] ...)) using the following code.
(defmacro def
[ id & others ]
(if (list? id)
`(defn ~(first id) [~#(rest id)] ~#others)
`(def ~id ~#others)))

def is not a macro, it is a special form. It interns a symbol into current namespace. You cannot redefine special forms, but even if you could, how would you get same behavior?
The most straightforward way is to write define macro on base of def and defn. If you want to use def word, you can write a wrapper replace-my-def-with-normal-def around all the module, i.e.
(replace-my-def-with-normal-def
(def x 0)
(def y (inc x))
(def z (inc y))
(def (my-func a b) (println a b))
)
but I'm not sure it won't break other definitions, which depend on def (for example, defn).

You can create a macro with the name of a special form (like if), but it won't help you. Special forms are evaluated before macros, therefore if you have a macro and a special form of same name the special form will always be used. More information here http://clojure.org/evaluation.

Related

Create a macro to return a reify (java Interface) but with a supplied quoted expression in clojure

What I am trying to achieve is to implement an abstract class with reify inside a macro, but the expressions that should return on expansion time would be supplied to the macro quoted:
(defmacro a-printable
[body]
`(reify Printable
(print [this g# pf# page#]
(if (= page# 0)
(do
~body ;; the supplied part
(Printable/PAGE_EXISTS))
(Printable/NO_SUCH_PAGE)))
(def exp '(do (.translate g (.getImageableX pf) (.getImageableY pf))
(.drawString g "foo" 10 10))) ;; the form to pass
(a-printable exp)
The proplem is that in the expression I pass, I want to use the automatic generated vars defined inside the macro and inside reify g#, pf#.
I tried to add the quoted expression with (ns-resolve *ns* g) (ns-resolve *ns* pf) but with no lack, I am not sure that is being resolved inside the macro.
The g is java.awt.Graphics which is an abstract class and the pf is java.awt.print.PageFormat, which is normal class with constructor.
Does anyone has any idea how to achieve that, or turn me to the correct direction?
I believe the trick is that if you don't want namespaced symbols in a macro, you can prefix them with ~', e.g. ~'g. Then I did the following other modifications to your macro:
Prefix the body parameter with & to make it variable length.
Splice the body into the macro
Remove the parenthesis around (Printable/PAGE_EXISTS) and (Printable/NO_SUCH_PAGE): Those are static variable values that you want to return, not function calls.
This is what the fixed macro looks like:
(defmacro a-printable
[& body]
`(reify Printable
(print [~'this ~'g ~'pf ~'page]
(if (= ~'page 0)
(do
~#body ;; Splice it!
Printable/PAGE_EXISTS)
Printable/NO_SUCH_PAGE))))
And this is how you create an instance. Note that I do not need to wrap the argument to the macro with do:
(def p (a-printable
(.translate g (.getImageableX pf) (.getImageableY pf))
(.drawString g "foo" 10 10)))
A note however: I am not sure it is a good practice to introduce new symbols, such as pf and g, but I cannot find the reference mentioning why that would be a bad practice. There are ways of achieving similar things to what is being asked in this question without resorting to macros. The version that does not use macros is not much longer:
(defn a-printable-fn [body-fn]
(reify Printable
(print [this g pf page]
(if (= ~'page 0)
(do
(body-fn this g pf page)
Printable/PAGE_EXISTS)
Printable/NO_SUCH_PAGE))))
(def p (a-printable-fn
(fn [this g pf page]
(.translate g (.getImageableX pf) (.getImageableY pf))
(.drawString g "foo" 10 10))))

Evaluate symbol passed to def in Clojure

I am working through Clojure for the Brave and True. In the chapter on macros there is this exercise:
Write a macro that defines an arbitrary number of attribute-retrieving functions using one macro call. Here’s how you would call it:
(defattrs c-int :intelligence
c-str :strength
c-dex :dexterity)
What these functions do is retrieve a value from a map. For example given: (def character {:name "Travis", :intelligence 20, :strength 23, :dexterity 13})
The result of (c-int character) would be 20 of course such a function could easily be defined as (def c-int #(:intelligence %))
This is the solution I came up with to the problem:
(defmacro defattrs
[& attributes]
`(let [attribute-pairs# (partition 2 (quote ~attributes))]
(map (fn [[function-name# attribute-key#]]
(def function-name# #(attribute-key# %)))
attribute-pairs#)))
The problem I am having is that def uses the generated symbol name instead of what it resolves to to define the function (which in hindsight makes sense given the usage of def). My attempts to use expressions with defining functions such as:
(let [x ['c-int :intelligence]]
(def (first x) #((second x) %)))
Have resulted in this error: CompilerException java.lang.RuntimeException: First argument to def must be a Symbol, compiling:(/tmp/form-init5664727540242288850.clj:2:1)
Any ideas on how I can achieve this?
There are ordinary manipulations that you do with the attributes parameter that don't need to be generated as forms:
splitting the attributes into attribute-pairs; and
defining the function to generate a def form for each pair.
Applying the above to your code, we get ...
(defmacro defattrs [& attributes]
(let [attribute-pairs (partition 2 attributes)]
(map (fn [[function-name attribute-key]]
`(def ~function-name #(~attribute-key %)))
attribute-pairs)))
The scope of the back-quote is restricted to the def we wish to generate.
The values of the function-name and attribute-key parameters of the function are inserted into the def form.
There is one problem remaining.
The result of the map is a sequence of def forms.
The first one will be interpreted as a function to
apply to the rest.
The solution is to cons a do onto the front of the sequence:
(defmacro defattrs [& attributes]
(let [attribute-pairs (partition 2 attributes)]
(cons 'do
(map (fn [[function-name attribute-key]]
`(def ~function-name ~attribute-key))
attribute-pairs))))
I've also abbreviated #(~attribute-key %) to the equivalent ~attribute-key within the back-quoted form.
Let's see what the expansion looks like:
(macroexpand-1 '(defattrs dooby :brrr))
;(do (def dooby :brrr))
Looks good. Let's try it!
(defattrs gosh :brrr)
(gosh {:brrr 777})
;777
It works.
You have found the use-case for the back-quote and tilde. Just try this:
(let [x ['c-int :intelligence]]
(eval `(def ~(first x) #(~(second x) %))))
(def character {:name "Travis", :intelligence 20, :strength 23, :dexterity 13})
(c-int character) => 20
The back-quote is similar to the single-quote in that it makes the next form into a data structure of lists, symbols, etc. The difference is that the data structure is intended to be used as a template, where internal bits can be substituted using the tilde. The cool part is that the tilde doesn't just substitute items, but works for live code that can be any arbitrary Clojure expression.

how to apply gensym to each specific variable

I want to write a macro (my-dotimes [x init end] & body) that computes the value of body for x going from init to end-1 in increments of 1. Here you again have to make sure to avoid the "variable capture problem". It should work like this:
user=> (my-dotimes [x 0 4] (print x))
0123nil
my code is :
(defmacro my-dotimes [[x initial end] & body]
`(loop [i# ~initial]
(when (< i# ~end)
~#body
(recur (inc i#))))))
but when I use macroexpand to check it and find:
user=> (macroexpand '(my-dotimes [x 0 4] (println x)))
(loop* [i__4548__auto__ 0] (clojure.core/when (clojure.core/<i__4548__auto__ 4)
(println x)
(recur (clojure.core/inc i__4548__auto__))))
I am wondering how to change
(println x) => (clojure.core/println i__4548__auto__)
Here, you supply the symbol that should be bound to the counter (here x), so you don't need to use gensyms.
Instead of using i#, just introduce the symbol given to you by the user of the macro.
You need gensyms when you introduce new symbols and don't want them to collide with existing symbols.
In Common Lisp, it would make sense to wrap the body with a binding from the user-supplied symbol to the current value of i, using (let ((,x ,i)) ,#body), because the user's code could change the value of the counter during iteration (which could be bad). But here I think you cannot mutate the variable directly, so you don't need to worry about that.
Your second example is:
(defmacro for-loop [[symb ini t change] & body]
`(loop [symb# ~ini]
(if ~t
~#body
(recur ~change))))
First problem: when you expand the body, which might be one or more form, you'll end-up with an if form with many branches instead of 2. You would have for example (if test x1 x2 x3 (recur ...)) if your body contains x1, x2 and x3. You need to wrap bodies in do expressions, with (do ~#body).
Now, the situation is not very different than before: you still have a symbol, given by the user, and you are responsible for establishing the bindings in the macro. Instead of using symb#, which creates a new symbol, completely distinct from symb, just use symb directly.
You could do this for example (untested):
(defmacro for-loop [[symb init test change] &body]
`(loop [~symb ~init]
(if ~test (do ~#body) (recur ~change))))
As long as you use the symbol provided by the caller of your macro, gensyms are not necessary. You need gensyms when you have to create a new variable in the generated code, which requires to have a fresh symbol. For example, you evaluate an expression only once and need a variable to hold its value:
(defmacro dup [expr]
`(let [var# ~expr]
[var# var#]))

Documenting functions defined using point-free style

When creating a library in Clojure, it's good practice to include docstrings and other metadata on each function, e.g.:
(defn ^Boolean foo
"Returns whether x is bar."
{:added "1.5"}
[x]
(bar? x))
Sometimes (when working with higher-order functions) it ends up being easier to define a function using def (something-that-returns-a-fn), like this:
(defn wrapper [f]
"Some HOF, let's say it just prints 'WHARRGARBL' and then returns the fn."
(println "WHARRGARBL")
f)
(def foo
"Prints 'WHARRGARBL' and then returns whether x is bar."
(wrapper (fn [x] (bar? x))))
If I'm not mistaken, defining functions in this way nullifies the advantages of using defn -- namely, the docstring being printed in a nice way than includes what arities the function supports, and the ability to concisely include an attribute map inside the function definition. Am I right, or is there some other concise way to document functions created via HOFs? I could just do this:
(defn foo
"Prints 'WHARRGARBL' and then returns whether x is bar."
{:added "1.5"}
[x]
((wrapper (fn [y] (bar? y))) x))
but that seems a little redundant and unnecessarily complicated, as I'm defining a function of x to be a function of y, applied to x. Is there a better way?
You can add whatever metadata you wish with the def.
(def ^{:doc "Does something."
:added "1.5"
:arglists '([x]) }
foo
(wrapper (fn [x] (bar? x))))

In Clojure, how to define a variable named by a string?

Given a list of names for variables, I want to set those variables to an expression.
I tried this:
(doall (for [x ["a" "b" "c"]] (def (symbol x) 666)))
...but this yields the error
java.lang.Exception: First argument to def must be a Symbol
Can anyone show me the right way to accomplish this, please?
Clojure's "intern" function is for this purpose:
(doseq [x ["a" "b" "c"]]
(intern *ns* (symbol x) 666))
(doall (for [x ["a" "b" "c"]] (eval `(def ~(symbol x) 666))))
In response to your comment:
There are no macros involved here. eval is a function that takes a list and returns the result of executing that list as code. ` and ~ are shortcuts to create a partially-quoted list.
` means the contents of the following lists shall be quoted unless preceded by a ~
~ the following list is a function call that shall be executed, not quoted.
So ``(def ~(symbol x) 666)is the list containing the symboldef, followed by the result of executingsymbol xfollowed by the number of the beast. I could as well have written(eval (list 'def (symbol x) 666))` to achieve the same effect.
Updated to take Stuart Sierra's comment (mentioning clojure.core/intern) into account.
Using eval here is fine, but it may be interesting to know that it is not necessary, regardless of whether the Vars are known to exist already. In fact, if they are known to exist, then I think the alter-var-root solution below is cleaner; if they might not exist, then I wouldn't insist on my alternative proposition being much cleaner, but it seems to make for the shortest code (if we disregard the overhead of three lines for a function definition), so I'll just post it for your consideration.
If the Var is known to exist:
(alter-var-root (resolve (symbol "foo")) (constantly new-value))
So you could do
(dorun
(map #(-> %1 symbol resolve (alter-var-root %2))
["x" "y" "z"]
[value-for-x value-for-y value-for z]))
(If the same value was to be used for all Vars, you could use (repeat value) for the final argument to map or just put it in the anonymous function.)
If the Vars might need to be created, then you can actually write a function to do this (once again, I wouldn't necessarily claim this to be cleaner than eval, but anyway -- just for the interest of it):
(defn create-var
;; I used clojure.lang.Var/intern in the original answer,
;; but as Stuart Sierra has pointed out in a comment,
;; a Clojure built-in is available to accomplish the same
;; thing
([sym] (intern *ns* sym))
([sym val] (intern *ns* sym val)))
Note that if a Var turns out to have already been interned with the given name in the given namespace, then this changes nothing in the single argument case or just resets the Var to the given new value in the two argument case. With this, you can solve the original problem like so:
(dorun (map #(create-var (symbol %) 666) ["x" "y" "z"]))
Some additional examples:
user> (create-var 'bar (fn [_] :bar))
#'user/bar
user> (bar :foo)
:bar
user> (create-var 'baz)
#'user/baz
user> baz
; Evaluation aborted. ; java.lang.IllegalStateException:
; Var user/baz is unbound.
; It does exist, though!
;; if you really wanted to do things like this, you'd
;; actually use the clojure.contrib.with-ns/with-ns macro
user> (binding [*ns* (the-ns 'quux)]
(create-var 'foobar 5))
#'quux/foobar
user> quux/foobar
5
Evaluation rules for normal function calls are to evaluate all the items of the list, and call the first item in the list as a function with the rest of the items in the list as parameters.
But you can't make any assumptions about the evaluation rules for special forms or macros. A special form or the code produced by a macro call could evaluate all the arguments, or never evaluate them, or evaluate them multiple times, or evaluate some arguments and not others. def is a special form, and it doesn't evaluate its first argument. If it did, it couldn't work. Evaluating the foo in (def foo 123) would result in a "no such var 'foo'" error most of the time (if foo was already defined, you probably wouldn't be defining it yourself).
I'm not sure what you're using this for, but it doesn't seem very idiomatic. Using def anywhere but at the toplevel of your program usually means you're doing something wrong.
(Note: doall + for = doseq.)