I stumbled upon the following syntax in Clojure
(defn function-name
{:style/indent 2}
[parameters]
(println "Function Body"))
what is the purpose of the {:style/indent 2} part and what does it do?
This is a hint for the Emacs (CIDER) editor. It means that the editor will automatically indent every invocation of this function handling the first two arguments as special:
(function-name arg1 arg2
arg3)
instead of the regular
(function-name arg1 arg2
arg3).
It doesn't affect the behaviour of the function in any manner.
See this for CIDER's indentation specifications.
It comes from CIDER. It tells CIDER how to indent code that calls function-name.
Related
In Practical Clojure's chapter on Java interop, the authors note the following about the Java interop "syntactic sugar" (e.g. (.method object arguments) instead of (. object method arguments)):
Since these “syntactic sugar” expansions happen in the same compilation phase as macro-expansion, macros that do complex code-generation may need to avoid them and use the new and . (dot) special forms directly.
I don't understand why "syntactic sugar" expansion happening in the same phase as macro expansion is a problem. Is it because there may be issues with the order of expansions?
Macros concerned with generating interop calls typically should use the desugared special form, but that's not because of when desugaring happens, nor is it a problem. And they don't have to: more times than I care to count, I've seen someone write:
(defmacro call [obj method & args]
`(~(symbol (str "." (name method))) ~obj ~#args))
which is just a total mess, compared to how it would look with the appropriate tool:
(defmacro call [obj method & args]
`(. ~obj ~method ~#args))
If you run the following it only prints "foo":
(if true (println "foo") (println "bar"))
;foo
However if you pass macros in as the arguments to the if, it seems to evaluate both macros immediately.
(defmacro foo
[]
(println "foo"))
(defmacro bar
[]
(println "bar"))
(if true (foo) (bar))
;foo
;bar
How do you avoid running both macros and just evaluate the one for the true condition?
EDIT:
The main source of my confusion is that this would work in common lisp. I don't know how common lisp handles compiling macros differently but I'm guessing it has to do with more freedom not being on the JVM.
To clarify the actual code was to create forms of a certain type without quoting them as arguments. The code was being iterated on and was going to get more complicated, but in the current state was along the lines of:
(defmacro foo
[arg1 arg2]
`(quote (~arg1 ~arg2 [])))
(defmacro bar
[arg1 arg2]
`(quote (~(first arg1) ~arg2 [~(second arg1)])))
(defmacro foobar
[arg1 arg2]
`(if (list? '~arg1)
(bar ~arg1 ~arg2)
(foo ~arg1 ~arg2)))
(foobar FOO "bar")
;; doesn't work since macros get compiled and you can't pass FOO as an argument to bar
(foobar (FOO "bar") "foobar")
;; (FOO "bar" ["foobar"])
I wanted both macros to not be expanded before evaluating the if since passing something other than a list to bar would cause an exception. I now understand that's not possible because expansion happens compile time. I've switched to using multimethods--which is more verbose, but more polymorphic I suppose.
Alan has the right of it (in terms of the immediate fix needed), but to speak to the reasoning:
Macros are evaluated at compile time, not runtime. It's patently impossible for something only known at runtime to control what's compiled, because all compilation is necessarily finished before runtime starts.
What you can do is make your if part of another macro, thus moving it to compile time as well.
You forgot the "syntax quote". The code should look like this:
(defmacro foo
[]
`(println "foo"))
(defmacro bar
[]
`(println "bar"))
(if true
(foo)
(bar))
;=> foo
Macros are abstraction on syntax. You use it when you see a pattern you often write, but because of argument evaluation you cannot use functions. Macros evaluate to code and there should not be side effects since you have no control over when it gets expanded (run).
foo and bar should have been functions. Then it will work as you intended.
(defn foo
[]
(println "foo"))
(defn bar
[]
(println "bar"))
(if true
(foo)
(bar)) ; prints "foo"
Using a macro when it's not needed is considered bad practice.
I have been looking at the source for defmacro which uses "let" in its definition:
(def
^{:doc "Like defn, but the resulting function name is declared as a
macro and will be used as a macro by the compiler when it is
called."
:arglists '([name doc-string? attr-map? [params*] body]
[name doc-string? attr-map? ([params*] body)+ attr-map?])
:added "1.0"}
defmacro (fn [&form &env
name & args]
(let [prefix (loop [p (list name) args args]
However, "let" is defined as a macro itself:
(defmacro let
"binding => binding-form init-expr
Evaluates the exprs in a lexical context in which the symbols in
the binding-forms are bound to their respective init-exprs or parts
therein."
{:added "1.0", :special-form true, :forms '[(let [bindings*] exprs*)]}
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(let* ~(destructure bindings) ~#body))
Can someone explain how this works as I can't understand how "defmacro" can be defined in terms of things which need "defmacro" to already be defined. (if that makes sense :)
This is possible because before defining defmacro function in core.clj there is already a definition of let at this location (which gets redefined later). Macros are just normal functions and the var they are bound to has meta data key :macro with value true so that at compile time the compiler can differentiate between a macro (which execute at compile time) with a function, without this meta key there is no way to differentiate between a macro and a function because macro itself is a function that happens to process S-expressions.
recusrive macros work fine and occur in many place in both the clojure language core and in other programs. macros are just functions that return S-Expressions, so they can be recursive just as functions can. In the case of let in your example it's actually caling let* which is a different function (its fine to have * in a functions name), so although recursive macros are fine, this doesn't happen to be an example of them
I apologize if the question is trivial, but some googling is not leading me anywhere. What is the general syntax of defmulti and defmethod? I can write simple multimethods, but I am not sure where I can put the docstring, pre and post conditions, metadata and so on.
I am actually interested in ClojureScript more than in Clojure, so if there are differences between the two, please tell me.
In a REPL you can use the doc function to get the function arguments and (most of the time) an explanation of the options. As for ClojureScript, these two functions are macros, which means they are expanded at compile time and should behave exactly as they do in regular Clojure. That is, as long as ClojureScript can handle the code the macro generates.
user=> (doc defmulti)
-------------------------
clojure.core/defmulti
([name docstring? attr-map? dispatch-fn & options])
Macro
Creates a new multimethod with the associated dispatch function.
The docstring and attribute-map are optional.
Options are key-value pairs and may be one of:
:default the default dispatch value, defaults to :default
:hierarchy the isa? hierarchy to use for dispatching
defaults to the global hierarchy
nil
user=> (doc defmethod)
-------------------------
clojure.core/defmethod
([multifn dispatch-val & fn-tail])
Macro
Creates and installs a new method of multimethod associated with dispatch-value.
nil
At Clojuredocs: defmulti, defmethod.
If you don't find the examples there detailed enough, you might consider adding your own (once you've gotten all your questions answered).
In a file i define these 2 macros:
(ns macros)
(defmacro foo [a]
`(+ ~a 2))
(defmacro bar [a]
`(* 2 (foo ~a)))
In clojure both macros work as intended.
In clojurescript only the macro "foo" works, "bar" produces this error:
"Error evaluating:" (bar 0) :as "(2 * macros.foo.call(null,0));\n"
org.mozilla.javascript.EcmaError: ReferenceError: "macros" is not defined. (<cljs repl>#4)
at <cljs repl>:4 (anonymous)
at <cljs repl>:4
It seems that here the "foo" macro gets not expanded but interpreted as a function call.
Ist this a bug in clojurescript or did i something wrong?
I believe the issue you're seeing here is due to the single element namespace for the macros file. If you change it to util.macros and put in the proper place on the classpath to account for that, it works.
Probably a bug given it works without issue in Clojure.