Find nth Element - Function composition - clojure

I am currently reading the book "The Joy of Clojure", 2nd edition.
In Chapter 7 "Functional Programming", I came across the following function that was used to describe function composition.
(defn fnth [n]
(apply comp
(cons first
(take (dec n) (repeat rest)))))
((fnth 5) '[a b c d e])
;=> e
I don't fully understand the mechanics of that function.
Trying to reproduce the inner scope without using comp, the function produces a repeating list:
(take (dec 5) (repeat (rest '[a b c d e])))
;=> ((b c d e) (b c d e) (b c d e) (b c d e))
What is the point of attaching first to that repeating list by using comp?
Is this also the last part of the function list which is fed into comp?
(first (take (dec 5) (repeat (rest '[a b c d e]))))
=> (b c d e)
Thank you in advance!

The fnth function works by constructing a sequence of the form (first rest rest ... rest) i.e. first followed by n - 1 rests. It then composes them into a single function by applying comp. For (fnth 5) this is
(apply comp (first rest rest rest rest))
When the result function is called on the vector [a b c d e] the resulting application is
(first (rest (rest (rest (rest [a b c d e])))))
i.e. the first element of the 4th tail of the input sequence.
Your attempted reconstruction only calls rest once and then reapeats the returned sequence instead.

This fnth does not (itself) return the nth item of a collection, but rather produces a function that does so.
What function should it produce to get the 1st item?
(defn nth-1 [coll]
(first coll))
What function should it produce to get the 2nd item?
(defn nth-2 [coll]
(first (rest coll)))
What function should it produce to get the 3rd item?
(defn nth-3 [coll]
(first (rest (rest coll))))
So there's a pattern! But the nesting would be a challenge for fnth.
An equivalent formulation for (first (rest (rest x))) is ((comp first rest rest) x). Now we can write nth-3 as
(defn nth-3 [coll]
((comp first rest rest) coll))
With this approach fnth is easier to write. But it would be easier still if we rewrote (comp first rest rest) as (apply comp [first rest rest]). There! Now fnth needs is to make a list of first + the right number of rest's, and apply comp to that list.

Related

How to call one defn function in another defn and how to debugging in Clojure

I am having a problem running my program in Clojure. I just start learning Clojure a couple of weeks ago. So I don't know the quick and easy way to debug a Clojure program. My func2 raises an exception at (adj(a b)) as followed:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
user/func2.
I don't know what is wrong with it. Can someone point out the problem with my coding?
And in func3, I call func2 recursively, but it throws:
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lan g.AFn.throwArity (AFn.java:437)
What is wrong with func3? Thank you.
(defn adj [value1 value2]
(def result (+ (/ value1 2) (/ value2 2)))
(if (= (mod result 2) 1)
(+ result 1)
result
)
)
(defn func2 [list]
(let [[a b c d] list]
(inc d)
([(adj c a) (adj a b) (adj b c) d]))
)
(defn func3 [list]
(loop [v list r []]
(if(= (v 0) (v 1) (v 2))
(conj list r)
(func3(func2(list)))
))
)
What's the intended result of these functions? We probably need to see some sample inputs and expected results to really be able to help you.
Here's my attempt at cleaning them up. I've noted the changes I made as comments. func3 has the most serious problem in that it's an infinite recursion - there's no end condition. What should cause it to stop working and return a result?
(defn adj [value1 value2]
;; don't use def within functions, use let
(let [result (+ (/ value1 2) (/ value2 2))]
(if (= (mod result 2) 1)
(+ result 1)
result)))
(defn func2 [list]
(let [[a b c d] list]
;; The extra parens around this vector were causing it
;; to be called as a function, which I don't think is
;; what you intended:
[(adj c a) (adj a b) (adj b c) d]))
;; This needs an end condition - it's an infinite recursion
(defn func3 [list]
(loop [v list r []]
(if (= (v 0) (v 1) (v 2))
(conj list r)
;; Removed extra parens around list
(func3 (func2 list)))))
The reason I say not to use def within functions is that it always creates a global function. For local bindings you want let.
Regarding the extra parens, the difference between [1 2 3] and ([1 2 3]) is that the former returns a vector containing the numbers 1, 2, and 3, whereas the latter tries to call that vector as a function. You had excess parens around the literal vector in func2 and around list in func3, which was causing exceptions.
As a style note, the name list isn't a good choice. For one thing, it's shadowing clojure.core/list, and for another you're probably using vectors rather than lists anyway. It would be more idiomatic to use coll (for collection) or s (for sequence) as the name.
This would suggest at least one other change. In func3 you use a vector-only feature (using the vector as a function to perform lookup by index), so to be more general (accept other data structures) you can convert to a vector with vec:
(defn func3 [coll]
(loop [v (vec coll) r []]
(if (= (v 0) (v 1) (v 2))
(conj v r)
(func3 (func2 v)))))
Oh, there is no need to debug that. I suggest you have a look at LightTable.
The first two functions are easily fixed:
(defn adj [value1 value2]
;(def result (+ (/ value1 2) (/ value2 2))) def creates a global binding in current namespace !!!
(let [result (+ (/ value1 2) (/ value2 2))]
(if
(= (mod result 2) 1)
(inc result)
result)))
(defn func2 [xx]
(let [[a b c d] xx]
[ (adj c a) (adj a b) (adj b c) (inc d)]
))
The third function is not clear to me. I don't read your intent. What I understand is: "Keep applying func2 to itself until the first three elements of its result are equal." But I'm afraid this condition is never met, so I replaced it with a true in order to see just one result without blowing the stack.
(defn func3 [xx]
(loop [ v (func2 xx) ]
(if
;(= (v 0) (v 1) (v 2))
true
v
(recur (func2 v))
)))
Useful link: http://clojure.org/cheatsheet
Cheers -

Is there a simpler way that this to get each element of a sequence, paired with "its" tail?

I find myself needing to convert a sequence of elements, to a sequence of "pairs", the first element of which is the element of the initial sequence, and the second element of while is the tail of the initial sequence from that element.
(a b c d e) -> ((a (b c d e)) (b (c d e)) (c (d e)) (d (e)) (e ()))
I wrote this:
(defn head-and-tail [s]
(cond (empty? s) ()
:else (cons (list (first s) (rest s)) (head-and-tail (rest s)))))
Is there is a built in function, or a simple combination of built in functions that can do this more easily?
Here's one approach:
(let [xs [1 2 3 4]]
(map list xs (iterate rest (rest xs))))
;= ((1 (2 3 4)) (2 (3 4)) (3 (4)) (4 ()))
This can of course be tweaked to suit your needs, for instance you might prefer map vector to map list etc.
Also, about the head-and-tail impl from the question text: the two-way-branching cond would be better written as an if.

Error with variadic function in Clojure

I am trying to write a custom max function in Clojure, which should support one or more arguments. However, I am running into an error that I cannot figure out. Here is the below function:
(defn my-max [arg & rest]
(loop [m arg c rest]
(cond (empty? c) m
(> m (first c)) (recur m (rest c))
:else (recur (first c) (rest c)))))
And I encounter the following error when attempting to evaluate the function:
user> (my-max 2 3 1 4 5)
ClassCastException clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn user/my-max (NO_SOURCE_FILE:5)
I thought this would work because I was under the assumption that rest was just a sequence. I was able to get this function to work without a variadic signature, where the argument is simply a sequence:
(defn my-max [coll]
(loop [m (first coll) c (rest coll)]
(cond (empty? c) m
(> m (first c)) (recur m (rest c))
:else (recur (first c) (rest c)))))
The problem appears to be a name collision. You have used the name rest for the tail sequence of your calling arguments. Then you subsequently try to use the function rest, but that sequence is seen instead.

Finding the position of an object in a sequence in Clojure

Essentially, I want a function that works like this:
user=> (pos 'c '(a b c d e f g) =)
2
user=> (pos 'z '(a b c d e f g) =)
nil
And I came up with this:
(defn pos
"Gets position of first object in a sequence that satisfies match"
[object sequence match]
(loop [aseq sequence position 0]
(cond (match object (first aseq)) position
(empty? aseq) nil
:else (recur (rest aseq) (inc position)))))
So my question is, is there some built-in function that would allow us to do this, or would there be a better, more functional/Clojure-ish way to write the pos function?
Well, if you really want to look for a particular item you can use .indexOf on the collection; if you're looking to do something more general with predicates you don't need a function and an item, just a function is plenty.
(defn pos [pred coll]
(->> coll
(map-indexed #(when (pred %2) %1))
(remove nil?)
(first)))
user> (pos #{'c} '(a b c d e f g))
2
On the other hand, there's a reason this isn't included in clojure.core: it's not very efficient, and you very rarely care about indices in a collection - if you do, you should usually rethink your algorithm.

Clojure tail call recursion with variable argument function

I basically want this:
(defn mymax
([a b] (if (> a b) a b))
([a b & rest] (apply recur (conj rest (mymax a b)))))
So that: (mymax 1 2 3 4) tail calls (mymax 2 3 4) which tail calls (mymax 3 4)
I see the problem that "apply" stops recur being in the tail position, which means it won't work. But I don't see how I can not use apply for variable arguement functions
[Note, I know you can solve this particular problem with reduce. Just wondering if you can do tail-call-recursion with variable params]
Make the function take a single vector as an argument rather than using aruguments as the sequence of values. That would allow you to get rid of apply.
(defn mymax [[a b & rest]]
(let [m (if (> a b) a b)]
(if (not rest)
m
(recur (conj rest m)))))