How do I evaluate the first step of a Clojure form? - clojure

If I have the following string containing a valid Clojure/ClojureScript form:
"(+ 1 (+ 2 (/ 6 3)))"
How would I evaluate the first "step" of this form? In other words, how would I turn the above form into this:
"(+ 1 (+ 2 2))"
and then turn that corresponding form into this:
"(+ 1 4)"

You use recursion.
You need to have a function that evaluates the numbers to themselves but if it's not a number you need to apply the operation on the evaluation of the arguments.. Thus
(evaluate '(+ 1 (+ 2 (/ 6 3))))
This should be treated as:
(+ (evaluate '1) (evaluate '(+ 2 (/ 6 3))))
When it starts doing your first step several steps are waiting for the results to be done as well.
Note I'm using list structure and not strings. With strings you would need to use some function to get it parsed.

The other answers are great if you want to execute code in steps, but I want to mention that this evaluation can also be visualized using a debugger. See below Cider's debugger in action:
By using cider-debug-defun-at-point we add a breakpoint on evaluate. Then when the evaluate definition is evaluated the breakpoint is hit, and we step through the code by pressing next repeatedly.
A debugger is very handy when you want to evaluate "steps" of forms.

Below is a very basic implementation that does what you're looking for. It would be more common to eval the entire form, but since you're wanting to just simplify the innermost expressions, this does it:
(defn leaf?
[x]
(and (list? x)
(symbol? (first x))
(not-any? list? (rest x))))
(defn eval-one
[expr]
(cond
(leaf? expr) (apply (-> (first expr) resolve var-get)
(rest expr))
(list? expr) (apply list (map eval-one expr))
:default expr
))
(read-string "(+ 1 (+ 2 (/ 6 3)))")
=> (+ 1 (+ 2 (/ 6 3)))
(eval-one *1)
=> (+ 1 (+ 2 2))
(eval-one *1)
=> (+ 1 4)
(eval-one *1)
=> 5
This is naive and for illustrative purposes only, so please don't be under the impression that a real eval would work this way.
We define a leaf as a list whose first element is a symbol and which does not contain any other lists which could be evaluated. We then process the form, evaluating leaf expressions, recursively evaluating non-leaf expressions which are lists, and for anything else, we just insert it into the resulting expression. The result is that all innermost expressions which can be evaluated, according to our definition, are evaluated.

To add to the other great answers, here is a simple function that should return the first form to evaluate in a given string:
(defn first-eval [form-str]
(let [form (read-string form-str)
tree-s (tree-seq sequential? identity form)]
(first (filter #(= % (flatten %)) tree-s))))
Usage:
(first-eval "(+ 1 (+ 2 (/ 6 3)))") ;; returns (/ 6 3)
tree-seq is fairly limited in it's ability to evalute ALL form, but it's a start.

Related

How does a macro work if it returns a sequence instead of a list?

I came across this macro definition for unless from the brave and true book
(defmacro unless
"Inverted 'if'"
[test & branches]
(conj (reverse branches) test 'if))
I believe the rest param is a sequence, and the conj returns a sequence, so this entire macro returns a sequence. I thought you needed to return a list for the return to be evaluated properly
On further investigation, why does (eval (sequence [+ 1 4 4])) do the same thing as (eval (list 1 4 4)). Where does it say that sequences are evaluated like lists? I don't see that in the docs. –
You have just proven that a list, a seq, and a sequence are all treated as function call sites by the Clojure compiler. That is your answer.
=> (def xxx [+ 2 3]) ; a function and 2 integers in a vector
=> (eval xxx) ; a vector doesn't work
[#object[clojure.core$_PLUS_ 0x375dfecb "clojure.core$_PLUS_#375dfecb"] 2 3]
=> (eval (seq xxx)) ; a seq works
5
=> (eval (sequence xxx)) ; a sequence works
5
=> (eval (apply list xxx)) ; converts xxx to a list (+ 2 3) which works
5
When the Clojure docs are ambiguous or are missing some detail, a small experiment like the above will answer your question.
If the answer applies to a specific area of the Clojure website, function docstring, or clojuredocs.org or clojure-doc.org, you may consider submitting a pull-request to update & improve the docs.

Clojure - Make first + filter lazy

I am learning clojure. While solving one of the problem, I had to use first + filter. I noted that the filter is running unnecessarily for all the inputs.
How can I make the filter to run lazily so that it need not apply the predicate for the whole input.
The below is an example showing that it is not lazy,
(defn filter-even
[n]
(println n)
(= (mod n 2) 0))
(first (filter filter-even (range 1 4)))
The above code prints
1
2
3
Whereas it need not go beyond 2. How can we make it lazy?
This happens because range is a chunked sequence:
(chunked-seq? (range 1))
=> true
And it will actually take the first 32 elements if available:
(first (filter filter-even (range 1 100)))
1
2
. . .
30
31
32
=> 2
This overview shows an unchunk function that prevents this from happening. Unfortunately, it isn't standard:
(defn unchunk [s]
(when (seq s)
(lazy-seq
(cons (first s)
(unchunk (next s))))))
(first (filter filter-even (unchunk (range 1 100))))
2
=> 2
Or, you could apply list to it since lists aren't chunked:
(first (filter filter-even (apply list (range 1 100))))
2
=> 2
But then obviously, the entire collection needs to be realized pre-filtering.
This honestly isn't something that I've ever been too concerned about though. The filtering function usually isn't too expensive, and 32 element chunks aren't that big in the grand scheme of things.

Clojure apply that does not realize the first four elements of a lazy sequence?

It appears that apply forces the realization of four elements given a lazy sequence.
(take 1
(apply concat
(repeatedly #(do
(println "called")
(range 1 10)))))
=> "called"
=> "called"
=> "called"
=> "called"
Is there a way to do an apply which does not behave this way?
Thank You
Is there a way to do an apply which does not behave this way?
I think the short answer is: not without reimplementing some of Clojure's basic functionality. apply's implementation relies directly on Clojure's implementation of callable functions, and tries to discover the proper arity of the given function to .invoke by enumerating the input sequence of arguments.
It may be easier to factor your solution using functions over lazy, un-chunked sequences / reducers / transducers, rather than using variadic functions with apply. For example, here's your sample reimplemented with transducers and it only invokes the body function once (per length of range):
(sequence
(comp
(mapcat identity)
(take 1))
(repeatedly #(do
(println "called")
(range 1 10))))
;; called
;; => (1)
Digging into what's happening in your example with apply, concat, seq, LazySeq, etc.:
repeatedly returns a new LazySeq instance: (lazy-seq (cons (f) (repeatedly f))).
For the given 2-arity (apply concat <args>), apply calls RT.seq on its argument list, which for a LazySeq then invokes LazySeq.seq, which will invoke your function
apply then calls a Java impl. method applyToHelper which tries to get the length of the argument sequence. applyToHelper tries to determine the length of the argument list using RT.boundedLength, which internally calls next and in turn seq, so it can find the proper overload of IFn.invoke to call
concat itself adds another layer of lazy-seq behavior.
You can see the stack traces of these invocations like this:
(take 1
(repeatedly #(do
(clojure.stacktrace/print-stack-trace (Exception.))
(range 1 10))))
The first trace descends from the apply's initial call to seq, and the subsequent traces from RT.boundedLength.
in fact, your code doesn't realize any of the items from the concatenated collections (ranges in your case). So the resulting collection is truly lazy as far as elements are concerned. The prints you get are from the function calls, generating unrealized lazy seqs. This one could easily be checked this way:
(defn range-logged [a b]
(lazy-seq
(when (< a b)
(println "realizing item" a)
(cons a (range-logged (inc a) b)))))
user> (take 1
(apply concat
(repeatedly #(do
(println "called")
(range-logged 1 10)))))
;;=> called
;; called
;; called
;; called
;; realizing item 1
(1)
user> (take 10
(apply concat
(repeatedly #(do
(println "called")
(range-logged 1 10)))))
;; called
;; called
;; called
;; called
;; realizing item 1
;; realizing item 2
;; realizing item 3
;; realizing item 4
;; realizing item 5
;; realizing item 6
;; realizing item 7
;; realizing item 8
;; realizing item 9
;; realizing item 1
(1 2 3 4 5 6 7 8 9 1)
So my guess is that you have nothing to worry about, as long as the collection returned from repeatedly closure is lazy

Clojure filter composition with reduce

I have a higher order predicate
(defn not-factor-of-x? [x]
(fn [n]
(cond
(= n x) true
(zero? (rem n x)) false
:else true)))
which returns a predicate that checks if the given argument n is not a factor of x.
Now I want to filter a list of numbers and find which are not factors of say '(2 3). One way to do this would be :
(filter (not-factor-of-x? 3) (filter (not-factor-of-x? 2) (range 2 100)))
But one can only type so much. In order to do this dynamically I tried function composition :
(comp (partial filter (not-factor-of-x? 2)) (partial filter (not-factor-of-x? 3)))
And it works. So I tried reducing the filters, like this:
(defn compose-filters [fn1 fn2]
(comp (partial filter fn1) (partial filter fn2)))
(def composed-filter (reduce compose-filters (map not-factor-of-x? '(2 3 5 7 11))))
(composed-filter (range 2 122)) ; returns (2 3 4 5 6 7 8 9 10 .......)
So, why the filter composition is not working as intended ?
There are many ways to compose functions and/or improve your code. Here's one:
(defn factor? [n x]
(and (not= n x) (zero? (rem n x))))
(->> (range 2 100)
(remove #(factor? % 2))
(remove #(factor? % 3)))
;; the same as the above
(->> (range 2 100)
(remove (fn [n] (some #(factor? n %) [2 3]))))
To see your problem with (reduce compose-filters ... let's look a bit at what that actually does. First, it uses filter on the first two predicates and composes them.. The result of that is a new function from sequences to sequences. The next iteration then calls filter on that function, when filter expects a predicate. Every sequence is a truthy value, so that new filter will now never remove any values because it's using a "predicate" which always returns truthy values. So in the end, only the very last filter actually does any filtering - in my REPL your code removes the numbers 22, 33, 44 and so on because 11 is a factor in them. I think the reduce you want to do here is more like
(reduce comp (map (comp (partial partial filter) not-factor-of-x?) '(2 3 5 7 11)))
Note how because we only want to call (partial filter) once per number, you can move that into the mapping step of the mapreduce. As to how I'd do this, considering that you produce all your predicates together:
(map not-factor-of-x? '(2 3 5 7 11))
it seems more natural to me to just combine the predicates at that point using every-pred
(apply every-pred (map not-factor-of-x? '(2 3 5 7 11)))
and use one filter on that predicate. It seems to communicate the intent a little more clearly ("I want values satisfying every one of these preds") and unlike composition of (partial filter ...) it avoids making an intermediate sequence for each predicate.
(In Clojure 1.7+ you can also avoid this by composing the transducer version of filter).

setf in Clojure

I know I can do the following in Common Lisp:
CL-USER> (let ((my-list nil))
(dotimes (i 5)
(setf my-list (cons i my-list)))
my-list)
(4 3 2 1 0)
How do I do this in Clojure? In particular, how do I do this without having a setf in Clojure?
My personal translation of what you are doing in Common Lisp would Clojurewise be:
(into (list) (range 5))
which results in:
(4 3 2 1 0)
A little explanation:
The function into conjoins all elements to a collection, here a new list, created with (list), from some other collection, here the range 0 .. 4. The behavior of conj differs per data structure. For a list, conj behaves as cons: it puts an element at the head of a list and returns that as a new list. So what is does is this:
(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 (list))))))
which is similar to what you are doing in Common Lisp. The difference in Clojure is that we are returning new lists all the time, instead of altering one list. Mutation is only used when really needed in Clojure.
Of course you can also get this list right away, but this is probably not what you wanted to know:
(range 4 -1 -1)
or
(reverse (range 5))
or... the shortest version I can come up with:
'(4 3 2 1 0)
;-).
Augh the way to do this in Clojure is to not do it: Clojure hates mutable state (it's available, but using it for every little thing is discouraged). Instead, notice the pattern: you're really computing (cons 4 (cons 3 (cons 2 (cons 1 (cons 0 nil))))). That looks an awful lot like a reduce (or a fold, if you prefer). So, (reduce (fn [acc x] (cons x acc)) nil (range 5)), which yields the answer you were looking for.
Clojure bans mutation of local variables for the sake of thread safety, but it is still possible to write loops even without mutation. In each run of the loop you want to my-list to have a different value, but this can be achieved with recursion as well:
(let [step (fn [i my-list]
(if (< i 5)
my-list
(recur (inc i) (cons i my-list))))]
(step 0 nil))
Clojure also has a way to "just do the looping" without making a new function, namely loop. It looks like a let, but you can also jump to beginning of its body, update the bindings, and run the body again with recur.
(loop [i 0
my-list nil]
(if (< i 5)
my-list
(recur (inc i) (cons i my-list))))
"Updating" parameters with a recursive tail call can look very similar to mutating a variable but there is one important difference: when you type my-list in your Clojure code, its meaning will always always the value of my-list. If a nested function closes over my-list and the loop continues to the next iteration, the nested function will always see the value that my-list had when the nested function was created. A local variable can always be replaced with its value, and the variable you have after making a recursive call is in a sense a different variable.
(The Clojure compiler performs an optimization so that no extra space is needed for this "new variable": When a variable needs to be remembered its value is copied and when recur is called the old variable is reused.)
For this I would use range with the manually set step:
(range 4 (dec 0) -1) ; => (4 3 2 1 0)
dec decreases the end step with 1, so that we get value 0 out.
user=> (range 5)
(0 1 2 3 4)
user=> (take 5 (iterate inc 0))
(0 1 2 3 4)
user=> (for [x [-1 0 1 2 3]]
(inc x)) ; just to make it clear what's going on
(0 1 2 3 4)
setf is state mutation. Clojure has very specific opinions about that, and provides the tools for it if you need it. You don't in the above case.
(let [my-list (atom ())]
(dotimes [i 5]
(reset! my-list (cons i #my-list)))
#my-list)
(def ^:dynamic my-list nil);need ^:dynamic in clojure 1.3
(binding [my-list ()]
(dotimes [i 5]
(set! my-list (cons i my-list)))
my-list)
This is the pattern I was looking for:
(loop [result [] x 5]
(if (zero? x)
result
(recur (conj result x) (dec x))))
I found the answer in Programming Clojure (Second Edition) by Stuart Halloway and Aaron Bedra.