How do I use nth correctly here? - clojure

I'm pretty new to this, so I apologize if this seems trivial.
When trying to use nth, I get an IndexOutOfBoundsException because the size of lst could be less than 2. How can I fix this?
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
thanks!

The nth function has a 3-arity option for the case where you don't want an exception thrown for being out of bounds. You provide, as the 3rd argument, the value you want returned in case the index is out of bounds. This avoids the inefficiency of first checking for the length and then doing nth in uncounted sequences.
user=> (nth [1 2 3] 5 nil)
nil
user=> (nth [1 2 3] 5 ::not-found)
:user/not-found

Related

How to make reduce more readable in Clojure?

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.

What is wrong with my Clojure implementation of permutations

I know that there are multiple ways to solve permutations using Clojure.
I have tried creating a DCG (definite clause grammar) using Core.Logic but
the DCG part of the library is too experimental and didn't work.
In the code below I try two different approaches. One is a list comprehension (commented out), which is similar to the way I would solve this problem in Haskell.
The second approach uses MapCat to apply cons/first to each return value from the
recursive call to permutation. Remove item makes sure that I don't use the same letter more than once for each position.
Can someone please explain what is wrong with the list comprehension approach and what is wrong with the MapCat approach. It is much easier to reason about this kind of problem in Haskell - is there some perspective I am missing about Clojure?
(defn remove-item [xs]
(remove #{(first xs)} xs )
)
(defn permutation [xs]
(if (= (count xs) 1)
xs
;(for [x xs y (permutation (remove-item xs))
; :let [z (map concat y)]]
; z)
(mapcat #(map cons first (permutation (remove-item %)) ) xs)
)
)
Edit: #thumbnail solved the MapCat sub-problem in the comments already
We can simplify the permutation function to
(defn permutation [xs]
(if (= (count xs) 1)
xs
(for [x xs
y (permutation (remove-item xs))]
(map concat y))))
Attempting to use it on anything plural produces java.lang.IllegalArgumentException: Don't know how to create ISeq from: ... whatever you are trying to permute.
There are two errors:
permutation should return a sequence of sequences, even when there is
only one of them; so xs should be (list xs). This is what causes the exception.
The permutation for a given x from xs and, given that, a permutation y of xs without xis just (cons x y).
With these corrected, we have
(defn permutation [xs]
(if (= (count xs) 1)
(list xs)
(for [x xs
y (permutation (remove-item x xs))]
(cons x y))))
For example,
(permutation (range 3))
;((0 1 2) (0 2 1) (1 0 2) (1 2 0) (2 0 1) (2 1 0))
The above works only if all the permuted things are different. At the other extreme ...
(permutation [1 1 1])
;()
Also,
count scans the whole of a sequence. To find out if there is only
one element, (seq (rest xs)) is faster than (= (count xs) 1).
And the remove in remove-item scans the whole sequence. There is
little we can do to mend this.
If we know that we are dealing with distinct things, it is simpler and faster to deal with them as a set:
(defn perm-set [xs]
(case (count xs)
0 '()
1 (list (seq xs))
(for [x xs, y (perm-set (disj xs x))]
(cons x y)))
It works for empty sets too.
count is instant and disj is almost constant time, so this is
faster.
Thus:
(perm-set (set '()))
;()
(perm-set (set (range 3)))
;((0 1 2) (0 2 1) (1 0 2) (1 2 0) (2 0 1) (2 1 0))
We can add support for duplicates by working with the index of the items in the original sequence. The function append-index returns a new sequence where the index and value are now in a vector. For example '(\a \b \c) -> '([0 \a] [1 \b] [2 \c] [3 \a]).
You then work with this sequence within the for loop, taking the index of the item when we want to remove it from the original and taking the value when we cons it to the tail sequence.
(defn remove-nth [coll n]
(into (drop (inc n) coll) (reverse (take n coll))))
(defn append-index [coll]
(map-indexed #(conj [%1] %2) coll))
(defn permutation [xs]
(let [i-xs (append-index xs)]
(if (= (count xs) 1)
(list xs)
(for [x i-xs
y (permutation (remove-nth xs (first x)))]
(cons (last x) y)))))
Thanks to the previous post, I was struggling with the permutation problem myself and had not considered using a for comprehension.

Clojure manually find nth element in a sequence

I am a newbie to clojure (and functional programming for that matter) and I was trying to do some basic problems. I was trying to find the nth element in a sequence without recursion.
so something like
(my-nth '(1 2 3 4) 2) => 3
I had a hard time looping through the list and returning when i found the nth element. I tried a bunch of different ways and the code that I ended up with is
(defn sdsu-nth
[input-list n]
(loop [cnt n tmp-list input-list]
(if (zero? cnt)
(first tmp-list)
(recur (dec cnt) (pop tmp-list)))))
This gives me an exception which says "cant pop from empty list"
I dont need code, but if someone could point me in the right direction it would really help!
You are using the function pop, which has different behavior for different data structures.
user> (pop '(0 1 2 3 4))
(1 2 3 4)
user> (pop [0 1 2 3 4])
[0 1 2 3]
user> (pop (map identity '(0 1 2 3 4)))
ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentStack clojure.lang.RT.pop (RT.java:640)
Furthermore, you are mixing calls to pop with calls to first. If iterating, use peek/pop or first/rest as pairs, mixing the two can lead to unexpected results. first / rest are the lowest common denominator, if you want to generalize over various sequential types, use those, and they will coerce the sequence to work if they can.
user> (first "hello")
\h
user> (first #{0 1 2 3 4})
0
user> (first {:a 0 :b 1 :c 2})
[:c 2]
With your function, replacing pop with rest, we get the expected results:
user> (defn sdsu-nth
[input-list n]
(loop [cnt n tmp-list input-list]
(if (zero? cnt)
(first tmp-list)
(recur (dec cnt) (rest tmp-list)))))
#'user/sdsu-nth
user> (sdsu-nth (map identity '(0 1 2 3 4)) 2)
2
user> (sdsu-nth [0 1 2 3 4] 2)
2
user> (sdsu-nth '(0 1 2 3 4) 2)
2
user> (sdsu-nth "01234" 2)
\2
given a list as list_nums, take up to n + 1 then from that return the last element which is nth.
(fn [list_nums n] (last (take (inc n) list_nums)))
and alternatively:
#(last (take (inc %2) %1))
proof:
(= (#(last (take (inc %2) %1)) '(4 5 6 7) 2) 6) ;; => true
What you would really want to do is use the built-in nth function as it does exactly what you're asking:
http://clojuredocs.org/clojure_core/clojure.core/nth
However, since you're learning this is still a good exercise. Your code actually works for me. Make sure you're giving it a list and not a vector -- pop does something different with vectors (it returns the vector without the last item rather than the first -- see here).
Your code works fine for lists if supplied index is not equal or greater then length of sequence (you've implemented zero indexed nth). You get this error when tmp-list gets empty before your cnt gets to the zero.
It does not work so well with vectors:
user> (sdsu-nth [1 2 3 4] 2)
;; => 1
user> (sdsu-nth [10 2 3 4] 2)
;; => 10
it seems to return 0 element for every supplied index. As noisesmith noticed it happens because pop works differently for vectors because of their internal structure. For vectors pop will remove elements form the end, and then first returns first value of any vector.
How to fix: use rest instead of pop, to remove differences in behavior of your function when applied to lists and vectors.
(fn [xs n]
(if (= n 0)
(first xs)
(recur (rest xs) (dec n))))
One more way that I thought of doing this and making it truly non recursive (ie without for/recur) is
(defn sdsu-nth
[input-list n]
(if (zero? (count input-list))
(throw (Exception. "IndexOutOfBoundsException"))
(if (>= n (count input-list))
(throw (Exception. "IndexOutOfBoundsException"))
(if (neg? n)
(throw (Exception. "IndexOutOfBoundsException"))
(last (take (+ n 1) input-list))))))

Cleaning up Clojure function

Coming from imperative programming languages, I am trying to wrap my head around Clojure in hopes of using it for its multi-threading capability.
One of the problems from 4Clojure is to write a function that generates a list of Fibonacci numbers of length N, for N > 1. I wrote a function, but given my limited background, I would like some input on whether or not this is the best Clojure way of doing things. The code is as follows:
(fn fib [x] (cond
(= x 2) '(1 1)
:else (reverse (conj (reverse (fib (dec x))) (+ (last (fib (dec x))) (-> (fib (dec x)) reverse rest first))))
))
The most idiomatic "functional" way would probably be to create an infinite lazy sequence of fibonacci numbers and then extract the first n values, i.e.:
(take n some-infinite-fibonacci-sequence)
The following link has some very interesting ways of generating fibonnaci sequences along those lines:
http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci
Finally here is another fun implementation to consider:
(defn fib [n]
(let [next-fib-pair (fn [[a b]] [b (+ a b)])
fib-pairs (iterate next-fib-pair [1 1])
all-fibs (map first fib-pairs)]
(take n all-fibs)))
(fib 6)
=> (1 1 2 3 5 8)
It's not as concise as it could be, but demonstrates quite nicely the use of Clojure's destructuring, lazy sequences and higher order functions to solve the problem.
Here is a version of Fibonacci that I like very much (I took the implementation from the clojure wikibook: http://en.wikibooks.org/wiki/Clojure_Programming)
(def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))
It works like this: Imagine you already have the infinite sequence of Fibonacci numbers. If you take the tail of the sequence and add it element-wise to the original sequence you get the (tail of the tail of the) Fibonacci sequence
0 1 1 2 3 5 8 ...
1 1 2 3 5 8 ...
-----------------
1 2 3 5 8 13 ...
thus you can use this to calculate the sequence. You need two initial elements [0 1] (or [1 1] depending on where you start the sequence) and then you just map over the two sequences adding the elements. Note that you need lazy sequences here.
I think this is the most elegant and (at least for me) mind stretching implementation.
Edit: The fib function is
(defn fib [n] (nth fib-seq n))
Here's one way of doing it that gives you a bit of exposure to lazy sequences, although it's certainly not really an optimal way of computing the Fibonacci sequence.
Given the definition of the Fibonacci sequence, we can see that it's built up by repeatedly applying the same rule to the base case of '(1 1). The Clojure function iterate sounds like it would be good for this:
user> (doc iterate)
-------------------------
clojure.core/iterate
([f x])
Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects
So for our function we'd want something that takes the values we've computed so far, sums the two most recent, and returns a list of the new value and all the old values.
(fn [[x y & _ :as all]] (cons (+ x y) all))
The argument list here just means that x and y will be bound to the first two values from the list passed as the function's argument, a list containing all arguments after the first two will be bound to _, and the original list passed as an argument to the function can be referred to via all.
Now, iterate will return an infinite sequence of intermediate values, so for our case we'll want to wrap it in something that'll just return the value we're interested in; lazy evaluation will stop the entire infinite sequence being evaluated.
(defn fib [n]
(nth (iterate (fn [[x y & _ :as all]] (cons (+ x y) all)) '(1 1)) (- n 2)))
Note also that this returns the result in the opposite order to your implementation; it's a simple matter to fix this with reverse of course.
Edit: or indeed, as amalloy says, by using vectors:
(defn fib [n]
(nth (iterate (fn [all]
(conj all (->> all (take-last 2) (apply +)))) [1 1])
(- n 2)))
See Christophe Grand's Fibonacci solution in Programming Clojure by Stu Halloway. It is the most elegant solution I have seen.
(defn fibo [] (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
(take 10 (fibo))
Also see
How can I generate the Fibonacci sequence using Clojure?

Clojure: How to replace an element in a nested list?

I have this deeply nested list (list of lists) and I want to replace a single arbitrary element in the list. How can I do this ? (The built-in replace might replace many occurrences while I need to replace only one element.)
As everyone else already said, using lists is really not a good idea if you need to do this kind of thing. Random access is what vectors are made for. assoc-in does this efficiently. With lists you can't get away from recursing down into the sublists and replacing most of them with altered versions of themselves all the way back up to the top.
This code will do it though, albeit inefficiently and clumsily. Borrowing from dermatthias:
(defn replace-in-list [coll n x]
(concat (take n coll) (list x) (nthnext coll (inc n))))
(defn replace-in-sublist [coll ns x]
(if (seq ns)
(let [sublist (nth coll (first ns))]
(replace-in-list coll
(first ns)
(replace-in-sublist sublist (rest ns) x)))
x))
Usage:
user> (def x '(0 1 2 (0 1 (0 1 2) 3 4 (0 1 2))))
#'user/x
user> (replace-in-sublist x [3 2 0] :foo)
(0 1 2 (0 1 (:foo 1 2) 3 4 (0 1 2)))
user> (replace-in-sublist x [3 2] :foo)
(0 1 2 (0 1 :foo 3 4 (0 1 2)))
user> (replace-in-sublist x [3 5 1] '(:foo :bar))
(0 1 2 (0 1 (0 1 2) 3 4 (0 (:foo :bar) 2)))
You'll get IndexOutOfBoundsException if you give any n greater than the length of a sublist. It's also not tail-recursive. It's also not idiomatic because good Clojure code shies away from using lists for everything. It's horrible. I'd probably use mutable Java arrays before I used this. I think you get the idea.
Edit
Reasons why lists are worse than vectors in this case:
user> (time
(let [x '(0 1 2 (0 1 (0 1 2) 3 4 (0 1 2)))] ;'
(dotimes [_ 1e6] (replace-in-sublist x [3 2 0] :foo))))
"Elapsed time: 5201.110134 msecs"
nil
user> (time
(let [x [0 1 2 [0 1 [0 1 2] 3 4 [0 1 2]]]]
(dotimes [_ 1e6] (assoc-in x [3 2 0] :foo))))
"Elapsed time: 2925.318122 msecs"
nil
You also don't have to write assoc-in yourself, it already exists. Look at the implementation for assoc-in sometime; it's simple and straightforward (compared to the list version) thanks to vectors giving efficient and easy random access by index, via get.
You also don't have to quote vectors like you have to quote lists. Lists in Clojure strongly imply "I'm calling a function or macro here".
Vectors (and maps, sets etc.) can be traversed via seqs. You can transparently use vectors in list-like ways, so why not use vectors and have the best of both worlds?
Vectors also stand out visually. Clojure code is less of a huge blob of parens than other Lisps thanks to widespread use of [] and {}. Some people find this annoying, I find it makes things easier to read. (My editor syntax-highlights (), [] and {} differently which helps even more.)
Some instances I'd use a list for data:
If I have an ordered data structure that needs to grow from the front, that I'm never going to need random-access to
Building a seq "by hand", as via lazy-seq
Writing a macro, which needs to return code as data
For the simple cases a recursive substitution function will give you just what you need with out much extra complexity. when things get a little more complex its time to crack open clojure build in zipper functions: "Clojure includes purely functional, generic tree walking and editing, using a technique called a zipper (in namespace zip)."
adapted from the example in: http://clojure.org/other_libraries
(defn randomly-replace [replace-with in-tree]
(loop [loc dz]
(if (zip/end? loc)
(zip/root loc)
(recur
(zip/next
(if (= 0 (get-random-int 10))
(zip/replace loc replace-with)
loc)))))
these will work with nested anything (seq'able) even xmls
It sort of doesn't answer your question, but if you have vectors instead of lists:
user=> (update-in [1 [2 3] 4 5] [1 1] inc)
[1 [2 4] 4 5]
user=> (assoc-in [1 [2 3] 4 5] [1 1] 6)
[1 [2 6] 4 5]
So if possible avoid lists in favour of vectors for the better access behaviour. If you have to work with lazy-seq from various sources, this is of course not much of an advice...
You could use this function and adapt it for your needs (nested lists):
(defn replace-item
"Returns a list with the n-th item of l replaced by v."
[l n v]
(concat (take n l) (list v) (drop (inc n) l)))
A simple-minded suggestion from the peanut gallery:
copy the inner list to a vector;
fiddle that vector's elements randomly and to your heart's content using assoc;
copy the vector back to a list;
replace the nested list in the outer list.
This might waste some performance; but if this was a performance sensitive operation you'd be working with vectors in the first place.