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).
Related
for example the Luminus website states that
Compojure route definitions are just functions that accept request
maps and return response maps...
(GET "/" [] "Show something")
...
But compojure routes are not functions
(defmacro GET "Generate a `GET` route."
[path args & body]
(compile-route :get path args body))
One can use the function make-route that returns a functions, but does not allow for destructuring. So as a function you can not use compojure's special syntax for destructing (i.e the vector) but does this stop any form of destructuring? Does the macro from given them a performance increase?
(make-route :get "/some_path" some_handler)
Couldn't the destructing syntax be passed to the function using a macro wrapper?
One reason macros are used is so the user can write function and symbol names without having to quote everything. Take this example from the Clojure Cookbook:
; Routing
(defroutes main-routes
(GET "/" [] (index))
(GET "/en/" [] (index))
(GET "/fr/" [] (index-fr))
(GET "/:greeting/" [greeting] (view greeting)))
All of the index* symbols, plus view and greeting would have to be quoted if GET were a function:
; Routing
(defroutes main-routes
(GET "/" [] '(index))
(GET "/en/" [] '(index))
(GET "/fr/" [] '(index-fr))
(GET "/:greeting/" '[greeting] '(view greeting)))
Since function arguments are evaluated before the function is invoked, (index) et al would be evaluated as soon as the form was read. Also, the greeting arg will be changing on each HTTP request, so it obviously is not known ahead of time.
The macro also takes care of all the destructuring magic which is not (normally) possible with a regular function.
The thing which is often confusing (and is not well explained to beginners) is that a line like:
(GET "/:greeting/" [greeting] (view greeting))
is not normal "Clojure code". Instead, it is a type of shorthand (Domain-Specific Language or DSL to be precise) that the GET macro will ingest and use as instructions on how to generate "legal" Clojure code. The DSL is normally much shorter, simpler, & more convenient for a human than the final generated code, just as Clojure is much shorter, simpler, & more convenient than the Java Bytecode produced by the Clojure compiler, or the machine assembly language code eventually produced by the JVM.
In short, each macro is a "pre-compiler" that turns the DSL into plain Clojure, which is then ingested by the Clojure compiler to generate Java bytecode.
Having said that, it could be re-arranged to put all of the macro magic into the defroutes macro so that the GET symbol was neither a function nor a macro, but just a type of marker like the :get keyword in the implementation. As a user, these kinds of implementation details normally don't matter much.
Update
It is best to use macros only when a function won't work or is very awkward. The deciding factor is usually if one wants to use bare (unquoted) symbols, but not evaluate them in advance. Core Clojure itself uses macros for many constructs that are "built-ins" in other languages, including defn, for, and, or, when, and others.
Also note that a macro cannot do some things a function can, such as being a parameter to a higher-order function like filter.
In summary, a function defines a behavior. A macro defines a language extension.
I need a function that can tell whether a symbol is pointing to a special form or a macro.
I found the function? function in the clojure.test namespace, so could use that, but I'm hesitant to use it because it seems to be intended only for testing purposes. Is it okay to use it for normal code? If not, how can I accomplish my goal.
As noted the comments, fn? does not work because it only works on functions themselves, not the symbols that point to them.
If it does what you want, use it. It's in clojure.test because it wasn't expected to be useful for non-test code, but if it's the best function for your particular use case, there's no reason to hamper yourself just because of where the function is located. In other words, clojure.test is separate from clojure.core for organization, not because it should only ever be used for tests.
you can find all special form, :-)
(defn special-symbol?
[s]
(contains? (. clojure.lang.Compiler specials) s))
Is there a way to use the reader with function values, e.g:
(read-string (pr-str +))
RuntimeException Unreadable form clojure.lang.Util.runtimeException
(Util.java:219)
?
As you might already know the output for (pr-str +) is not valid Clojure code that the reader can parse: "#<core$_PLUS_ clojure.core$_PLUS_#ff4805>". The output for function values when using the functions pr, prn, println and such, is intentionally wrapped around the #< reader macro that dispatches to the UnreadableReader, which throws the exception you are seeing.
For the example you provided you can use the print-dup function that works for basic serialization:
(defn string-fn [f]
(let [w (java.io.StringWriter.)]
(print-dup f w)
(str w)))
(let [plus (read-string (string-fn +))]
(plus 1 2))
The serialization done for the + function is actually generating the call to the class' constructor:
#=(clojure.core$_PLUS_. )
This only works of course if the class is already compiled in the Clojure environment where you are reading the string. If you serialized an anonymous function, saving it to a file and then reading it back in, when running a new REPL session, it will most likely not work since the class name for each anonymous function is different and depends on Clojure internals.
For arbitrary functions things get a lot more complicated. Sharing the source code might not even be enough, the function could rely on the usage of any number of other functions or vars that only exist in the source environment. If this is what you are thinking of doing, maybe considering other approaches to the problem you are trying to solve, will eliminate the need to serialize the value of arbitrary functions.
Hope it helps,
If you only need the name, can you just send the symbol with (name '+).
But generally speaking, it is a bad idea to use clojure read, if you want to read it back, as clojure's reader might execute some code in the process. Maybe have a look at the edn reader : clojure.edn/read-string
But maybe you just need to convert the string back to a symbol, in which case the (symbol name) function would be enough.
I was looking through the src of string? fn and had the a few questions. Below is the source of the string? fn -
(def
^{:arglists '([x])
:doc "Return true if x is a String"
:added "1.0"
:static true}
string? (fn ^:static string? [x] (instance? String x)))
What does giving a fn static metadata do?
Why is the static metadata given two times, shouldnt it be enough to specify it either for the fn or for the var?
Why does the anonymous fn have a name ?
For answers to 1. and 2., see d.j.sheldrick's comment on the question. Answer to 3.:
Firstly, although this is not relevant here, named functions can refer to themselves by their name. This allows them to return themselves as values or to call themselves through the usual call mechanism rather than recur to the top. Importantly, this is the correct self-call strategy for functions generating lazy seqs; I've gone into the reasons why in an earlier SO answer (see the part after the "How come you can wrap recursive calls in a lazy sequence..." block quote).
Secondly, functions are compiled to JVM classes. The classes are named by the Clojure compiler based on the namespace in which the function is defined if the function is unnamed; otherwise the name is used to generate a more meaningful name for the class. This is useful for debugging, since it makes stack traces more intelligible.
Is there an idiomatic way to get available namespaces that can be used?
(all-ns) returns only already used namespaces. (Package/getPackages) returns all Java packages available for import, but only those Clojure namespaces that are already used.
Then I stumbled upon this post, but it uses some classpath magic.
So I want to get something like ('clojure.core 'clojure.set ... 'clojure.contrib.accumulators 'clojure.contrib.condition ...) if I have the clojure.jar and contrib.jar on my classpath, but I haven't used anything yet.
You will need to do "classpath magic". Since there is no kind of registry, you have to walk the classpath and look in every clojure source file to determine what namespaces are available. (In case the files are not AOT compiled. Otherwise you'll need a different heuristic.)
I think the function used in the linked post is the best way to go: clojure.contrib.find-namespaces/find-namespaces-on-classpath.
Deprecated since Clojure 1.3.0; use now clojure.tools.namespace.find/find-namespaces and clojure.java.classpath/classpath from http://github.com/clojure/java.classpath
I have found bultitude to be a great tool for doing this.
Example:
user=> (require '[bultitude.core :as b])
nil
user=> (take 10 (b/namespaces-on-classpath))
(bultitude.core-test bultitude.core clojure.data clojure.string clojure.test clojure.xml clojure.inspector clojure.repl clojure.set clojure.test.junit)
user=> (b/namespaces-on-classpath :prefix "bultitude")
(bultitude.core-test bultitude.core)