What's the best way to rename Clojure's special forms?
For example, if I preferred defvar over def or defun over defn, what would be the best way to go about it?
Just use def and defn instead. You can define macros that forward to the underlying special forms, but it's in much better taste to just use the same primitives everyone else does.
While I perfectly agree with amalloy's answer it may be interesting to see the quick and dirty solution. You can forward the macro call by taking all the arguments of the original call and constructing another macro call using the genuine Clojure version.
(defmacro defvar [& xs] `(def ~#xs))
(defmacro defun [& xs] `(defn ~#xs))
Related
If the argument is a symbol return it. If the argument is a list call another method.
New to Clojure and cannot find the canonical way to do it. In Python, one could do:
def return_on_arg_type(arg):
if type(arg) is str:
return arg
if type(arg) is list:
return another_method(arg)
May be I could use multi-methods but how to match on type of the argument and also is matching on type acceptable in Clojure?
There's essentially 3 dispatch methods in Clojure:
Use cond combined with predicates (that's methods that return true or false and often have a name ending in ?) as Alan has described.
Use Protocols which dispatch on the type of the first argument. The reference documentation for this would be at https://clojure.org/reference/protocols
Multimethods. You can think of Multimethods as a programmable dispatch method. They can do much more than just look at the type of their arguments, they could also look into arguments, count elements on a vector argument and much more. Canonical documentation at https://clojure.org/reference/multimethods
Take a look at Clojure multimethods vs. protocols for a short discussion on Multimethods vs Protocols.
Not sure of the goal, but this should work:
(defn something [arg]
(cond
(str? arg) arg
(list? arg) (other-fn arg)))
It is ok to check for types in Clojure. It is not an un-typed language.
The code proposed by Alan is idiomatic IMHO if you need a simple dispatch mechanism.
There are other possibilities here. One you mentioned already: multi-methods.
Your example could be written as
(defmulti something class [arg])
(defmethod something String [arg] arg)
(defmethod something java.util.List [arg] (some-other arg))
The dispatch fn is class in this case, but you can implement any kind of dispatch condition.
There's also clojure.match, a general purpose matching library (among others). See https://github.com/clojure/core.match
Next to using a multimethod or a method to explicitly check, it's also possible to dispatch on the type of first argument with a protocol:
(defprotocol OnArgTypeReturner
(return-on-arg-type [arg]))
(extend-protocol OnArgTypeReturner
String
(return-on-arg-type [arg] arg)
clojure.lang.IPersistentList
(return-on-arg-type [arg] "another-method-called"))
(return-on-arg-type "foo")
;; => "foo"
(return-on-arg-type '(1 2 3))
;; => "another-method-called"
Clojure, has a declare macro that allows you to forward-declare functions or variables. It seems to function exactly as def: Both (declare x) and (def x) create #<Unbound Unbound: #'user/x>
When should (declare x) be used instead of (def x)?
Both declare and def do create an unbound var, but there are 3 advantages to using declare:
You can create multiple vars in one statement, e.g. (declare x y z)
The vars are tagged with the additional metadata {:declared true}
Using the word declare is arguably more clear and idiomatic
(source declare):
(defmacro declare
"defs the supplied var names with no bindings, useful for making forward declarations."
{:added "1.0"}
[& names] `(do ~#(map #(list 'def (vary-meta % assoc :declared true)) names)))
The documentation gives the answer:
=> (doc declare)
-------------------------
clojure.core/declare
([& names])
Macro
defs the supplied var names with no bindings, useful for making forward declarations.
Looking at the implementation, it's clear that declare is defined in terms of def and provides a little bit of syntax sugar. So functionally, they're pretty much the same.
The advantage of declare is to show intent for a later reader. (declare x y z) means I intended to make a forward declaration of those symbols, because the macro is useful for making forward declarations.
(def x) (def y) (def z) means I'm interning these symbols, but you don't know if I meant to give them definitions and forgot to or whether I'm making forward declarations, or maybe something else subtle.
So, (declare x) should be preferred over (def x) when you're making a forward declaration, to show mercy on future readers of your code.
def always applies to the root binding, even if the var is thread-bound at the point where def is called.
def yields the var itself (not its value). Throws an exception if symbol is already in the namespace and not mapped to an interned var.
Declare defs the supplied var names with no bindings, useful for making forward declarations.
Is it possible to do this in one function:
(binding [*configs* (merge default-configs configs)]
(let [{:keys [login url max-pages]} *configs*]
..
When I tried this:
(binding [{:keys [login url max-pages] :as *configs*} (merge default-configs configs)]
It gave me this error:
CompilerException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.Symbol
A little googling showed me that Common Lisp has a function called destructure-bind but I'm not sure if that's related.
No, nothing like this will work with core macros.
The reason is that both binding and let (and friends, e.g. with-bindings) do just one thing. In the case of binding, that thing is installing thread-local bindings for Vars; for let, it is introducing local bindings. These are entirely different operations.
In let, destructuring has a clear meaning: it introduces new locals, which is exactly what the basic, non-destructuring let bindings do. This is also clearly useful, as prying appart data structures and binding different parts to different locals is a common need. The names of the locals are also locally determined, so things like :keys in associative destructuring work well.
In binding, to be consistent with its main purpose, destructuring would need to bind several Vars simultaneously to several parts of a data structure. This is not nearly as useful. If instead destructuring in binding were to introduce locals, then all of a sudden binding would do two unrelated things, possibly both in the same binding pair (note how the failing binding form from the question text expects the bindings introduced by :keys to be locals, but the binding made by :as to be the usual thread-local binding of a Var). Thus binding simply opts not to support destructuring. (If you need to bind parts of a data structure to several Vars, you can use a let to perform the destructuring, then install the bindings with binding.)
As for destructuring-bind, it's basically the destructuring-enabled version of let in Common Lisp. CL's let does not support destructuring.
"Binding Forms (Destructuring)" section:
Clojure supports abstract structural binding, often called
destructuring, in let binding lists, fn parameter lists, and any macro
that expands into a let or fn. ...
AFAIK binding itself doesn't use destructuring mechanism (via fn of let).
I've seen the ^:static metadata on quite a few function in the Clojure core.clj source code, e.g. in the definition of seq?:
(def
^{:arglists '([x])
:doc "Return true if x implements ISeq"
:added "1.0"
:static true}
seq? (fn ^:static seq? [x] (instance? clojure.lang.ISeq x)))
What precisely does this metadata do, and why it it used so frequently throughout core.clj?
In the development of Clojure 1.3 Rich wanted to add the ability for functions to return types other than Object. This would allow native math operators to be used without having to cram everything into one function.
The original implementation required functions that supported this to be marked :static. this meta data caused the compiler to produce two versions to the function, one that returned Object and one that returned that specific type. in cases where the compiler determined that the types would always match the more specific version would be used.
This was later made fully automatic so you don't need to add this anymore.
According to the Google Groups thread “Type hinting inconsistencies in 1.3.0”, it’s a no-op.
^:static has been a no-op for a while AFAIK, made unnecessary after changes to vars a while back.
— a May 2011 post by Chas Emerick
Seems it's a new metadata attribute in clojure 1.3. And you can compare the source between 1.3 and 1.2:
http://clojuredocs.org/clojure_core/clojure.core/seq_q
http://clojuredocs.org/clojure_core/1.2.0/clojure.core/seq_q
So I think it has something to do with ^:dynamic which indicates whether the var is allowed for dynamic binding. Just my guess. Not sure until I see document about this attribute.
With clojure functions, I can define:
(defn f [x & xs] (apply some-function x xs))
I'm attempting to do this same sort of thing with a protocol, e.g.
(defprotocol foo
(bar [f])
(baz [f & gs]))
This compiles (at least in the REPL), but any implementing type seems to fail on this (the variadic, baz) method. Is this officially not supported? The sources that I've consulted are silent.
This is not supported, for the reasons Stuart Sierra gives. To go into a little more detail, the & symbol is special only in a destructuring context like let or function arguments. As Stuart makes clear, defprotocol is not such a context.
But & is still a legal symbol, so you've defined a protocol with two functions: bar takes one argument, named f, and baz takes three, named f, &, and gs.
As answered Stuart Sierra in following thread, variadic methods aren't supported, and possibly will not supported in the future