Re: [ANN] Planck 1.0 - Bootstrapped ClojureScript OS X REPL
Hi Zach, Yeah, it definitely sounds like your Homebrew install has an issue. You can also just download the binary from http://planck.fikesfarm.com http://planck.fikesfarm.com/ (it is a self-contained single-file executable). It works on Mavericks or later. - Mike On Aug 5, 2015, at 1:24 PM, Zach Oakes zsoa...@gmail.com wrote: Mike, thanks for this tool. I want to use it to introduce ClojureScript to some local JavaScript devs, since they would be less likely to install anything that required the JVM. I cannot seem to get `brew install planck` to work, however. It just hangs. It looks like `brew upgrade` hangs indefinitely as well, though, so this may just be my mac's fault. If anyone knows how to fix this, please let me know. -- 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: [meta] Can't view one unread topic here.
I recently posted in mistake and deleted the post. Perhaps that is causing what you are seeing. - Mike On Aug 4, 2015, at 10:09 AM, Fluid Dynamics a2093...@trbvm.com wrote: The front page of this group shows no unread threads to me, but shows a (1) next to Google Groups in the page title. So there's one topic with unread posts, but I can't get the interface to show it to me. I've tried refresh, shift-refresh, and navigate-away-and-back. I'm sure I haven't done anything that would filter my view of the group. What do I need to do to make the unread topic visible? -- 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 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 mailto:clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout. -- 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.
[ANN] Planck OS X REPL
Planck is a self-contained bootstrapped ClojureScript REPL for OS X. http://planck.fikesfarm.com http://planck.fikesfarm.com/ Planck is now available via Homebrew: http://blog.fikesfarm.com/posts/2015-08-04-pour-a-pint-of-planck.html http://blog.fikesfarm.com/posts/2015-08-04-pour-a-pint-of-planck.html - Mike -- 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: [ANN] Planck 1.0 - Bootstrapped ClojureScript OS X REPL
Planck 1.3 is now available via Homebrew: http://blog.fikesfarm.com/posts/2015-08-04-pour-a-pint-of-planck.html -- 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.
[ANN] Planck 1.0 - Bootstrapped ClojureScript OS X REPL
Happy to announce that Planck 1.0 is available: http://planck.fikesfarm.com http://planck.fikesfarm.com/ -- 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: [ANN] Replete ClojureScript REPL iOS app available
It was approved as is. Out of curiosity, how painful/painless was the process of getting it accepted into the app store? I've heard that Apple is pretty sensitive about letting anything in that does any kind of evaluation of arbitrary code. -- 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.
[ANN] Replete ClojureScript REPL iOS app available
Replete 1.0 is now in the App Store http://blog.fikesfarm.com/posts/2015-07-20-ios-clojurescript-repl-available-in-app-store.html -- 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: Different macro definitions via reader conditionals?
I’m interested in whether there is a nice answer to this as well. FWIW, I was recently pondering a closely related subject—portability that additionally extends to bootstrapped ClojureScript: http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-musing.html http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-musing.html (Hoping things don’t become excessively combinatorial.) - Mike On Jul 2, 2015, at 8:09 AM, Michael Sperber sper...@deinprogramm.de wrote: I'd like to define a macro differently for Clojure and for ClojureScript. Is there a way to do this via reader conditionals? (My mind boggles.) Regards, Mike -- 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 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 mailto:clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout. -- 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.
[ANN] Replete 1.0 beta: ClojureScript REPL iOS app
Wondering what all this “bootstrapped ClojureScript” hubbub is all about, and have an iOS device? There's a REPL app for that! Try the beta; experience it firsthand: https://github.com/mfikes/replete/wiki/Beta Special thanks to David Nolen and Joel Martin for making this possible! - Mike Fikes -- 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: [ANN] Bocko 0.2.0
Yeah I agree. I misremembered them from 33 years ago as being HLINE and VLINE and corrected them when I looked them up. :) By the way, it is available for ClojureScript / iOS now: https://github.com/mfikes/bocko-ios (I have to say, CLJC rocks!) - Mike On May 8, 2015, at 10:16 PM, David Sargeant da...@dsargeant.com wrote: I guess HLIN and VLIN have a historical significance. Still kind of confusing, but I understand now how you arrived at those names. -- 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. -- 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.
[ANN] Bocko 0.2.0
I created a tiny library that makes it easy to plot points in a low-res graphics mode: https://github.com/mfikes/bocko The motivation was to help encourage interest in my own kids (10 and 12-yo) to learn tidbits of Clojure, and it seems to be working. :) I remember that, with the BASIC REPLs built into the hardware in the 80s, the ability to easily futz with graphics added an extra dimension to the learning experience. Bocko imitates the gr mode from the Apple ][. - Mike -- 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: ANN: ClojureScript 0.0-3211
Hey Tony, try updating the version of Clojure in your project.clj to 1.7.0-beta1, which is used by 0.0-3211. (In short, reader/read was given a second arity to allow options to be passed, thus supporting #? conditional reading.) -- 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: [ClojureScript] Re: ANN: ClojureScript 0.0-3115
If that is true, then it is a problem, indicative either of a widespread lack of discipline among the tool makers or (more likely) a strong need for some additional well-specified (and maintained!) APIs in the compiler for tools to hook into. Sometimes it is just a simple bug or lack of robustness in a downstream tool that needs to be sorted before rushing to blame and/or burden upstream ClojureScript. Take https://github.com/omcljs/ambly/issues/61 as an example. Previously ClojureScript 0.0-3030 would not print anything when evaluating (doc unknown-symbol), and with 0.0-3053 onwards it prints an empty string. This broke Ambly. This doesn't really reflect a lack of discipline with APIs, but does illustrates the need to do downstream triage first. -- 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: [ANN] Clojure 1.7.0-alpha5 now available
Alex, 1.7.0-alpha5 looks OK to me. It passed with some regression testing for an AOTd http-kit compojure / core.async REST server using Lucene, clojure/java.jdbc / MySQL, Java 1.7.0_65 on Ubuntu 10.04.1 LTS. -- 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: Has the old invalid constant tag: -57 bug been fixed?
I did some digging and for those interested, this appears to be the way piggieback and tools.nrepl work for ClojureScript. Details are in the Cursive ticket: https://github.com/cursiveclojure/cursive/issues/680 -- 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: Has the old invalid constant tag: -57 bug been fixed?
I've recently seen the same error: Loading test/cljs/classroom_checkout/test1.cljs... done CompilerException java.lang.ClassFormatError: Unknown constant tag 117 in class file classroom_checkout/utils_test$eval12853, compiling:(/private/var/folders/m0/161fm8fx069fk_fny08nrmkmgp/T/form-init7703020558715930971.clj:1:1131) I caused this by making a copy of Nolen's recently added cljs.core tests and by trying to load them in my browser REPL. It appears to be related to the size of the file: If I try just a few forms in the ns, it works, but once beyond say 500 or 1000 lines, I get this error, with the exact number changing depending on the size of the file. -- 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: Has the old invalid constant tag: -57 bug been fixed?
You are absolutely right, Andy. Getting out my bantha shears in order to provide a good reduction for a bug report… -- 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: Has the old invalid constant tag: -57 bug been fixed?
I found that the problem I'm experiencing is, in essence, the same issue as discussed (and fixed) here https://code.google.com/p/counterclockwise/issues/detail?id=429, but with some new tool in my toolchain (Cursive/simple-brepl/Weasel). TL;DR: Something produces a .class file that exceeds the 65535 bytes allowed by the JVM. The evidence: I can take the large test foo.clj file attached to the thread and reproduce the problem, and eliminate it by deleting a few lines. This is consistent with what I was seeing earlier when trying to load all of ClojureScript's core tests. I'll start with Colin to see if he has any thoughts on whether Cursive is involved. I can successfully evaluate and use the results of a (load-file path/to/filename.cljs) form in the REPL, but hit the error only when using Cursive's “Load File in REPL” menu item. -- 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.
rest arguments and desctructuring / nil vs. empty
For rest arguments, as in (defn foo [x r] r), when the remaining arguments are rolled up into a sequence, you will get nil instead of an empty sequence. Is it fair to say that the rest nomenclature came about back at the beginning of Clojure, when rest really did return nil, prior to the introduction of next and lazy sequences? In other words would it be fair to, given today's behavior, characterize them as really being next arguments, but with a historical name? -- 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: Clojurescript to target JVM?
I too was intrigued by this and cobbled together a quick test to see if this made it possible to create command-line apps that start up more quickly [1]. It appears that this is indeed the case, but, of course you still need to pay JVM startup time. I was also interested in what Sam Beran accomplished, wishing the same approach was available in iOS. I haven't thought of a clean way to do it and simply load the JS into JavaScriptCore [2], paying several hundred milliseconds at startup, which would be nice to eliminate. The main aspect of all of this appears to be the whole-program optimization aspect eliminating lots of unnecessary code. I'm currently wondering if this is on the plate for Clojure 7. [1] https://github.com/mfikes/cljs-cl [2] https://github.com/mfikes/goby -- 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: Persistent Data Structures for Objective-C/LLVM
I'm thinking Anton's persistent collections could be useful on iOS. Out of curiosity, I made a small iOS project that compares the performance of Anton's map to ClojureScript's, when adding lots of key-value pairs (using transients): https://github.com/mfikes/persistent-objc-cljs Interestingly, they both run at nearly the same speed on an iOS device. But, when running on a Mac, the ClojureScript is currently about a factor of 7 times faster than the Objective-C. -- 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: uniqueness of hash if computed on different jvms across different machines.
In addition to Andy's caveats, remember that hash code equality doesn't imply object equality. In concrete terms, a = b implies h(a) = h(b), with the useful bit being h(a) ≠ h(b) implies a ≠ b. On Monday, October 13, 2014 2:04:57 AM UTC-4, Sunil Nandihalli wrote: Hi, Is the clojure hash function guaranteed to produce the same hash on different jvms running on different jvms for the same data-structure which would satisfy equality if checked on a single jvm. The data structure is simply a hash-map. Thanks, Sunil. -- 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: Do this or that
Thanks all! FWIW, the snake game in Programming Clojure has an example (where refs are conditionally updated) which is consistent with the advice given here. Two nice things I noticed in that example: 1. The first form inside do is kept on the same line (a small but nice improvement reducing the percieved visual weight of the approach). 2. In the snake game, the entire construct is inside a function that explicitly returns nil (because there is no intent to return the value that the if might evaluate to). -- 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: Why is my function faster with eval?
Hey Michael, Since your eval solution essentially cookie-cutters out maps, each with the same keys, as fast as it can, I was playing around with what would happen if you used records, and I cobbled together something that appears to run twice as fast as the eval approach: (defn read-to-structs [rows] (let [headers (- rows first (take-while (complement #{})) (map keyword)) s (apply create-struct headers)] (for [row (rest rows)] (apply struct s row Here are comparative timings: (time-fn read-to-maps) Elapsed time: 4871.02175 msecs = nil (time-fn read-to-maps-partial) Elapsed time: 4814.730643 msecs = nil (time-fn read-to-maps-fn) Elapsed time: 4815.230087 msecs = nil (time-fn read-to-maps-eval) Elapsed time: 2466.048578 msecs = nil (time-fn read-to-structs) Elapsed time: 1273.462618 msecs I didn't test it too much, but it passed this: (= (read-to-maps csv-fix) (read-to-structs csv-fix)) = true On Friday, October 10, 2014 4:21:01 PM UTC-4, Michael Blume wrote: https://github.com/MichaelBlume/eval-speed eval-speed.core= (time-fn read-to-maps) Elapsed time: 5551.011069 msecs nil eval-speed.core= (time-fn read-to-maps-fn) Elapsed time: 5587.256991 msecs nil eval-speed.core= (time-fn read-to-maps-partial) Elapsed time: 5606.649172 msecs nil eval-speed.core= (time-fn read-to-maps-eval) Elapsed time: 2627.521592 msecs nil Ben, I'd still like to understand exactly what work the CPU is doing in the uneval'd version that it's skipping in the eval'd version. It seems like in the generated bytecode there's going to be *some* concept of iterating through the row in either case, if only as part of the destructuring process. On Friday, October 10, 2014 1:07:08 PM UTC-7, Ben wrote: I believe it's because the `mapper` function is just creating and returning a map literal. The mapper function in the evaled version is something like this: user (def names '[n1 n2 n3 n4]) #'user/names user (def headers '[h1 h2 h3 h4]) #'user/headers user `(fn [[~@names]] ~(zipmap headers names)) (clojure.core/fn [[n1 n2 n3 n4]] {h4 n4, h3 n3, h2 n2, h1 n1}) ;; just a map literal, whose keys are already known. Whereas in the first version, zipmap has to be called, iterating over headers and names each time. On Fri, Oct 10, 2014 at 1:04 PM, Sean Corfield se...@corfield.org wrote: It may be more to do with the difference between `for` and `map`. How do these versions compare in your benchmark: (defn read-to-maps-partial [rows] (let [headers (- rows first (take-while (complement #{})) (map keyword))] (map (partial zipmap headers) (rest rows (defn read-to-maps-fn [rows] (let [headers (- rows first (take-while (complement #{})) (map keyword)) mapper (fn [row] (zipmap headers row))] (map mapper (rest rows Sean On Oct 10, 2014, at 11:42 AM, Michael Blume blume...@gmail.com wrote: So I'm reading a bunch of rows from a huge csv file and marshalling those rows into maps using the first row as keys. I wrote the function two ways: https://gist.github.com/MichaelBlume/c67d22df0ff9c225d956 and the version with eval is twice as fast and I'm kind of curious about why. Presumably the eval'd function still implicitly contains a list of keys, it's still implicitly treating each row as a seq and walking it, so I'm wondering what the seq-destructuring and the map literal are doing under the hood that's faster. -- Ben Wolfson Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure. [Larousse, Drink entry] -- 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 edit EDN value in cljs
Can you use update-in or assoc-in? On Friday, October 10, 2014 2:28:26 PM UTC-4, Dustin Getz wrote: I have an arbitrarily nested EDN value stored in an atom in ClojureScript. What is the best way to make edits to an arbitrary subtree of this value? -- 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.
Do this or that
Here's a style question: If you have to conditionally do one set of side effects or another set, is your preference to use when and when-not, or an if containing do blocks? Or perhaps some other construct? In terms of a concrete example: (let [boolean-value (some-predicate?)] (when boolean-value (do-alpha) (do-beta)) (when-not boolean-value (do-gamma) (do-delta))) or: (if (some-predicate?) (do (do-alpha) (do-beta)) (do (do-gamma) (do-delta))) -- 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: core.async | compojure ... odd error ... help!!
Hi mond, I've been using HTTPkit with Compojure and core.async (all fronted by Nginx so the entire stack is async FWIW). To glue core.async with HTTPkit when handling inbound requests, I have a utility function (defn handle-async! [handler req] (http-server/with-channel req channel (take! (handler req) #(http-server/send! channel % and I make use of that utility function when defining routes (defroutes all-routes (GET /covers/v1/:cover [] (partial http/handle-async! fetch-cover!)) (context /books/v1 [] (GET /search [] (partial http/handle-async! search-handler!)) (GET /:isbn [] (partial http/handle-async! get-book-by-isbn! The handler functions fetch-cover!, search-handler!, get-book-by-isbn!, all return channels (they either call go for stuff that needs to be async, or to-chan on collections read directly from memory. - Mike On Saturday, September 27, 2014 5:01:36 AM UTC-4, mond wrote: Hi James, Er, nice tip on the routes - that was another thing that I didn't expect to work but was happy when it did ;-) I will of course adapt it to your recommendation. Speaking to the main point, no I don't want to put a channel on to the response so that's a mistake that I see and would like to avoid. I would like to understand where I have gone wrong. Maybe I need to use HTTPkit instead? Thanks Ray On Saturday, 27 September 2014 02:08:50 UTC+2, James Reeves wrote: Hi Ray, I don't entirely understand why you expected this to work. Channels aren't a valid Ring response body. The error message is essentially telling you that Compojure has no way of turning the channel object you've returned into a valid response. The other problem you have is that the Ring Jetty adapter doesn't have any support for asynchronous operations. Another small point. You're using * as an argument name, but this isn't really recommended. This only works by coincidence, and it may be removed in future versions. Instead use something like: (GET [/:brand/:country/:resource :resource #.*] [brand country resource] ...) - James On 27 September 2014 00:14, mond r...@mcdermott.be wrote: My first core.async program ... all works outside of the web app but barfs once I put the functions inside a web container. I hope somebody in the group can point to my obvious mistake... The idea is that the function 'respond-within-sla' will give back a result or a come back later message after N milliseconds. It is passed a number of ms, three functions and the arguments for the final function ... which is the one that should operate within the SLA. (defn respond-within-sla [expected-result-milliseconds respond-ok respond-later data-fetcher args] (let [data-channel (timeout expected-result-milliseconds)] (go (if-let [data (!! data-channel)] ((async/close! data-channel) (respond-ok data)) (respond-later))) (go (! data-channel (apply data-fetcher args) To keep the volume of code to parse to a minimum I have made a few toy functions that demonstrate the failure... ; test funcs (defn ok [data] (prn (str send HTTP 200 ... got data data))) (defn later [] (prn (str send HTTP 202 ... request received, come back later))) (defn fetcher [arg1 arg2 arg3] (prn (str fetching data with args arg1 arg2 arg3)) response-data) (defn failer [ args] (Thread/sleep 1000) (str never gets here args)) ; test funcs (defn ok [data] (prn (str send HTTP 200 ... got data data))) (defn later [] (prn (str send HTTP 202 ... request received, come back later))) (defn fetcher [arg1 arg2 arg3] (prn (str fetching data with args arg1 arg2 arg3)) response-data) (defn failer [ args] (Thread/sleep 1000) (str never gets here args)) (defn generate-response [brand country resource] (let [sla (or (env :sla-milliseconds) 100)] (respond-within-sla sla ok later fetcher brand country resource))) (defn generate-fail [brand country resource] (let [sla (or (env :sla-milliseconds) 100)] (respond-within-sla sla ok later failer brand country resource))) From within the REPL it all works fine... (generate-response A B C) = #ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@4b7ae3f7 fetching data with args A B C send HTTP 200 ... got data response-data (generate-fail A B C) = #ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@4eb8b5a9 send HTTP 202 ... request received, come back later Here is the compojure route.. (defroutes app (GET /:brand/:country/* [brand country *] (generate-response brand country *)) (ANY * [] (route/not-found You must use a REST style to specify brand and country keys in the URL))) If I now start it up 'lein run' and try to exercise the functions from
Newbie: adding items to a global vector in doseq
Read up on atoms. The results of your conj call are being discarded. For example, check out the behavior of this: (def urls2 (atom [])) (swap! urls2 conj http://foo.bar;) -- 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: Newbie: adding items to a global vector in doseq
Thomas is absolutely right, Philippe. Things also get easier if you avoid, or defer side effects, and first focus on pure functions. So, for example at the REPL, you might first try processing a literal sequence of lines, repeatedly adjusting the processing code, tweaking the regex, until you get it right: (mapv #(re-find #\w+\.\w+ %) [abc def.g apple.com ibm.com foo]) ;= [apple.com ibm.com] You could turn the above into a pure function that works on a sequence of lines: (defn lines-urls [lines] (mapv #(re-find #\w+\.\w+ %) lines)) You could then define your file reading code in terms of that pure function: (defn readf [file] (with-open [r (clojure.java.io/reader file)] (lines-urls (line-seq r -- 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: Clojure XML - is there a better way?
My only gut reaction is that, without a root node, it doesn't seem that you have XML. (It is certainly not a well formed document, and I would suspect lots of XML tools/libraries would have difficulty coping with the example you provided.) -- 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: Moving average from Java to Clojure
There actually is a queue implementation. Here is a way to use it for your problem: (defn make-moving-average-queue [n] (atom {:lengthn :current-total 0.0 :old-values(clojure.lang.PersistentQueue/EMPTY)})) (defn update-moving-average-queue [old-queue next-value] (let [current-total (+ (:current-total old-queue) next-value) old-values (conj (:old-values old-queue) next-value)] (if ( (count old-values) (:length old-queue)) (let [current-total (- current-total (first old-values)) old-values (pop old-values)] (assoc old-queue :current-total current-total :old-values old-values)) (assoc old-queue :current-total current-total :old-values old-values (defn moving-average [old-queue next-value] (let [new-queue (swap! old-queue update-moving-average-queue next-value)] (/ (:current-total new-queue) (count (:old-values new-queue) (def queue-06 (make-moving-average-queue 6)) (def inputs-06 [20 22 21 24 24 23 25 26 20 24 26 26 25 27 28 27 29 27 25 24]) (doseq [input inputs-06] (println (moving-average queue-06 input))) (def queue-10 (make-moving-average-queue 10)) (def inputs-10 [20 22 24 25 23 26 28 26 29 27 28 30 27 29 28]) (doseq [input inputs-10] (println (moving-average queue-10 input))) -- 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: Moving average from Java to Clojure
Hey Cecil, In addition to using peek instead of first, as indicated by Plinio, the moving-average function above uses some poor names, in hindsight, especially the old-queue parameter name. I'd suggest naming it queue, as it refers to an atom. You could even consider naming the function moving-average!. -- 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: unexpected behavior of clojure.core/empty
MapEntry is a collection: (coll? (clojure.lang.MapEntry. a 1)) ;= true (ancestors (class (clojure.lang.MapEntry. a 1))) ;= (a set that includes clojure.lang.IPersistentCollection) The docstring for empty implies it would return an empty MapEntry. But perhaps since MapEntry is a special collection type that must have a size exactly equal to 2, empty must return nil. Perhaps ClojureScript will one day introduce a MapEntry type and behave the same way as Clojure (ClojureScript currently returns a PersistentVector). -- 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: unexpected behavior of clojure.core/empty
I did a little “code archaeology” in an attempt to elucidate what Rich may had been thinking: In mid 2007, some of the persistent collection implementations had an EMPTY value defined. [1, 2]. (But, of course, no such EMPTY value was defined for MapEntrys.) Around a year later, MapEntrys were revised to participate in the vector abstraction [3]. A couple of months *after* this, “empty” was added to the collection abstraction [4], and usually implemented in terms of the EMPTY value, and MapEntry was made to return null. My analysis is inconclusive: Making MapEntry return null is logical, given that there is no EMPTY value to return. But, the MapEntry / vector business happening prior to this blurs the argument. Perhaps the real problem is that not all collections can be emptied, and thus thus empty shouldn't have been added to the collection abstraction. (ClojureScript separates out the idea, introducing IEmptyableCollection.) [1] https://github.com/clojure/clojure/commit/12457e7bf29747232bbfda2a0de3b72fbb14f3a9 [2] https://github.com/clojure/clojure/commit/4232de83a53e12741252d31aef9cecee5b8981da [3] https://github.com/clojure/clojure/commit/978af02b0a7e2b430c917b32b58215edcae2ad2d [4] https://github.com/clojure/clojure/commit/697b69fe9c8f5e2e8d40382e70d4ddd490c4a9ee -- 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: unexpected behavior of clojure.core/empty
In *Clojure Programming* (Emerick, Carper, Grand) a swap-pairs function is defined in the section describing how empty allows you to write functions against abstractions. That function operates on sequentials, and, importantly, is carefully designed (invoking empty) so that its return type is consistent with its argument's type. For example: (swap-pairs [1 2 3 4]) ;= [2 1 4 3] (swap-pairs '(1 2 3 4)) ;= (3 4 1 2) Things go awry with MapEntry: (sequential? (first {:a 1})) ;= true (swap-pairs (first {:a 1})) ;= (:a 1) Compare this with what you get in ClojureScript: (sequential? (first {:a 1})) ;= true (swap-pairs (first {:a 1})) ;= [1 :a] -- 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: unexpected behavior of clojure.core/empty
My guess: Perhaps this is a bug, or alternatively, a known issue that won't be addressed because to do so would be a breaking change. There is an old demo of Clojure given by Rich where MapEntry's were printed using some sort of un-readable notation #:foo 5. But clearly MapEntry's have been revised to act a lot like 2-element vectors. user= (rseq (first (mapv identity {:foo 5}))) (5 :foo) user= (conj (first (mapv identity {:foo 5})) :x) [:foo 5 :x] user= (assoc (first (mapv identity {:foo 5})) 1 7) [:foo 7] user= (subvec (first (mapv identity {:foo 5})) 0 1) [:foo] FWIW, ClojureScript behaves in your expected way: (empty (first (mapv identity {:foo 5}))) = [] -- 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: Calculating the number of timestamps logged within a specific time period
You could use frequencies: user= (frequencies (map #(quot % 1000) epochs)) {1405060202 1, 1405060201 8, 1405060200 1, 1405060205 1} -- 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: Calculating the number of timestamps logged within a specific time period
As a start, you could use group-by with a function that squashes together items that fall in the same second and then count the size of each value. (reduce-kv (fn [c k v] (assoc c k (count v))) {} (group-by #(quot % 1000) epochs)) ;= {1405060205 1, 1405060200 1, 1405060201 8, 1405060202 1} -- 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: handling only a part of a hash-map
select-keys makes it easy to extract a portion of a map: (select-keys {:id 1 :ts 2 :ignore 3} [:id :ts]) = {:ts 2, :id 1} -- 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.
import functions from different .clj files
Normally, the initial elements of the namespace are used to create directories and the last element matches the filename. So, for your first example, there would be an a/b/c.clj file. Perhaps this is at the root of the issue. -- 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.
import functions from different .clj files
And alternatively you could declare the first namespace as being a.b.c.fileB -- 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: import functions from different .clj files
I think the root cause is that you need to follow the directory name and filename conventions. For example clojure.java.jdbc is in a clojure/java/jdbc.clj file https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj -- 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: Clojure on iOS devices - Swift as a host?
That's cool! What I haven't been able to figure out is if we actually get FTL with JavaScriptCore on iOS 8, or better yet, if we can somehow gain access to a JSContext from the WKWebView. More detail: I'm using ClojureScript to develop what are otherwise native iOS apps. (Meaning using UIKit, StoryBoards, UIButtons, UITextFields, view hierarchies, animations, etc.—the same stuff you would work with if you sat down at Xcode and wrote a conventional iOS app.) In other words, not self-contained web apps that manipulate the DOM of a page hosted in the app in order to render its UI (in which case WKWebView would be directly applicable and FTL would be enabled). You can do this using JavaScriptCore, which is akin to a bare-bones JavaScript engine that you can use to drive Objective-C objects that you've exported into JavaScriptCore, and vice-versa (drive the JavaScript from Objective-C). UIWebView, on the other hand, adds additional stuff to its JavaScript environment. You can certainly run the output of the ClojureScript compiler in JavaScriptCore, but the first thing you will run into is the lack console.log, which is easy to add back in via Objective-C. Then the next thing you might encounter is the lack of setTimeout (which occurs, for example if you use a core.async timeout channel)—which you can also add back in. Then, if you try to establish a REPL into JavaScriptCore, then you may find you are lacking socket.io, which you could also theoretically add to JavaScriptCore. At that point (essentially trying to run a browser REPL inside something that is arguably not a browser), I decided to just use UIWebView, simply for the purpose of REPL development, grabbing its JSContext (which is the same thing you get when you are working with JavaScriptCore), using private API. This is cool for development using the REPL, but it is safer to go back to JavaScriptCore for actual release builds that must pass review for the App Store. So, with WKWebView (the JITed replacement for UIWebView), those same questions come into play. Can we gain access to the JSContext of a hidden WKWebView using public API? (In that case it can be used all of the time, both for REPL dev and for release builds). Failing that, is JavaScriptCore JITed in iOS 8? On Wednesday, June 25, 2014 2:23:32 AM UTC-4, Steve Tickle wrote: In the upcoming IOS8, UIWebView has the same (JITed) performance as the Safari, the distinction has been removed due to using the new inter-app communication mechanism. This allows the remote application (Safari/JavascriptCore/UIWebView) to display a view into another process, thus bypassing the no-executable-pages issue. So basically... get the IOS8 beta new XCode beta and play with it... -- 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.
Style-question: self-named attribute getters?
I'm curious about this stuff too. (I'm very new to Clojure.) I wouldn't be surprised if the general sentiment is: “Don't.” The argument goes along these lines: By encapsulating, you have introduced a tiny new little API that clients need to learn the semantics of. Additionally, that API is likely not amenable to the plethora of other functions available in the standard library that are designed to work against a compact set of abstractions. Part of me is with you, though, and I'm curious if there are patterns that let you encapsulate in a way that works out cleanly. -- 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: IntelliJ Cursive ClojureScript IDE slowdown
Thanks. You're all awesome! -- 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: Clojure on iOS devices - Swift as a host?
(Apologies to Greg for having essentially hijacked this thread, but I suspect he'd find this cool.) I have no experience with the Swift REPL yet, but I'm still finding this a little surreal: https://lh6.googleusercontent.com/-Z7ulXotc4N4/U6nCQgnWuPI/AJc/700UBdqm3d0/s1600/repl.jpg (It's a picture of me holding an iPod touch, jacked into it wirelessly via a ClojureScript REPL, live updating a UITextField's text.) -- 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: Clojure on iOS devices - Swift as a host?
Thanks David! Targeting ClojureScript to iOS just got an order of magnitude easier for me. I want to say that Colin Fleming (Cursive) has been extremely helpful in helping me sort out how to achieve this. -- 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: IntelliJ Cursive ClojureScript IDE slowdown
Hi Colin, I'm still in the habit of manually saving, but I've noticed that IntelliJ saves quite often on its own. I usually work with :whitespace optimizations so that compilation completes within 3/10 s of saving. (I'm using this to build an iOS app using JavaScriptCore, so this is much quicker than I can switch over to Xcode to test a change.) -- 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: IntelliJ Cursive ClojureScript IDE slowdown
Me too. I suspect it is an IntelliJ-specific problem, unrelated to Cursive. Perhaps Colin has the ability and insight to see where the problem lies. -- 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.
IntelliJ Cursive ClojureScript IDE slowdown
Just sharing a tooling hint: If you are using IntelliJ / Cursive to edit ClojureScript (on a Mac at least), opening a Terminal “pane” at the bottom of the IDE in order to run `lein cljsbuild auto` is nice because you can readily see any errors or warnings the ClojureScript compiler might emit. But… this ends up fairly quickly slowing down editing in IntelliJ to the point where keystrokes feel “mushy” rather than “crisp.” A more dramatic way to see this is to select some lengthy ClojureScript text and drag and watch the selection UI updates follow behind the cursor. The simple fix: Instead run `lein cljsbuild auto` in an OS X Terminal window. -- 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.
Best tools for profiling Clojure programs?
I can speak to existence but not optimality :) I've use JProfiler, and my experience is that, just like debuggers work, so does this particular profiler. -- 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: Invalid timestamp
It it perhaps reading the first line of your file and running it trough the parser? -- 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: ClojureScript ^:export defprotocol
I found the solution to the original question I had posed: Is there a way to indicate the protocol names should be preserved? (Analogous to the way ^:export can be used on function definitions.) You simply need to place the meta directly in the method signature forms, as illustrated here: (defprotocol TableViewDataSource (^:export number-of-sections [this]) (^:export number-of-rows-in-section [this section]) (^:export cell-for-row-at-index-path [this section row])) I came to this solution after reading the implementation of emit-protocol :) With this change, the protocol methods can be called as regular functions from the JavaScriptCore / Obj-C host, even with :advanced optimizations enabled. -- 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.
ClojureScript ^:export defprotocol
Is there a way to indicate that a (ClojureScript) protocol is intended to be used from the host? Details: I can define a protocol and an implementation of it in ClojureScript using defprotocol and reify. I can also successfully call methods on reified instances returned to the host (Obj-C embedding JavaScriptCore on iOS). The method names are mangled: In addition to the expected and usual conversion of hyphens to underscores, the mangled names incorporate dollar signs ($) and arity encoding, an example of which is: my$full$ns$MyProtocol$a_method_defined_in_this_protocol$arity$1 This can be called, passing this mangled string in as the method name of JSValue -invokeMethod:withArguments:. All cool (so long as this mangling is stable from one ClojureScript release to the next—but it smells like the mangling could be an implementation detail, subject to change). The killer is if I turn on Google Closure advanced optimizations; these mangled names get renamed. Is there a way to indicate the protocol names should be preserved? (Analogous to the way ^:export can be used on function definitions.) -- 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: ClojureScript ^:export defprotocol
Even without JIT available in JavaScriptCore, I have been unable to notice a difference in the on-device performance of the “view controller” code I have been writing when turning on :advanced. Thanks for the suggestion, I'll go with :simple and :static-fns. The reified protocol instance works with those optimizations. On Wednesday, June 18, 2014 2:34:45 PM UTC-4, David Nolen wrote: On iOS is advanced compilation really necessary? :simple + :static-fns true should suffice. -- 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: ClojureScript ^:export defprotocol
Right, Gary, Initially I simply wrote exported functions. The motivation for experimenting with protocols is so that I can write a ClojureScript protocol that mimics, say the iOS UITableViewDataSource Objective-C @protocol. Then, with that in place, I can write ClojureScript reifications of that protocol to be passed back to Objective-C. It is then a simple matter on the Objective-C side to make that reification *be* a UITableView's dataSource delegate (with the help of a little reusable wrapper Obj-C object around the JSValue.) In addition to perhaps keeping things tidy (keeping like methods together), it makes it easier to pass multiple @protocol instances back to iOS. (Imagine the case of two or more table views on one iOS screen, each with their own distinct ClojureScriipt implementation.) Also, a lot of this ends up being boilerplate that needs to only be written once, and then, I recoup the costs of fleshing out this plumbing by simply spitting out a (reify ... ) form whenever needed. Arguably, none of this is required because all of the UITableViewDataSource methods have the tableView as the first argument, which could be used by straightforward exported functions to dispatch or otherwise switch to the right implementation, which could in turn be a reified protocol. It just seems that, since Objective-C *wants* an object as a dataSource, that it would be interesting to try to satisfy that need (more or less directly) using the facilities available in ClojureScript. I'll ditch all of this when Apple introduces FunctionalSwift along with functional APIs, and the Clojure(Swift) compiler targets that new language. :) - Mike On Wednesday, June 18, 2014 2:48:33 PM UTC-4, Gary Trakhman wrote: 'any problem.. fixed.. by another layer of indirection' You could also just make exportable functions that call the protocols, keeping them more as impl-details, core.cljs does this, and you gain things like varargs (hmm, do protocol-varargs work on cljs? nope: http://dev.clojure.org/jira/browse/CLJS-362 ) -- 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: ClojureScript ^:export defprotocol
That's cool. I see no reason why Clojure / ClojureScript's “reach” can't extend significantly into iOS. On Wednesday, June 18, 2014 3:58:18 PM UTC-4, Gary Trakhman wrote: I was just telling a local ios dev there's like five guys using clojure + objective-c. To me it's impressive. To them, well, I don't know what they'd think :-). -- 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.
Help with writing a function to merge two maps
I want to use merge-with * to solve your problem. To do so, define a couple of helper functions (defn v-m [v] (into (sorted-map) (for [{:keys [id val]} v] [id val]))) (defn m-v [m] (mapv (fn [[k v]] {:id k :val v}) m)) that can convert your structure to and from sorted maps. With these, it boils down to a call to merge-with (m-v (merge-with * (v-m xs) (v-m ys))) -- 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: Clojure on iOS devices - Swift as a host?
Hey Devin, You had asked to see some code. Here is a little, to give a feel for the “top level” without digging into the plumbing. Let's say you want an authentication UI that lets you enter a 6-digit code with a keypad and asterisk indicators showing how many digits have been keyed. Here is a screenshot of that UI (actually being driven by ClojureScript): https://lh4.googleusercontent.com/-2RTQ5tlyTZo/U50NOx2DvDI/AJM/PrwustID-0E/s1600/keypad.png This UI simply comprises some labels and some buttons. The ClojureScript code that runs the UI binds to those iOS components via tag number (which is set in interface builder), and has a little logic to maintain a model that consists of a vector of the digits entered so far, and code to color the asterisks. In the picture above, two button presses have occurred and the code has logged: *2014-06-14 22:47:11.291 Test App[2428:60b] JS: code-entered: [1]* *2014-06-14 22:47:12.213 Test App[2428:60b] JS: code-entered: [1 4]* The “view controller namespace” hooked up to this view is this ClojureScript code below. In it you can see an atom per UI element along with bits of code manipulating the maps in the atoms (such as set-enabled!). The “plumbing” that I haven't shown is a bit of boring code that marshals information between the atom values and the iOS components. A sample atom value for a text field might look like {:text foo :enabled true}. (ns test-app.view-controller (:require [fikesfarm.ios.interop :refer [bind!]] [fikesfarm.ios.view-model :refer [set-text! set-callback! set-enabled! set-hidden!]]) (:require-macros [fikesfarm.ios.util :refer [with-try]])) ;; View-Model (def asterisk-labels (vec (repeatedly 6 #(atom {} (def number-buttons (vec (repeatedly 10 #(atom {} (def clear-button (atom {})) ;; Model (def code-entered (atom [] :validator #( (count %) 7))) (defn- update-asterisk-labels! [count-entered] (dorun (map-indexed (fn [n asterisk-label] (set-enabled! asterisk-label ( n count-entered))) asterisk-labels))) (defn- set-number-buttons-enabled! [enabled] (dorun (map #(set-enabled! % enabled) number-buttons))) (defn ^:export init-myvc! [view] (with-try ;; Bind the UI elements (dorun (map #(bind! view %1 %2) (range 21 27) asterisk-labels)) (dorun (map #(bind! view %1 %2 :touch-up-inside) (range 1 11) number-buttons)) (bind! view 11 clear-button :touch-up-inside) ;; When a number button is pressed, conj value to the code-entered vector (dorun (map #(set-callback! %1 (fn [] (swap! code-entered conj (mod %2 10 number-buttons (range 1 11))) ;; Empty the code-entered vector if clear button pressed (set-callback! clear-button (fn [] (reset! code-entered []))) ;; Set the asterisk labels to the correct initial rendering (update-asterisk-labels! 0) ;; As the code-entered model changes, update the number of asterisks shown (add-watch code-entered :code-entered (fn [_ _ old-code-entered new-code-entered] (when-not (= old-code-entered new-code-entered) (println code-entered: new-code-entered) (update-asterisk-labels! (count new-code-entered)) (when (= new-code-entered [1 4 7 2 5 8]) (set-number-buttons-enabled! false) (set-enabled! clear-button false))) - Mike On Wednesday, June 11, 2014 10:46:28 PM UTC-4, Devin Walters (devn) wrote: If I had a small fortune I would pay you to sit down and show me how this business you're talking about works. Sounds really cool. Is doing this kind if thing documented well anywhere? I'd love to see some code and your workflow. '(Devin Walters) -- 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: Clojure on iOS devices - Swift as a host?
Hi Devin, A great place to start is http://web.cecs.pdx.edu/~cpinera/javascriptcore-integration-with-clojurescript-in-ios.html (some slight modifications are required to get that blog post examples working with the latest, but it's not that hard). Another great resource is the WWDC 2013 video on JavaScriptCore. Once you have a sample project up and running, then you are “cooking with fire.” Roughly the workflow involves editing ClojureScript (I use Cursive in IntelliJ, but any IDE would do) where the results of lein cljsbuild auto are being consumed in a “sibling” Xcode workspace. Make a change to ClojureScript, rebuild your Xcode app, observe the change in behavior, repeat. Debugging is nearly impossible, so I rely heavily on logging, and on producing lots of pure functions that can be independently verified in a REPL. So the first thing you would want to do is set up things do that when you call a logging function in your ClojureScript, it is routed to iOS and logged in the console. To avoid needing to add lots of new JSExport methods for new functionality, I take the approach of writing some plumbing code that can work with the UI by referencing UIComponents via their “tag” integer, which I manually set in IB and then call a “bind!” function in ClojureScript to set up the needed interactions. For example, I might have a (def text-field (atom {})) and then in an init method marked ^:export that takes a view argument, I do (bind! text-field view 1), where the literal 1 is the tag for a text field in IB. I've written bind to call into Objective C and register for notifications on that tag, setting things so that, for example, whenever the text changes, it calls back into ClojureScript executing a function that ends up calling (swap! text-view assoc :text updated-text). You can take a similar approach to have button tap events drop a message into a core.async channel, and associated plumbing to bind a UI button to the channel. The end result is that you can essentially write what would normally be view controller code in ClojureScript. A lot of the above (especially the code fragments) are from memory—ask if you'd like more elaboration. But in the end, it's simpler and less elaborate than you might initially think. - Mike -- 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: Clojure on iOS devices - Swift as a host?
Not me, but if I needed to build a web app, Cappuccino and Om would be on my list of things to dig into -- 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.
delete-file needs to be vector?
I had the same happen to me several times and then I got wise to it :) It is a correct diagnostic, but it would arguably be better if it could somehow simply indicate “function definition is missing a parameter declaration.” -- 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.
if else list of commands
Also, check out when and when-not, which are great for conditionally executing some imperative code. -- 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.
Functions in data structures?
Is there anything wrong with doing something like this? (def foo (atom {:fn inc})) ((:fn @foo) 1) ; = 2 This works in Clojure and ClojureScript. Just wondering if placing functions into immutable data structures could cause any grief. Or are functions sufficiently “first class” so that this is perfectly fine? -- 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: Clojure on iOS devices - Swift as a host?
While Gal's approach of ditching IB is fine, I still use it, but bind UI components to atoms in ClojureScript. Once that is done, you have a lot of power at your disposal on the ClojureScript side of the JavaScriptCore bridge: With atom watchers you can react to UI state changes, feed them through core.async channels if you'd like to create FRP-like solutions, etc. You can create macros as needed to simplify any complexities that arise with the fact that iOS is on the other side of that bridge. You can nearly have your cake and eat it too :) -- 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: bigint and biginteger
Thanks for the historical perspective, puzzler! In addition to performance considerations, *Clojure Programming* points to an inconsistency between hash codes for longs and BigIntegers as a motivation. Using the example number from that excellent book on Clojure 1.5.1 (on Java 8, FWIW), I can cause this: #{6948736584 (biginteger 6948736584)} ; = #{6948736584 6948736584} #{6948736584 (bigint 6948736584)} ; = IllegalArgumentException Duplicate key: 6948736584 clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56) (System/getProperty java.version) ; = 1.8.0_05 (clojure-version) ; = 1.5.1 On Clojure 1.6, thankfully both fail, even in the face of the inconsistency between .hashCode implementations. If that essentially addresses the 2nd rationale for introducing a special BigInt class, maybe with both things being fixed with Java 8 and Clojure 1.6 BigInteger could come back as the sole arbitrary precision representation of ℤ. -- 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: Clojure on iOS devices - Swift as a host?
Maybe ClojureSwift does have potential, even with respect to *performance* as well: There's decent speculative chatter [1] about Swift’s safety enabling aggressive optimizations that can't be performed in unsafe languages like Objective-C, with Swift outperforming on RC4 and other benchmarks. [1] http://programmers.stackexchange.com/questions/242816/how-can-swift-be-so-much-faster-than-objective-c-in-these-comparisons -- 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.
Clojure on iOS devices - Swift as a host?
I have been experimenting writing an iOS app using ClojureScript embedded in JavaScriptCore, where the ClojureScript essentially implements the logic of my view controllers which drive native UI. So far, this approach seems like a reasonable one to “writing iOS apps using Clojure.” You essentially trade off direct tooling support and gain the ease of developing using ClojureScript (this is important to me, as my server is in Clojure and I can effectively master one language.) -- 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.
Effective Clojure book?
Are there any books yet that prescribe best practices for Clojure, à la Meyers or Bloch? -- 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.
Migrating from 1.5.1 to 1.6 and dependencies
I'm making use of core.async, which specifies 1.6. Does leiningen help with ensuring any libraries I'm using are also compatible with 1.6? I'm concerned that I may have another dependency (perhaps transitive) that is incompatible, perhaps simply by being AOT compiled with 1.5.1. -- 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: Migrating from 1.5.1 to 1.6 and dependencies
Thanks Alex. That's great! My fear of a “dependency yak shave” is unfounded. I noticed the following (once) in my server log file, but have been unable to trace it down not see any ill effects and presumed it could be caused by mixing versions. I'll report if I find anything specific. #NoClassDefFoundError java.lang.NoClassDefFoundError: clojure/core$drop_last$fn__4284 -- 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.
loop/recur being functional
I'm trying to “internalize” loop/recur as being a functional construct. I'm sure I'm not alone in this: I initially struggled with it, with my view unduely influenced by its implementation, especially when multiple loop heads are present. (It could be viewed as vulgar but necessary imperative optimization, playing tricks with the instruction pointer). Here is a line of reasoning that I'm interested in comments on: Take this example: (defn vrange [n] (loop [i 0 v []] (if ( i n) (recur (inc i) (conj v i)) v))) This can be rewritten applying a named inline function that closes over n: (defn vrange2 [n] ((fn loop-recur [i v] (if ( i n) (loop-recur (inc i) (conj v i)) v)) 0 [])) Then, this could be further transformed: (defn loop-recur [i v n] (if ( i n) (loop-recur (inc i) (conj v i)) v)) (defn vrange3 [n] loop-recur 0 [] n) which is clearly functional. I'm cool with this view. It with it, you see recur not so much as as not “jumping” to the nearest loop head, but instead as returning a value that results from ”calling” a function, where that function is kind-of defined by the loop head. I was wondering? Is the above transformation always possible, even given multiple loop heads? Is it always this simple, or are there corner cases that this naïve view misses? -- 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: text processing function
Array destructuring appears to provide what you want with respect to nils (note the extra set of square braces within the argument list): (defn make-map [[fullname lastname firstname middlename]] {:fullname fullname :lastname lastname :firstname firstname :middlename middlename}) (make-map [John Lou Doe Doe John Lou]) ;= {:fullname John Lou Doe, :lastname Doe, :firstname John, :middlename Lou} (make-map [John Lou Doe Doe John]) ;= {:fullname John Lou Doe, :lastname Doe, :firstname John, :middlename nil} (make-map [John Lou Doe Doe]) ;= {:fullname John Lou Doe, :lastname Doe, :firstname nil, :middlename nil} (make-map [John Lou Doe]) ;= {:fullname John Lou Doe, :lastname nil, :firstname nil, :middlename nil} (make-map []) ;= {:fullname nil, :lastname nil, :firstname nil, :middlename nil} (make-map nil) ;= {:fullname nil, :lastname nil, :firstname nil, :middlename nil} On Sunday, June 1, 2014 12:09:35 PM UTC-4, Glen Rubin wrote: I am doing some text processing using clojure and attempting to extract a person's name by regex and then assign it to a map. The result I get takes one of several forms: nil (if i can't find the name) [fullname] [fullname lastname] [fullname lastname firstname] [fullname lastname firstname middlename] now, basically want to assign these entries to a map like so {:fullname some name, :lastname some name, etc...} if there is no entry than I would like to assign it as nil, e.g. {:fullname nil, lastname nil, etc...} I want to code this in the most proper way. I am thinking I need to define a function that works differently based on how long the vector is? How do I turn the contents of the vector into function arguments? 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.
Re: text processing function
Just golfing for fun: (apply hash-map (interleave [:fullname :lastname :firstname :middlename] (concat [John Lou Doe Doe John] (repeat nil ;= {:firstname John, :lastname Doe, :middlename nil, :fullname John Lou Doe} -- 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: text processing function
Hey Glen, it appears that zipmap most directly corresponds to your initial question. The only complicating aspect is your desire for nils, which (concat result (repeat nil)) addresses. (zipmap [:fullname :lastname :firstname :middlename] (concat result (repeat nil))) If it weren't for the need for nils, (zipmap [:fullname :lastname :firstname :middlename] result) is simple and noise-free. Note that the nils are unnecessary if later using map destructuring: (defn use-names [{:keys [fullname lastname firstname middlename]}] (println fullname lastname firstname middlename)) For example, nils are generated at call time for you by the map destructuring: (use-names (zipmap [:fullname :lastname :firstname :middlename] [John Lou Doe Doe John])) ;= John Lou Doe Doe John 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.
core.async variant of some
I want to execute a sequence of database queries (in order) and stop when the first one returns a result. I've set up things so that a query returns a channel that will be populated with the result, and I set up the queries lazily using a for comprehension. A simplified illustrative example of all of this is below. Note that async/to-chan should not even be called for the items beyond the one containing foo. (async/!! (let [chans (for [coll [[] [] [foo] [] [bar]]] (async/to-chan coll))] (async/go (loop [[ch rest] chans] (if-let [val (! ch)] val (when rest (recur rest))) = foo This smells a lot like a core.async variant of some having behavior analogous to the simpler example: (some identity [nil nil foo nil bar]) = foo I'm curious if there already exists a core.async construct that either directly or indirectly matches what I'm trying to do I'd also accept advice that the entire approach is wrong. Lazily evaluating queries (which cause database I/O only when are evaluated) could seem reasonable in blocking / synchronous code, but perhaps there is a much better way to achieve this in a style that is consistent with core.async. -- 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.
symbol grammar
Hey Greg, did your benchmark compare /|[\\D[^/]] to \\D or did it compare the existing Clojure regex to a shortened one, making your substitution? (If it was the former, perhaps the existing regex is more efficient owing to the repetition of the expression /|[\\D[^/]] ). - Mike -- 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-blocking file I/O Clojure library?
Does anyone know of any libraries for Clojure that wrap up non-blocking file I/O? I'm interested in one suitable for use with core.async on Java 7+. Below is a naïve stab at a function that reads file and returns it on a channel. It blocks somewhat (in the open and length calls), but overall, it is trying to be fast and non-blocking enough to usable in one of the core.async worker threads under mild load. Of course, there are lots of things to be concerned about, such as whether it is safe to pass a ByteBuffer across a channel (thread safety concerns), etc. It also puts exceptions on the channel, so the client can use Nolen's ? macro [1]. I'd rather not be solving a problem alone that I believe lots of core.async users will encounter. (def asynch-file-executor (Executors/newFixedThreadPool 8)) (defn read-file [file] (let [ch (async/chan) path (java.nio.file.Paths/get (java.net.URI. file)) fileChannel (AsynchronousFileChannel/open path #{StandardOpenOption/READ} asynch-file-executor (make-array FileAttribute 0)) buffer (ByteBuffer/allocate (.length (.toFile path)))] (.read fileChannel buffer 0 buffer (proxy [CompletionHandler] [] (completed [result _] (.close fileChannel) (.flip buffer) (async/go (async/! ch buffer) (async/close! ch))) (failed [e _] (async/go (async/! ch e) (async/close! ch) ch)) [1] http://swannodette.github.io/2013/08/31/asynchronous-error-handling/ -- 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.
Advice on data structure communication and awareness
I've never used a dynamically-typed language and an issue I've encountered with Clojure is a difficulty with readily seeing the data structures being consumed or returned by functions I'm writing, especially when I come back to them several days later and if those structures get to be somewhat nested or otherwise complex. As a small concrete example, lets say that I currently have a function that accepts data that looks like {:a A :b B} and, at some point I change the internals of the function to instead operate on data that looks like [[:a A] [:b B]]. I could see the docstring communicating that the initial implementation of the function accepts a map, and then perhaps it boils down to finding suitable language to describe the structure in the revised implementation (sequence of pairs, relation, or some other language suitable to the abstraction). I suppose this is no different than the documentation aspect that generics provided in Java when we went from raw types like List to ListString, but, of course, generics can get unwieldy rather quickly with things like ListMapString,SetInteger. Does there exist idiomatic language that developers employ in their docstrings to quickly convey this kind of info? I see that the docstrings for clojure.core are fairly readable, but they tend to operate on very simple data structures. -- 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: Immutable or Effectively Immutable?
In the sample code I pasted, there is nothing to prevent the fill(1) and fill(2) from running concurrently, and essentially write into the same array concurrently. My intent was that the fill(1) be complete before the second thread proceeds. A simple change to have the 1st thread instead fill a temporary byte[] followed by assigning the temporary reference to the static volatile byte[] causes the program to no longer print “false”. This behavior, while it doesn't prove anything, is consistent with the JLS paragraph I quoted. But, it doesn't disprove Alexandru's claim either... -- 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: Expected inconsistency between set and map w/ ArrayList?
To facilitate inlining, the patch calls out to a separate larger method which handles a group of cases. +if(o.getClass().getName().startsWith(java.util.)) +return doalienhasheq(o); +return o.hashCode(); I was wondering whether an efficient improvement is possible that would support things like Guava ImmutableList. In particular, I was wonder which default cases are currently handled by the return o.hashCode() above. Replacing the three lines above with +return doalienhasheq(o); would allow the patch to also handle non-java.util collection implementations, but push the default cases down into the bottom of that method. On Tuesday, May 13, 2014 12:38:54 AM UTC-4, Michał Marczyk wrote: I've posted a patch that makes java.util.{List,Map,Map.Entry,Set} hashes consistent with those of appropriate Clojure collection types on the ticket. -- 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: Nominalization
That's interesting. I haven't learned about reductions yet—I'll check it out. If you consider the following, (defn dot-product [v1 v2] (reduce + (map * v1 v2))) perhaps dot-product would be considered a noun, while since the reduce it is defined in terms of speaks of *how* instead of *what,* is better though of as a verb. I find the concept of the elimination of time interesting. The expression (reduce + (map * [1 2 3] [5 0 1])) brings to mind a tiny machine, while (dot-product [1 2 3] [5 0 1]) feels like a *thing*. But, they both are simply the thing: 8 and perhaps both could be evaluated at compile time, eliminating the time-based machine that mentally cranks away while reduce and map “run.” On Saturday, May 10, 2014 12:52:34 AM UTC-4, Gary Trakhman wrote: Never thought of it that way, I always verb the noun. Did you learn about reductions, yet? It's clear that the name corresponds to the intended output at least in that case. -- 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: How to convert this list into map?
user= (apply hash-map (conj '(:= :language Clojure) :op)) {:op :=, :language Clojure} On Saturday, May 10, 2014 5:56:59 PM UTC-4, Hussein B. wrote: Hi, I have this list: (:= :language Clojure) And I want to convert it to the following map data structure: {:op := , :language Clojure} I can't really think of a clear way how to do it. Would you please help? Thanks for help and time. -- 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: How to convert this list into map?
Here is how you can derive that expression: {:op :=, :language Clojure} is the same as (hash-map :op := :language Clojure) which is the same as (apply hash-map '(:op := :language Clojure)) So, all you need is '(:op := :language Clojure) which can be produced by prepending :op to your original list (conj '(:= :language Clojure) :op) -- 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: How to convert this list into map?
That looks much better IMHO :) -- 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: Immutable or Effectively Immutable?
Thanks Alexandru! That was insightful. :) Even the JLS's (non-normative?) text is confusing IMHO. Section 17.5 ends with this paragraph: The usage model for final fields is a simple one. Set the final fields for an object in that object's constructor. Do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. *It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.* If you read that paragraph, it would lead you to believe the bit in bold would be applicable to the program below. It seems that the key is, as you pointed out, simply extending the concept of this escaping to cover mutable references stored during construction. import java.util.Arrays; public class Main { static class Foo { final byte[] bytes; Foo(byte[] bytes) { this.bytes = bytes; Arrays.fill(this.bytes, (byte) 2); } } static volatile byte[] bytes; static volatile Foo foo; public static void main(String[] args) { new Thread(new Runnable() { public void run() { // Create an array filled with 1s and spin for other thread bytes = new byte[1024*1024]; Arrays.fill(bytes, (byte) 1); while (foo == null) {} // Check to see if we get the array contents set by other thread byte[] expected = new byte[1024*1024]; Arrays.fill(expected, (byte) 2); boolean match = Arrays.equals(expected, foo.bytes); System.out.println(match); // Will print false at times } }).start(); new Thread(new Runnable() { public void run() { // Spin for first thread while (bytes == null) {} // Create an immutable object using bytes, while mutating bytes prior to construction completion and publication foo = new Foo(bytes); } }).start(); } } On Thursday, May 8, 2014 4:43:10 PM UTC-4, Alexandru Nedelcu wrote: On Wed, May 7, 2014 at 6:31 AM, Alex Miller al...@puredanger.comjavascript: wrote: It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ I believe that while JCIP is useful, it is also confusing, because it is trying to explain Java’s memory model in layman’s terms. I recently experienced “enlightenment”, by making an effort to understand how things work at a lower level. Happens-before relationships / ordering guarantees are given by the compiler, in combination with the CPU, with the rules being implied by usage of memory fences (barriers). Without ordering guarantees, several things can happen - the compiler could optimize the code by reordering or eliminating instructions, the CPU might optimize the code by reordering or eliminating instructions and - what bits beginners the most - today’s multi-core CPUs are tricky, as each CPU has a store buffer that’s local to each core (i.e. other cores cannot see it) and published values only become visible to other cores when the store buffer gets flushed to the L1 cache. And you have no guarantee that this flush will *ever* happen, or even after it happens, you have no guarantee that other processors that already have a cached value will make an effort to read the more up-to-date value … unless ordering semantics are enforced. And actually thinking in terms of flushes to memory is dangerous, as nothing you do guarantees a flush - everything being relative, specified in terms of happens-before relationships, implied by memory barriers. And memory barriers are tricky beasts, as they come in multiple shapes and sizes. The JSR 133 Cookbookhttp://gee.cs.oswego.edu/dl/jmm/cookbook.htmlis a useful document for shedding some light on how they work. In particular, for final fields, you get a guarantee for a *StoreStore*memory barrier, like so: x.finalField = v; *StoreStore*; sharedRef = x; This guarantee basically says that the finalFields’ value will always be stored before the write sharedRef
Expected inconsistency between set and map w/ ArrayList?
Perhaps this is a consequence of the hashing changes in 1.6. (http://dev.clojure.org/display/design/Better+hashing) -- 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.
Nominalization
I am new to functional programming and caught myself reading “reduce” as “the reduction of.” Do you experienced Clojure programmers find yourselves thinking in terms of nouns instead of verbs? (Non-temporal expressions as opposed to actions?) Some of the operations reinforce this way of thinking (“range” and “max”) while others don't (“map” and “take”) while some can easily be either (“count” and “mod”) and some that resist being either (“if” and “let”). -- 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: Immutable or Effectively Immutable?
Phil, that's an interesting point. Consider (def x (cons (new java.util.Date) ())) The object identified by x is *mutable*, but if the contained Date will not be modified by the program, then the resulting object can be treated as *effectively immutable, *as you pointed out. But, it would seem that you could pass x to another thread without synchronization, and then safely read the contained Date instance by that thread, because it has been safely published by virtue of having been conveyed by a final field of the Cons instance. Of course, you would run into trouble if you took that Date instance and passed it directly to another thread without synchronization. In other words, you could step outside of the limited profile of the Java memory model that JCIP prescribes treating x as something (useful) between *effectively immutable *and *immutable, *with the end result being that you can treat x as being *immutable.* On Wednesday, May 7, 2014 7:13:31 AM UTC-4, Phillip Lord wrote: Since the data structures and interfaces, they are effectively immutable. Consider this: final public class Cons extends ASeq implements Serializable { private final Object _first; private final ISeq _more; public Cons(Object first, ISeq _more){ this._first = first; this._more = _more; } } Although Cons uses final fields and constructor fields, _more is an ISeq; given that this could be mutable, so could cons. Phil Mike Fikes mike...@me.com javascript: writes: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- Phillip Lord, Phone: +44 (0) 191 222 7827 Lecturer in Bioinformatics, Email: philli...@newcastle.ac.ukjavascript: School of Computing Science, http://homepages.cs.ncl.ac.uk/phillip.lord Room 914 Claremont Tower, skype: russet_apples Newcastle University, twitter: phillord NE1 7RU -- 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: Immutable or Effectively Immutable?
Yep. PersistentVector is *mutable* per the JCIP definition. If it is *mutable* then you need to use locks or synchronization to access its contents. If your program doesn't modify its the vector, it is *effectively immutable. *But, you need to ensure that you safely publish it. But, if you create a PersistentVector, and somehow ensure that the array's contents are never modified, you can pass it freely between threads without synchronization. In short, even though you can't claim that PersistentVector is *immutable*, if you discipline yourself on how you use it, you can pretend that it is. This is a consequence of the use of final on the array field in PersistentVector. On Wednesday, May 7, 2014 10:17:38 AM UTC-4, Andy Fingerhut wrote: Mike, I believe I understand the definition of truly immutable you are using here, and what it means in the JVM as far as synchronization of object values across threads. What seems a bit odd is to use the phrase truly immutable to describe something that is clearly mutable, or at least it is by the definition of mutable: can be modified after construction, which PersistentVector and others can be. Thanks, Andy On Tue, May 6, 2014 at 6:20 PM, Mike Fikes mike...@me.com javascript:wrote: Hi Andy, Marking Java fields as final has semantics with respect to threading, defined in the JLS in section 17.5 ( http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5) If you do this, then it makes it possible to freely pass a truly immutable object instance to another thread and be guaranteed that that other thread will see the value initialized for that field in the constructor. If you don't do this, then the object can still be effectively immutable, which essentially means that you can pass the object to another thread, so long as you do it in a safe manner (using a volatile, or some synchronization mechanism). JCIP helps clarify all of this unfortunately complex topic. The important thing (and key to Closure), is that, if you are implementing the class that you want to be immutable, then if you can mark everything as final, then you truly achieve the benefits immutability give you with concurrency (in short, you need no synchronization whatsoever). If you fail to do this, then you have effective immutability, which is good, but complex and comes with caveats on how you can safely pass objects between threads. JCIP is a great book. But, the approach taken by Clojure makes a lot of the complicated concerns covered by the book largely ignorable, IMHO. On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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 be patient with your first post. To unsubscribe from this group, send email to clojure+u...@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+u...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- 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
Re: Immutable or Effectively Immutable?
I would offer that the key distinction is whether final is used: This prescribes what you must do when using the object. Take Date for example. You can't just pass one directly from one thread to another. The receiving thread could read a date associated with System.currentTimeMillis() of 0. But, String, since it uses final on its char[], fundamentally changes this. (If the final keyword were not present in String, even though you have no way to change its char[], it would be broken with respect to threading semantics.) On Wednesday, May 7, 2014 10:35:04 AM UTC-4, Andy Fingerhut wrote: Sorry if I'm beating a dead horse here. I agree that my example is not using published Clojure APIs, and I never do that kind of thing in a Clojure program, except as an example that PersistentVector's are mutable if you use Java APIs instead of restricting yourself to Clojure APIs. You don't even need to use reflection in Java or know about JVM security policies to mutate them (I am not suggesting that Clojure should be changed in any way here). I've actually got a copy of Java: Concurrency in Practice, and looked up (some of) what they say about immutability. Here is one definition they give of immutability, with some preceding text. I have added emphasis to one phrase: Neither the Java Language Specification nor the Java Memory Model formally defines immutability, but __immutability is *not* equivalent to simply declaring all fields of an object 'final'__. An object whose fields are all final may still be mutable, since final fields can hold references to mutable objects. An object is *immutable* if: + Its state cannot be modified after construction; + All its fields are 'final'; and + It is *properly constructed* (the 'this' reference does not escape during construction). I have no argument with PersistentVector satisfying the 2nd and 3rd bullet points above, but (1) seems not to hold. According to JCIP's definition of effectively immutable (Objects that are not technically immutable, but whose state will not be modified after publication), PersistentVector appears to me to be effectively immutable, but not truly immutable. Andy On Tue, May 6, 2014 at 8:31 PM, Alex Miller al...@puredanger.comjavascript: wrote: Hey Andy, It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ Alex On Tuesday, May 6, 2014 7:35:43 PM UTC-5, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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 be patient with your first post. To unsubscribe from this group, send email to clojure+u...@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+u...@googlegroups.com. For more options
Re: Reduce vs. Comp
I agree with the re-implementing comp sentiment. It reminds me of *A tutorial on the universality and expressiveness of fold http://www.cs.nott.ac.uk/~gmh/fold.pdf *where, essentially lots of standard functions can be defined in terms of reduce which could be considered primitive. In fact, section 5 of that document defines comp as a reduce involving the identify function in some way. (Now, I want to re-read this paper, but translated into Clojure.) On Wednesday, May 7, 2014 9:17:46 AM UTC-4, Mark Watson wrote: What is the difference between: (reduce #(%2 %) 6 [(partial + 12) (partial * -1)]) and ((apply comp [(partial * -1) (partial + 12)]) 6) Using reduce *looks* nicer to me, but I feel like I'm re-implementing comp. Their performance is also the same (go inlining!). -- 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.
Immutable or Effectively Immutable?
Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
Hi Andy, Marking Java fields as final has semantics with respect to threading, defined in the JLS in section 17.5 (http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5) If you do this, then it makes it possible to freely pass a truly immutable object instance to another thread and be guaranteed that that other thread will see the value initialized for that field in the constructor. If you don't do this, then the object can still be effectively immutable, which essentially means that you can pass the object to another thread, so long as you do it in a safe manner (using a volatile, or some synchronization mechanism). JCIP helps clarify all of this unfortunately complex topic. The important thing (and key to Closure), is that, if you are implementing the class that you want to be immutable, then if you can mark everything as final, then you truly achieve the benefits immutability give you with concurrency (in short, you need no synchronization whatsoever). If you fail to do this, then you have effective immutability, which is good, but complex and comes with caveats on how you can safely pass objects between threads. JCIP is a great book. But, the approach taken by Clojure makes a lot of the complicated concerns covered by the book largely ignorable, IMHO. On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comjavascript: wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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 javascript:. For more options, visit https://groups.google.com/d/optout. -- 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: Immutable or Effectively Immutable?
Thanks! I initially saw that the count field of ArrayNode (in PersistentHashMap) is non-final and also mutated in at least one case, and began to question things. But, for that particular example, if that field is only mutated in the case of editing transients, then for the non-transient case ArrayNode is effectively immutable but also safely published by any truly immutable data structures by being referred to in final fields. Excellent! I had to look for myself, and now I feel much more comfortable that Clojure is built upon the bedrock it needs to be :) On Tuesday, May 6, 2014 7:49:07 PM UTC-4, Alex Miller wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Achieving structural sharing when composing data
Thanks Gary, Leif, Alex! I suspected memoization might be the way to go—the leap I needed to make was: writing my own data constructors. On Monday, May 5, 2014 9:10:40 AM UTC-4, Alex Miller wrote: To clarify slightly, the Java Language Specification section 5.1.7 requires that the implementation cache *boxed* ints from -128 to 127, boolean true/false, and characters from \u and \u007f. Because Clojure defaults to boxing in many cases you'll see the same effect. The persistent collections do go through factories and already cache one special case: empty list/vector/set/map. This is also where the choice is made as to the type of persistent map (array or hash impl) based on size ( https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L1457 ). I think in general, there is not enough commonality across programs for the cost of the check to be more costly than the benefits to be saved in memory so this is not something Clojure would ever do generically. But, if this is tradeoff is important to you, then creating your own factory function for collections and memoizing it would be a good way to achieve that. On Sunday, May 4, 2014 10:21:28 PM UTC-5, Leif wrote: The general technique in lisp is called hash consing (a.k.a. flyweight pattern, a.k.a. interning). Java strings, clojure symbols, and keywords are interned. And small integers, apparently. The basic idea is to create memoized versions of all the data constructors and only use them. This is basically what you did in your example and what Gary suggested. So, if you truly wanted something general, you'd probably have to reimplement a lot of clojure.core, or restrict yourself to a small number of constructor fns. If the vectors in your example are the only composite structure that needs sharing, and they represent points, say: (def mk-point (memoize (fn [x y] [x y]))) ; obviously lots of options here (caching strategy, weak refs) (def m1 {:a (mk-point 1 2)}) (def m2 (assoc m1 :b (mk-point 1 2))) (identical? (m2 :a) (m2 :b)) ; = true If the maps themselves need to be shared, you'll have to make your own version of assoc, dissoc, maybe conj into, etc etc, and remember to always use them. It could get complicated. --Leif On Saturday, May 3, 2014 10:27:29 PM UTC-4, Mike Fikes wrote: Are there common techniques or idioms for achieving structural sharing when composing data where equivalences exist? (My motivation is to reduce heap usage for a particular problem I'm working on that involves a lot of repeated data.) As a specific example, consider sharing equivalent map values: (def m1 {:a [1 2]}) (def m2 (assoc m1 :b [1 2])) (identical? (m2 :a) (m2 :b)) ;; = false For this simple example, I can force sharing by introducing a variant of assoc which looks at existing values: (defn assoc-id [map key val] (assoc map key (get (apply hash-set (vals map)) val val))) And using it results in a map with two identical values: (def m3 (assoc-id m1 :b [1 2])) (identical? (m3 :a) (m3 :b)) ;; = true But, of course, this approach could get to be expensive and/or unwieldy if not done carefully. So, I was wondering if there are general techniques in this area. I'm sure I'm not the first to come across it. We already get this automatically for boxing of small integers: (identical? 5 5) ;; = true (identical? 500 500) ;; = false So I suppose I'm essentially looking for the same idea but for larger non-primitive values. -- 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.
Achieving structural sharing when composing data
Are there common techniques or idioms for achieving structural sharing when composing data where equivalences exist? (My motivation is to reduce heap usage for a particular problem I'm working on that involves a lot of repeated data.) As a specific example, consider sharing equivalent map values: (def m1 {:a [1 2]}) (def m2 (assoc m1 :b [1 2])) (identical? (m2 :a) (m2 :b)) ;; = false For this simple example, I can force sharing by introducing a variant of assoc which looks at existing values: (defn assoc-id [map key val] (assoc map key (get (apply hash-set (vals map)) val val))) And using it results in a map with two identical values: (def m3 (assoc-id m1 :b [1 2])) (identical? (m3 :a) (m3 :b)) ;; = true But, of course, this approach could get to be expensive and/or unwieldy if not done carefully. So, I was wondering if there are general techniques in this area. I'm sure I'm not the first to come across it. We already get this automatically for boxing of small integers: (identical? 5 5) ;; = true (identical? 500 500) ;; = false So I suppose I'm essentially looking for the same idea but for larger non-primitive values. -- 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.