Does clojure have identifier macros? - clojure

In other words, is there any way to trigger macro expansion on forms that don't look like (MACRO arg* ...).
To give a hypothetical example:
(defmacro my-var
(do (printf "Using my-var!\n") 42))
(+ my-var 1) ;; Should print & return 43
What I really want to do is call macroexpand on a term with free variables. I want to these free variables should have special meaning during macro expansion, but should go back to "normal" afterward.

This facility currently exists in Clojure as one of the features of the Clojure Contrib library tools.macro. The relevant tools.macro macros are defsymbolmacro, with-symbol-macros and symbol-macrolet – here's a symbol-macrolet example from the README (as found on the tip of the master branch right now):
(symbol-macrolet [def foo]
(def def def))
expands to (def def foo)
symbol-macrolet is used to introduce lexically scoped symbol macros, while defsymbolmacro introduces symbol macros to be applied inside any with-symbol-macros blocks (doing away with with-symbol-macros would only be possible with support from the Clojure compiler itself).
AFAIK, some version of symbol-macrolet has been a planned feature for inclusion in Clojure's compiler itself for quite a while; it is expected that when and if it lands, it will likely be called letmacro. There's no concrete public timeline for that, though, and it is certainly not guaranteed to land at all.
The names that tools.macro uses are inspired by Common Lisp, where the relevant macros are known as define-symbol-macro and symbol-macrolet. Since this is a standard compiler feature in CL, symbol macros introduced with define-symbol-macro are actually applied globally without assistance from any helper macros.

Sorry, no, Clojure does not have this feature.
With the exception of the reader macros such as quote ', syntax-quote `, dispatch #, etc. which do expand outside the function argument position, you cannot add macros that expand in this position.
Reader literals are slightly related in that you can define literal syntax that will be converted into a data structure at read time, though these cannot be used as variables like you are describing.
The auto-gensym feature of the syntax-quote reader macro has a little of this flavor though in a much more limited way.

Related

Getting more useful warnings when compiling Clojure

In the function bellow, I used cond in the place of case. It took me a long time to single out this function. I am learning clojure, so the error was not obvious to me. When I tried to run the code up to the map function (using the cursive/Intellij debugger), Intellij complained: There is no executable code at core.clj:144. If the clojure compiler knows that, is there an option to get a warning at compiler time? Are there other checks that the compiler (or a lint) can do in my code?
(defn uri-gen [uri fields line]
(let [remo "[//\\:*?()<>|.%'\"&]"]
(cond (count fields)
0 (correct-uri ...)
1 (let ...)
(correct-empty
uri
(apply str
(map (fn [it] ...)))))))
Unfortunately, compiler warnings & error messages in Clojure are often terse, nonsensical, or just plain missing.
I'm not sure if it would help in this instance, but you might try the eastwood Clojure lint tool (see others in the Clojure Toolbox). I also make extensive use of Plumatic Schema which has helped me to avoid many simple type errors.
The Clojure Toolbox
Eastwood
Plumatic Schema
It's not really the compiler's problem.
From the compiler's point of view, what you wrote makes perfect sense. You've got an s-expression composed of an s-expression followed by more s-expressions - what's the problem? A Lisp, such as Clojure, has darned little "syntax" for the compiler to "know" about. It does not, for example, have to worry about silly things like operator precedence and "if" and "while" and "until" statements and all the tons of other things that compilers for other languages dither over. It has no knowledge of what cond and case and and and whatever do - it just knows that, because they're the first value in an unquoted form, they must be a function; the compiler can in some sense "find" that function, so it can create the code to call the function; and there's a bunch of other valid expressions following it that need to be passed to the function. (And of course those other expressions may consist of more s-expressions, representing more functions to be called, and down the Lisp-hole we go!). KEWL! It's the function which has to make some sort of sense of the arguments it's passed and do whatever it is that the function is supposed to do. The compiler doesn't know anything about all that - in a very very oversimplified sense, it just reads s-expressions and generates code to call functions.
If you insist on passing case-ish arguments to cond, the compiler doesn't care. It will merrily do what you asked. The fact that cond will (probably) barf all over those arguments is not something for the compiler to deal with - it's the programmer's problem. Lisp/Clojure puts the responsibility for getting it right squarely on the shoulders of the programmer, where it belongs.
Lisp's are a kind of like a super-power for programmer's. In the right hands it's a valuable tool in the service of mankind. In the wrong hands, it's a recipe for disaster. Try not to be Tighten - use your powers wisely. :-)

Why does Crystal's macro syntax for iterating differ from the rest of Crystal

Coming from the Ruby world, I instantly understood why Crystal chose not to implement a for method. But then I was surprised to see that Crystal does implement a for method for macros. I was even more surprised to find that macros don't allow an enumerable (.each, etc) syntax (i.e. {% ["one", "two", "three"].each do |value| %} isn't valid macro syntax).
Is there a logical reason for this syntax difference? It's possible that the answer is simply ~"because the devs decided that macro syntax looks like x, and non-macro syntax looks like y", but I'm guessing that there is more to it then that (an arbitrary syntax inconsistency seems like a flaw).
Thanks!
The main reason is that when the parser parses foo.bar do |arg| ... end, it expects an expression after |arg|, not %}, which is a parse error. So to allow that we'd need to enhance the parser (which is already quite complex) to take that into account. for was decided because of this, but also to make it clear that it's just not regular crystal but a different thing (it's an interpreted subset of crystal and the standard library).
Another reason is that if each and other iteration methods are allowed, why not while and until? That could allow endless loops in macros, which with just for aren't possible, so you can guarantee a macro finishes executing. Which... is actually not true given that we have run inside macros.
So I think I'm not opposed to change the language to allow each, each_with_index, etc., inside macros, and allow that syntax, and eventually remove for from the macro language. Opening an issue requesting this is a good way in this direction.

What is the :inline keyword in Clojure functions?

I've came across this code snippet in Clojure's source code:
(defn ==
"Returns non-nil if nums all have the equivalent
value (type-independent), otherwise false"
{:inline (fn [x y] `(. clojure.lang.Numbers (equiv ~x ~y)))
:inline-arities #{2}
:added "1.0"}
.....
What does :inline do?
Update: Also found good example here.
An inline definition for a Clojure function gives the compiler the option of treating the operator as a macro instead of as a function. The trouble is that you have to provide a distinct macro body that need have nothing in common with the function body. You could define an inlinable version of + that actually did -!
This is highly dubious and quite undocumented. It seems to be used to plant faster code for small core functions.
By way of contrast, In C++, inline is a hint to the compiler to consider an inline expansion of any call of the function. An inline expansion is required to have the same semantics as an ordinary function call. Accessor and mutator functions are often inlined.
It is odd indeed to find an aspect of the Clojure language with soggier semantics than the corresponding C++.
I thought the feature was deprecated. It is not. It is the similar definline operator that is - not deprecated - but experimental. To be deprecated, it would have to be established first, and it has never reached that stage.
I am indebted to Alan Malloy's comments for the above corrections.
Note that in general, inlining provides little to no performance benefits, because the JVM JIT is able to inline hot function calls at runtime. A warmed-up JIT will thus often produce the same performance as an explicitly inlined function.
The benefits to inlining explicitly in Clojure are thus minimal, and it isn't even too clear to me when it would kick in, but arguably it would save you a tiny fraction of time when the JIT is cold, so on the first few times executing.
Another benefit of inlining is that it bypasses the Clojure boxing that normal function calls have. If you are using interop in a function where the Java method has overloads for specific primitive types, when wrapping it in a Clojure function, Clojure will at the call-site convert things back into boxed numbers, and your Java method will end up being called with a boxed variant. But if you inline it, it skips the function and so no boxing will happen, the value as-is, in the type it is currently, will be provided to the Java method.
How inlining works is as follows:
When the compiler sees a call to a Var, if the Var has :inline meta defined, instead of calling the function in the body of the Var, the compiler will call the :inline function where it passes to it the rest of the form non-evaluated and it will never call the function of the Var, but instead it will replace the whole form with the expansion returned by the :inline function.
If you only want to inline certain arities, but not all of them, you can optionally provide an :inline-arities meta on the Var as well, which is a predicate that will be called with the number of arguments of the current call and if it returns true, will use the :inline function to expand it, otherwise will call the function inside the Var as normal.
Remark that this works at the Var level, you cannot add :inline meta to a fn and expect it to be inlined, it only works if you have a Var.
Inlining is very similar to macros, in fact, you can inline things with a macro as well, the only difference is that macros have no fallback functions for where they can't be used, for example they cannot be used where only functions are supported, notably in higher-order calls. For example, you can't pass a macro as the reducing function to reduce. That's where inlining comes in, an inlinable function has both a macro that can inline the call where it can, and a function for where it can't, that way they work as a hybrid macro/function where the macro is used where macros can be used and the function is used where macros can't be used.
Because of that, it would be a little strange, even though it is permitted, that the inlined function, where it can run "as-a macro", would behave in a different way than when it can only run "as-a function".
This is why when you inline a function, please make sure the inlined function expands in a way that will behave as a function, and similarly to the fallback function for when it can't be inlined.
There also exists a definline macro, that defines an inlined function where it automatically infers the fallback function from the provided inlining function, that serves as a bit of a convenience in not having to write both. It is "experimental" I believe because I think it isn't clear if it would always successfully infer the fallback function you'd have written yourself. And also because I think they didn't know how useful it be, and it isn't as flexible as using the meta, since you can't control for specific arities. That said, it is usable if you want too.
Here's an example that explains well the difference between inline and macro:
(defmacro add-macro
[a b]
`(+ ~a ~b))
(definline add-inline
[a b]
`(+ ~a ~b))
(add-macro 1 2)
;; => 3
(add-inline 1 2)
;; => 3
(reduce add-macro [1 2])
;; Syntax error compiling at (src/playground.clj:62:1).
;; Can't take value of a macro: #'playground/add-macro
(reduce add-inline [1 2])
;; => 3
Macros work similar in that it applies to Vars with a meta tagged with :macro true, which tells the compiler not to call the function in the Var with the evaluated arguments, but instead with the non-evaluated arguments and replace the whole form with the expansion it returns. The compiler will check for the :macro meta before it does so for :inline, this is a detail, but if you were wondering, in the case both meta are found :macro and :inline, the macro will win.

Clojure: is `fn` a special-symbol, a macro or a special form?

The doc says that it's a special form, although I see that
it's defined as a macro.
Also (meta #'fn) has both :macro and :special-form as true.
Finally, (special-symbol? 'fn) is false although (special-symbol? 'fn*) is true.
Can someone clear this up for me?
Are there any other weird symbols in Clojure that are both special-form and macro
and not special-symbol?
And one more thing, it's the only callable symbol that I've seen so far that
has this (meta #'fn):
{:arglists ([& sigs]),
:forms [(fn name? [params*] exprs*)
(fn name? ([params*] exprs*) +)]...}
So the arg list isn't in :arglists like other symbols, but in :forms.
Any other symbols like this in Clojure?
Other examples are
let let*
letfn letfn*
loop loop*
The starred versions are truly special symbols at the compiler level, primitives of the language. The non-starred versions are vars defined within Clojure. These are helpers to the lower level starred versions that do things like destructuring, argument checking, and documentation at a more convenient level, i.e. in Clojure.
Clojure's documentation defines special forms rather strictly as "primitives built-in to Clojure that perform core operations". But this is really meant to less strictly apply to their non-starred helpers when applicable as in the documentation's list of special forms.
This is just semantics. In other places, other lisps, you'll see special form used to talk about any form that alters the normal rules of evaluation. So in that sense, you'd call the macro and a special form as it does short-circuit evaluation. In Clojure and is not tagged or documented as such, which is consistent with reserving the term for primitives or their helpers.

How to identify which forms are macros and which are functions while looking at a Clojure code?

Lisp/Clojure code have consistency in their syntax and it is a plus point as one doesn't need to understand various different constructs.
But at times It is easier to understand by looking at a piece of code just by the different syntax being used like this is a switch case or this is the pattern matching construct etc without actually reading the text.
I have started out with Clojure couple of months ago and I have realized I can't understand the code without reading the name of the form and then googling whether it is a macro or a function and how it works.
So it turns out that, a piece of Clojure code, irrespective fo the uniformity of the syntax isn't uniform.
It may seem like a function but if at all it is a macro then it might not be evaluating all its arguments.
Is there a naming convention or indentation style that all macros use so it is easier for someone to grasp by the name what is going on ?
The most useful intuition in my opinion comes from understanding the purpose of a given operator / Var. Well-designed macros simply could not be written as functions and still offer the same functionality with the same syntax, for if they could, they would in fact be written as functions (see the "well-designed" part above!).1 So, if you're dealing with a construct which couldn't possibly be a regular function, then you know it isn't; otherwise it likely is.
Additionally, the usual ways of learning about the Vars exported by a library tell you whether you're dealing with a macro or a function up front. That is true of doc ((doc foo) says that foo is a macro near the top of its output if that is indeed the case), source (since it gives you the entire code) and M-. (jump to definition in Emacs with nrepl.el or swank-clojure; M-, jumps back). Documentation may be expected to mention what is a macro and what isn't (except that's not necessarily true of docstrings, since all usual ways of accessing a docstring already tell you whether you're dealing with a macro, as explained above).
If you're skimming a body of code with the intention of forming a rough understanding of what it probably does on the assumption that the various operators perform the functions suggested by their names, then either (1) the names are suggestive enough and you get an idea of what's intended by the code, so you don't even need to care which operators happen to be macros, or (2) the names are not suggestive enough, so you'll need to dive into the docs or the source for some of the operators anyway, and then the first thing you'll learn is which of them are registered as macros.
Finally, there is no single naming style for macros, although there are certain conventions specific to particular use cases. For example with-foo-style constructs tend to be convenience macros whose purpose is to simplify dealing with resources of type foo; dofoo-style constructs tend to be macros which take a body of expressions to be executed (how many times and with which additional context set up depends on the macro; the most basic member of this family, do, is actually a special form rather than a macro); deffoo-style constructs introduce new Vars or type-like entities.
It's worth pointing out that similar patterns are sometimes broken. For instance, most threading constructs (-> & Co.) are macros, but xml-> from clojure.data.zip.xml is a function. That makes perfect sense when one considers the functionality provided, which brings us back to the point about the purpose of an operator being the most useful source of intuition.
1 There might be some exceptions to this rule. One would expect these to be documented. Some projects are of course not documented at all (or very nearly so); here the issue goes away completely, since one must go to the source to make sense of things anyway.
There are two attributes that typically distinguish a macro (or sometimes special form) from a function:
When the form does some sort of binding (i.e. declaring new identifiers for later use)
When some of the arguments are evaluated lazily
Examples of the first case are let, letfn, binding and with-local-vars. Strangely though, defn is defined as a function, but I'm pretty sure it has something to do with Clojure's bootstrapping process (defn is defined before defmacro is defined).
Examples of the second would be and, or and lazy-seq. In all these constructs, the arguments are evaluated lazily by either putting them in conditional branches (like if) or moving them inside a function body.
Both of those attributes are really just manifestations of the macro manipulating the Clojure syntax. I don't think the threading macros (-> and ->>) fit very well into either of those categories, but the nil-safe versions (-?> and -?>>) kind of fall under having lazy arguments.
As far as I know there is no enforced naming convention.
As a rule of thumb, functions are preferred wherever possible, but macros can sometimes be spotted when they follow the pattern def<something> for setting up a something or with-<resource> for doing something with an open resource.
Because of this, you may find clojure's doc macro helpful. It will tell you whether a form is a macro/function/special form, as well as give it's arg list and doc string (if present). For example
(use 'clojure.repl)
(doc and)
Will print the following to the repl.
clojure.core/and
([] [x] [x & next])
Macro
Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true.
Some editors (e.g. emacs) will provide this documentation as a pop-up or on a key combination, which makes accessing it (and reading) much faster.