passing partitions to another function in clojure - clojure

I am just started clojure but I can't seem to figure out using/creating higher order functions.
I have partitioned a collection and I want to pass that into another function that will do something to the window of items. I am not sure how to go about doing this.
(def foo [:a :b :c :d :e])
(partition 3 1 foo)
;;=> ((:a :b :c) (:b :c :d) (:c :d :e))
(defn bar [start next end])
I think the basic outline would be.
(defn faz [collect]
(partition 3 1 collect)
;;maybe do here before passing
(bar stand next end)
)
I might be getting ahead of myself but I also see there are other functions like reduce and apply they can do something similar right? Although, most examples I see have it so they perform operations on two items at a time which are similar to (partition 2 1 foo)

You can do something like
(defn bar [start next end])
(defn faz [collect]
(let [partitions (partition 3 1 collect)]
(apply bar partitions)
))
or if you want to call bar directly, you can use destructuring
(defn bar [start next end])
(defn faz [collect]
(let [partitions (partition 3 1 collect)
[start next end] partitions]
(bar start next end)
))

Your question is general and there is more ways to achieve this, based on expected result and used function.
If you want to return sequence of results, use map and apply:
(defn results-for-triplets [collect]
(map #(apply + %) (partition 3 1 collect)))
(results-for-triplets [1 2 3 4 5])
=> (6 9 12)
For better readability, you can use ->> macro.
(defn results-for-triplets [collect]
(->> collect
(partition 3 1)
(map #(apply + %))))
(results-for-triplets [1 2 3 4 5])
=> (6 9 12)
You can avoid apply, if your function destructures passed sequence:
(defn sum3 [[a b c]]
(+ a b c))
(defn results-for-triplets [collect]
(->> collect
(partition 3 1)
(map sum3)))
(results-for-triplets [1 2 3 4 5])
=> (6 9 12)
If you want to call function for side effect and then return nil, use run!:
(defn print3 [[a b c]]
(println a b c))
(defn results-for-triplets [collect]
(->> collect
(partition 3 1)
(run! print3)))
(results-for-triplets [1 2 3 4 5])
1 2 3
2 3 4
3 4 5
=> nil

Related

Juxtaposed transducers

Let's imagine we want to compute two different functions on some given input. How can we do that with transducers?
For example, let's say we have these two transducers:
(def xf-dupl (map #(* 2 %)))
(def xf-inc (map inc))
Now, I would like some function f that takes a collection of transducers and returns a new transducer that combines them, as follows:
(into [] (f [xf-dupl xf-inc]) (range 5))
; => [[0 2 4 6 8] [1 2 3 4 5]]
There should probably be a very simple solution to this, but I cannot find it.
Note: I have tried with cgrand/xforms library's transjuxt, but there I get the following
(into [] (x/transjuxt {:a xf-dupl :b xf-inc}) (range 5))
; => [{:a 0 :b 1}]
Thanks for your help!
Using cgrand/xforms you can define f as
(defn f
[xfs]
(comp
(x/multiplex (zipmap (range) xfs))
(x/by-key (x/into []))
(map second)))
Calling f as you outlined in your question yields
user> (into [] (f [xf-dupl xf-inc]) (range 5))
[[0 2 4 6 8] [1 2 3 4 5]]

Putting singles and lists into a list in clojure

Is there a more elegant way to have into work with single items and lists than the following (admittedly atrocious) function?
(defn into-1-or-more
[this-list list-or-single]
(into this-list (flatten (conj [] list-or-single))))
Which can handle either:
(into-1-or-more [1 2 3 4] 5)
;[1 2 3 4 5]
Or:
(into-1-or-more [1 2 3 4] [5 6 7 8])
;[1 2 3 4 5 6 7 8]
I am building a collection with reduce using into [] with results from functions in a list. However some of the functions return single items, and others return lists of items. Like:
(reduce #(into [] (% data)) [func-return-item func-return-list func-return-either])
Would the best solution be to just do the following instead?
(into [] (flatten (map #(% data) [func-return-item ...])
Although it would be more ideal to know for sure what return type you are getting, here is a simple answer:
(flatten [ curr-list (mystery-fn) ] )
Examples:
(flatten [[1 2 3] 9 ] )
;=> (1 2 3 9)
(flatten [[[1] 2 3] [4 5] 6 ] )
;=> (1 2 3 4 5 6)
You could wrap it into a function if you want, but it hardly seems necessary.
This transducer flattens sequential inputs, but only by one "level":
(defn maybe-cat [rf]
(let [catrf (cat rf)]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (sequential? input)
(catrf result input)
(rf result input))))))
Example:
(into [] maybe-cat [[:foo] :bar [[:quux]]])
;= [:foo :bar [:quux]]
As this example demonstrates, this approach makes it possible to include sequential collections in the output (by wrapping them in an additional sequential layer – [[:quux]] produces [:quux] in the output).

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)

clojure map over sequence of pairs

(def tmp = [ 1 2 3 9 4 8])
I'm trying to create pairs of 2, then for each pair, subtract the second number from the first.
desired result: (1 6 4)
Here is what I was trying:
(map #(apply - %2 %1) (partition 2 tmp))
how can I do this?
Partition produces a sequence of sequences so the function you map over them needs to expect a sequence of two items. There are several ways to express this:
(def tmp [ 1 2 3 9 4 8])
user> (map #(- (second %) (first %)) (partition-all 2 tmp ))
(1 6 4)
user> (map #(apply - (reverse %)) (partition-all 2 tmp ))
(1 6 4)
user> (map (fn [[small large]] (- large small)) (partition-all 2 tmp ))
(1 6 4)
The version using apply is different because it will still "work" on odd length lists:
user> (map #(apply - (reverse %)) (partition-all 2 [1 2 3 4 5 6 7] ))
(1 1 1 -7)
The others will crash on invalid input, which you may prefer.
Here's a solution using reduce
(reduce #(conj %1 (apply - (reverse %2))) [] (partition-all 2 [1 2 3 9 4 8]))
=> [1 6 4]
I wonder why this solution was overlooked...
Since switching the order of subtraction is simply the negative of the original subtraction, (a-b=-(b-a)),
the solution becomes more efficient (only in this particular case!!)
(map #(- (apply - %)) (partition-all 2 [1 2 3 9 4 8]))
Pedagogically, Arthur's solution is correct. This is just a solution that is more suited the specfic question.

return sequence of clojure map values in a specific order

If I have a map, for example,
(def mymap { :b 1 :a 2 :d 3 :e 4 :f 5})
I can use vals to get a sequence of all of the values
(vals mymap)
;=> (1 2 3 4 5)
how do I get the sequence of values in my own custom order, to get for example
;=> (4 2 3 1 5)
what I eventually want to do is serialize the values to a string, doing something like this
(defn serialize [m sep] (apply str (concat (interpose sep (vals m)) ["\n"])))
(this example function was taken from the "serialize an input-map into string" post)
but I need to specify the order of the vals.
Maps are functions of their keys, so you can do this:
(map mymap [:e :a :d :b :f])
=> (4 2 3 1 5)
For 1.3 you can use the priority-map,
http://clojure.github.com/clojure-contrib/branch-master/priority-map-api.html
or you can use sort-by,
(let [m { 1 8 3 6 5 4 7 2}]
(println (map first (sort-by second m)))
(println (map first (sort-by first m))))
(7 5 3 1)
(1 3 5 7)
In case you want to sort the map depending on the keys, and then get the values,
Brian has an example on how to do this using sort-by
Or you can just implement your own sort comparator
I don't want to sort (although thanks for the sorting tips), I just want to specify the order
when I pull the values from the map.
I found a way to do it - destructuring the map.
(let [{:keys [a b d e f]} mymap]
(println e a d b f))