How does this Clojure function expand? - clojure

From The Joy of Clojure :
(defn fac-cps [n k]
(letfn [(cont [v] (k (* v n)))]
(if (zero? n)
(k 1)
(recur (dec n) cont))))
(defn fac [n]
(fac-cps n identity))
(fac 10)
3628800
I am interested to learn how the above function expands.
fac-cps is called with 10 and identity...
but in letfn cont[v] is defined as (k (* v n))
which equates to k = identity, n = 10
But i don't understand what v equates to and what recur expands into.

All of the lines are the same. I've just used substitution rules:
(fac-cps 10 identity)
(recur 9 (fn [v] (identity (* v 10))))
(recur 8 (fn [v] ((fn [v] (identity (* v 10))) (* v 9))))
(recur 7 (fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))))
(recur 6 (fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))))
(recur 5 (fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))))
(recur 4 (fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))))
(recur 3 (fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))))
(recur 2 (fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* v 3))))
(recur 1 (fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* v 3))) (* v 2))))
(recur 0 (fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* v 3))) (* v 2))) (* v 1))))
((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* v 3))) (* v 2))) (* v 1))) 1)
((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* v 3))) (* v 2))) (* 1 1))
((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* v 3))) (* (* 1 1) 2))
((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* v 4))) (* (* (* 1 1) 2) 3))
((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* v 5))) (* (* (* (* 1 1) 2) 3) 4))
((fn [v] ((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* v 6))) (* (* (* (* (* 1 1) 2) 3) 4) 5))
((fn [v] ((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* v 7))) (* (* (* (* (* (* 1 1) 2) 3) 4) 5) 6))
((fn [v] ((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* v 8))) (* (* (* (* (* (* (* 1 1) 2) 3) 4) 5) 6) 7))
((fn [v] ((fn [v] (identity (* v 10))) (* v 9))) (* (* (* (* (* (* (* (* 1 1) 2) 3) 4) 5) 6) 7) 8))
((fn [v] (identity (* v 10))) (* (* (* (* (* (* (* (* (* 1 1) 2) 3) 4) 5) 6) 7) 8) 9))
(identity (* (* (* (* (* (* (* (* (* (* 1 1) 2) 3) 4) 5) 6) 7) 8) 9) 10))
(identity 3628800)
; ==> 3628800

This function evaluates factorial by building up a continuation (basically a function that will do the work in the future), then evaluating it at (fac-cps 0).
E.g. at (fac-cps 3), continuation is "take a number, multiply it with 3, then pass it to the previous continuation, which will leave it alone (identity)".
At (fac-cps 2), continuation is "take a number, multiply it with 2, then pass it to the previous continuation, which will multiply it by 2 and pass it to the previous continuation, which will leave it alone".
At (fac-cps 1), continuation is "take a number, multiply it with 1, then pass it to the previous continuation, which will multiply it by 2 and pass it to the previous continuation, which will multiply it by 3 and pass it to the previous continuation, which will leave it alone."
Then finally, at (fac-cps 0), the number is given: 1 * 3 * 2 * 1 is the result.

On the first call to fac-cps, k is the identity function. The letfn form immediately creates a new function that takes an argument v, and captures k (identity) in a closure.
Then it checks if n is zero, which is the base/terminal case for this recursion.
Otherwise, there's more work to do, so it recurs while decrementing n, but now passing the new cont function that closed over k. This will happen over and over until n reaches zero, creating a blooming onion of nested closures. This is called continuation passing style and that's what the cps in fac-cps stands for. Contrast this with a purely recursive approach where those values that were captured in closures would instead be on the call stack.
Note that the work in cont (in all of them, nested in each other) isn't done until the very end when n reaches zero. When k is invoked in the terminal case, it's a function that may be wrapping many other functions. In other words, this is building up a thunk to be evaluated at the end. For example, (fac-cps 3) would end up evaluating this function:
(fn [v] ((fn [v] ((fn [v] (identity (* v 3))) (* v 2))) (* v 1)))
but i don't understand what v equates to
v is an argument to cont, so it won't be known until cont is invoked.
what recur expands into
recur is a special form that re-enters the function "recursively" but without consuming stack. You could replace recur with fac-cps, but you'd get a stack overflow if n is big enough.

Related

Get lost in parentheses (Clojure)

Please comment how to restructure the following function more readable and less parentheses.
(defn forwardDifference2nd [fn x h]
(->
(/ (+ (-
(fn (+ (+ x h) h))
(* (fn (+ x h)) 2.0))
(fn x))
(Math/pow h 2))))
Source Code
(def x 1.0)
(def h 0.1)
(defn forwardDifference2nd [fn x h]
(->
(/ (+ (-
(fn (+ (+ x h) h))
(* (fn (+ x h)) 2.0))
(fn x))
(Math/pow h 2))))
(defn myPolynomial [x]
(->
(+ (* 2
(Math/pow x 3))
(* 4
(Math/pow x 2)))
(- (* 5 x))))
(forwardDifference2nd myPolynomial x h)
Here is one example:
(defn forwardDifference2nd [f x h]
(let [fh #(f (+ x (* h %)))]
(/ (+ (fh 2) (* -2 (fh 1)) (f x))
h h)))
Simplifications:
Remove (-> ...)
Factor out similar looking expressions into local function
Flatten nested sums and differences
Replace (/ ... (Math/pow h 2)) by (/ ... h h)
Update:
Your computation could more generally be expressed as
(defn difference-at-depth [f x h depth]
(if (zero? depth)
(f x)
(let [depth (dec depth)]
(/ (- (difference-at-depth f (+ x h) h depth)
(difference-at-depth f x h depth))
h))))
(defn forwardDifference2nd [f x h]
(difference-at-depth f x h 2))
but this code is obviously longer. On the other hand, it better shows what is going on mathematically and is in that sense arguably more readable.
Locally naming with let and then using named parts for calculation not only enhances readability of formulas but also is computationally more efficient.
For re-occuring patterns like a polynom in polynomial, define a function with a name.
(defn forward-difference-2nd [f x h]
(let [f_xhh (f (+ x h h))
f_xh (f (+ x h))
f_x (f x)
h**2 (* h h)]
(/ (- f_xhh f_xh f_xh f_x) h**2)))
(defn polynom [coeff x power] (* coeff (Math/pow x power)))
(defn my-polynomial [x]
(+ (polynom 2 x 4) (polynom 4 x 2) (polynom -5 x 1)))
(def x 1.0)
(def h 0.1)
(forward-difference-2nd my-polynomial x h)

Trapezoidal Integration is not accurate enough in Clojure

So currently, I wrote a Clojure code to do Trapezoidal integration of a polynomial function in HackerRank.com:
https://www.hackerrank.com/challenges/area-under-curves-and-volume-of-revolving-a-curv
(defn abs[x]
(max x (- 0 x))
)
(defn exp[x n]
(if (> n 0)
(* x (exp x (- n 1)))
1
)
)
(defn fact[x]
(if (> x 0)
(* x (fact (- x 1)))
1)
)
(defn func[x lst1 lst2]
((fn step [sum lst1 lst2]
(if (> (.size lst1) 0)
(step (+ sum (* (last lst1) (exp x (last lst2)))) (drop-last lst1) (drop-last lst2))
sum
)
)
0 lst1 lst2
)
)
(defn integrate[f a b]
(def h 0.001)
(def n (/ (abs (- b a)) h))
((fn step[i sum]
(if (< i n)
(step (+ i 1) (+ sum (f (+ (* i h) a))))
(* h (+ (/(+ (f a) (f b)) 2) sum))
)
) 0 0)
)
(defn volumeIntegral[f a b]
(defn area[r]
(* 3.14159265359 (* r r)))
(def h 0.001)
(def n (/ (abs (- b a)) h))
((fn step[i sum]
(if (< i n)
(step (+ i 1) (+ sum (area (f (+ (* i h) a)))))
(* h (+ (/ (+ (f a) (f b)) 2) sum))
)
) 0 0)
)
(defn lineToVec[line_str] (clojure.string/split line_str #"\s+"))
(defn strToDouble [x] (Double/parseDouble (apply str (filter #(Character/isDigit %) x))))
(defn readline[vec]
((fn step[list vec]
(if (> (.size vec) 0)
(step (conj list (last vec)) (drop-last vec))
list
)
) '() vec)
)
(integrate (fn [x] (func x '(1 2 3 4 5 6 7 8) '(-1 -2 -3 -4 1 2 3 4))) 1 2)
(volumeIntegral (fn [x] (func x '(1 2 3 4 5 6 7 8) '(-1 -2 -3 -4 1 2 3 4))) 1 2)
However, the output I have is:
107.38602491666647
45611.95754801859
While is supposed to be around:
101.4
41193.0
My code passed the first two test cases, but didn't manage to pass the rest. I assume is because of the issue accuracy. I looked through my code several times but couldn't seem to make it better. What am I doing wrong here ? Thank you.
Your exp function isn't quite right -- it doesn't handle negative exponents correctly. Probably best just to use Math/pow.
The other thing you could do is adjust your h value in volumeIntegral but to avoid stack issues, use recur (which gives you tail recursion), e.g. here's a slightly modified version:
(defn volume-integral [f a b]
(defn area[r]
(* Math/PI (* r r)))
(def h 0.000001)
(def n (/ (abs (- b a)) h))
((fn [i sum]
(if (not (< i n))
(* h (+ (/ (+ (f a) (f b)) 2) sum))
(recur (+ i 1) (+ sum (area (f (+ (* i h) a)))))))
0 0))
(I did the something similar with integral.) All in all, I wasn't able to quite hit the second figure, but this should get you on the right track:
101.33517384995224
41119.11576557253

Determining the cause of StackOverflow in code using lazy-seq

I have the following snippet:
(defn explode [e]
(seq [e e e e]))
(defn f [coll]
(when-first [e coll]
(cons e
(lazy-seq (f (lazy-cat (next coll)
(explode e)))))))
When I try to access an element, I get a StackOverflow error:
user=> (nth (f (seq [1 2 3])) 1000)
3
user=> (nth (f (seq [1 2 3])) 10000)
StackOverflowError clojure.core/concat/fn--3923 (core.clj:678)
How can I structure this code in a way that doesn't blow the stack?
You'll have to keep track of the remaining work explicitly, perhaps like so:
(defn f [coll]
(letfn [(go [xs q]
(lazy-seq
(cond
(seq xs)
(cons (first xs)
(go (next xs) (conj q (explode (first xs)))))
(seq q)
(go (peek q) (pop q)))))]
(go coll clojure.lang.PersistentQueue/EMPTY)))
From the REPL:
(nth (f [1 2 3]) 1000)
;= 3
(nth (f [1 2 3]) 10000)
;= 2
;; f-orig is f as found in the question text
(= (take 1000 (f-orig [1 2 3])) (take 1000 (f [1 2 3])))
;= true

Is it possible to implement "partition" function using clojure.core.reducers?

I have a following function:
(defn map-pairs [f coll]
(map f (partition 2 1 coll)))
Is it possible to avoid creating of the intermediate 2-element collections using clojure.core.reducers?
Not out of the box. But you can:
=> (into [] (map2 + (range 10)))
[1 3 5 7 9 11 13 15 17]
See:
(deftype Fn2 [f1 f ^:volatile-mutable a ^:volatile-mutable b]
clojure.lang.IFn
(invoke [this] (f1))
(invoke [this _] (set! b this)) ; hack to init the sentinel
(invoke [this ret v]
(set! a b)
(set! b v)
(if (identical? a this)
ret
(f1 ret (f a b))))
#_(invoke [this ret k v] to do))
(defn fn2 [f1 f] 1
(let [f2 (Fn2. f1 f nil nil)]
(f2 nil)
f2))
(defn map2 [f coll]
(r/reducer coll
(fn [f1]
(fn2 f1 f))))

clojure.core/or partial function works well with first argument but not with second

(defn divisible [x y] (zero? (rem x y)))
((or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 3)
((or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 5)
the first expression evals to true but not the second one why?
can some on explain whats going on here?
An expression of the form (or foo bar) does not "glue together" two predicates into one compound predicate; it returns foo if it is truthy, else bar. In your code, (fn [x] (divisible x 3)) is of course truthy (the only falsey values are false and nil), so the whole thing is equivalent to
((fn [x] (divisible x 3)) 3)
((fn [x] (divisible x 3)) 5)
What you want to do is something like
(some #(apply % 3) [(fn [x] (divisible x 3)) (fn [x] (divisible x 5)])
(some #(apply % 5) [(fn [x] (divisible x 3)) (fn [x] (divisible x 5)])
; ^- here goes the thing being tested
In general,
(defn or-preds [& preds]
(fn [& args]
(some #(apply % args) preds)))
((or-preds (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 3)
((or-preds (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 5)
;; or simpler...
((or-preds #(divisible % 3) #(divisible % 5)) 3)
You seem to think that or somehow combines the functions that it receives as arguments, but that's not the case. or can take any kind of values as arguments and simply returns the first one that is "truthy".
So (or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) returns (fn [x] (divisible x 3)) (because functions are "not nothing" and thus "truthy").
So when you do ((or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) something), you're really just doing ((fn [x] (divisible x 3)) something).