How do I test a predicate against a seq of args? - unit-testing

I've generated a seq of arg lists, e.g.:
[[a b c]
[d e f]
[g h i]]
... such that (map (partial apply f) that-seq) should produce a list of the same result. I want to check if all of these indeed produce that same result. Normally, you'd use the are macro for something like this, but I don't have a literal bunch of exprs to test against: I have a seq. So, I guess I want the "equivalent" of (apply are ...). As far as I can tell, my options are:
write a macro
Use every? true?, giving up on useful error messages.
Are there any better ways to do this?

Use this for more accurate reporting
(testing "blake2b defaults are accurate"
(doseq [args-variation blake2b-empty-args-variations]
(is (= (seq empty-string-digest)
(seq (blake2b args-variation)))
(str "Args variation: " (seq args-variation)))))

FYI, for now, I've gone with:
(testing "blake2b defaults are accurate"
(let [results (map #(apply blake2b %) blake2b-empty-args-variations)]
(is (every? (partial array-eq empty-string-digest) results))))

Related

In Clojure, can a default value be provided while using sequential destructuring?

Seems like providing a default value in Associative destructuring is well documented. https://clojure.org/guides/destructuring
Any known way to supply a default value in sequential destructuring?
For instance:
(let [[hey you guys] ["do" "re"]]
(println hey)
(println you)
(println guys))
Output:
do
re
nil
How would you provide a default value for 'guys'?
Have tried
(let [[hey you (or guys "me")] ["do" "re"]]
(let [[hey you #(or % "me")] ["do" "re"]]
and a few variations of
(let [[hey you guys :or "me"] ["do" "re"]]
Thanks!
No I don't believe there is a way to offer default values in non-associative destructuring.
There would be more than one way to accomplish that, depending on what you're after. The closest to the snippets you provide might be:
(let [input ["do" "re"]
defaults ["def1" "def2" "def3" "def4"]
[hey you guys] (concat input (drop (count input) defaults))]
(println hey you guys)) ;; do re def3
If you only have a default value for the 3rd arg, then you can use:
(let [[hey you guys] (conj ["do" "re"] "def3")]
(println hey you guys)) ;; do re def3
or
(let [[hey you guys] ["do" "re"]
guys (or guys "def3")]
(println hey you guys)) ;; do re def3
You can find a good overview of Clojure destructuring here:
http://blog.brunobonacci.com/2014/11/16/clojure-complete-guide-to-destructuring/
You can get what you want with a simple function:
(defn apply-defaults
[vals defaults]
(vec (map-indexed
(fn [idx val-default]
(or (get vals idx) ; replaces both missing and `nil` values
val-default))
defaults)))
with result:
data => [:a nil :c]
defaults => [:def-a :def-b :def-c :def-d]
(apply-defaults data defaults) => [:a :def-b :c :def-d]
Note that you have to modify it if you want to retain any nil values in the input.
If the length is short, you can do this:
(let [[hey you guys] (merge defaults values)]
(println hey)
(println you)
(println guys))
Merge is a function that you must define/choose depending on the behaviour that you want, it will probably be one of these two (as in the previous answers):
Overwrite the values in defaults that are present in values
concat the values from the first one missing

Clojure - Using a variable as a function call

I am currently trying to make a simple Clojure macro that applies the inputted function twice: (f (f args)), (e.g (inc (inc 4)) => 6)
The problem is, when I run the below code using (reapply-function '(inc 4)), I get nil. This doesn't make sense to me since I can print out both the value of f and the result to get inc and 5. There must be a really simple thing I'm missing. Can anyone see the issue?
(defmacro reapply-function
[args]
(list 'let ['f (list 'first (list 'quote args))
'result args]
(list 'f 'result)))
Initial Note
This answer is provided assuming that you're trying to learn to use macros for its own sake. I fully agree with #Thumbnail's answer: Don't use macros except when you absolutely, positively cannot avoid it -- and this is not one of those times.
Shorter Implementation
Consider:
(defmacro reapply-function [[func & rest]]
`(~func (~func ~#rest)))
macroexpand demonstrates how it works:
user=> (macroexpand '(reapply-function (inc 4)))
(inc (inc 4))
...and it functions in the repl:
user=> (reapply-function (inc 4))
6
...But Why Didn't The Original Work?
With your original implementation, macroexpand-1 gives us this:
(let [f (first (quote (inc 4)))
result (inc 4)]
(f result))
...which does indeed evaluate to nil.
But why? In short: f is, in this code, a symbol, not the function that symbol points to.
Thus, to make the shortest possible change that makes the original code function:
(defmacro reapply-function
[args]
(list 'let ['f (list 'first (list 'quote args))
'result args]
(list '(resolve f) 'result)))
The first rule of macro club is ... don't use macros unless you have to.
In this case,
(defn twice [f]
(fn [& args] (f (apply f args))))
((twice inc) 4)
;6
Or, if you prefer to swallow the function and its arguments at once,
(defn reapply-function [f & args]
(f (apply f args)))
(reapply-function inc 4)
;6
You can find the rules of macro club in Programming Clojure by Halloway & Bedra. Also, the above rather casts a side-light on the question than answer it.

What is the difference between the reader monad and a partial function in Clojure?

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.

Better way of creating a flat list out of numbers and vectors

I've got a function like this:
(defn magic
[a b c]
(flatten (conj [] a b c)))
So on these inputs I get the following:
(magic 1 2 3) => (1 2 3)
(magic 1 [2 3] 4) => (1 2 3 4)
My question is, is there a better way of doing this?
The problem can be summarised as:
I don't know whether I will get numbers or vectors as input, but I need to return a single flat list
This could be slightly simplified (and generalized) as:
(defn magic [& args]
(flatten (apply list args)))
Or, as pointed out in the comments, it can be simplified even further (since args above is already a seq):
(defn magic [& args]
(flatten args))
Other than that, I don't see much else that can be improved about this. Is there anything in particular that's bothering you about your implementation?
If you can get seqs of seqs then you need to be more careful. And will have to recursively go into the list. There is a clojure native function for this tree-seq see the examples here:
http://clojuredocs.org/clojure_core/clojure.core/tree-seq
You'd want something like this (untested):
(defn nonempty-seq [x]
"returns x as a seq if it's a non-empty seq otherwise nil/false"
(and (coll? x) (seq x)))
(tree-seq nonempty-seq seq expr)

"->>" macro and iterative function application

I'm working through a book on clojure and ran into a stumbling block with "->>". The author provides an example of a comp that converts camelCased keywords into a clojure map with a more idiomatic camel-cased approach. Here's the code using comp:
(require '[clojure.string :as str])
(def camel->keyword (comp keyword
str/join
(partial interpose \-)
(partial map str/lower-case)
#(str/split % #"(?<=[a-z])(?=[A-Z])")))
This makes a lot of sense, but I don't really like using partial all over the place to handle a variable number of arguments. Instead, an alternative is provided here:
(defn camel->keyword
[s]
(->> (str/split s #"(?<=[a-z])(?=[A-Z])")
(map str/lower-case)
(interpose \-)
str/join
keyword))
This syntax is much more readable, and mimics the way I would think about solving a problem (front to back, instead of back to front). Extending the comp to complete the aforementioned goal...
(def camel-pairs->map (comp (partial apply hash-map)
(partial map-indexed (fn [i x]
(if (odd? i)
x
(camel->keyword x))))))
What would be the equivalent using ->>? I'm not exactly sure how to thread map-indexed (or any iterative function) using ->>. This is wrong:
(defn camel-pairs->map
[s]
(->> (map-indexed (fn [i x]
(if (odd? i)
x
(camel-keyword x)))
(apply hash-map)))
Three problems: missing a parenthesis, missing the > in the name of camel->keyword, and not "seeding" your ->> macro with the initial expression s.
(defn camel-pairs->map [s]
(->> s
(map-indexed
(fn [i x]
(if (odd? i)
x
(camel->keyword x))))
(apply hash-map)))
Is this really more clear than say?
(defn camel-pairs->map [s]
(into {}
(for [[k v] (partition 2 s)]
[(camel->keyword k) v])))