I'm trying to get a Clojure record to implement a protocol from another namespace using the defrecord syntax, however calling "satisfies?" gives a null pointer exception. The code compiles and I can call the protocol's methods on record instances successfully, only I can't get "satisfies?" to work. I've tried using "extend" instead of implementing the protocol within the defrecord syntax and got the same problem.
The record (in a namespace which imports the protocol):
(defrecord LoxFunction [declaration]
LoxCallable
(arity [this] (count (:params declaration)))
(call [this _ arguments]
(let [env (env/new-environment #globals)
env-with-params
(reduce
(fn [env [param argument]]
(env/define-pure env (:lexeme param) argument))
env
(map vector (:params declaration) arguments))]
(execute-block (:body declaration) env-with-params)))
Object
(toString [this]
(str "<fn " (-> declaration :name :lexeme) ">")))
and the protocol in another namespace:
(defprotocol LoxCallable
(arity [this])
(call [this interpreter-variables arguments]))
The error when calling "satisfies" on a record invocation is:
Execution error (NullPointerException) at interpr.interpreter/eval17428$fn (interpreter.clj:164).
core.clj: 144 clojure.core/instance?
core_deftype.clj: 536 clojure.core/find-protocol-impl
core_deftype.clj: 569 clojure.core/satisfies?
core_deftype.clj: 569 clojure.core/satisfies?
interpreter.clj: 164 interpr.interpreter/eval17428/fn
MultiFn.java: 229 clojure.lang.MultiFn/invoke
interpreter.clj: 176 interpr.interpreter/eval17432/fn
MultiFn.java: 229 clojure.lang.MultiFn/invoke
interpreter.clj: 203 interpr.interpreter/eval17457/fn
MultiFn.java: 229 clojure.lang.MultiFn/invoke
interpreter.clj: 266 interpr.interpreter/interpret
interpreter.clj: 261 interpr.interpreter/interpret
core.clj: 15 interpr.core/run
core.clj: 9 interpr.core/run
REPL: 91 interpr.core/eval17499
...and so on.
Edit: the code calling satisfies? is:
(defmethod evaluate Call [expr]
(let [callee (evaluate (:callee expr))
arguments (map evaluate (:arguments expr))]
(cond
(not (satisfies? LoxCallable callee))
(throw (error/runtime-error "Can only call functions and classes." (:paren expr)))
(not (= (count arguments) (arity callee)))
(throw (error/runtime-error (:paren expr)
(str "Expected " (arity callee) " arguments but got " (count arguments) ".")))
:else
(call callee interpreter arguments))))
Thanks
Related
I am currently implementing solution for one of Project Euler problems, namely Sieve of Eratosthenes (https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes), in Clojure. Here's my code:
(defn cross-first-element [coll]
(filter #(not (zero? (rem % (first coll)))) coll))
(println
(last
(map first
(take-while
(fn [[primes sieve]] (not (empty? sieve)))
(iterate
(fn [[primes sieve]] [(conj primes (first sieve)) (cross-first-element sieve)])
[[] (range 2 2000001)])))))
The basic idea is to have two collections - primes already retrieved from the sieve, and the remaining sieve itself. We start with empty primes, and until the sieve is empty, we pick its first element and append it to primes, and then we cross out the multiples of it from the sieve. When it's exhausted, we know we have all prime numbers from below two millions in the primes.
Unfortunately, as good as it works for small upper bound of sieve (say 1000), it causes java.lang.StackOverflowError with a long stacktrace with repeating sequence of:
...
clojure.lang.RT.seq (RT.java:531)
clojure.core$seq__5387.invokeStatic (core.clj:137)
clojure.core$filter$fn__5878.invoke (core.clj:2809)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:51)
...
Where is the conceptual error in my solution? How to fix it?
the reason for this is the following: since the filter function in your cross-first-element is lazy, it doesn't actually filter your collection on every iterate step, rather it 'stacks' filter function calls. This leads to the situation that when you are going to actually need the resulting element, the whole load of test functions would be executed, roughly like this:
(#(not (zero? (rem % (first coll1))))
(#(not (zero? (rem % (first coll2))))
(#(not (zero? (rem % (first coll3))))
;; and 2000000 more calls
leading to stack overflow.
the simplest solution in your case is to make filtering eager. You can do it by simply using filterv instead of filter, or wrap it into (doall (filter ...
But still your solution is really slow. I would rather use loop and native arrays for that.
You have (re-)discovered that having nested lazy sequences can sometimes be problematic. Here is one example of what can go wrong (it is non-intuitive).
If you don't mind using a library, the problem is much simpler with a single lazy wrapper around an imperative loop. That is what lazy-gen and yield give you (a la "generators" in Python):
(ns tst.demo.core
(:use demo.core tupelo.test)
(:require [tupelo.core :as t]))
(defn unprime? [primes-so-far candidate]
(t/has-some? #(zero? (rem candidate %)) primes-so-far))
(defn primes-generator []
(let [primes-so-far (atom [2])]
(t/lazy-gen
(t/yield 2)
(doseq [candidate (drop 3 (range))] ; 3..inf
(when-not (unprime? #primes-so-far candidate)
(t/yield candidate)
(swap! primes-so-far conj candidate))))))
(def primes (primes-generator))
(dotest
(is= (take 33 primes)
[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 ])
; first prime over 10,000
(is= 10007 (first (drop-while #(< % 10000) primes)))
; the 10,000'th prime (https://primes.utm.edu/lists/small/10000.txt)
(is= 104729 (nth primes 9999)) ; about 12 sec to compute
)
We could also use loop/recur to control the loop, but it's easier to read with an atom to hold the state.
Unless you really, really need a lazy & infinite solution, the imperative solution is so much simpler:
(defn primes-upto [limit]
(let [primes-so-far (atom [2])]
(doseq [candidate (t/thru 3 limit)]
(when-not (unprime? #primes-so-far candidate)
(swap! primes-so-far conj candidate)))
#primes-so-far))
(dotest
(is= (primes-upto 100)
[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]) )
I am adding my practice code here for reference. The description is given below.
(defmacro block [ctx & expr]
(println expr)
`(let [~#(mapcat (fn [[k v]] [k `~v]) ctx)] ~#expr))
(defmacro uia [metadata ctx arity & expr]
`(block ~metadata
(fn ~arity (prn "got" ~arity ~'mt))
)
)
(def auto1 (uia {mt "dt"}
[{ et "wa" s "a1"}
{et "wa" s "a2"}
{et "um" s "a3"}] [et1 id cid]
(block {} (prn "auto1"))
))
(let [myarr ["x" 11 22]] (apply auto1 myarr))
On running above code, it will print "got" ["x" 11 22] "dt"only once. This is for arity inside this macro.
I want to now print it, depending on the number of elements passed inside ctx to my funciton uia.
For Eg :
from auto1, I will be passing 3 compulsory arguments to uia:
metadata : {mt "dt"}
ctx : [{ et1 "wa" s "a1"} {et1 "wa" s "a2"} {et1 "um" s "a3"}]
arity : [et id cid]
Now ctx is a vector with 3 maps in it. I want to call the anonymous function inside uia for 3 times. So it will now print;
"got" "x" 11 22 wa a1 "dt" --> on first call
"got" "x" 11 22 wa a2 "dt" --> on second call
"got" "x" 11 22 um a3 "dt" --> on third call
So the respective output statement according to code will be ;
(prn "got" ~'et ~'id ~'cid ~'et1 ~'s ~'md) ;=> "got x 11 22 wa a1 "dt" ;; on first call
(prn "got" ~'et ~'id ~'cid ~'et1 ~'s ~'md) ;=> "got x 11 22 wa a2 "dt" ;; on second call
(prn "got" ~'et ~'id ~'cid ~'et1 ~'s ~'md) ;=> "got x 11 22 um a3 "dt" ;; on third call and
and so on.. ;; on nth call (where n is the number or elements present inside ctx)
Please suggest me a way through which it can be attained.
Note :
It should not print all the elements of ctx in one iteration.
Whatever changes are done, must be done inside uia.
And please let me know if some extra information related to this is required.
Your final function returned from calling uia doesn't include the context map anywhere:
>>> (macroexpand-1
'(uia {mt "dt"}
[{ et "wa" s "a1"}
{et "wa" s "a2"}
{et "um" s "a3"}]
[et1 id cid]
(block {} (prn "auto1"))))
(user/block
{mt "dt"}
(clojure.core/fn [et1 id cid]
(clojure.core/prn "got" [et1 id cid] mt)))
>>> (macroexpand-1
'(user/block
{mt "dt"}
(clojure.core/fn [et1 id cid]
(clojure.core/prn "got" [et1 id cid] mt))))
(clojure.core/let [mt "dt"]
(clojure.core/fn [et1 id cid] (
clojure.core/prn "got" [et1 id cid] mt)))
The result is a function that takes your specified ariety, with a closed over free variable mt bound to "dt" - the context map is nowhere to be found.
I suspect your definition of block is not what you intended, or at the very least the signature is wrong.
(defmacro block [ctx & expr]
`(let [~#(mapcat (fn [[k v]] [k v]) ctx)] ~#expr))
The actual argument you pass to block is the metadata map, not the context map. If this is intentional I would change the signature to reflect that replacing ctx with mt in the signature and body.
As to why it only prints three times, looking at the final expansion above should make that clear - the returned closure takes 3 arguments and simply prints them inside a vector along with the metdata (referenced by the closed over symbol mt from the outer let.
(defmacro uia [metadata ctx arity & expr]
`(block ~metadata
(fn ~arity
(dotimes [n# ~(count ctx)]
(prn "got" ~arity ~'mt)))))
With this change, now when you call uia the following prints:
"got" ["x" 11 22] "dt"
"got" ["x" 11 22] "dt"
"got" ["x" 11 22] "dt"
That's a step in the right direction, but your question indicates you also want the values inside the map to be printed along with the closed over metadata and the 3 function arguments. To print based on the items in the context map, two changes need to be made:
First, the context map keys either need to be quoted symbols 'et and not et, or keywords. This is because the returned map tries to evaluate the unquoted symbol keys at run-time which are unbound (assuming you don't have some global context in which they are bound, which was not provided).
Second, you need to iterate over each map inside the returned function and pull out the relevant values. Other than changing map keys from symbols to keywords, the only other changes are to uia as requested, and for me it seemed easiest to keep changes there anyhow.
(defmacro block [ctx & expr]
`(let [~#(mapcat (fn [[k v]] [k v]) ctx)] ~#expr))
(defmacro uia [metadata ctx arity & expr]
`(block ~metadata
(fn ~arity
(doseq [m# ~ctx]
(prn "got" ~arity (:et m#) (:s m#) ~'mt)))))
(def auto1
(uia {mt "dt"}
[{:et "wa" :s "a1"}
{:et "wa" :s "a2"}
{:et "um" :s "a3"}]
[et1 id cid]
(block {} (prn "auto1"))))
(let [myarr ["x" 11 22]] (apply auto1 myarr))
I have the following code:
(ns macroo)
(def primitives #{::byte ::short ::int})
(defn primitive? [type]
(contains? primitives type))
(def pp clojure.pprint/pprint)
(defn foo [buffer data schema]
(println schema))
(defmacro write-fn [buffer schema schemas]
(let [data (gensym)]
`(fn [~data]
~(cond
(primitive? schema) `(foo ~buffer ~data ~schema)
(vector? schema) (if (= ::some (first schema))
`(do (foo ~buffer (count ~data) ::short)
(map #((write-fn ~buffer ~(second schema) ~schemas) %)
~data))
`(do ~#(for [[i s] (map-indexed vector schema)]
((write-fn buffer s schemas) `(get ~data ~i)))))
:else [schema `(primitive? ~schema) (primitive? schema)])))) ; for debugging
(pp (clojure.walk/macroexpand-all '(write-fn 0 [::int ::int] 0)))
The problem is, upon evaluating the last expression, I get
=>
(fn*
([G__6506]
(do
[:macroo/int :macroo/int true false]
[:macroo/int :macroo/int true false])))
I'll explain the code if necessary, but for now i'll just state the problem (it might be just a newbie error I'm making):
`(primitive? ~schema)
and
(primitive? schema)
in the :else branch return true and false respectively, and since i'm using the second version in the cond expression, it fails where it shouldn't (I'd prefer the second version as it would be evaluated at compile time if i'm not mistaken).
I suspect it might have something to do with symbols being namespace qualified?
After some investigations (see edits), here is a working Clojure alternative. Basically, you rarely need recursive macros. If you
need to build forms recursively, delegate to auxiliary functions and call them from the macro (also, write-fn is not a good name).
(defmacro write-fn [buffer schemas fun]
;; we will evaluate "buffer" and "fun" only once
;; and we need gensym for intermediate variables.
(let [fsym (gensym)
bsym (gensym)]
;; define two mutually recursive function
;; to parse and build a map consisting of two keys
;;
;; - args is the argument list of the generated function
;; - body is a list of generated forms
;;
(letfn [(transformer [schema]
(cond
(primitive? schema)
(let [g (gensym)]
{:args g
:body `(~fsym ~schema ~bsym ~g)})
(sequential? schema)
(if (and(= (count schema) 2)
(= (first schema) ::some)
(primitive? (second schema)))
(let [g (gensym)]
{:args ['& g]
:body
`(doseq [i# ~g]
(~fsym ~(second schema) ~bsym i#))})
(reduce reducer {:args [] :body []} schema))
:else (throw (Exception. "Bad input"))))
(reducer [{:keys [args body]} schema]
(let [{arg :args code :body} (transformer schema)]
{:args (conj args arg)
:body (conj body code)}))]
(let [{:keys [args body]} (transformer schemas)]
`(let [~fsym ~fun
~bsym ~buffer]
(fn [~args] ~#body))))))
The macro takes a buffer (whatever it is), a schema as defined by your language and a function to be called for each value being visited by the generated function.
Example
(pp (macroexpand
'(write-fn 0
[::int [::some ::short] [::int ::short ::int]]
(fn [& more] (apply println more)))))
... produces the following:
(let*
[G__1178 (fn [& more] (apply println more)) G__1179 0]
(clojure.core/fn
[[G__1180 [& G__1181] [G__1182 G__1183 G__1184]]]
(G__1178 :macroo/int G__1179 G__1180)
(clojure.core/doseq
[i__1110__auto__ G__1181]
(G__1178 :macroo/short G__1179 i__1110__auto__))
[(G__1178 :macroo/int G__1179 G__1182)
(G__1178 :macroo/short G__1179 G__1183)
(G__1178 :macroo/int G__1179 G__1184)]))
First, evaluate buffer and fun and bind them to local variables
Return a closure which accept one argument and destructures it according to the given schema, thanks to Clojure's destructuring capabilities.
For each value, call fun with the appropriate arguments.
When the schema is [::some x], accept zero or more values as a vector and call the function fun for each of those values. This needs to be done with a loop, since the size is only know when calling the function.
If we pass the vector [32 [1 3 4 5 6 7] [2 55 1]] to the function generated by the above macroexpansion, the following is printed:
:macroo/int 0 32
:macroo/short 0 1
:macroo/short 0 3
:macroo/short 0 4
:macroo/short 0 5
:macroo/short 0 6
:macroo/short 0 7
:macroo/int 0 2
:macroo/short 0 55
:macroo/int 0 1
In this line:
`(do ~#(for [[i s] (map-indexed vector schema)]
((write-fn buffer s schemas) `(get ~data ~i)))))
you are calling write-fn, the macro, in your current scope, where s is just a symbol, not one of the entries in schema. Instead, you want to emit code that will run in the caller's scope:
`(do ~#(for [[i s] (map-indexed vector schema)]
`((write-fn ~buffer ~s ~schemas) (get ~data ~i)))))
And make a similar change to the other branch of the if, as well.
As an aside, it looks to me at first glance like this doesn't really need to be a macro, but could be a higher-order function instead: take in a schema or whatever, and return a function of data. My guess is you're doing it as a macro for performance, in which case I would counsel you to try it out the slow, easy way first; once you have that working you can make it a macro if necessary. Or, maybe I'm wrong and there's something in here that fundamentally has to be a macro.
I want to transfer code from
("AAA" ("BB" 11 #"XXX"))
to
("AAA" ("BB" 11 "YYY"))
I just want to change #"XXX" to "YYY".
I write a function it works.
(defn tt [clause]
(cond (not (sequential? clause)) clause
(and (sequential? clause)
(= 2 (count clause))
(= `deref (first clause))
(string? (second clause)))
"YYY"
:else (map tt clause)))
there is my result:
(tt '("AAA" ("BB" 11 #"XXX"))) --> ("AAA" ("BB" 11 "YYY"))
But when I change the function to macro , it raise exception.
(defmacro test [& clause]
(let [f (fn tt [clause]
(cond (not (sequential? clause)) clause
(and (sequential? clause)
(= 2 (count clause))
(= `deref (first clause))
(string? (second clause)))
"YYY"
:else (map tt clause)))]
(f clause)))
and it raise exception like this
(test "AAA" ("BB" 11 #"XXX")) --> ClassCastException java.lang.String cannot be cast to clojure.lang.IFn
I have test map for prewalk function. Both of them raise exception.
I have no idea what is wrong with it and how to fix this error in macro??
I'm converting some Scheme code to Clojure. The original uses a dispatching pattern that's very similar to multimethods, but with an inverted approach to the matching predicates. For example, there a generic function "assign-operations". The precise implementation details aren't too important at the moment, but notice that it can take a list of argument-predicates.
(define (assign-operation operator handler . argument-predicates)
(let ((record
(let ((record (get-operator-record operator))
(arity (length argument-predicates)))
(if record
(begin
(if (not (fix:= arity (operator-record-arity record)))
(error "Incorrect operator arity:" operator))
record)
(let ((record (make-operator-record arity)))
(hash-table/put! *generic-operator-table* operator record)
record)))))
(set-operator-record-tree! record
(bind-in-tree argument-predicates
handler
(operator-record-tree record)))))
The dispatched functions supply these predicates, one per argument in the arity of the function.
(assign-operation 'merge
(lambda (content increment) content)
any? nothing?)
(assign-operation 'merge
(lambda (content increment) increment)
nothing? any?)
(assign-operation 'merge
(lambda (content increment)
(let ((new-range (intersect-intervals content increment)))
(cond ((interval-equal? new-range content) content)
((interval-equal? new-range increment) increment)
((empty-interval? new-range) the-contradiction)
(else new-range))))
interval? interval?)
Later, when the generic function "merge" is called, each handler is asked if it works on the operands.
As I understand multimethods, the dispatch function is defined across the set of implementations, with dispatch to a specific method based on the return value of the dispatch-fn. In the Scheme above, new assign-operation functions can define predicates arbitrarily.
What would be an equivalent, idiomatic construct in Clojure?
EDIT: The code above comes from "The Art of the Propagator", by Alexey Radul and Gerald Sussman.
You can do this with Clojure's multimethods fairly easily - the trick is to create a dispatch function that distinguishes between the different sets of predicates.
The easiest way to do this is probably just to maintain a vector of "composite predicates" that apply all of the individual predicates to the full argument list, and use the index of this vector as the dispatch value:
(def pred-list (ref []))
(defn dispatch-function [& args]
(loop [i 0]
(cond
(>= i (count #pred-list)) (throw (Error. "No matching function!"))
(apply (#pred-list i) args) i
:else (recur (inc i)))))
(defmulti handler dispatch-function)
(defn assign-operation [function & preds]
(dosync
(let [i (count #pred-list)]
(alter pred-list conj
(fn [& args] (every? identity (map #(%1 %2) preds args))))
(defmethod handler i [& args] (apply function args)))))
Then you can create operations to handle whatever predicates you like as follows:
(assign-operation (fn [x] (/ x 2)) even?)
(assign-operation (fn [x] (+ x 1)) odd?)
(take 15 (iterate handler 77))
=> (77 78 39 40 20 10 5 6 3 4 2 1 2 1 2)