I understand keywords in Clojure being :keyword. But what is the :: used for? Why does it look like it has a binding?
user=> :foo
:foo
user=> ::foo
:user/foo
The double colon is there to fully qualify keywords with your current namespace. This is intended to avoid name clashes for keywords which are meaningful for different libraries. Without fully qualified keywords you might accidentally overwrite some values in a map and break compatibility with a library.
As now documented for Clojure as well as for ClojureScript, :: keywords can also be used to resolve namespace aliases. For example, ::foo/bar will evaluate to :clojure.core/bar if foo is an alias of clojure.core. Reader exception is thrown if foo does not resolve to a namespace.
Related
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.
(defn hi[](+ 5 6))
(hi)
(defn hi[](+ 6 7))
(hi)
Hi,
i'm new to clojure . as above writen code i wrote two functions with same name.
can we have same name for multiple functions in clojure. if yes does it conflict within same namespaces?
You cannot have several functions with the same name in the same namespace. If you define function foo and then redefine it again, newer version will replace the older.
It's not quite clear what you're trying to achieve, but Clojure has quite a few ways to have several implementations under one name.
Arity Dispatch
You can dispatch functions on arity:
(defn foo
([x] :version-one)
([x y] :version-two)
([x y & more] :version-tree))
Different arities of the same function can call one another, and this is somewhat equivalent to having several functions with the same name.
Multimethods
You can dispatch using multimethods. They allow you to define a function that will be called on arguments and its result will be used for dispatching.
(defmulti foo odd?)
(defmethod foo true [x]
(format "look, ma, %d is odd!" x))
(defmethod foo false [x]
(format "look, ma, %d is even!" x))
Protocols
This technique is similar to polymorphism in other languages. You can dispatch on argument type. Here is example:
(defprotocol foo
(my-fnc [x] "description..."))
(extend-protocol foo
Number
(my-fnc [x] :number-version)
String
(my-fnc [x] :string-version))
Multimethods are most powerful tool, you can emulate protocols with them this way:
(defmulti foo class)
I wrote two functions with same name.
Yes and No:
You wrote two function definitions with the same name.
The second definition overwrote the first.
The functions never shared the name.
Can we have same name for multiple functions in clojure?
Not in the same namespace. A second def or defn for a symbol erases the first.
There is only one symbol with a given name in a namespace.
A symbol refers to only one var at a time.
The def form ties a symbol to the var it refers to.
The fn form creates a function.
The defn macro is a wrapper round the def and fn forms,
causing the named symbol to refer to a var holding the function.
Symbols with the same name in different namespaces do not conflict:
they are different symbols.
If yes does it conflict within the same namespace?
Yes.
But ...
One function can have several arities - argument counts. This applies to functions referred to by symbols through vars and in other contexts.
Function definition is a side-effect of evaluating a defn. The best explanation I know of how lisps evaluate function definitions is Chapter 2 of Paul Graham's On Lisp.
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 declare a multmethod with defmulti but then I have defmethods scattered all around my code base and it seems to "just work" without having to declare any explicit namespace in front of the multimethod declaration! Is this because all multimethods use some form of global namespace?
You don't need to repeat the multimethod's namespace in front of the multimethod's name because you have already referred the multimethod's name in your namespace, probably via the use of :use in the namespace decl.
In clojure, how do I type type hint a type that I have created? (I want to nest the types.)
e.g. I had thought that this would work:
(deftype A
[#^somePrimitive someField])
(deftype B
[#^A Avalue])
This brings up an error message:
Unknown location:
error: java.lang.ClassNotFoundException: A
Note: clojure types are a new feature which currently exists only in the 'new' branch of clojure.
Edit: I was confused by the different ways of type hinting in clojure for java and clojure types.
java classes are hinted as
#^java.some.class
while clojure types are hinted as:
#^:some.Namespace/type
For each deftype, a type tag (basically a namespace-qualified keyword) is created so you don't have to AOT-compile your code before you can use the resulting class.
If type A is in the current namespace, you can write it like this:
(deftype B [^::A Avalue])
For types in other namespaces, qualify the keyword using its namespace:
(deftype B [^:user/A Avalue])
(deftype B [#^:user/A Avalue]) works for me.