Anonymous function consuming another anonymous function - clojure koan - clojure

I am working on the clojure koans and one of the questions in the functions needs further explanation for me to “get it” and have an aha moment. I am able to write the function that satisfies the question. But I don't fully understand why all the bits work.
Clojure> (= 25 ((fn [a b] (b a)) 5 (fn [n] (* n n))))
true
Question 1.
I do not understand why this throws an error:
Clojure> (= 25 ((fn [b a] (b a)) 5 (fn [n] (* n n))))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
So the only change in the above is switching the order of b and a.
In my brain I read “a function that takes an a and b” or a “b and an a” but how they are used is up to the subsequent statement in the parens. Why does the order matter at this point?
Questions 2.
Clojure> (= 25 ((fn [a] (5 a)) (fn [n] (* n n))))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
Why when I substitute out the value of b for the int it represents do I get an error?
Quentions 3.
((fn [a b] (b a)) 5 (fn [n] (* n n))))
Why does this not throw an error (b a) b in this instance is 5 which is a symbol.
The first item in brackets is expected to be a function or a special form unless it is a list?

look at your expression in the first function:
(b a)
since b is first, b has to be a function. In your second example, you're trying to pass 5 to b, but 5 is not a function. With descriptive names you can see that you're trying to use 5 as a function:
((fn [argument function] (argument function)) ;; problem!!
5
(fn [n] (* n n)))
Remember the evaluation rules for lisps: given this s-expression:
(f x y z)
evaluate f, x, y, and z, and apply f as a function to x, y, and z.
see answer to 1 -- '5' is not a function. Use descriptive names, and easily spot the problem:
((fn [function] (5 function)) ;; problem!!
(fn [n] (* n n)))
Change to:
((fn [a] (a 5)) ;; 'a' and '5' flipped
(fn [n] (* n n)))
to get this to run.
this isn't a problem: a is 5, b is a function in (b a). With descriptive names it makes more sense:
((fn [argument function] (function argument))
5
(fn [n] (* n n)))

Related

Clojure: succinctly forward optional values

I've written a probability function in Clojure that takes an optional hash-map of options:
(defn roll-lte
([n d] (/ n d))
([n d options]
(let [p (/ n d)
roll-type (:type options :normal)]
(cond
(= roll-type :advantage) (- (* p 2) (* p p))
(= roll-type :disadvantage) (* p p)
(= roll-type :normal) p
:else (throw (IllegalArgumentException. "Invalid roll type."))))))
This works as intended, but the idea is to write other functions that build off of this one -- for example:
(defn roll-gte
([n d] (roll-lte (- d n -1) d))
([n d options] (roll-lte (- d n -1) d options)))
The two arities in roll-lte make building off of the function awkward and repetitive, especially in cases like the above where options is simply being forwarded to roll-lte. Is there a more concise and less repetitive way to achieve this?
When I have functions with multiple arities, I usually try to have the lower-arity versions call the higher-arity versions with safe default arguments. The "main" implementation of the function usually ends up being the highest-arity body:
(defn roll-lte
([n d] (roll-lte n d nil))
([n d {:keys [type]
:or {type :normal}}]
(let [p (/ n d)]
(case type ;; used case instead of cond here
:advantage (- (* p 2) (* p p))
:disadvantage (* p p)
:normal p
(throw (IllegalArgumentException. "Invalid roll type."))))))
I also used :or in the options map destructuring above to set the default value for type, which allows the lower-arity functions to just pass a nil options map.
(defn roll-gte
([n d] (roll-gte n d nil))
([n d options] (roll-lte (- d n -1) d options)))
(roll-gte 3 4) ;=> 1/2
(roll-gte 3 4 {:type :advantage}) ;=> 3/4

What are the limitations of forward declaring in Clojure? Why can't I use comp in this example?

I like my code to have a "top-down" structure, and that means I want to do exactly the opposite from what is natural in Clojure: functions being defined before they are used. This shouldn't be a problem, though, because I could theoretically declare all my functions first, and just go on and enjoy life. But it seems in practice declare cannot solve every single problem, and I would like to understand what is exactly the reason the following code does not work.
I have two functions, and I want to define a third by composing the two. The following three pieces of code accomplish this:
1
(defn f [x] (* x 3))
(defn g [x] (+ x 5))
(defn mycomp [x] (f (g x)))
(println (mycomp 10))
2
(defn f [x] (* x 3))
(defn g [x] (+ x 5))
(def mycomp (comp f g))
3
(declare f g)
(defn mycomp [x] (f (g x)))
(defn f [x] (* x 3))
(defn g [x] (+ x 5))
But what I would really like to write is
(declare f g)
(def mycomp (comp f g))
(defn f [x] (* x 3))
(defn g [x] (+ x 5))
And that gives me
Exception in thread "main" java.lang.IllegalStateException: Attempting to call unbound fn: #'user/g,
That would mean forward declaring works for many situations, but there are still some cases I can't just declare all my functions and write the code in any way and in whatever order I like. What is the reason for this error? What does forward declaring really allows me to do, and what are the situations I must have the function already defined, such as for using comp in this case? How can I tell when the definition is strictly necessary?
You can accomplish your goal if you take advantage of Clojure's (poorly documented) var behavior:
(declare f g)
(def mycomp (comp #'f #'g))
(defn f [x] (* x 3))
(defn g [x] (+ x 5))
(mycomp 10) => 45
Note that the syntax #'f is just shorthand (technically a "reader macro") that translates into (var f). So you could write this directly:
(def mycomp (comp (var f) (var g)))
and get the same result.
Please see this answer for a more detailed answer on the (mostly hidden) interaction between a Clojure symbol, such as f, and the (anonymous) Clojure var that the symbol points to, namely either #'f or (var f). The var, in turn, then points to a value (such as your function (fn [x] (* x 3)).
When you write an expression like (f 10), there is a 2-step indirection at work. First, the symbol f is "evaluated" to find the associated var, then the var is "evaluated" to find the associated function. Most Clojure users are not really aware that this 2-step process exists, and nearly all of the time we can pretend that there is a direct connection between the symbol f and the function value (fn [x] (* x 3)).
The specific reason your original code doesn't work is that
(declare f g)
creates 2 "empty" vars. Just as (def x) creates an association between the symbol x and an empty var, that is what your declare does. Thus, when the comp function tries to extract the values from f and g, there is nothing present: the vars exist but they are empty.
P.S.
There is an exception to the above. If you have a let form or similar, there is no var involved:
(let [x 5
y (* 2 x) ]
y)
;=> 10
In the let form, there is no var present. Instead, the compiler makes a direct connection between a symbol and its associated value; i.e. x => 5 and y => 10.
I think Alan's answer addresses your questions very well. Your third example works because you aren't passing the functions as arguments to mycomp. I'd reconsider trying to define things in "reverse" order because it works against the basic language design, requires more code, and might be harder for others to understand.
But... just for laughs and to demonstrate what's possible with Clojure macros, here's an alternative (worse) implementation of comp that works for your preferred syntax, without dealing directly in vars:
(defn- comp-fn-arity [variadic? args f & fs] ;; emits a ([x] (f (g x)) like form
(let [args-vec (if variadic?
(into (vec (butlast args)) ['& (last args)])
(apply vector args))
body (reduce #(list %2 %1)
(if variadic?
(apply list 'apply (last fs) args)
(apply list (last fs) args))
(reverse (cons f (butlast fs))))]
`(~args-vec ~body)))
(defmacro momp
([] identity)
([f] f)
([f & fs]
(let [num-arities 5
args-syms (repeatedly num-arities gensym)]
`(fn ~#(map #(apply comp-fn-arity (= % (dec num-arities)) (take % args-syms) f fs)
(range num-arities))))))
This will emit something kinda like comp's implementation:
(macroexpand '(momp f g))
=>
(fn*
([] (f (g)))
([G__1713] (f (g G__1713)))
([G__1713 G__1714] (f (g G__1713 G__1714)))
([G__1713 G__1714 G__1715] (f (g G__1713 G__1714 G__1715)))
([G__1713 G__1714 G__1715 & G__1716] (f (apply g G__1713 G__1714 G__1715 G__1716))))
This works because your (unbound) functions aren't being passed as values to another function; during compilation the macro expands "in place" as if you'd written the composing function by hand, as in your third example.
(declare f g)
(def mycomp (momp f g))
(defn f [x] (* x 3))
(defn g [x] (+ x 5))
(mycomp 10) ;; => 45
(apply (momp vec reverse list) (range 10)) ;; => [9 8 7 6 5 4 3 2 1 0]
This won't work in some other cases, e.g. ((momp - dec) 1) fails because dec gets inlined and doesn't have a 0-arg arity to match the macro's 0-arg arity. Again, this is just for the sake of example and I wouldn't recommend it.

I don't understand the (doc fn)...it says I can name a function, but I can't invoke it by its name?

I'm new to Clojure and am grasping to understand the concepts. The REPL helpfully lets me get docs of "stuff". So I want to define a function...
clojure-noob.core> (doc fn)
-------------------------
clojure.core/fn
(fn name? [params*] exprs*)
(fn name? ([params*] exprs*) +)
Special Form
...
name => symbol
...and the doc suggests that I can name my function. The REPL accepts my function, but I can't invoke it, "Unable to resolve symbol.."...
clojure-noob.core> (fn add-pair [a b] (+ a b))
#<core$eval3364$add_pair__3365 clojure_noob.core$eval3364$add_pair__3365#6fb5a33b>
clojure-noob.core> (add-pair 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: add-pair in this context, compiling:(/private/var/folders/1g/fnytl2x93sx6hp2f1rsf4h1r5xtqv_/T/form-init6828995349142227131.clj:1:1)
clojure-noob.core>
Leaving off the name and building a proper def of the fn does get the job done as does leveraging the defn macro thing...
clojure-noob.core> (def another-add-pair (fn [a b] (+ a b)))
clojure-noob.core> (another-add-pair 1 2)
3
clojure-noob.core> (defn yet-another-add-pair [a b] (+ a b))
#'clojure-noob.core/yet-another-add-pair
clojure-noob.core> (yet-another-add-pair 3 4)
7
There is obviously something I don't understand about the output of (doc fn). In particluar, what is the name? there and what can you do with it? I am as much trying to learn how to read the docs as well as understand the fn special form. Thanks.
calling (fn add-pair [a b] (+ a b)) from the REPL builds an instance of that function and then prints it to the screen. After that it goes away and is not saved anywhere. This is why you can't get it's docs using the doc function. The name parameter in the fn literal is often used for making recursive calls and does not mean that it will be saved by that name anywhere.
if you call (defn add-pair [a b] (+ a b)) then it saves the function into the namespace and then the doc function is able to look it up later and print it's doc string.
A fn form evaluates to a function object.
You can apply the function object immediately:
((fn [a b] (+ a b)) 1 1) ;=> 2
If you want to refer to the function object locally, use a let
binding:
(let [add-pair (fn [a b] (+ a b))] (add-pair 1 1)) ;=> 2
A function object is as much a value as 1
or [3 :a]:
(let [double (fn [n] (* 2 n))]
(({double (comp double double)} double) 3)
;=> 12
The let binding does not exist within the fn form - you need a
name parameter for that:
((fn fact [n] (case n, 0 1, (* n (fact (dec n))))) 5) ;=> 120
letfn does both:
(letfn [(fact [n] (case n, 0 1, (* n (fact (dec n)))))] (fact 5)) ;=> 120
If you want the function to be accessible globally, bind it to a
var using def:
(def fact (fn fact [n] (case n, 0 1, (* n (fact (dec n))))))
(fact 5) ;=> 120
The defn macro does the same more succinctly:
(defn fact [n] (case n, 0 1, (* n (fact (dec n)))))
(fact 5) ;=> 120

How to create a lazy-seq that repeats elements of another collection, in random order?

I would like to create a lazy sequence that repeats elements from another collection. It should generate one of each element before repeating. And the order of elements must be random.
Here's what it should behave like:
=> (take 10 x)
(B A C B A C A B C C)
This seems to work:
(def x (lazy-seq (concat (lazy-seq (shuffle ['A 'B 'C])) x)))
However it is using two lazy-seq's. Is there a way to write this sort of lazy sequence by using just one lazy-seq?
If this cannot be done with one lazy-seq, how do values get generated? Since my collection has only three items, I expect the inner lazy-seq to be calculated completely in the first chunk.
Before coming up with the sequence above I tried the one below:
=> (def x (lazy-seq (concat (shuffle ['A 'B 'C]) x)))
=> (take 10 x)
(C A B C A B C A B C)
I would appreciate any explanation why this one doesn't randomize each batch.
How about just repeating the sequence and then mapcatting over it with the shuffle function? Here is an example:
(take 10 (mapcat shuffle (repeat ['A 'B 'C])))
;=> (B C A B A C B A C B)
I would appreciate any explanation why this one doesn't randomize each batch.
Your (shuffle '[a b c]) is evaluated only once, when beginning of the sequence is realized, then the shuffled list is used again and again.
Here is a little test:
user> (defn test-fnc [coll]
(do (print "boom!")
(shuffle coll)))
;; => #'user/test-fnc
user> (def x (lazy-seq (concat (test-fnc '[a b c]) x)))
;; => #'user/x
user> (take 10 x)
;; => (boom!b c a b c a b c a b)
user> (take 10 x)
;; => (b c a b c a b c a b)
You also can use lazy-cat instead:
user> (def x (lazy-cat (shuffle '[a b c]) x))
;; => #'user/x
but is won't solve your problem :-)
This happens because of lazy-seq:
Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls.
If you rewrite your definition in terms of function calls:
(defn x [] (lazy-seq (concat (shuffle ['A 'B 'C]) (x))))
it will work:
user> (take 10 (x))
;; => (C B A C A B B A C B)
because there will be different lazy seq on every call, not the same cached seq that repeats itself.

Why am I getting a cast error when trying to use Simpson's rule in Clojure?

I'm trying to work through some of the exercises in SICP using Clojure, but am getting an error with my current method of executing Simpson's rule (ex. 1-29). Does this have to do with lazy/eager evalution? Any ideas on how to fix this? Error and code are below:
java.lang.ClassCastException: user$simpson$h__1445 cannot be cast to java.lang.Number
at clojure.lang.Numbers.divide (Numbers.java:139)
Here is the code:
(defn simpson [f a b n]
(defn h [] (/ (- b a) n))
(defn simpson-term [k]
(defn y [] (f (+ a (* k h))))
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y)))
(* (/ h 3)
(sum simpson-term 0 inc n)))
You define h as a function of no arguments, and then try to use it as though it were a number. I'm also not sure what you're getting at with (sum simpson-term 0 inc n); I'll just assume that sum is some magic you got from SICP and that the arguments you're passing to it are right (I vaguely recall them defining a generic sum of some kind).
The other thing is, it's almost always a terrible idea to have a def or defn nested within a defn. You probably want either let (for something temporary or local) or another top-level defn.
Bearing in mind that I haven't written a simpson function for years, and haven't inspected this one for algorithmic correctness at all, here's a sketch that is closer to the "right shape" than yours:
(defn simpson [f a b n]
(let [h (/ (- b a) n)
simpson-term (fn [k]
(let [y (f (+ a (* k h)))]
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y))))]
(* (/ h 3)
(sum simpson-term 0 inc n))))