Running the following code in Clojure gives a StackOverflow Error:
(cond
(= 1 2) 1
(= 2 3) 2
(= 3 4) 3
...
(= 1022 1023) 1022
(= 1023 1024) 1023
:else 1024)
I would like to create a function/macro that can handle a huge number of clauses without creating a stack that overflows.
Please advise as to how I might attempt this.
If you look at the full stack trace, you'll see that cond emits a deeply-nested if structure; the exception then occurs when the compiler tries to parse this structure. The problem might have more to do with simply compiling deeply nested Clojure code than the specific use of cond.
I was able to come up with the following macro that takes a list of clauses, wraps them in thunks to provide the deferred evaluation that you get with if, and then uses some to find the first logical true test expression. Its performance probably isn't as good due to the creation of so many anonymous functions, but it gets around the stack overflow exception.
(defmacro cond' [& clauses]
`(:result
(some (fn [[pred-thunk# val-thunk#]]
(if (pred-thunk#) {:result (val-thunk#)}))
(partition 2 (list ~#(map (fn [c] `(fn [] ~c)) clauses))))))
Note the wrapping and unwrapping of the returned value in a map, to ensure that some correctly handles a value clause that evaluates to nil.
A cond with 513 clauses in unlikely to be used in practice.
Here is a functional implementation of your example.
(or (some identity (map #(if (= %1 %2) %1)
(range 1 1024)
(range 2 1025)))
1024)
The requirement is like this:
Given a list of condition and result mappings, e.g.
[ [cond1 r1] [cond2 r2] ...], where
cond1: (= 1 1),
r1: 1
Find the result - rn - where condn evaluates to true
Solution using some is perfect here in solving the problem, but I think we can avoid using macro.
(defn match [[condition result]]
(when condition result))
(some match [[(= 1 2) 100] [(= 2 3) 200] [(= 3 3) 300]]) ;; => 300
Related
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.
I tried to solve the find two numbers index in a list where nums[i]+nums[j]==target:
(defn two-sum [nums target]
"Find sum of two numbers equals to target"
(if (<= 1 (count nums))
nil)
(let [hdict (hash-map)]
(for [i (range 1 (count nums))]
(if (get hdict (nums i))
[(get hdict (nums i)) i] ;return hdict[nums[i]] and i
(assoc hdcit (- target (nums i)) i)))))
I got this error:
1. Caused by java.lang.RuntimeException
Unable to resolve symbol: hdcit in this context
I'm confused: I've alread bind hdict as a hash-map, why still unable solved?
The error is a simple typo, though there are a couple other points worth considering:
Clojure if expressions always return a value and if you don't specify an else clause (the second expression) then it defaults to nil
So the if in the code above basically says:
(if contition
nil ;; the true case
nil ;; the false case)
Always returns nil. Though since it's not the last expression in the function this value will be ignored because:
The return value of a function (and most other expressions) is the last value in the expression.
Most likely you want to move the ) after the nil to the end of the function.
Clojure data structure are immutable, calling assoc on a map produces a new map that has an additional value while leaving the old on unchanged because someone else might be working on it.
So the assoc on the last line will never do anything.
for is not a "for loop", rather it produces a sequence of new values, lazily, based on a very powerful expression "mini language" (DSL)
This means that it only produces a value when it's read. So this for loop will not run unless something prints the value. The REPL will print this and make this function work only in development. I call this "the lazy bug".
Immutable data is a core concept in Clojure and basically all the goodness of the language flows, at least in part, from it.
Clojure's for expression is powerful enough to completely solve this problem:
user> (let [data [1 2 3 4 5 6 7 42 12]
target 12]
(for [x data
y data
:when (= (+ x y) target)]
[x y]))
([5 7] [6 6] [7 5])
I don't quite understand the behavior or clojure.core.typed/cf as explained below.
I assume cf is used to infer the type of a form
(t/cf (+ 1 2)) => Long
Now, this fails
(t/cf (/ 1 0)) => Error
This indicates to me that the sexpr was evaluated prior to be type checked. I had expected Long.
When I define a custom function:
(t/ann my-fn [t/Any -> t/Num])
(defn my-fn [x]
(assert (number? x))
(println "CALLED")
x)
I can used this in the same expression again and it fails, indicating that the fn was indeed called.
(t/cf (/ 1 (my-fn 0)) => Error, because it evaluates my-fn. no type inference here??
However, then the following makes no sense to me.
(t/cf (range)) => (t/ASeq t/AnyInteger)
Why is in this case function range NOT evaluated, also if it did evaluate the expression, the following examples should return the same type:
(t/cf (->> (range 2) vec)) => (t/AVec (t/U Short Byte Integer BigInteger Long BigInt))
(t/cf [0 1]) => [(t/HVec [(t/Val 0) (t/Val 1)]) {:then tt, :else ff}]
But they return different types.
My gut feeling is that it has to do with constants, i.e. when I type check a form that contains t/Val's, then core.typed autoamtically evaluates it. This however doesn't explain why for certain functions it does not evaluate it. The 2 in (range 2) is definitely a constant, so why this difference in behavior.
If the forms are evaluated before type checking then the following should have the same behavior
(t/cf (map inc (range 10))))
(t/cf (map #(inc %) (range 10))))
But core.typed does indeed see a difference. The second example fails because the anonymous fn receives a t/Any by default and you cannot call inc on it. So this means that core.typed must do some analysis of the form plus it also evaluates it. I find this a bit confusing I confess, maybe someone can enlighten me.
Edit: A short summary
Why does the following relation seems to be true in some but not all cases?
(t/cf form) <=> (let [x form] (t/cf x))
core.typed performs completely static type checking.
The compilation pipleline for cf is read -> analyze -> type check -> eval.
If there is a static type error, that is considered fatal.
Otherwise the evaluation will be performed.
(cf (/ 1 0)) throws a runtime error because (/ 1 0) is a well-typed expression.
The reason evaluation is needed is related to the practicalities of analysing Clojure code — strange things happen if you analyze code then don’t evaluate it.
I'm a total beginer in Clojure and I've ran into a problem that I'm not even sure if can be done in Closure.
So the issue is the following. I've implemented a function that computes the prime numbers from an interval (up to a limit).
(defn gather_primes_in_range [range_start range_end target_number prime_list]
(if (or (= 0 target_number) (> range_start range_end) (= FIND_MORE_PRIMES false))
prime_list
(do
(if (is_prime? range_start)
(gather_primes_in_range (+ range_start 1) range_end (- target_number 1) (conj, prime_list, range_start))
(gather_primes_in_range (+ range_start 1) range_end target_number prime_list)
)
)
)
)
(defn find_nr_of_primes_in_range [range_start range_end target_number]
(if (< range_start 2)
(gather_primes_in_range 2 range_end target_number [])
(gather_primes_in_range range_start range_end target_number [])
)
)
This works just fine. But what I want now is to have a global variable that should store on each method call the primes that are found in a variable to lookup later. In other languages like Python, Ruby or Scala I would just do this by having a Set to which I add entries before returing from the function. But in Clojure I have no ideea how to go around this.
Basically what I tried is, have somewhere global declared:
(def PRIMES_FOUND_SO_FAR #{})
And then somehow on return add the entries to this variable. Is this possible at all in Clojure and if so how? I've tried on other variables to change their values using either swap! and atom, or set! but could not make it to work here in any situation.
Firstly, I strongly advice you to read about clojure code conventions What are Clojure's Naming Conventions?
Let me show you some improvements of your code.
1) Applying clojure naming conventions.
Then switch from (+ variable 1) to (inc variable) (the same optimizations with dec).
Also (= FIND_MORE_PRIMES false) can be simply replaced by find-more-primes?
And finally the condition (= 0 smthng) could be written in more idiomatic style (zero? smthng)
Now your code looks a bit more readable:
(defn gather-primes-in-range [range-start range-end target-number prime-list]
(if (or (zero? target-number) (> range-start range-end) need-more-primes?)
prime-list
(do
(if (is-prime? range-start)
(gather-primes-in-range (inc range-start) range-end (dec target-number) (conj prime-list range-start))
(gather-primes-in-range (inc range-start) range-end target-number prime-list)))))
2) Now we should remove redundant do call cause it wraps the only one function call.
And the last trick is to apply tail recursion (http://clojure.org/special_forms#Special%20Forms--(recur%20exprs*)) via swapping entire gather-primes-in-range calls to recur
(defn gather-primes-in-range
[range-start range-end target-number prime-list]
(if (or (zero? target-number) (> range-start range-end) need-more-primes?)
prime-list
(if (is-prime? range-start)
(recur (inc range-start) range-end (dec target-number) (conj prime-list range-start))
(recur (inc range-start) range-end target-number prime-list))))
And here comes time for answering your question. You wouldn't benefit from this approach
(def PRIMES_FOUND_SO_FAR #{})
because you haven't opportunity to change this set. The only thing that you can deal with it is to create some new immutable data structure from that one.
As #georgek mention you could simply use atom in this particular case.
(def PRIMES_FOUND_SO_FAR (atom #{}))
Adding new prime number to atom:
(swap! PRIMES_FOUND_SO_FAR conj prime-number)
Deref atom for extracting the value:
#PRIMES_FOUND_SO_FAR ;; or (deref PRIMES_FOUND_SO_FAR)
-> #{2 3 5 7 11}
Anyway your code is a little bit imperative but you should always remember that clojure is functional language with immutable data structures, functions as arguments, etc. using global variables is not good idea at all. BTW thats how your function should look like in clojure style:
(defn gather-primes-in-range [start end target-number]
(take target-number (filter is-prime? (range start end))))
for those who have spent too much time searching how to modify a global (root) variable in clojure here is the solution:
(def user-remote-browser "anonymous")
you can modify it from anywhere i suppose but in the same namepace with:
(alter-var-root #'user-remote-browser (constantly name))
alter-var-root use a function to modify a variable,
constantly create a constant function returning here the string name
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.