how can the clojure.algo.generic library be used? - clojure

I know that the library https://github.com/clojure/algo.generic provides ways of implementing generic arithmetic operators + * / - but there I couldn't find a simple example of how to create them and then how to use it as a library.
say if I wanted to implement vector addition, etc:
> (+ [1 2 3 4 5] 5)
;; => [6 7 8 9 10]
how would I go about:
defining the + operator with algo.generic
using the + operator previously defined within another project?

(ns your.custom.operators
(:import
clojure.lang.IPersistentVector)
(:require
[clojure.algo.generic.arithmetic :as generic]))
(defmethod generic/+
[IPersistentVector Long]
[v x]
(mapv + v (repeat x)))
(ns your.consumer.project
(:refer-clojure :exclude (+))
(:use
[clojure.algo.generic.arithmetic :only (+)])
(:require
your.custom.operators))
(defn add-five
[v]
(+ v 5))

edit 2,
user=> (defn + [coll i] (map #(clojure.core/+ % i) coll))
#'user/+
user=> (+ [1 2 3 4 5] 5)
(6 7 8 9 10)
edit, You can also do
(in-ns 'algo.generic)
(defn + [& args])
-- Edit --
You should use (require [lib :as namespacehere]) and call (namespacehere/+ ...). Below is the code for the problem presented.
user=> (map #(+ % 5) [1 2 3 4 5])
(6 7 8 9 10)
Also, check out (in-ns).

Related

Why doesn't map convey dynamic bindings? [duplicate]

From what I understand, setting a new binding on a dynamic var affects all functions called within that binding, and all functions called from those functions.
Why does the binding appear to be lost in the first example below?
(def ^:dynamic *out-dir* "/home/user")
(binding [*out-dir* "/home/dave"] (map #(str *out-dir* %) [1 2 3]))
; gives: ("/home/user1" "/home/user2" "/home/user3")
; expected: ("/home/dave1" "/home/dave2" "/home/dave3")
(binding [*out-dir* "/home/dave"] (conj (map #(str *out-dir* %) [1 2 3]) *out-dir*))
; gives: ("/home/dave" "/home/dave1" "/home/dave2" "/home/dave3")
This is caused by lazyness - map returns a lazy sequence which is defined inside the binding but is evaluated outside. You need to force the evaluation from inside:
(binding [*out-dir* "/home/dave"]
(doall (map #(str *out-dir* %) [1 2 3])))
It's true that laziness and dynamic bindings can cause problems; however, abandoning laziness is not the only solution. If you wish to preserve laziness (or to use dynamic bindings with pmap), use bound-fn or bound-fn*.
(def ^:dynamic x 0)
=> (binding [x 3] (map #(+ x %) (range 10)))
;; (0 1 2 3 4 5 6 7 8 9)
=> (binding [x 3] (map (bound-fn [y] (+ x y)) (range 10)))
;; (3 4 5 6 7 8 9 10 11 12)
=> (binding [x 3] (map (bound-fn* #(+ % x)) (range 10)))
;; (3 4 5 6 7 8 9 10 11 12)
Another solution is to use Python-style generator functions available via lazy-gen and yield from the Tupelo library:
(ns tst.demo.core
(:use demo.core tupelo.test)
(:require
[tupelo.core :as t] ))
(t/refer-tupelo)
(def ^:dynamic foo 1)
(dotest
(let [result (binding [foo 3]
(lazy-gen
(doseq [x (range 3)]
(yield {:foo foo :x x})))) ]
(println result)))
result => ({:foo 3, :x 0}
{:foo 3, :x 1}
{:foo 3, :x 2})

clojure: pop and push

I'm looking for a sequential data structure which is perfect for the following operation. The lenght of the list remains constant, it will never be longer or shorter than a fixed length.
Omit the first item and add x to the end.
(0 1 2 3 4 5 6 7 8 9)
(pop-and-push "10")
(1 2 3 4 5 6 7 8 9 10)
There is only one other reading-operation that has to be done equally often:
(last coll)
pop-and-push could be implemented like this:
(defn pop-and-push [coll x]
(concat (pop coll) ["x"]))
(unfortunately this does not work with sequences produced by e.g. range, it just pops when the sequence declared by the literals '(..) is passed.)
but is this optimal?
The main issue here (once we change "x" to x) is that concat returns a lazy-seq, and lazy-seqs are invalid args to pop.
user=> (defn pop-and-push [coll x] (concat (pop coll) [x]))
#'user/pop-and-push
user=> (pop-and-push [1 2 3] 4)
(1 2 4)
user=> (pop-and-push *1 5)
ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentStack clojure.lang.RT.pop (RT.java:730)
My naive preference would be to use a vector. This function is easy to implement with subvec.
user=> (defn pop-and-push [v x] (conj (subvec (vec v) 1) x))
#'user/pop-and-push
user=> (pop-and-push [1 2 3] 4)
[2 3 4]
user=> (pop-and-push *1 5)
[3 4 5]
as you can see, this version can actually operate on its own return value
As suggested in the comments, PersistentQueue is made for this situation:
user=> (defn pop-and-push [v x] (conj (pop v) x))
#'user/pop-and-push
user=> (pop-and-push (into clojure.lang.PersistentQueue/EMPTY [1 2 3]) 4)
#object[clojure.lang.PersistentQueue 0x50313382 "clojure.lang.PersistentQueue#7c42"]
user=> (into [] *1)
[2 3 4]
user=> (pop-and-push *2 5)
#object[clojure.lang.PersistentQueue 0x4bd31064 "clojure.lang.PersistentQueue#8023"]
user=> (into [] *1)
[3 4 5]
The PersistentQueue data structure, though less convenient to use in some ways, is actually optimized for this usage.

Clojure binding of dynamic var not working as expected

From what I understand, setting a new binding on a dynamic var affects all functions called within that binding, and all functions called from those functions.
Why does the binding appear to be lost in the first example below?
(def ^:dynamic *out-dir* "/home/user")
(binding [*out-dir* "/home/dave"] (map #(str *out-dir* %) [1 2 3]))
; gives: ("/home/user1" "/home/user2" "/home/user3")
; expected: ("/home/dave1" "/home/dave2" "/home/dave3")
(binding [*out-dir* "/home/dave"] (conj (map #(str *out-dir* %) [1 2 3]) *out-dir*))
; gives: ("/home/dave" "/home/dave1" "/home/dave2" "/home/dave3")
This is caused by lazyness - map returns a lazy sequence which is defined inside the binding but is evaluated outside. You need to force the evaluation from inside:
(binding [*out-dir* "/home/dave"]
(doall (map #(str *out-dir* %) [1 2 3])))
It's true that laziness and dynamic bindings can cause problems; however, abandoning laziness is not the only solution. If you wish to preserve laziness (or to use dynamic bindings with pmap), use bound-fn or bound-fn*.
(def ^:dynamic x 0)
=> (binding [x 3] (map #(+ x %) (range 10)))
;; (0 1 2 3 4 5 6 7 8 9)
=> (binding [x 3] (map (bound-fn [y] (+ x y)) (range 10)))
;; (3 4 5 6 7 8 9 10 11 12)
=> (binding [x 3] (map (bound-fn* #(+ % x)) (range 10)))
;; (3 4 5 6 7 8 9 10 11 12)
Another solution is to use Python-style generator functions available via lazy-gen and yield from the Tupelo library:
(ns tst.demo.core
(:use demo.core tupelo.test)
(:require
[tupelo.core :as t] ))
(t/refer-tupelo)
(def ^:dynamic foo 1)
(dotest
(let [result (binding [foo 3]
(lazy-gen
(doseq [x (range 3)]
(yield {:foo foo :x x})))) ]
(println result)))
result => ({:foo 3, :x 0}
{:foo 3, :x 1}
{:foo 3, :x 2})

Clojure - how to do reductions function but drop state?

If I use the reductions function like so:
(reductions + [1 2 3 4 5])
Then I get
(1 3 6 10 15)
Which is great - but I'd like to apply a binary function in the same way without the state being carried forward - something like
(magic-hof + [1 2 3 4 5])
leads to
(1 3 5 7 9)
ie it returns the operation applied to the first pair, then steps 1 to the next pair.
Can someone tell me the higher-order function I'm looking for? (Something like reductions)
This is my (non-working) go at it:
(defn thisfunc [a b] [(+ a b) b])
(reduce thisfunc [1 2 3 4 5])
You can do it with map:
(map f coll (rest coll))
And if you want a function:
(defn map-pairwise [f coll]
(map f coll (rest coll)))
And if you really need the first element to remain untouched (thanx to juan.facorro's comment):
(defn magic-hof [f [x & xs :as s]]
(cons x (map f s xs)))
partition will group your seq:
user> (->> [1 2 3 4 5] (partition 2 1) (map #(apply + %)) (cons 1))
(1 3 5 7 9)
So, you want to apply a function to subsequent pairs of elements?
(defn pairwise-apply
[f sq]
(when (seq sq)
(->> (map f sq (next sq))
(cons (first sq)))))
Let's try it:
(pairwise-apply + (range 1 6))
;; => (1 3 5 7 9)
This is sufficient:
(#(map + (cons 0 %) %) [1 2 3 4 5])
;; => (1 3 5 7 9)

Changing map behaviour in Clojure

I need to modify map function behavior to provide mapping not with minimum collection size but with maximum and use zero for missing elements.
Standard behavior:
(map + [1 2 3] [4 5 6 7 8]) => [5 7 9]
Needed behavior:
(map + [1 2 3] [4 5 6 7 8]) => [5 7 9 7 8]
I wrote function to do this, but it seems not very extensible with varargs.
(defn map-ext [f coll1 coll2]
(let [mx (max (count coll1) (count coll2))]
(map f
(concat coll1 (repeat (- mx (count coll1)) 0))
(concat coll2 (repeat (- mx (count coll2)) 0)))))
Is there a better way to do this?
Your method is concise, but inefficient (it calls count). A more efficient solution, which does not require the entirety of its input sequences to be stored in memory follows:
(defn map-pad [f pad & colls]
(lazy-seq
(let [seqs (map seq colls)]
(when (some identity seqs)
(cons (apply f (map #(or (first %) pad) seqs))
(apply map-pad f pad (map rest seqs)))))))
Used like this:
user=> (map-pad + 0 [] [1] [1 1] (range 1 10))
(3 3 3 4 5 6 7 8 9)
Edit: Generalized map-pad to arbitrary arity.
Another lazy variant, usable with an arbitrary number of input sequences:
(defn map-ext [f ext & seqs]
(lazy-seq
(if (some seq seqs)
(cons (apply f (map #(if (seq %) (first %) ext) seqs))
(apply map-ext f ext (map rest seqs)))
())))
Usage:
user> (map-ext + 0 [1 2 3] [4 5 6 7 8])
(5 7 9 7 8)
user> (map-ext + 0 [1 2 3] [4 5 6 7 8] [3 4])
(8 11 9 7 8)
If you just want it to work for any number of collections, try:
(defn map-ext [f & colls]
(let [mx (apply max (map count colls))]
(apply map f (map #(concat % (repeat (- mx (count %)) 0)) colls))))
Clojure> (map-ext + [1 2] [1 2 3] [1 2 3 4])
(3 6 6 4)
I suspect there may be better solutions though (as Trevor Caira suggests, this solution isn't lazy due to the calls to count).
How about that:
(defn map-ext [f x & xs]
(let [colls (cons x xs)
res (apply map f colls)
next (filter not-empty (map #(drop (count res) %) colls))]
(if (empty? next) res
(lazy-seq (concat res (apply map-ext f next))))))
user> (map-ext + [1 2 3] [4] [5 6] [7 8 9 10])
(17 16 12 10)
Along the lines of #LeNsTR's solution, but simpler and faster:
(defn map-ext [f & colls]
(lazy-seq
(let [colls (filter seq colls)
firsts (map first colls)
rests (map rest colls)]
(when (seq colls)
(cons (apply f firsts) (apply map-ext f rests))))))
(map-ext + [1 2 3] [4] [5 6] [7 8 9 10])
;(17 16 12 10)
I've just noticed Michał Marczyk's accepted solution, which is superior: it deals properly with asymmetric mapping functions such as -.
We can make Michał Marczyk's answer neater by using the convention - which many core functions follow - that you get a default or identity value by calling the function with no arguments. For examples:
(+) ;=> 0
(concat) ;=> ()
The code becomes
(defn map-ext [f & seqs]
(lazy-seq
(when (some seq seqs)
(cons (apply f (map #(if (seq %) (first %) (f)) seqs))
(apply map-ext f (map rest seqs)))
)))
(map-ext + [1 2 3] [4 5 6 7 8] [3 4])
;(8 11 9 7 8)
I've made the minimum changes. It could be speeded up a bit.
We may need a function that will inject such a default value into a function that lacks it:
(defn with-default [f default]
(fn
([] default)
([& args] (apply f args))))
((with-default + 6)) ;=> 6
((with-default + 6) 7 8) ;=> 15
This could be speeded up or even turned into a macro.