I'm learning Clojure and I have seen pieces of code with :some-value. What's that ? I saw some code like this
(defn relay [x i]
(when (:next x)
(send (:next x) relay i))
(when (and (zero? i) (:report-queue x))
(.put (:report-queue x) i))
x)
if I print the when documentation, I don't find :next there
(doc when)
-------------------------
clojure.core/when
([test & body])
Macro
Evaluates test. If logical true, evaluates body in an implicit do.
nil
Where is :next definition ?
Thanks!
Those are keywords. Googling what they are can be surprisingly difficult if you don't already know what they are.
They evaluate to themselves:
user=> :foo ; evaluates to :foo
They are unique, potentially namespace-qualified identifiers. Which is why they are frequently used as keys in maps:
(def stuff {:a 1
:b 2})
They know how to look themselves up (i.e. you can call them as functions):
(:a stuff) ; 1
...which is the use-case in your example code. They're quite nice.
Related
Given that :post takes a form that gets evaluated later (e.g. {:post [(= 10 %)]}). How could one dynamically pass a 'pre-made' vector of functions to :post?
For example:
(def my-post-validator
[prediate1 predicate2 predicate3])
(defn foo [x]
{:post my-post-validator}
x)
this throws a syntax error
Don't know how to create ISeq from: clojure.lang.Symbol
With my fuzzy understanding, it's because defn is a macro, and the thing that allows the % syntax in :post is that it's quoted internally..?
I thought maybe I then use a macro to pass a 'literal' of what I wanted evaluated
(defmacro my-post-cond [spec]
'[(assert spec %) (predicate2 %) (predicate n)])
example:
(defn foo [x]
{:post (my-post-cond :what/ever)}
x)
However, this attempt gives the error:
Can't take value of a macro
Is there a way to pass a vector of things to :post rather than having to define it inline?
You can't pass a vector of predefined predicates, but you can combine multiple predicates under a single name and use that name in :post:
(defn my-post-cond [spec val]
(and
;; Not sure if this is exactly what you want,
;; given that `val` becomes an assert message.
(assert spec val)
(predicate2 val)
;; You used `n` - I assume it was supposed to be `%`.
(predicate val)))
(defn foo [x]
{:post [(my-post-cond :what/ever %)]}
x)
I started off as a fan of pre- and post-conditions, but I've changed over the years.
For simple things, I prefer to use Plumatic Schema to not only test inputs & outputs, but to document them as well.
For more complicated tests & verifications, I just put in an explicit assert or similar. I also wrote a helper function in the Tupelo library to reduce repetition, etc when debugging or verifying return values:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn oddly
"Transforms its input. Throws if result is not odd"
[x]
(let [answer (-> x (* 3) (+ 2))]
(with-result answer
(newline)
(println :given x)
(assert (odd? answer))
(println :returning answer))))
(dotest
(is= 5 (oddly 1))
(throws? (oddly 2)))
with result
------------------------------------
Clojure 1.10.3 Java 11.0.11
------------------------------------
Testing tst.demo.core
:given 1
:returning 5
:given 2
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
Passed all tests
So with either the println or assert, the returned value is easy to see. If it fails the assert, an Exception is thrown as normal.
Given a binding form such as [{a :a} {b :b}] how can I find all the symbols? (a b)
The naïve approach would be to just treat the binding form as some nested collection, find all the symbols in that collection, and return the sequence of those symbols:
(defn symbols [x]
(filter symbol? (tree-seq coll? seq x)))
(symbols '[{a :a} {b :b}])
;;=> (a b)
However, as #amalloy noted, this won't work in all cases. Here are some examples where the above implementation of symbols gives an undesirable result:
;; & isn't actually bound to anything
(symbols '[foo & bar])
;;=> (foo & bar)
;; duplicates
(symbols '{x :foo :or {x :bar}})
;;=> (x x)
;; keys and default values are evaluated, not bound
(symbols '{x (keyword "foo") :or {x (keyword 'bar)}})
;;=> (x keyword x keyword quote bar)
;; namespaced keywords and symbols don't work
(symbols '{:keys [::foo :bar/baz qux/quux]})
;;=> (qux/quux)
He suggests using the built-in destructure function instead, but as he demonstrated in his answer, this causes some garbage to show up in the result:
(take-nth 2 (destructure '[{:keys [x]} (last y)]))
;;=> (map__10938 map__10938 x)
While this technically gives the list of symbols that Clojure will bind, that map__10938 is just an implementation artifact, and has nothing to do with the destructuring language itself.
Thankfully, it's not too hard to parse the binding form manually and assemble a set of the symbols, taken from the original binding form, that would be bound:
(require '[clojure.set :as set])
(defn symbols [binding]
(cond
(symbol? binding)
#{binding}
(vector? binding)
(apply set/union (map symbols (remove #{'& :as} binding)))
(map? binding)
(apply set/union
(for [[k v] binding]
(case k
:or #{}
:as #{v}
(:keys :strs :syms) (set (map (comp symbol name) v))
(symbols k))))))
Much better is to use clojure.core/destructure, which understands which symbols are names that will be bound, rather than values that will be taken apart. For example, consider:
(let [{:keys [x]} (last y)]
x)
In that context you almost certainly don't want to include last in the list of symbols, presuming that you are using this to better understand a destructuring spec. And if you call destructure, it tells you exactly what names will be bound to what values:
user> (destructure '[{:keys [x]} (last y)])
[map__10938 (last y)
map__10938 (if (clojure.core/seq? map__10938)
(clojure.lang.PersistentHashMap/create (clojure.core/seq map__10938))
map__10938)
x (clojure.core/get map__10938 :x)]
Now on the one hand you are getting a symbol that wasn't actually typed in by the caller, but that's probably still useful, because it tells you what Clojure will actually do to handle this let expression. To get just the left-hand side, ie the names that will be bound, you can use
(take-nth 2 (destructure '[{:keys [x]} (last y)]))
Leonardo Borges has put together a fantastic presentation on Monads in Clojure. In it he describes the reader monad in Clojure using the following code:
;; Reader Monad
(def reader-m
{:return (fn [a]
(fn [_] a))
:bind (fn [m k]
(fn [r]
((k (m r)) r)))})
(defn ask [] identity)
(defn asks [f]
(fn [env]
(f env)))
(defn connect-to-db []
(do-m reader-m
[db-uri (asks :db-uri)]
(prn (format "Connected to db at %s" db-uri))))
(defn connect-to-api []
(do-m reader-m
[api-key (asks :api-key)
env (ask)]
(prn (format "Connected to api with key %s" api-key))))
(defn run-app []
(do-m reader-m
[_ (connect-to-db)
_ (connect-to-api)]
(prn "Done.")))
((run-app) {:db-uri "user:passwd#host/dbname" :api-key "AF167"})
;; "Connected to db at user:passwd#host/dbname"
;; "Connected to api with key AF167"
;; "Done."
The benefit of this is that you're reading values from the environment in a purely functional way.
But this approach looks very similar to the partial function in Clojure. Consider the following code:
user=> (def hundred-times (partial * 100))
#'user/hundred-times
user=> (hundred-times 5)
500
user=> (hundred-times 4 5 6)
12000
My question is: What is the difference between the reader monad and a partial function in Clojure?
The reader monad is a set of rules we can apply to cleanly compose readers. You could use partial to make a reader, but it doesn't really give us a way to put them together.
For example, say you wanted a reader that doubled the value it read. You might use partial to define it:
(def doubler
(partial * 2))
You might also want a reader that added one to whatever value it read:
(def plus-oner
(partial + 1))
Now, suppose you wanted to combine these guys in a single reader that adds their results. You'll probably end up with something like this:
(defn super-reader
[env]
(let [x (doubler env)
y (plus-oner env)]
(+ x y)))
Notice that you have to explicitly forward the environment to those readers. Total bummer, right? Using the rules provided by the reader monad, we can get much cleaner composition:
(def super-reader
(do-m reader-m
[x doubler
y plus-oner]
(+ x y)))
You can use partial to "do" the reader monad. Turn let into a do-reader by doing syntactic transformation on let with partial application of the environment on the right-hand side.
(defmacro do-reader
[bindings & body]
(let [env (gensym 'env_)
partial-env (fn [f] (list `(partial ~f ~env)))
bindings* (mapv #(%1 %2) (cycle [identity partial-env]) bindings)]
`(fn [~env] (let ~bindings* ~#body))))
Then do-reader is to the reader monad as let is to the identity monad (relationship discussed here).
Indeed, since only the "do notation" application of the reader monad was used in Beyamor's answer to your reader monad in Clojure question, the same examples will work as is with m/domonad Reader replaced with do-reader as above.
But, for the sake of variety I'll modify the first example to be just a bit more Clojurish with the environment map and take advantage of the fact that keywords can act as functions.
(def sample-bindings {:count 3, :one 1, :b 2})
(def ask identity)
(def calc-is-count-correct?
(do-reader [binding-count :count
bindings ask]
(= binding-count (count bindings))))
(calc-is-count-correct? sample-bindings)
;=> true
Second example
(defn local [modify reader] (comp reader modify))
(def calc-content-len
(do-reader [content ask]
(count content)))
(def calc-modified-content-len
(local #(str "Prefix " %) calc-content-len))
(calc-content-len "12345")
;=> 5
(calc-modified-content-len "12345")
;=> 12
Note since we built on let, we still have destructing at our disposal. Silly example:
(def example1
(do-reader [a :foo
b :bar]
(+ a b)))
(example1 {:foo 2 :bar 40 :baz 800})
;=> 42
(def example2
(do-reader [[a b] (juxt :foo :bar)]
(+ a b)))
(example2 {:foo 2 :bar 40 :baz 800})
;=> 42
So, in Clojure, you can indeed get the functionality of the do notation of reader monad without introducing monads proper. Analagous to doing a ReaderT transform on the identity monad, we can do a syntactic transformation on let. As you surmised, one way to do so is with partial application of the environment.
Perhaps more Clojurish would be to define a reader-> and reader->> to syntactically insert the environment as the second and last argument respectively. I'll leave those as an exercise for the reader for now.
One take-away from this is that while types and type-classes in Haskell have a lot of benefits and the monad structure is a useful idea, not having the constraints of the type system in Clojure allows us to treat data and programs in the same way and do arbitrary transformations to our programs to implement syntax and control as we see fit.
How to make clojure to count '() as nil?
For example:
How to make something like
(if '() :true :false)
;to be
:false
;Or easier
(my-fun/macro/namespace/... (if '() :true :false))
:false
And not just if. In every way.
(= nil '()) or (my-something (= nil '()))
true
And every code to be (= '() nil) save.
(something (+ 1 (if (= nil '()) 1 2)))
2
I was thinking about some kind of regural expression. Which will look on code and replace '() by nil, but there are some things like (rest '(1)) and many others which are '() and I am not sure how to handle it.
I was told that macros allow you to build your own languages. I want to try it by changing clojure. So this is much about "How clojure works and how to change it?" than "I really need it to for my work."
Thank you for help.
'() just isn't the same thing as nil - why would you want it do be?
What you might be looking for though is the seq function, which returns nil if given an empty collection:
(seq [1 2 3])
=> (1 2 3)
(seq [])
=> nil
(seq '())
=> nil
seq is therefore often used to test for "emptiness", with idioms like:
(if (seq coll)
(do-something-with coll)
(get-empty-result))
You say you would like to change Clojure using the macros. Presently, as far as I know, this is not something you could do with the "regular" macro system (terminology fix anyone?). What you would really need (I think) is a reader macro. Things I have seen online (here, for example) seem to say that there exists something like reader macros in Clojure 1.4--but I have no familiarity with this because I really like using clooj as my IDE, and it currently is not using Clojure 1.4. Maybe somebody else has better info on this "extensible reader" magic.
Regardless, I don't really like the idea of changing the language in that way, and I think there is a potentially very good alternative: namely, the Clojure function not-empty.
This function takes any collection and either returns that collection as is, or returns nil if that collection is empty. This means that anywhere you will want () to return nil, you should wrap it not-empty. This answer is very similar to mikera's answer above, except that you don't have to convert your collections to sequences (which can be nice).
Both using seq and not-empty are pretty silly in cases where you have a "hand-written" collection. After all, if you are writing it by hand (or rather, typing it manually), then you are going to know for sure whether or not it is empty. The cases in which this is useful is when you have an expression or a symbol that returns a collection, and you do not know whether the returned collection will be empty or not.
Example:
=> (if-let [c (not-empty (take (rand-int 5) [:a :b :c :d]))]
(println c)
(println "Twas empty"))
;//80% of the time, this will print some non-empty sub-list of [:a :b :c :d]
;//The other 20% of the time, this will return...
Twas empty
=> nil
What about empty? ? It's the most expressive.
(if (empty? '())
:true
:false)
You can override macros and functions. For instance:
(defn classic-lisp [arg]
(if (seq? arg) (seq arg) arg))
(defn = [& args]
(apply clojure.core/= (map classic-lisp args)))
(defmacro when [cond & args]
`(when (classic-lisp ~cond) ~#args))
Unfortunately, you can't override if, as it is a special form and not a macro. You will have to wrap your code with another macro.
Let's make an if* macro to be an if with common-lisp behavior:
(defmacro if* [cond & args]
`(if (classic-lisp ~cond) ~#args)
With this, we can replace all ifs with if*s:
(use 'clojure.walk)
(defn replace-ifs [code]
(postwalk-replace '{if if*} (macroexpand-all code)))
(defmacro clojure-the-old-way [& body]
`(do ~#(map replace-ifs body)))
Now:
=> (clojure-the-old-way (if '() :true :false) )
:false
You should be able to load files and replace ifs in them too:
(defn read-clj-file [filename]
;; loads list of clojure expressions from file *filename*
(read-string (str "(" (slurp filename) ")")))
(defn load-clj-file-the-old-way [filename]
(doseq [line (replace-ifs (read-clj-file filename))] (eval line))
Note that I didn't test the code to load files and it might be incompatible with leiningen or namespaces. I believe it should work with overriden = though.
So I thought it would be a nice idea to name a function that calculates the exponential ^, but it seems like the caret actually does something special, as the Clojure REPL generates an error when evaluating '^. Googling mostly gave me this, so I was wondering what the actualy use for the caret in Clojure is.
(Also, would it be possible after all to name a function ^?)
^ is "the meta character" it tells the reader to add the symbol starting with ^ as metadata to the next symbol (provided it is something that implements IMetas)
user=> (def x ^:IamMeta [1 2 3])
#'user/x
user=> x
[1 2 3]
user=> (meta x)
{:tag :IamMeta}
user=>
You can learn a lot about how clojure works under the hood by looking at the meta of things, for instance functions:
user=> (meta foo)
{:ns #<Namespace user>,
:name foo, :file "NO_SOURCE_PATH",
:line 5, :arglists ([s])}
this is very often used for type hints
(defn foo [^String s] (.charAt s 1))
it is generally a good idea to turn on reflection warnings (set! *warn-on-reflection* true) and then add type hints until the warnings go away. without these Clojure will look up the type of the function operands at run-time, which saves you the trouble of fussing with types though at a slight cost.
PS: My next favorite reader character is the "dispatch" character #, it is well worth learning about it next :)
PPS: this is different in clojure 1.2.x vs clojure 1.3.x
in Clojure 1.2.1 metadata does not compose when you use the meta-character:
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:tag :foo}
and in 1.3 it "does the right thing" and also keywords are options instead of "tags":
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:foo true, :bar true}
It seems to me that the answer to your question is, unfortunately, no. In Clojure, you cannot name a function ^.
I tried the following in the REPL:
user=> (println \^)
^
nil
This seems to imply that you can escape the carat (^) with a backslash. However, if I try to declare a function using \^ as a name then I get an error message:
user=> (defn \^ [n e] (cond (= e 0) 1 :else (* n (\^ n (- e 1)))))
IllegalArgumentException First argument to defn must be a symbol
clojure.core/defn (core.clj:277)
The same code works with a regular text name:
user=> (defn exp [n e] (cond (= e 0) 1 :else (* n (exp n (- e 1)))))
#'user/exp
user=> (exp 3 3)
27
I would be delighted if someone with better Clojure-fu than mine could prove me wrong! :)