I have 3 previous files with a function each and am trying to use comp in ex4.clj to combine all 3 but am currently getting an error about the wrong number of args being passed. I've tried using map, reduce, and filter with it but they all fail and I'm not sure how to tell which one would be desired since all functions use a different one.
ex1.clj
(defn round [input] (Math/round (double input)))
(def testList [4.7 3.3 -17 17 -5.6 -3.3 0])
(def roundedList (map round testList))
ex2.clj
(defn isDivisibleBy [factor]
(fn [number]
(def result (/ number factor))
(def roundedResult (Math/round (double result)))
(and (= result roundedResult))
)
)
(def divisibleBy2 (isDivisibleBy 2))
(def testList [2 3 4 17 3000 -3 -6 0])
(def divisibleSuccess (filter divisibleBy2 testList))
ex3.clj
(defn findMax [accum value]
(if (> accum value) accum value)
)
(def testList [2 3 4 17 3000 -3 0 -3001])
(def maxValue (reduce findMax testList))
ex4.clj (Problem file)
(load-file "ex1.clj")
(load-file "ex2.clj")
(load-file "ex3.clj")
(def testList [4.7 3.3 -17 17 -5.6 -3.3 0])
(def allThree (comp findMax divisibleBy2 round))
(def output ((map/reduce/filter) allThree testList))
(println "Original list: " testList)
(println "Highest rounded number divisible by 2: " output)
Thank you!
Your functions there are used for different jobs: one is a predicate,
you want to filter with. One is a transformation, you want to map
over. And the last one is an aggregate, you want to use as final step
(via reduce).
So you have to compose over the transformations you want to do:
((comp
(partial reduce findMax)
(partial filter divisibleBy2)
(partial map round))
testList)
If you want to do that alot, you should also have a look at
transducers, which allow
doing this without the cost of intermediate sequences.
Random style critique:
Clojure uses kebab-case and not camelCase
Never def outside of the namespace; use let instead
It's common to have a trailing ? on predicates (e.g. divisible-by-2?)
Related
I have two lists. For e.g.: list A is [1 2 3 2 2 1] and list B is [1.2 2.2 1 1 1 1]. I want to have the unique numbers of list A on the x-axis and sum of the corresponding entries in list B. For eg: For the above example, I want to plot {(1,2.2),(2,4.2),(3,1)} as a histogram ( not a scatter plot).
My requirement involves two steps.
First to sum values in list B for each unique value in list A
Plotting these sums against the corresponding values in list A as a histogram.
Can you please help me.
Edit:
Here is my attempt, based on the little I could understand from reading other answers on SO:
(def A [1 2 3 2 1])
(def B [1.2 2.3 2 1 1])
(for [x (distinct A)] (map first
(filter #(= (second %) x)
(map-indexed vector A))))
;; This gives the indices for each unique element in A
;; In this case, it gives ((0 4) (1 3) (2))
I am unable to figure out how to find how to get corresponding sum from list B. I tried the following but it does not work.
(apply nth B (map first
(filter #(= (second %) 1)
(map-indexed vector A))) )
;; In this case, it gives on the first element i.e. 1.2
As you can see, I am new to Clojure and functional programming languages. Can you please point me towards some examples which have solved similar problems?
Thanks in advance.
Edit:
Final solution for the first task:
(for [x (distinct A)] (reduce + 0.0 (map #(nth B %) (map first
(filter #(= (second %) x)
(map-indexed vector A))) ) ) )
;; This gives me the correct output (2.2 3.3 2.0)
P.S: I did not understand this concept of using (map #(nth B%)... I just stumbled onto it from other examples.
For the first task, I guess this way is a bit simpler:
(def A [1 2 3 2 2 1])
(def B [1.2 2.2 1 1 1 1])
(def C
(reduce (partial merge-with +)
(map hash-map A B))) ; Vector of key-values [{1 1.2} {2 2.2} ...]
; {1 2.2, 2 4.2, 3 1}
For the second task, there are many chart library options out there. I picked up clj-xchart as an example:
(require '[com.hypirion.clj-xchart :as c])
(let [x-values (keys C)
min-x (apply min x-values)
max-x (apply max x-values)]
(c/view
(c/category-chart
{"C" C}
{:title "Example"
:legend {:visible? false}
:x-axis {:order (range min-x max-x)}
:theme :ggplot2})))
And the final plot:
A reduce call has its f argument first. Visually speaking, this is often the biggest part of the form.
e.g.
(reduce
(fn [[longest current] x]
(let [tail (last current)
next-seq (if (or (not tail) (> x tail))
(conj current x)
[x])
new-longest (if (> (count next-seq) (count longest))
next-seq
longest)]
[new-longest next-seq]))
[[][]]
col))
The problem is, the val argument (in this case [[][]]) and col argument come afterward, below, and it's a long way for your eyes to travel to match those with the parameters of f.
It would look more readable to me if it were in this order instead:
(reduceb val col
(fn [x y]
...))
Should I implement this macro, or am I approaching this entirely wrong in the first place?
You certainly shouldn't write that macro, since it is easily written as a function instead. I'm not super keen on writing it as a function, either, though; if you really want to pair the reduce with its last two args, you could write:
(-> (fn [x y]
...)
(reduce init coll))
Personally when I need a large function like this, I find that a comma actually serves as a good visual anchor, and makes it easier to tell that two forms are on that last line:
(reduce (fn [x y]
...)
init, coll)
Better still is usually to not write such a large reduce in the first place. Here you're combining at least two steps into one rather large and difficult step, by trying to find all at once the longest decreasing subsequence. Instead, try splitting the collection up into decreasing subsequences, and then take the largest one.
(defn decreasing-subsequences [xs]
(lazy-seq
(cond (empty? xs) []
(not (next xs)) (list xs)
:else (let [[x & [y :as more]] xs
remainder (decreasing-subsequences more)]
(if (> y x)
(cons [x] remainder)
(cons (cons x (first remainder)) (rest remainder)))))))
Then you can replace your reduce with:
(apply max-key count (decreasing-subsequences xs))
Now, the lazy function is not particularly shorter than your reduce, but it is doing one single thing, which means it can be understood more easily; also, it has a name (giving you a hint as to what it's supposed to do), and it can be reused in contexts where you're looking for some other property based on decreasing subsequences, not just the longest. You can even reuse it more often than that, if you replace the > in (> y x) with a function parameter, allowing you to split up into subsequences based on any predicate. Plus, as mentioned it is lazy, so you can use it in situations where a reduce of any sort would be impossible.
Speaking of ease of understanding, as you can see I misunderstood what your function is supposed to do when reading it. I'll leave as an exercise for you the task of converting this to strictly-increasing subsequences, where it looked to me like you were computing decreasing subsequences.
You don't have to use reduce or recursion to get the descending (or ascending) sequences. Here we are returning all the descending sequences in order from longest to shortest:
(def in [3 2 1 0 -1 2 7 6 7 6 5 4 3 2])
(defn descending-sequences [xs]
(->> xs
(partition 2 1)
(map (juxt (fn [[x y]] (> x y)) identity))
(partition-by first)
(filter ffirst)
(map #(let [xs' (mapcat second %)]
(take-nth 2 (cons (first xs') xs'))))
(sort-by (comp - count))))
(descending-sequences in)
;;=> ((7 6 5 4 3 2) (3 2 1 0 -1) (7 6))
(partition 2 1) gives every possible comparison and partition-by allows you to mark out the runs of continuous decreases. At this point you can already see the answer and the rest of the code is removing the baggage that is no longer needed.
If you want the ascending sequences instead then you only need to change the < to a >:
;;=> ((-1 2 7) (6 7))
If, as in the question, you only want the longest sequence then put a first as the last function call in the thread last macro. Alternatively replace the sort-by with:
(apply max-key count)
For maximum readability you can name the operations:
(defn greatest-continuous [op xs]
(let [op-pair? (fn [[x y]] (op x y))
take-every-second #(take-nth 2 (cons (first %) %))
make-canonical #(take-every-second (apply concat %))]
(->> xs
(partition 2 1)
(partition-by op-pair?)
(filter (comp op-pair? first))
(map make-canonical)
(apply max-key count))))
I feel your pain...they can be hard to read.
I see 2 possible improvements. The simplest is to write a wrapper similar to the Plumatic Plumbing defnk style:
(fnk-reduce { :fn (fn [state val] ... <new state value>)
:init []
:coll some-collection } )
so the function call has a single map arg, where each of the 3 pieces is labelled & can come in any order in the map literal.
Another possibility is to just extract the reducing fn and give it a name. This can be either internal or external to the code expression containing the reduce:
(let [glommer (fn [state value] (into state value)) ]
(reduce glommer #{} some-coll))
or possibly
(defn glommer [state value] (into state value))
(reduce glommer #{} some-coll))
As always, anything that increases clarity is preferred. If you haven't noticed already, I'm a big fan of Martin Fowler's idea of Introduce Explaining Variable refactoring. :)
I will apologize in advance for posting a longer solution to something where you wanted more brevity/clarity.
We are in the new age of clojure transducers and it appears a bit that your solution was passing the "longest" and "current" forward for record-keeping. Rather than passing that state forward, a stateful transducer would do the trick.
(def longest-decreasing
(fn [rf]
(let [longest (volatile! [])
current (volatile! [])
tail (volatile! nil)]
(fn
([] (rf))
([result] (transduce identity rf result))
([result x] (do (if (or (nil? #tail) (< x #tail))
(if (> (count (vswap! current conj (vreset! tail x)))
(count #longest))
(vreset! longest #current))
(vreset! current [(vreset! tail x)]))
#longest)))))))
Before you dismiss this approach, realize that it just gives you the right answer and you can do some different things with it:
(def coll [2 1 10 9 8 40])
(transduce longest-decreasing conj coll) ;; => [10 9 8]
(transduce longest-decreasing + coll) ;; => 27
(reductions (longest-decreasing conj) [] coll) ;; => ([] [2] [2 1] [2 1] [2 1] [10 9 8] [10 9 8])
Again, I know that this may appear longer but the potential to compose this with other transducers might be worth the effort (not sure if my airity 1 breaks that??)
I believe that iterate can be a more readable substitute for reduce. For example here is the iteratee function that iterate will use to solve this problem:
(defn step-state-hof [op]
(fn [{:keys [unprocessed current answer]}]
(let [[x y & more] unprocessed]
(let [next-current (if (op x y)
(conj current y)
[y])
next-answer (if (> (count next-current) (count answer))
next-current
answer)]
{:unprocessed (cons y more)
:current next-current
:answer next-answer}))))
current is built up until it becomes longer than answer, in which case a new answer is created. Whenever the condition op is not satisfied we start again building up a new current.
iterate itself returns an infinite sequence, so needs to be stopped when the iteratee has been called the right number of times:
(def in [3 2 1 0 -1 2 7 6 7 6 5 4 3 2])
(->> (iterate (step-state-hof >) {:unprocessed (rest in)
:current (vec (take 1 in))})
(drop (- (count in) 2))
first
:answer)
;;=> [7 6 5 4 3 2]
Often you would use a drop-while or take-while to short circuit just when the answer has been obtained. We could so that here however there is no short circuiting required as we know in advance that the inner function of step-state-hof needs to be called (- (count in) 1) times. That is one less than the count because it is processing two elements at a time. Note that first is forcing the final call.
I wanted this order for the form:
reduce
val, col
f
I was able to figure out that this technically satisfies my requirements:
> (apply reduce
(->>
[0 [1 2 3 4]]
(cons
(fn [acc x]
(+ acc x)))))
10
But it's not the easiest thing to read.
This looks much simpler:
> (defn reduce< [val col f]
(reduce f val col))
nil
> (reduce< 0 [1 2 3 4]
(fn [acc x]
(+ acc x)))
10
(< is shorthand for "parameters are rotated left"). Using reduce<, I can see what's being passed to f by the time my eyes get to the f argument, so I can just focus on reading the f implementation (which may get pretty long). Additionally, if f does get long, I no longer have to visually check the indentation of the val and col arguments to determine that they belong to the reduce symbol way farther up. I personally think this is more readable than binding f to a symbol before calling reduce, especially since fn can still accept a name for clarity.
This is a general solution, but the other answers here provide many good alternative ways to solve the specific problem I gave as an example.
Consider a query function q that returns, with a delay, some (let say ten) results.
Delay function:
(defn dlay [x]
(do
(Thread/sleep 1500)
x))
Query function:
(defn q [pg]
(lazy-seq
(let [a [0 1 2 3 4 5 6 7 8 9 ]]
(println "q")
(map #(+ (* pg 10) %) (dlay a)))))
Wanted behaviour:
I would like to produce an infinite lazy sequence such that when I take a value only needed computations are evaluated
Wrong but explicative example:
(drop 29 (take 30 (mapcat q (range))))
If I'm not wrong, it needs to evaluate every sequence because it really doesn't now how long the sequences will be.
How would you obtain the correct behaviour?
My attempt to correct this behaviour:
(defn getq [coll n]
(nth
(nth coll (quot n 10))
(mod n 10)))
(defn results-seq []
(let [a (map q (range))]
(map (partial getq a)
(iterate inc 0)))) ; using iterate instead of range, this way i don't have a chunked sequence
But
(drop 43 (take 44 (results-seq)))
still realizes the "unneeded" q sequences.
Now, I verified that a is lazy, iterate and map should produce lazy sequences, so the problem must be with getq. But I can't understand really how it breaks my laziness...perhaps does nth realize things while walking through a sequence? If this would be true, is there a viable alternative in this case or my solution suffers from bad design?
I'd like to know how to create an infinite, impure sequence of unique values in Clojure.
(def generator ...) ; def, not defn
(take 4 generator) ; => (1 2 3 4)
(take 4 generator) ; => (5 6 7 8). note the generator's impurity.
I think that such a design could be more convenient than e.g. wrapping a single integer value into a reference type and increment it from its consumers, as:
The proposed approach reduces the implementation details to a single point of change: the generator. Otherwise all the consumers would have to care about both the reference type (atom), and the concrete function that provides the next value (inc)
Sequences can take advantage many clojure.core functions. 'Manually' building a list of ids out of an atom would be a bit bulky: (take 4 (repeatedly #(swap! _ inc)))
I couldn't come up with a working implementation. Is it possible at all?
You can wrap a lazy sequence around an impure class (like a java.util.concurrent.atomic.AtomicLong) to create an id sequence:
(def id-counter (java.util.concurrent.atomic.AtomicLong.))
(defn id-gen []
(cons
(.getAndIncrement id-counter)
(lazy-seq
(id-gen))))
This works, but only if you don't save the head of the sequence. If you create a var that captures the head:
(def id-seq (id-gen))
Then call it repeatedly, it will return ids from the beginning of the sequence, because you've held onto the head of the sequence:
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
If you re-create the sequence though, you'll get fresh values because of the impurity:
(take 3 (id-gen))
;; (3 4 5)
(take 3 (id-gen))
;; (6 7 8)
(take 3 (id-gen))
;; (9 10 11)
I only recommend doing the following for educational purposes (not production code), but you can create your own instance of ISeq which implements the impurity more directly:
(def custom-seq
(reify clojure.lang.ISeq
(first [this] (.getAndIncrement id-counter))
(next [this] (.getAndIncrement id-counter))
(cons [this thing]
(cons thing this))
(more [this] (cons
(.getAndIncrement id-counter)
this))
(count [this] (throw (RuntimeException. "count: not supported")))
(empty [this] (throw (RuntimeException. "empty: not supported")))
(equiv [this obj] (throw (RuntimeException. "equiv: not supported")))
(seq [this] this)))
(take 3 custom-seq)
;; (12 13 14)
(take 3 custom-seq)
;; (15 16 17)
I had a fun time discovering something during answering your question. The first thing that occured to me was that perhaps, for whatever ultimate goal you need these IDs for, the gensym function might be helpful.
Then, I thought "well hey, that seems to increment some impure counter to generate new IDs" and "well hey, what's in the source code for that?" Which led me to this:
(. clojure.lang.RT (nextID))
Which seems to do what you need. Cool! If you want to use it the way you suggest, then I would probably make it a function:
(defn generate-id []
(. clojure.lang.RT (nextID)))
Then you can do:
user> (repeatedly 5 generate-id)
=> (372 373 374 375 376)
I haven't yet tested whether this will produce always unique values "globally"--I'm not sure about terminology, but I'm talking about when you might be using this generate-id function from within different threads, but want to still be sure that it's producing unique values.
this is another solution, maybe:
user=> (defn positive-numbers
([] (positive-numbers 1))
([n] (cons n (lazy-seq (positive-numbers (inc n))))))
#'user/positive-numbers
user=> (take 4 (positive-numbers))
(1 2 3 4)
user=> (take 4 (positive-numbers 5))
(5 6 7 8)
A way that would be more idiomatic, thread-safe, and invites no weirdness over head references would be to use a closure over one of clojures built in mutable references. Here is a quick sample I worked up since I was having the same issue. It simply closes over a ref.
(def id-generator (let [counter (ref 0)]
(fn [] (dosync (let [cur-val #counter]
(do (alter counter + 1)
cur-val))))))
Every time you call (id-generator) you will get the next number in the sequence.
Here's another quick way:
user> (defn make-generator [& [ii init]]
(let [a (atom (or ii 0 ))
f #(swap! a inc)]
#(repeatedly f)))
#'user/make-generator
user> (def g (make-generator))
#'user/g
user> (take 3 (g))
(1 2 3)
user> (take 3 (g))
(4 5 6)
user> (take 3 (g))
(7 8 9)
This is hack but it works and it is extremely simple
; there be dragons !
(defn id-gen [n] (repeatedly n (fn [] (hash #()))))
(id-gen 3) ; (2133991908 877609209 1060288067 442239263 274390974)
Basically clojure creates an 'anonymous' function but since clojure itselfs needs a name for that, it uses uniques impure ids to avoid collitions. If you hash a unique name then you should get a unique number.
Hope it helps
Creating identifiers from an arbitrary collection of seed identifiers:
(defonce ^:private counter (volatile! 0))
(defn- next-int []
(vswap! counter inc))
(defn- char-range
[a b]
(mapv char
(range (int a) (int b))))
(defn- unique-id-gen
"Generates a sequence of unique identifiers seeded with ids sequence"
[ids]
;; Laziness ftw:
(apply concat
(iterate (fn [xs]
(for [x xs
y ids]
(str x y)))
(map str ids))))
(def inf-ids-seq (unique-id-gen (concat (char-range \a \z)
(char-range \A \Z)
(char-range \0 \9)
[\_ \-])))
(defn- new-class
"Returns an unused new classname"
[]
(nth inf-ids-seq (next-int)))
(repeatedly 10 new-class)
Demonstration:
(take 16 (unique-id-gen [\a 8 \c]))
;; => ("a" "8" "c" "aa" "a8" "ac" "8a" "88" "8c" "ca" "c8" "cc" "aaa" "aa8" "aac" "a8a")
My question is how can I capture the index of the vector row where a match occurred? In the code below, what am I doing wrong?
I have a vector of vectors
(def v1 [[44 2 3 4 5][1 6 7 5 10][11 12 13 14 15]])
a column index, and a comparison value
(def cmp-val1 11)
(def col-idx 0)
I want to return the row index where a comparison returned true. With col-idx = 0 and cmp-val1 = 11, I should see (first row-num) return 2, and it is returning 1.
(defn ret-match-row
"Return the index of the row, in which the cmp-val is found.
It is okay to increment 0."
[in-seq cmp-val col-idx]
(let [rn 0]
(let [row-num
(for [seq-row in-seq
:let [local-row-num (inc rn)]
:when (= cmp-val (nth seq-row col-idx nil))]
local-row-num)]
(first row-num))))
From lein repl:
bene-csv.core=> (ret-match-row v1 cmp-val1 col-idx)
1
=> (defn ret-match-row
[coll cmp idx]
(keep-indexed (fn [i v] (if (= cmp (get v idx)) i)) coll))
=> (ret-match-row v1 11 0)
(2)
A flexible answer comes from separating this into three distinct problems and composing them.
creating the data you seek
finding the data you want
presenting the way it should look.
first we number the rows by adding row numbers to them
(map vector v1 (range))
then filter out the rows not containing the number you want:
(filter (fn [[data index]] (some #{11} data)) (map vector v1 (range)))
> ([[11 12 13 14 15] 2])
here i used the trick that sets are functions that test their input for inclusion in the set which allows this to test for multiple values:
(filter (fn [[data index]] (some #{11 44} data)) (map vector v1 (range)))
> ([[44 2 3 4 5] 0] [[11 12 13 14 15] 2])
then since you only want to know where it matched and not what matched we filter that out:
(map second (filter (fn [[data index]] (some #{11 44} data)) (map vector v1 (range))))
> (0 2)
to wrap this into a nice function we write out the steps:
(defn with-row-numbers [col] (map vector col (range)))
(defn find-my-rows [rows goals]
(filter (fn [[data index]] (some (set goals) data)) rows))
(defn present-rows [rows] (map second rows))
and then compose them:
(defn ret-match-row [data rows]
(-> data
(with-row-numbers)
(find-my-rows rows)
(present-rows)))
(ret-match-row v1 [11])
(2)
sorry i couldn't help making it work with multiple values, its a habit.
(ret-match-row v1 [11 15 44])
> (0 2)
There may be other ways to do what your'e asking, but you can use a loop/recur to achieve the iteration you're after:
(defn ret-match-row [rows val col-idx]
(loop [[row & rows] rows
pos 0]
(cond
(not row)
nil
(= val (nth row col-idx))
pos
:not-found
(recur rows (inc pos)))))
(ret-match-row [[44 2 3 4 5]
[1 6 7 8 10]
[11 12 13 14 15]]
11
0)
;; => 2
You're also running into Clojure's immutability - the (inc rn) is not actually modifying rn. The loop / recur solution uses inc as well, but it passes the result of inc to the next iteration of the loop.
Clojure's for (list comprehension) form also will loop over all of the values in the sequence, resulting in a new sequence -- which is most likely not what you want. Even if you made the for loop do what you want, it will find all the matches, not just the first. The loop / recur example stops at the first match.
My take, using
clojure.contrib.seq find-first, indexed:
(defn ret-match-row [rows val col-idx]
(first
(find-first #(= val (nth (second %) col-idx))
(indexed rows))))