I'm creating a macro that will accept a sum in infix notation and return an equivalent list in prefix notation. Whilst the code probably isn't logically correct yet, I've run into the following error when calling the macro:
CompilerException java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 0 args, got: 5, compiling:(/tmp/form-init1201331851685991945.clj:1:1)
Here's the macro's code:
(defmacro infixer [o1 outlist i1 i2 i3]
`(if (empty? ~i3)
(concat ~i1 ~i2)
(if (= ~i2 ~o1)
;then recur list of i2 i1 i3 at outlist tail
(recur ~o1
(concat ~outlist (~i2 ~i1 ~(first i3)))
()
~(second i3)
~(rest (rest i3)))
;else recur i1 at outlist tail
(recur ~o1
(concat ~outlist ~i1)
~i2
~i3
~(rest i3)
))))
I'm using the following to test it, after which the above error is thrown:
(def s1 '(1 + 3 * 2 / 2 * 5 - 3))
(infixer * () (first s1)(second s1)(rest (rest s1)))
I can't see any recur targets, so shouldn't recur be seeing the five arguments after the macro name? I haven't used syntax quoting before, so my suspicions are that I've misunderstood how to use it. Please can someone explain why the error is being thrown?
Also, if I'm way off on the logic of trying to convert infix to prefix, feel free to point me in the right direction! I'm new to Clojure and FP so any guidance is extremely appreciated - thanks in advance.
Related
To preface this, I'm very new to Clojure. I was wondering why I'm getting a ClassCastExpection on this piece of code. I've looked at it and syntactically and logically it looks correct?
Clojure Code:
; (load-file "cje842asg1.clj")
(def lstnum '(76 85 71))
; 2a
(defn sum [list] (
(if (empty? list)
0
(+ (first list (sum (rest list))))
)
)
)
; if empty return zero, else add the first num in list and pass in the
; rest.
(sum lstnum)
Any help is appreciated.
The code has 2 separate errors.
The first is calling (first list (sum (rest list))) which is calling first with 2 arguments when you meant to make the second part the second argument to +.
The other one leading to the actual exception is the extra () around the function body. Note the ((if ...)) which means you are trying to call whatever the if returns as a function. In this case it is returning a number, leading to the class java.lang.Long cannot be cast to class clojure.lang.IFn error.
The corrected version would be
(defn sum [list]
(if (empty? list)
0
(+ (first list)
(sum (rest list)))))
Moving the arguments to + into separate lines makes it easier to read in this case (IMHO).
I'm trying to write a Clojure macro that creates a prefix notation list for evaluation from a simple infix notation list, say (2 * 3 + 4 * 2) to an evaluated(+ (* 2 3) (*4 2)) (resulting in 14 being returned).
I have written the following code:
(defmacro infix [op inlist]
(let [[i1 i2 & i3] inlist
last-group? (nil? (second i3))]
(if last-group?
`(if (= ~op ~i2)
(~i2 ~i1 ~(first i3)) ; return unevaluated prefix list
(~i1 ~i2 ~(first i3))) ; return unevaluated infix list
`(if (= ~op ~i2)
; recur with prefix list in i1 position
(infix ~op ~(conj (rest i3) (list i2 i1 (first i3)) ))
; return as list: i1 and i2, recur i3 (probably wrong)
(~i1 ~i2 (infix ~op ~i3))
))))
With the intention of enforcing operator precedence by calling the macro recursively with different op (operator function) parameters:
(infix + (infix * (2 * 3 + 4 * 2)))
Above, I'm just using it with two * and +, but ultimately I'd want to call the macro for all (or at least for the sake of this exercise, / * + -) operators.
When I execute the above nested macro call, I get the following error:
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'cbat.ch7.ex2/infix, compiling:(/tmp/form-init4661580047453041691.clj:1:1)
Calling the macro for a single operator and a list of the same operator (i.e. (infix * (2 * 3 * 4))) works as expected. If I call the macro with a single (i1 i2 i3) list, if op differs from i2, it tries to (understandably) return the unevaluated infix list with the error:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn cbat.ch7.ex2/eval3003 (form-init4661580047453041691.clj:1)
I was hoping calling the macro recursively would mean that I could process the unevaluated infix list before the entire line was evaluated, but this doesn't seem to work.
I'm pretty sure the else branch of the latter, inner if (i.e. (~i1 ~i2 (infix ~op ~i3))) is incorrect and I may just need the inner infix call, but I'm more concerned with getting the nested macro calls for the different operators working prior to evaluation.
I know that this isn't the usual way of converting infix to prefix notation, and have since found out about Dijkstra's shunting-yard algorithm, but please could someone kindly enlighten me as to:
whether such nested macro calls are possible?
whether my logic is reasonable, and not too far from a solution? If so...
... what changes I need to make to get things running?
I'm really focused on learning Clojure, so any thorough explanation (where possible) will be most welcome.
You can nest macro calls as this code demonstrates:
(defmacro mac [tag & forms]
`(do
(println "mac - enter" ~tag)
~#forms
(println "mac - exit " ~tag)))
(mac :a
(doseq [i (range 3)]
(mac :b (println i))))
mac - enter :a
mac - enter :b
0
mac - exit :b
mac - enter :b
1
mac - exit :b
mac - enter :b
2
mac - exit :b
mac - exit :a
You can also make recursive macro calls as this shows:
(defmacro macr [n]
(if (zero? n)
1
`(* ~n (macr ~(dec n)))))
(macr 5) => 120
Without delving too deep into your particular implementation, I would suggest 2 points:
At least to start, keep your forms as simple as possible. This means only forms like (2 + 3). And especially don't force the macro to figure out operator precedence in the early versions (or ever!).
Macros are almost never necessary, and it is unfortunate IMHO that they are somewhat "over-hyped" when learning Clojure & other lisps. I would suggest you don't even think about them for the first year or two, as they are more brittle than functions and less powerful in important ways (you can't pass a macro into a function, for example).
Update
Whenever you want to write something complicated (a macro definitely qualifies!), start small and
build it up one step at a time. Using the lein-test-refresh plugin and the Tupelo library definitely help
here.
First, make the simplest possible macro and observe its behavior:
(ns tst.clj.core
(:use clj.core clojure.test tupelo.test)
(:require [tupelo.core :as t] ))
(t/refer-tupelo)
(defn infix-fn [[a op b]]
(spyx a)
(spyx op)
(spyx b)
)
(defmacro infix [form]
(infix-fn form))
(infix (2 + 3))
a => 2
op => +
b => 3
For many macros, it is helpfully to send the marcro args to a helper function like infix-fn. The
spyx helps us by printing the symbol and its value. At this point, we can simply re-order the
args into prefix notation and away we go:
(defn infix-fn [[a op b]] (list op a b))
(defmacro infix [form] (infix-fn form))
(deftest master
(is= 5 (infix (2 + 3)))
(is= 6 (infix (2 * 3))))
What if we have a recursive tree structure? Check if we need to recurse in infix-fn:
(declare infix-fn)
(defn simplify [arg]
(if (list? arg)
(infix-fn arg)
arg))
(defn infix-fn [[a op b]]
(list op (simplify a) (simplify b)))
(is= 7 (infix ((2 * 2) + 3)))
(is= 9 (infix ((1 + 2) * 3)))
(is= 35 (infix ((2 + 3) * (3 + 4))))
(is= 26 (infix ((2 * 3) + (4 * 5))))
I would not want to add in the complication of operator precedence. If absolutely necessary, I
would not code it up myself but would use the excellent Instaparse library for that purpose.
expansion of your call would give you a clue:
(if (= + *)
(* infix (2 * 3 + 4 * 2))
(infix * (2 * 3 + 4 * 2)))
You've got the wrong presumption that the argument of macro would be expanded before the macro itself, i guess. But in fact in this one: (~i2 ~i1 ~(first i3)) i1 is still infix symbol. As far as i can see, the solution is to add some new condition branch, treating infix form some special way.
I am having a hard time tracking down a stackoverflow error produced by my clojure implementation of the Bron-Kerbosch algorithm.
Below is my implementation of the algorithm itself, and here is a link to a SSCCE outlining the issue http://pastebin.com/gtpTT4B4.
(defn Bron-Kerbosch [r p x graph cliques]
;(println (str "R:" r " P:" p " X:" x " Clq:" cliques))
(cond (and (empty? p) (empty? x)) (concat cliques r)
:else
(let [neigh (neighV graph (dec (count p)))]
(loop [loop-clq '(cliques)
loop-cnt (dec (count p))
loop-p '(p)
loop-x '(x)]
(cond (= -1 loop-cnt) loop-clq
:else
(recur (concat loop-clq
(Bron-Kerbosch (concat r loop-cnt)
(concat p neigh)
(filter (set x) neigh)
graph cliques))
(dec loop-cnt)
(filter (set p) loop-cnt)
(concat x loop-cnt)))))))
I would have to assume that the issue obviously lies within one of my two bootstrap conditions (cond (and (empty? p) (empty? x)) and (cond (= -1 loop-cnt) because the function algorithm is recursive.
Though this assumes that I am building the lists x r p correctly. Judging by the output of the commented out print statement (cliques is always printed as an EmptyList) I assume that my list comprehension might also be the issue.
Along the same lines, the other issue I can somewhat see is that I am not actually calling the algorithm properly in the BK-Call function (in the SSCCEE).
My overall question is what is causing this? Though this is somewhat too open, another question that might lead me to my answer is how I might go about using the print statement on the first line.
When the print statement is uncommented it produces the output
R:clojure.lang.LazySeq#2044e0b9 P:clojure.lang.LazySeq#7f9700a5 X:clojure.lang.LazySeq#1 Clq:clojure.lang.PersistentList$EmptyList#1
I assume that if I could see that x r p are at each call I might be able to see where the algorithm is going wrong.
Can anyone point me in the right direction?
EDIT: The neighV function from the SSCCE
(defn neighV [graph nodenum]
(let [ret-list (for [i (range (count graph)) :when (contains? (graph i) nodenum)] i)]
ret-list))
EDIT2: Noisesmith's answers had gotten me closer to the solution and made sense to me. I wrapped all of my concat in doall. After trying to call the function again I was getting "Cannot cast Long to Seq" errors, I figured that these stemmed from trying to concat loop-cnt onto lists in the function
fptests.core> (BK-Call (sanity1))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
fptests.core> (concat 1 '(2 3))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
So I then wrapped each loop-cnt in a '() to turn it into a list before it is concat
fptests.core> (concat '(1) '(2 3))
(1 2 3)
Which, after I made all of these changes, I ended back at my stack overflow.. Here is the new Bron-Kerbosch function with all of the edits. I guess I now have the same questions as I did before..
Though the new ones are, did I implement that changes that I should have correctly, does the usage of '() make sense to fix the issue that came up after implementing noisesmith's changes?
(defn Bron-Kerbosch1 [r p x graph cliques]
(cond (and (empty? p) (empty? x)) (doall (concat cliques r))
:else
(let [neigh (neighV graph (dec (count p)))]
(loop [loop-clq '(cliques)
loop-cnt (dec (count p))
loop-p '(p)
loop-x '(x)]
(cond (= -1 loop-cnt) loop-clq
:else
(recur (doall (concat loop-clq
(Bron-Kerbosch1 (doall (concat r '(loop-cnt)))
(doall (concat p neigh))
(filter (set x) neigh)
graph cliques)))
(dec loop-cnt)
(filter (set p) '(loop-cnt))
(doall (concat x '(loop-cnt)))))))))
EDIT3: After patiently waiting for my prn statements to stop (not sure why I put them in when I knew it was in a SO) I found that most if not all statements printed were along the lines of
"R:" (loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt ...)
"P:" (range (count graph) 0 2 3) " X:" () " Clq:" ()
After inspecting this some I realized that I have not been recursively calling the function properly. I have been union'ing items to P instead of removing them. This causes P to continuously grow. This is most likely the cause of my stack overflow. Though there are still some issues. I still am creating a stackoverflow, yet again.
Once I fixed my issue of continuing to union to P my issue is that when I concat loop-cnt it is not, I guess to say, evaluated to a value but it stays as a variable name loop-cnt. I suspect that my stack overflow now lies with my bootstrap condition not being met because it cannot be met if loop-cnt is not evaluated to a number.
So I think my issue now lies with concat loop-cnt to a list as a number and not a variable.
concat is lazy. Recursive calls that build concat on top of concat, without realizing any of the prior layers of laziness, each add to the size of the stack of calls that will be needed to realize the lazy-seq.
Does this concatenation need to be lazy at all? If not, wrap the calls to concat in calls to doall. This will make the concatenation eager, which reduces the size of the call stack needed to realize the final result, and thus eliminating the StackOverflowError.
Also, the correct way to print a lazy-seq and see the contents is prn, you can use pr-str to get the form of the value that pr or prn would use as a string, if needed.
You are misusing quoted lists, I think.
For example, in (defn Bron-Kerbosch1 [ ... ] ... ), '(cliques) evaluates to a list containing the symbol cliques, not to a list containing the argument cliques as its one element. You want (list cliques) for that.
Similar cases abound.
I'm trying to solve the Count a Sequence problem on 4Clojure, but I can't work out what's wrong with my use of recur:
fn [s] (
fn [t n] (
if (empty t)
n
(recur (rest t) (+ n 1))
) s 0
)
It gives the following exception:
java.lang.UnsupportedOperationException: Can only recur from tail position, compiling:(NO_SOURCE_PATH:0)
But to me it seems that the call to recur is in a tail position for the inner function. What am I missing?
Two problems:
Your parentheses are misplaced.
You are using empty where you want empty?.
Parentheses
The fn special form for defining a function takes the shape
(fn name? [params* ] exprs*) with the parentheses around it.
Another level of parentheses applies the function ((fn [n] (* n n))
3) => 9.
Using defn instead of fn for the moment, we get
(defn l [s]
((fn [t n] (if (empty? t) n (recur (rest t) (+ n 1))))
s 0))
Then, for example,
(l ())
; 0
and
(l [1 2 3])
; 3
#Thumbnail is right -- your code will work just fine if you fix the placement of your parentheses (most importantly, you need to add a ( before (fn [t n] ... and a corresponding ) after s 0, in order to actually return the result of calling that function (the one that takes t and n as arguments) on the values s and 0. Otherwise, you are returning the function itself.), and change empty to empty?.
If you wanted to simplify things a bit, you might consider using a loop/recur structure instead, like this:
(fn [s]
(loop [t s, n 0]
(if (empty? t)
n
(recur (rest t) (+ n 1)))))
I am using fungp (a genetic programming tool) to model a complex function and having trouble with sqrt.
Basically, I have to pass a vector of functions and their arity into fungp so that it can compose expressions from them. The expressions will then be evaluated and the best one will be returned. This vector of functions looks like:
(def functions
'[[+ 2]
[- 2]
[* 2]
[fungp.util/abs 1]
[fungp.util/sdiv 2]
[fungp.util/sin 1]
[fungp.util/sqrt 1]
[inc 1]
[dec 1]])
That setup gives me a hundred lines of errors like:
#<ClassCastException java.lang.ClassCastException: java.lang.Double cannot be cast to clojure.lang.IFn>
Which I believe is due to the definition of fungp.util/sqrt:
(defn sqrt [x] (if (x > 0) (Math/sqrt x) 0))
I think the 0 is causing the failure to evaluate, but I'm not sure. I've tried defining my own version of the safe square root, but couldn't get the syntax correct.
So, this is where I'm stuck. I need a version of square root that is safe (returns 0 for negative inputs) and evaluates properly in the fungp expression.
EDIT: For completeness, this is one of the (many) variations I've tried for writing my own square root wrapper:
(defn sqrt-fn [x] `(if (~x > 0) (Math/sqrt ~x) 0))
And the output (the middle bit is the expression that was generated from the functions):
#<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to java.lang.Number>
(let [] (- (dec (- (- (fungp.util/sin (tutorial.tut1/sqrt-fn 8.0)) (fungp.util/sdiv (* x 2.0) (dec 9.0))) (fungp.util/sdiv (tutorial.tut1/sqrt-fn (* x x)) (- (- x 4.0) (+ x x))))) (fungp.util/sdiv (tutorial.tut1/sqrt-fn (fungp.util/sin (
+ (dec x) (inc x)))) (fungp.util/sdiv (* (inc (inc 1.0)) (* (+ x 9.0) (fungp.util/sin 9.0))) (tutorial.tut1/sqrt-fn (- (tutorial.tut1/sqrt-fn x) (fungp.util/abs 3.0)))))))
NullPointerException clojure.lang.Numbers.ops (Numbers.java:942)
I am not writing the expressions, so if there are extra parentheses or missing parentheses, they are coming from the way that I've defined sqrt.
There are a couple of things wrong with this:
(defn sqrt-fn [x] `(if (~x > 0) (Math/sqrt ~x) 0))
First, as hinted at in the comments, (x > 0) is trying to call x (presumably a number) as a function. > is the function, so it must come first, as in (> x 0).
Also, you probably don't want they syntax quote here - that prevents evaluation of the contents, so your function is returning a quoted list of symbols.