Re: ArithmeticException from unchecked-add
Thanks. I've got to pay more attention to the distinction between long and Long in the documentation. The docs for unchecked-add ( http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/unchecked-add ) only cover the case of both arguments being primitive longs. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Joy of Clojure example not working
Yes, the examples in the book are missing some lines. I think the following log shows what they were going for: joy.udp= (remove-method compiler ::osx) joy.udp= (def unix (into unix {::c-compiler /usr/bin/gcc})) joy.udp= (def osx (into osx {:c-compiler gcc})) oy.udp= osx {:home /Users, :llvm-compiler clang, :os :joy.udp/osx, :joy.udp/prototype {:home /home, :os :joy.udp/unix, :c-compiler cc, :dev /dev}, :c-compiler gcc} joy.udp= unix {:home /home, :joy.udp/c-compiler /usr/bin/gcc, :os :joy.udp/unix, :c-compiler cc, :dev /dev} joy.udp= (compiler osx) gcc joy.udp= (compile-cmd osx) /usr/bin/gcc About your question: Isn't there a core function/macro where I can derive and set hierarchy all at once? Such a function would need to know in advance what hierarchy you want to construct. If you have a desired pattern of hierarchy that you want to reuse, you could define a function to create it using derive and optionally make-hierarchy. On Monday, May 19, 2014 4:38:00 PM UTC-7, gamma235 wrote: I actually just wanna know why I need to use derive so many times. Isn't there a core function/macro where I can derive and set hierarchy all at once? I'm just looking for a more efficient way. My bad for not stating that more clearly in the original post. The real problem though is the last two calls to compile-cmd. I've been messing with it for a couple of days so any help there would be well appreciated. Thanks J -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Joy of Clojure example not working
The second edition of Joy of Clojure, MEAP v10 shows the same error and progressive solution about half way down pdf-page 318 in section 9.2.4. On Monday, May 19, 2014 6:39:26 AM UTC-7, gamma235 wrote: Hi guys, I am working through the pre-release second edition of Joy of Clojure's section on multi-methods (section 9.2.~ : pg. 313), and am getting different outputs from what they have printed in the book. I could just skip over it, but I really want to understand this stuff. Could someone tell me how to get the *(compile-cmd osx) *call at the end of the code to produce the expected output: */usr/bin/gcc *? I have commented out redundancy and moved a couple of lines for readability. Thanks in advance! J (ns joy.udp (:refer-clojure :exclude [get])) (defn beget [this proto] (assoc this ::prototype proto)) (defn get [m k] (when m (if-let [[_ v] (find m k)] v (recur (::prototype m) k (def put assoc) ;;; compiler (defmulti compiler :os) (defmethod compiler ::unix [m] (get m :c-compiler)) (defmethod compiler ::osx [m] (get m :llvm-compiler)) (def clone (partial beget {})) (def unix {:os ::unix, :c-compiler cc, :home /home, :dev /dev}) (def osx (- (clone unix) (put :os ::osx) (put :llvm-compiler clang) (put :home /Users))) ;;; home (defmulti home :os) (defmethod home ::unix [m] (get m :home)) (defmethod home ::bsd [m] /home) ;; the error on the call to (home osx) is contingent upon toggling the following lines. ;(derive ::osx ::unix) ;(derive ::osx ::bsd) (prefer-method home ::unix ::bsd) ;(remove-method home ::bsd) (derive (make-hierarchy) ::osx ::unix) ;;; compile-cmd (defmulti compile-cmd (juxt :os compiler)) (defmethod compile-cmd [::osx gcc] [m] (str /usr/bin/ (get m :c-compiler))) (defmethod compile-cmd :default [m] (str Unsure where to locate (get m :c-compiler))) ;; (home osx) ;= java.lang.IllegalArgumentException: No method in multimethod 'home' for dispatch value: :joy.udp/osx … ;; Should be: ;= /Users (compile-cmd osx) ;= Unsure where to locate cc ;; Should be: ;= /usr/bin/gcc (compile-cmd unix) ;= Unsure where to locate cc ;; this is the expected output -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Best way to pass parameters?
Not an answer to your question, but you may want to check out: Datomic: The fully transactional, cloud-ready, immutable database.http://www.datomic.com/ On Monday, May 19, 2014 10:07:15 AM UTC-7, Ivan Schuetz wrote: Hi, I'm building a webservice, have 2 layers: webservice and database. Webservice layer receives e.g. a product, to add to the database: {:id 1 :name phone :price 100} Database layer has a method to insert the product, insert-product. I could do 1): (defn insert-product [params]) or 2): (defn insert-product [id name price]) or 3): (defn insert-product [{:keys [id name price]}) I tend to prefer 2) because it's safer than 1) and will allow me to add type check later, don't think this is possible with 3). It doesn't feel very idiomatic though and makes me feel like I might be thinking in Java... I also want make possible to change the keys before inserting in the database, where 2) and 3) are better than 1). Is 2) the best option? Is there any reason to use 3) instead? Or is there maybe a different, better way? Thanks! -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
ArithmeticException from unchecked-add
I didn't expect this one. See the illustrative sequence below. Should I be reporting this as a bug, or re-read the docs? ; CIDER 0.5.0 (Clojure 1.6.0, nREPL 0.2.3) user (require '[clojure.stacktrace :as st]) user (unchecked-add (Long/MAX_VALUE) (Long/MAX_VALUE) ) -2 user (unchecked-add ^long(Long/MAX_VALUE) ^long(Long/MAX_VALUE) ) -2 user (unchecked-add ^Long(Long/MAX_VALUE) ^Long(Long/MAX_VALUE) ) ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1424) user (st/e) java.lang.ArithmeticException: integer overflow at clojure.lang.Numbers.throwIntOverflow (Numbers.java:1424) clojure.lang.Numbers.add (Numbers.java:1723) clojure.lang.Numbers$LongOps.add (Numbers.java:447) clojure.lang.Numbers.add (Numbers.java:126) clojure.lang.Numbers.unchecked_add (Numbers.java:1671) user$eval2514.invoke (form-init3948440390155694364.clj:1) clojure.lang.Compiler.eval (Compiler.java:6703) clojure.lang.Compiler.eval (Compiler.java:) nil -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Improving pprint behavior for anonymous functions
Simpler yet using metadata: (ns example.ppfn) (defn print-pf [pf] (if-let [ppf (::ppf (meta pf))] ppf pf)) (defmacro partial* [ args] `(let [m# (pr-str '(partial* ~@args)) pf# (with-meta (partial ~@args) {::ppf m#})] (defmethod print-method (class pf#) [o# w#] (print-simple (example.ppfn/print-pf o#) w#)) pf#)) In use: user= (def p1 (partial* + 1)) #'user/p1 user= (p1 5) 6 user= p1 (example.ppfn/partial* + 1) user= (def comma-join (partial* clojure.string/join , )) #'user/comma-join user= (comma-join ['a 'b 'c]) a, b, c user= comma-join (example.ppfn/partial* clojure.string/join , ) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: puzzled by RuntimeException
Thanks Alex and Steve, I've based a ton of work on keywords where the second character is numeric. The http://clojure.org/readers page should be the normative reference. The work is based on *reliance* on the definitions in the readers page. I believe it is unambiguous in demanding a colon as the first character of a keyword, and allowing the second character to be numeric. I am frightened that opinions differ; especially Rich's, obviously. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Improving pprint behavior for anonymous functions
I don't know if this is considered good Clojure, but you could define a print-method within a macro to set up the normal string representation for the partial function: (defmacro partial* [fname arg0 args] `(let [pf# (partial ~fname ~arg0 ~@args) cpf# (class pf#)] (defmethod print-method cpf# [o# w#] (if (nil? '~args) (print-simple (str (partial '~fname (pr-str ~arg0) )) w#) (print-simple (str (partial '~fname (pr-str ~arg0) ~@(map #(str (pr-str %)) args) )) w#))) pf#)) A transcript of some quick examples: user= (def p6 (partial* + 1 2 3)) #'user/p6 user= p6 (partial + 1 2 3) user= (p6 7) 13 user= (def re-find-foo (partial* re-find #foo)) #'user/re-find-foo user= re-find-foo (partial re-find #foo) user= (re-find-foo abcdefooghi) foo On Friday, April 25, 2014 9:01:37 AM UTC-7, Matthew DeVore wrote: Hi, There has been one thing bugging me for a long time that seems worth it to fix, and I was wondering if anyone else has had the same problem. I have enjoyed using Clojure's REPL and embracing a Clojure-style data model for my app, where everything is a glorified map or vector and there are no private fields. I even have a simple dump feature that tells me the entire state of my app https://github.com/google/hesokuri that was ridiculously easy to implement, and that takes advantage of the lack of black box data structures. One thing that doesn't really fit in this paradigm is (ironically) anonymous functions with closures. For instance, (partial + 42) returns an anonymous function, and in the REPL or an app dump, it looks hideous: #core$partial$fn__4228 clojure.core$partial$fn__4228@1ee1dea2 So I've avoided anonymous functions in my app except when they exist transiently, and don't appear in the dump (for instance, in (map #(str % !) foo)). But sometimes I just can't avoid a long-lived anonymous function practically. The best solution I've come up with is to transform anonymous functions when preparing the application dump. (See the implementationhttps://github.com/google/hesokuri/blob/b60cb7222cfdd672e394ef6f22b80c94278fe3a0/src/hesokuri/see.clj#L35) This makes (partial + 42) look like this: {:fn-class clojure.core$partial$fn__4228, arg1 42, f {:fn-class clojure.core$_PLUS_}} Which isn't great (I'd like to have filenames and line numbers for each anon fn, and a nicer name for clojure.core/+), but it's a big improvement. The function's JVM class and the closured values are revealed. It would be nice to implement this natively. Having only passing familiarity with the Clojure code base, to solve it I think one could: - give anonymous functions a .getClosure method which creates a view of the closure on-demand - (optional) change their .toString implementation to include this information - add logic to clojure.pprint to use the .getClosure method (I guess (defmethod clojure.pprint/simple-dispatch clojure.lang.AFunction etc...) ?) Another feature that would go nicely with this is smarter equality semantics for anonymous functions, so that any two anonymous functions generated at the same point in code with equal closures are equal. This means if I have a function like this: (defn exclaimer [bangs] #(apply str % (repeat bangs !))) then the following would be true: (= (exclaimer 10) (exclaimer 10)), making functions behave a lot more like values. I would love to have this particular feature too, although I'm having trouble coming up with a non-contrived example. I'd like to hear some thoughts on this. Thanks! Matt -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Improving pprint behavior for anonymous functions
I guess I don't understand the problem, or what is meant by different classes. A counter-example would be helpful. Further transcript using the macro: (def p6 (partial* + 1 2 3)) #'user/p6 user= (class p6) clojure.core$partial$fn__4194 user= (def p10 (partial* + 1 2 3 4)) #'user/p10 user= (class p10) clojure.core$partial$fn__4196 user= p6 (partial + 1 2 3) user= p10 (partial + 1 2 3 4) user= (p6 100) 106 user= (p10 100) 110 On Friday, April 25, 2014 2:33:50 PM UTC-7, Gary Trakhman wrote: That's not going to work, all the return classes of partial are the same class. On Fri, Apr 25, 2014 at 5:26 PM, Greg D gregoir...@gmail.comjavascript: wrote: I don't know if this is considered good Clojure, but you could define a print-method within a macro to set up the normal string representation for the partial function: (defmacro partial* [fname arg0 args] `(let [pf# (partial ~fname ~arg0 ~@args) cpf# (class pf#)] (defmethod print-method cpf# [o# w#] (if (nil? '~args) (print-simple (str (partial '~fname (pr-str ~arg0) )) w#) (print-simple (str (partial '~fname (pr-str ~arg0) ~@(map #(str (pr-str %)) args) )) w#))) pf#)) A transcript of some quick examples: user= (def p6 (partial* + 1 2 3)) #'user/p6 user= p6 (partial + 1 2 3) user= (p6 7) 13 user= (def re-find-foo (partial* re-find #foo)) #'user/re-find-foo user= re-find-foo (partial re-find #foo) user= (re-find-foo abcdefooghi) foo On Friday, April 25, 2014 9:01:37 AM UTC-7, Matthew DeVore wrote: Hi, There has been one thing bugging me for a long time that seems worth it to fix, and I was wondering if anyone else has had the same problem. I have enjoyed using Clojure's REPL and embracing a Clojure-style data model for my app, where everything is a glorified map or vector and there are no private fields. I even have a simple dump feature that tells me the entire state of my app https://github.com/google/hesokuri that was ridiculously easy to implement, and that takes advantage of the lack of black box data structures. One thing that doesn't really fit in this paradigm is (ironically) anonymous functions with closures. For instance, (partial + 42) returns an anonymous function, and in the REPL or an app dump, it looks hideous: #core$partial$fn__4228 clojure.core$partial$fn__4228@1ee1dea2 So I've avoided anonymous functions in my app except when they exist transiently, and don't appear in the dump (for instance, in (map #(str % !) foo)). But sometimes I just can't avoid a long-lived anonymous function practically. The best solution I've come up with is to transform anonymous functions when preparing the application dump. (See the implementationhttps://github.com/google/hesokuri/blob/b60cb7222cfdd672e394ef6f22b80c94278fe3a0/src/hesokuri/see.clj#L35) This makes (partial + 42) look like this: {:fn-class clojure.core$partial$fn__4228, arg1 42, f {:fn-class clojure.core$_PLUS_}} Which isn't great (I'd like to have filenames and line numbers for each anon fn, and a nicer name for clojure.core/+), but it's a big improvement. The function's JVM class and the closured values are revealed. It would be nice to implement this natively. Having only passing familiarity with the Clojure code base, to solve it I think one could: - give anonymous functions a .getClosure method which creates a view of the closure on-demand - (optional) change their .toString implementation to include this information - add logic to clojure.pprint to use the .getClosure method (I guess (defmethod clojure.pprint/simple-dispatch clojure.lang.AFunction etc...) ?) Another feature that would go nicely with this is smarter equality semantics for anonymous functions, so that any two anonymous functions generated at the same point in code with equal closures are equal. This means if I have a function like this: (defn exclaimer [bangs] #(apply str % (repeat bangs !))) then the following would be true: (= (exclaimer 10) (exclaimer 10)), making functions behave a lot more like values. I would love to have this particular feature too, although I'm having trouble coming up with a non-contrived example. I'd like to hear some thoughts on this. Thanks! Matt -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com
Re: Improving pprint behavior for anonymous functions
I guess I don't understand the problem, or what is meant by all the return classes of partial are the same class. A counter-example would be helpful. Further transcript using the macro: user= (def p6 (partial* + 1 2 3)) #'user/p6 user= (class p6) clojure.core$partial$fn__4194 user= (def p10 (partial* + 1 2 3 4)) #'user/p10 user= (class p10) clojure.core$partial$fn__4196 user= p6 (partial + 1 2 3) user= p10 (partial + 1 2 3 4) user= (p6 100) 106 user= (p10 100) 110 On Friday, April 25, 2014 2:33:50 PM UTC-7, Gary Trakhman wrote: That's not going to work, all the return classes of partial are the same class. On Fri, Apr 25, 2014 at 5:26 PM, Greg D gregoir...@gmail.comjavascript: wrote: I don't know if this is considered good Clojure, but you could define a print-method within a macro to set up the normal string representation for the partial function: (defmacro partial* [fname arg0 args] `(let [pf# (partial ~fname ~arg0 ~@args) cpf# (class pf#)] (defmethod print-method cpf# [o# w#] (if (nil? '~args) (print-simple (str (partial '~fname (pr-str ~arg0) )) w#) (print-simple (str (partial '~fname (pr-str ~arg0) ~@(map #(str (pr-str %)) args) )) w#))) pf#)) A transcript of some quick examples: user= (def p6 (partial* + 1 2 3)) #'user/p6 user= p6 (partial + 1 2 3) user= (p6 7) 13 user= (def re-find-foo (partial* re-find #foo)) #'user/re-find-foo user= re-find-foo (partial re-find #foo) user= (re-find-foo abcdefooghi) foo On Friday, April 25, 2014 9:01:37 AM UTC-7, Matthew DeVore wrote: Hi, There has been one thing bugging me for a long time that seems worth it to fix, and I was wondering if anyone else has had the same problem. I have enjoyed using Clojure's REPL and embracing a Clojure-style data model for my app, where everything is a glorified map or vector and there are no private fields. I even have a simple dump feature that tells me the entire state of my app https://github.com/google/hesokuri that was ridiculously easy to implement, and that takes advantage of the lack of black box data structures. One thing that doesn't really fit in this paradigm is (ironically) anonymous functions with closures. For instance, (partial + 42) returns an anonymous function, and in the REPL or an app dump, it looks hideous: #core$partial$fn__4228 clojure.core$partial$fn__4228@1ee1dea2 So I've avoided anonymous functions in my app except when they exist transiently, and don't appear in the dump (for instance, in (map #(str % !) foo)). But sometimes I just can't avoid a long-lived anonymous function practically. The best solution I've come up with is to transform anonymous functions when preparing the application dump. (See the implementationhttps://github.com/google/hesokuri/blob/b60cb7222cfdd672e394ef6f22b80c94278fe3a0/src/hesokuri/see.clj#L35) This makes (partial + 42) look like this: {:fn-class clojure.core$partial$fn__4228, arg1 42, f {:fn-class clojure.core$_PLUS_}} Which isn't great (I'd like to have filenames and line numbers for each anon fn, and a nicer name for clojure.core/+), but it's a big improvement. The function's JVM class and the closured values are revealed. It would be nice to implement this natively. Having only passing familiarity with the Clojure code base, to solve it I think one could: - give anonymous functions a .getClosure method which creates a view of the closure on-demand - (optional) change their .toString implementation to include this information - add logic to clojure.pprint to use the .getClosure method (I guess (defmethod clojure.pprint/simple-dispatch clojure.lang.AFunction etc...) ?) Another feature that would go nicely with this is smarter equality semantics for anonymous functions, so that any two anonymous functions generated at the same point in code with equal closures are equal. This means if I have a function like this: (defn exclaimer [bangs] #(apply str % (repeat bangs !))) then the following would be true: (= (exclaimer 10) (exclaimer 10)), making functions behave a lot more like values. I would love to have this particular feature too, although I'm having trouble coming up with a non-contrived example. I'd like to hear some thoughts on this. Thanks! Matt -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send
Re: Improving pprint behavior for anonymous functions
Got it. The macro, as is, will displace the print method for the same arity. On Friday, April 25, 2014 2:50:34 PM UTC-7, Gary Trakhman wrote: Ah, I think I was mistaken in a detail, but generally correct. Try it with two partials of the same arity. https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2460 On Fri, Apr 25, 2014 at 5:47 PM, Greg D gregoir...@gmail.comjavascript: wrote: I guess I don't understand the problem, or what is meant by different classes. A counter-example would be helpful. Further transcript using the macro: (def p6 (partial* + 1 2 3)) #'user/p6 user= (class p6) clojure.core$partial$fn__4194 user= (def p10 (partial* + 1 2 3 4)) #'user/p10 user= (class p10) clojure.core$partial$fn__4196 user= p6 (partial + 1 2 3) user= p10 (partial + 1 2 3 4) user= (p6 100) 106 user= (p10 100) 110 On Friday, April 25, 2014 2:33:50 PM UTC-7, Gary Trakhman wrote: That's not going to work, all the return classes of partial are the same class. On Fri, Apr 25, 2014 at 5:26 PM, Greg D gregoir...@gmail.com wrote: I don't know if this is considered good Clojure, but you could define a print-method within a macro to set up the normal string representation for the partial function: (defmacro partial* [fname arg0 args] `(let [pf# (partial ~fname ~arg0 ~@args) cpf# (class pf#)] (defmethod print-method cpf# [o# w#] (if (nil? '~args) (print-simple (str (partial '~fname (pr-str ~arg0) )) w#) (print-simple (str (partial '~fname (pr-str ~arg0) ~@(map #(str (pr-str %)) args) )) w#))) pf#)) A transcript of some quick examples: user= (def p6 (partial* + 1 2 3)) #'user/p6 user= p6 (partial + 1 2 3) user= (p6 7) 13 user= (def re-find-foo (partial* re-find #foo)) #'user/re-find-foo user= re-find-foo (partial re-find #foo) user= (re-find-foo abcdefooghi) foo On Friday, April 25, 2014 9:01:37 AM UTC-7, Matthew DeVore wrote: Hi, There has been one thing bugging me for a long time that seems worth it to fix, and I was wondering if anyone else has had the same problem. I have enjoyed using Clojure's REPL and embracing a Clojure-style data model for my app, where everything is a glorified map or vector and there are no private fields. I even have a simple dump feature that tells me the entire state of my app https://github.com/google/hesokuri that was ridiculously easy to implement, and that takes advantage of the lack of black box data structures. One thing that doesn't really fit in this paradigm is (ironically) anonymous functions with closures. For instance, (partial + 42) returns an anonymous function, and in the REPL or an app dump, it looks hideous: #core$partial$fn__4228 clojure.core$partial$fn__4228@1ee1dea2 So I've avoided anonymous functions in my app except when they exist transiently, and don't appear in the dump (for instance, in (map #(str % !) foo)). But sometimes I just can't avoid a long-lived anonymous function practically. The best solution I've come up with is to transform anonymous functions when preparing the application dump. (See the implementationhttps://github.com/google/hesokuri/blob/b60cb7222cfdd672e394ef6f22b80c94278fe3a0/src/hesokuri/see.clj#L35) This makes (partial + 42) look like this: {:fn-class clojure.core$partial$fn__4228, arg1 42, f {:fn-class clojure.core$_PLUS_}} Which isn't great (I'd like to have filenames and line numbers for each anon fn, and a nicer name for clojure.core/+), but it's a big improvement. The function's JVM class and the closured values are revealed. It would be nice to implement this natively. Having only passing familiarity with the Clojure code base, to solve it I think one could: - give anonymous functions a .getClosure method which creates a view of the closure on-demand - (optional) change their .toString implementation to include this information - add logic to clojure.pprint to use the .getClosure method (I guess (defmethod clojure.pprint/simple-dispatch clojure.lang.AFunction etc...) ?) Another feature that would go nicely with this is smarter equality semantics for anonymous functions, so that any two anonymous functions generated at the same point in code with equal closures are equal. This means if I have a function like this: (defn exclaimer [bangs] #(apply str % (repeat bangs !))) then the following would be true: (= (exclaimer 10) (exclaimer 10)), making functions behave a lot more like values. I would love to have this particular feature too, although I'm having trouble coming up with a non-contrived example. I'd like to hear some thoughts on this. Thanks! Matt -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.com Note that posts from new members are moderated - please
Re: Improving pprint behavior for anonymous functions
The code below accounts for partials of the same arity. However, there might be a better way to do this with clojure.reflect: (defn print-partial [a-fn] (let [c (class a-fn) fields (into {} (- c .getDeclaredFields (map #(vector (.getName %) (do (.setAccessible % true) (.get % a-fn)) f (get fields f) fname (loop [[ns namespaces] (all-ns)] (let [nsmap (into {} (map #(try (vector (deref (second %)) (first %)) (catch Exception e [::e nil])) (ns-publics ns)))] (if-let [fname (get nsmap f)] #_(symbol (str ns) fname) (str (ns-name ns) / fname) (if (empty? namespaces) f (recur namespaces) args (loop [args arg-num 1] (if-let [arg (get fields (str arg arg-num))] (recur (str args (pr-str arg)) (inc arg-num)) args))] (str (partial fname args (defmacro partial* [fname arg0 args] `(let [pf# (partial ~fname ~arg0 ~@args) cpf# (class pf#)] (defmethod print-method cpf# [o# w#] (print-simple (print-partial o#) w#)) pf#)) Trying out: (def p6 (partial* + 1 2 3)) #'user/p6 user= p6 (partial clojure.core/+ 1 2 3) user= (def t7 (partial* * 1 1 7)) #'user/t7 user= t7 (partial clojure.core/* 1 1 7) user= p6 (partial clojure.core/+ 1 2 3) user= (def comma-join (partial* clojure.string/join , )) #'user/comma-join user= comma-join (partial clojure.string/join , ) user= (p6 100) 106 user= (t7 5) 35 user= (comma-join ['a 'b 'c]) a, b, c On Friday, April 25, 2014 2:55:23 PM UTC-7, Greg D wrote: Got it. The macro, as is, will displace the print method for the same arity. On Friday, April 25, 2014 2:50:34 PM UTC-7, Gary Trakhman wrote: Ah, I think I was mistaken in a detail, but generally correct. Try it with two partials of the same arity. https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2460 On Fri, Apr 25, 2014 at 5:47 PM, Greg D gregoir...@gmail.com wrote: I guess I don't understand the problem, or what is meant by different classes. A counter-example would be helpful. Further transcript using the macro: (def p6 (partial* + 1 2 3)) #'user/p6 user= (class p6) clojure.core$partial$fn__4194 user= (def p10 (partial* + 1 2 3 4)) #'user/p10 user= (class p10) clojure.core$partial$fn__4196 user= p6 (partial + 1 2 3) user= p10 (partial + 1 2 3 4) user= (p6 100) 106 user= (p10 100) 110 On Friday, April 25, 2014 2:33:50 PM UTC-7, Gary Trakhman wrote: That's not going to work, all the return classes of partial are the same class. On Fri, Apr 25, 2014 at 5:26 PM, Greg D gregoir...@gmail.com wrote: I don't know if this is considered good Clojure, but you could define a print-method within a macro to set up the normal string representation for the partial function: (defmacro partial* [fname arg0 args] `(let [pf# (partial ~fname ~arg0 ~@args) cpf# (class pf#)] (defmethod print-method cpf# [o# w#] (if (nil? '~args) (print-simple (str (partial '~fname (pr-str ~arg0) )) w#) (print-simple (str (partial '~fname (pr-str ~arg0) ~@(map #(str (pr-str %)) args) )) w#))) pf#)) A transcript of some quick examples: user= (def p6 (partial* + 1 2 3)) #'user/p6 user= p6 (partial + 1 2 3) user= (p6 7) 13 user= (def re-find-foo (partial* re-find #foo)) #'user/re-find-foo user= re-find-foo (partial re-find #foo) user= (re-find-foo abcdefooghi) foo On Friday, April 25, 2014 9:01:37 AM UTC-7, Matthew DeVore wrote: Hi, There has been one thing bugging me for a long time that seems worth it to fix, and I was wondering if anyone else has had the same problem. I have enjoyed using Clojure's REPL and embracing a Clojure-style data model for my app, where everything is a glorified map or vector and there are no private fields. I even have a simple dump feature that tells me the entire state of my app https://github.com/google/hesokuri that was ridiculously easy to implement, and that takes advantage of the lack of black box data structures. One thing that doesn't really fit in this paradigm is (ironically) anonymous functions with closures. For instance, (partial + 42) returns an anonymous function, and in the REPL or an app dump, it looks hideous: #core$partial$fn__4228 clojure.core$partial$fn__4228@1ee1dea2 So I've avoided anonymous functions in my app except when they exist transiently, and don't appear in the dump (for instance, in (map #(str % !) foo)). But sometimes I just can't
Re: puzzled by RuntimeException
I believe this is a problem in REPL-y, which is used when using 'lein repl'. I used Cider to start a nREPL server, then used 'leing repl :connect' to get the REPL-y interface. The problem was evident in the latter, but not the former. I opened an issue for REPL-y. Thanks again, Steve -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
puzzled by RuntimeException
The sequence in the transcript below shows runtime exceptions when a numeric keyword is followed by a list starting with a symbol or character. Would anyone help me with a reason for the failing cases? user= (clojure-version) 1.6.0 user= '(:42 a) (:42 a) user= '(:42 a) (:42 a) user= '(:42 \a) (:42 \a) user= '(:42 nil) (:42 nil) user= '(:42 true) (:42 true) user= '(:42 :43) (:42 :43) user= '(:42 (a)) RuntimeException EOF while reading, starting at line 1 clojure.lang.Util.runtimeException (Util.java:221) RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) user= '(:42 (a)) (:42 (a)) user= '(:42 (\a)) RuntimeException EOF while reading, starting at line 1 clojure.lang.Util.runtimeException (Util.java:221) RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) user= '(:42 (nil)) RuntimeException EOF while reading, starting at line 1 clojure.lang.Util.runtimeException (Util.java:221) user= RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) user= '(:42 (true)) RuntimeException EOF while reading, starting at line 1 clojure.lang.Util.runtimeException (Util.java:221) user= RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) user= '(:42 (:43)) (:42 (:43)) user= -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: puzzled by RuntimeException
Steve, Thanks. I did a quick check, and it seems that I don't get exceptions when I start the repl as you do. I normally start mine with 'lein repl'. You've given me a good lead to investigate. Greg -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Thoughts on bags?
While searching for MultiSet or Bag resources, I found this implementation by Achim Passen at: A simple multiset/bag implementation for Clojure. However, I found I could meet my needs by adding functions to treat vectors, or other collection types, as unordered. These can then be used directly, or in the definition of your own specialized types. For the hash, from Clojure Data Structures: (defn hash-unordered [collection] (- (reduce unchecked-add-int 0 (map hash collection)) (mix-collection-hash (count collection For equality: (defn equals-unordered [coll-a coll-b] Treat collections as unordered for 1st level of comparison. (or (identical? coll-a coll-b) (and (empty? coll-a) (empty? coll-b)) (and (= (hash-unordered coll-a) (hash-unordered coll-b)) (let [set-a (set coll-a) set-b (set coll-b)] (and (= set-a set-b) (loop [[item items] (seq set-a)] (let [finder #(= item %) found-a (filter finder coll-a) found-b (filter finder coll-b)] (if (not= (count found-a) (count found-b)) false (if (empty? items) true (recur items)) Neither Achim's deftype, nor the above, is likely as efficient as implementation as a core collection MultiSet. The attached file has a trivial implementation of a deftype showing the functions in use. It defines a shopping cart where the items are kept on a vector, which is treated as an unordered collection. A transcript of playing with the shopping cart follows: user= (load-file shopping_cart.clj) #'example.multi-set/make-shopping-cart user= (use 'example.multi-set) nil user= (def cart0 (make-shopping-cart 'carrots 'beans 'eggs)) #'user/cart0 user= cart0 (make-shopping-cart carrots beans eggs) user= (def cart1 (make-shopping-cart 'eggs 'carrots 'beans)) #'user/cart1 user= cart1 (make-shopping-cart eggs carrots beans) user= (def cart2 (make-shopping-cart 'ham 'eggs 'carrots 'beans)) #'user/cart2 user= cart2 (make-shopping-cart ham eggs carrots beans) user= (= cart0 cart1) true user= (= cart1 cart2) false Greg -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. shopping_cart.clj Description: Binary data
Re: Thoughts on bags?
Added link missing in previous post. A simple multiset/bag implementation for Clojurehttps://github.com/achim/multiset -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Thoughts on bags?
While searching for MultiSet or Bag resources, I found this implementation by Achim Passen at: A simple multiset/bag implementation for Clojurehttps://github.com/achim/multiset . However, I found I could meet my needs by adding functions to treat vectors, or other collection types, as unordered. For the hash, from Clojure Data Structureshttp://clojure.org/data_structures#hash : (defn hash-unordered [collection] (- (reduce unchecked-add-int 0 (map hash collection)) (mix-collection-hash (count collection For equality: (defn equals-unordered [coll-a coll-b] Treat collections as unordered for 1st level of comparison. (or (identical? coll-a coll-b) (and (empty? coll-a) (empty? coll-b)) (let [set-a (set coll-a) set-b (set coll-b)] (and (= set-a set-b) (loop [[item items] (seq set-a)] (let [finder #(= item %) found-a (filter finder coll-a) found-b (filter finder coll-b)] (if (not= (count found-a) (count found-b)) false (if (empty? items) true (recur items) Neither Achim's deftype, nor the above, is likely as efficient as a core collection MultiSet. In the meantime, I hope these observations are useful. Greg -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Questions regarding Map vs Record and usage
FWIW, I use: - (-Book Lord of the Rings, Tolkien) - when I define the record instance with the default fields, and the number of default fields is a small number - (map-Book {:title The Fellowship of the Ring, :author Tolkien, :series The Lord of the Rings, :publisher Mariner Books, :year 2012, :ISBN-10 0547928211, :my-rating 10}) - The explicit key names are good documentation when - there are many fields in the defrecord, or - when adding entries not in the defrecord (eg. my-rating) Greg -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
self-evaluation of record instances
Greetings, The nuance below took a long time to identify and reduce from a test failure. Should it be considered a bug? $ lein repl nREPL server started on port 52758 on host 127.0.0.1 REPL-y 0.3.0 Clojure 1.6.0 snipped user= (defrecord Fields0 []) ; record with 0 fields user.Fields0 user= (defrecord Fields1 [f]) ; record with 1 field user.Fields1 user= (def f0 (-Fields0)); instance with empty map #'user/f0 user= (def f0x (map-Fields0 {:x 0})) ; instance with not-empty map, due to extra field #'user/f0x user= (def f1 (map-Fields1 {})) ; instance with not-empty map, declared field is nil #'user/f1 user= f0 #user.Fields0{} user= f0x #user.Fields0{:x 0} user= f1 #user.Fields1{:f nil} user= (eval f0) ; *** morphs to empty map on eval *** {} user= (eval f0x) ; self-evaluates when non-empty map, field added #user.Fields0{:x 0} user= (eval f1) ; self-evaluates when non-empty map, declared field #user.Fields1{:f nil} user= Greg p.s. A little help with not quite getting refshttps://groups.google.com/forum/#!topic/clojure/o9FiG1kCt6I, please? Or is this the wrong forum for such a question? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
not quite getting refs
I've looked, but can't find, a discussion of the choice of a history mechanism for refs. I can't understand why the transactions just don't check #'identical? for the ref value, rather than maintaining a history queue. In other words, I don't see why (dosync (ref-set foo @foo))) should cause other ongoing transactions, that use foo, to retry. Nothing about foo has changed that will alter a retried transaction. Since an #'identical? mechanism would seem to - be easier to implement - be faster to check at the end of a tranaction - cause fewer retries it must be that I don't really get it yet. Does anyone have a doc pointer that would help with the details? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: STM history queues, when is a snapshot pushed
Having learned a little more about refs and transactions from M. Fogus and C. Houser The Joy of Clojure, Second Editionhttp://www.manning.com/fogus2/, I altered the stress-ref function from 10.2.4. Using Clojure 1.5.1: (defn stress-ref [r] (let [slow-tries (atom 0)] (future (dosync (swap! slow-tries inc) (Thread/sleep 200) @r) (println (format r is: %s, meta: %s, history: %d, after: %d tries @r (meta @r) (.getHistoryCount r) @slow-tries))) (dotimes [i 500] (Thread/sleep 10) (dosync (alter r #(let [r0 (first %)] (condp = r0 :identical % := (with-meta % {:mkw (inc (:mkw (meta %)))}) (with-meta [(inc r0)] {:mkw (inc (:mkw (meta %)))})) :done)) Using this function in the following ways user= (stress-ref (ref (with-meta [:identical] {:mkw 0}))) :done r is: [:identical], meta: {:mkw 0}, history: 10, after: 26 tries user= (stress-ref (ref (with-meta [:=] {:mkw 0}))) :done r is: [:=], meta: {:mkw 500}, history: 10, after: 26 tries user= (stress-ref (ref (with-meta [0] {:mkw 0}))) :done r is: [500], meta: {:mkw 500}, history: 10, after: 26 tries From these results I infer that a snapshot is pushed to history whenever alter (et al) are used. Any efficiencies need to be implemented in the Clojure code, eg. (defn stress-ref-equal [r] (let [slow-tries (atom 0)] (future (dosync (swap! slow-tries inc) (Thread/sleep 200) @r) (println (format r is: %s, meta: %s, history: %d, after: %d tries @r (meta @r) (.getHistoryCount r) @slow-tries))) (dotimes [i 500] (Thread/sleep 10) (dosync (let [r0 (first @r)] (condp = r0 :identical (ensure r) := (ensure r) (alter r #(with-meta [(inc r0)] {:mkw (inc (:mkw (meta %)))})) :done)) user= (stress-ref-equal (ref (with-meta [:identical] {:mkw 0}))) r is: [:identical], meta: {:mkw 0}, history: 0, after: 1 tries :done user= (stress-ref-equal (ref (with-meta [:=] {:mkw 0}))) r is: [:=], meta: {:mkw 0}, history: 0, after: 1 tries :done user= (stress-ref-equal (ref (with-meta [0] {:mkw 0}))) :done r is: [500], meta: {:mkw 500}, history: 10, after: 26 tries The documentation at Refs and Transactions http://clojure.org/refs only refers to change without defining what is meant by change. Given the admonition not to rely on inferences as made above, what's a coder to do? Future optimization of refs and transactions may break the code. As a beginner, I can't tell if I'm just confused, or if this is actually confusing. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
STM history queues, when is a snapshot pushed
Is a new snapshot pushed onto the history queue of a ref when 1. every time the ref is a target of alter, commute, ref-set, reset, alter-meta!, or reset-meta!, or 2. only when the committed value for the ref is not identical to the value at the end of the history queue? When checking the committability of a ref before the end of a transaction, is the check that 1. the end position of the history queue for that ref is the same as it was at the beginning of the transaction, or 2. the value of the ref at the end of the history queue is identical to the value at the beginning of the transaction? For both questions, choice 1 appears to be unquestionable safe, but could sponsor a higher number of retries. The choice 2s may conserve some retries, but I'm not sure about the safety. For both questions, the implementation complexity and efficiency seem similar. At any rate, the actual implementation is not a part of the documented API, yet could affect how one codes transaction functions. Even if I dug through the Java source to form my own impressions, one is not supposed to rely on such behaviour. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
non-equality (=) of records nuance
Greetings, I'm confused by the failure of 2 record instances to compare as equal, only when generated by a protocol method and having extra fields. The code below shows this, with uninformative REPL responses snipped. The attached file has similar code as a clojure.test. Would somebody please help me understand the underlying mechanism. I'll need to develop a workaround to avoid confounding library users. Thanks, Greg user= ;;; Set up protocol and records user= (defprotocol FooBar (clone [this]) (switch [this])) user= (defrecord Foo []) user= (defrecord Bar []) user= (extend-type Foo FooBar (clone [this] (map-Foo this)) (switch [this] (map-Bar this))) user= (extend-type Bar FooBar (clone [this] (map-Bar this)) (switch [this] (map-Foo this))) user= ;;; Create 4 (.equal) instances of Bar, no fields; all works as expected user= (def foo0 (-Foo)) user= (def bar0 (-Bar)) user= (def bar1 (-Bar)) user= (def bar-switch-foo0 (switch foo0)) user= (def bar-clone-bar0 (clone bar0)) user= bar0 #user.Bar{} user= bar1 #user.Bar{} user= bar-switch-foo0 #user.Bar{} user= bar-clone-bar0 #user.Bar{} user= (= bar0 bar1); gets expected true true user= (= bar0 bar-switch-foo0) ; gets expected true true user= (= bar0 bar-clone-bar0) ; gets expected true true user= ;;; Create 4 (.equal) instances of Bar with an added field; unexpected results user= (def x-foo0 (map-Foo {:field xtra})) user= (def x-bar0 (map-Bar {:field xtra})) user= (def x-bar1 (map-Bar {:field xtra})) user= (def bar-switch-x-foo0 (switch x-foo0)) user= (def bar-clone-x-bar0 (clone x-bar0)) user= x-bar0 #user.Bar{:field xtra} user= x-bar1 #user.Bar{:field xtra} user= bar-switch-x-foo0 #user.Bar{:field xtra} user= bar-clone-x-bar0 #user.Bar{:field xtra} user= (= x-bar0 x-bar1); gets expected true true user= (= x-bar0 bar-switch-x-foo0) ; gets UNEXPECTED false user= (= x-bar0 bar-clone-x-bar0) ; gets UNEXPECTED false user= (= bar-switch-x-foo0 bar-clone-x-bar0) ; gets UNEXPECTED false user= (.equals x-bar0 bar-switch-x-foo0) ; .equals is true true user= (.equals x-bar0 bar-clone-x-bar0); .equals is true true user= (.equals bar-switch-x-foo0 bar-clone-x-bar0) ; .equals is true true -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. record_instance_equality_test.clj Description: Binary data
Re: non-equality (=) of records nuance
I'm on 1.5.1 I have a workaround: - instead of - (map-Foo this) - use - (map-Foo (into {} this)) On Tuesday, March 18, 2014 5:47:46 PM UTC-7, Alex Miller wrote: What Clojure version are you on? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.