Re: [ANN] Clojure 1.9.0-alpha15 is now available
<http://emojipedia.org/thumbs-up-sign/> On Tuesday, March 14, 2017 at 1:45:13 PM UTC-4, Alex Miller wrote: > > Yes, this is a bad use of refer-clojure which fails with the new spec. It > has been fixed and a release job for core.async is waiting on the build box. > > On Tuesday, March 14, 2017 at 12:38:53 PM UTC-5, Dmitri wrote: >> >> looks like the latest core.async fails Spec validation with alpha15: >> >> Caused by: clojure.lang.ExceptionInfo: Call to clojure.core/refer-clojure >> did not conform to spec: >> In: [2] val: (quote :as) fails at: [:args :exclude :op :spec] predicate: >> #{:exclude} >> In: [2 1] val: :as fails at: [:args :exclude :op :quoted-spec :spec] >> predicate: #{:exclude} >> In: [2] val: (quote :as) fails at: [:args :only :op :spec] predicate: >> #{:only} >> In: [2 1] val: :as fails at: [:args :only :op :quoted-spec :spec] >> predicate: #{:only} >> In: [2] val: (quote :as) fails at: [:args :rename :op :spec] predicate: >> #{:rename} >> In: [2 1] val: :as fails at: [:args :rename :op :quoted-spec :spec] >> predicate: #{:rename} >> :clojure.spec/args ((quote :exclude) (quote [reduce transduce into merge >> map take partition partition-by bounded-count]) (quote :as) (quote core)) >> {:clojure.spec/problems ({:path [:args :exclude :op :spec], :pred >> #{:exclude}, :val (quote :as), :via [], :in [2]} {:path [:args :exclude :op >> :quoted-spec :spec], :pred #{:exclude}, :val :as, :via [], :in [2 1]} >> {:path [:args :only :op :spec], :pred #{:only}, :val (quote :as), :via [], >> :in [2]} {:path [:args :only :op :quoted-spec :spec], :pred #{:only}, :val >> :as, :via [], :in [2 1]} {:path [:args :rename :op :spec], :pred >> #{:rename}, :val (quote :as), :via [], :in [2]} {:path [:args :rename :op >> :quoted-spec :spec], :pred #{:rename}, :val :as, :via [], :in [2 1]}), >> :clojure.spec/args ((quote :exclude) (quote [reduce transduce into merge >> map take partition partition-by bounded-count]) (quote :as) (quote core))}, >> compiling:(clojure/core/async.clj:9:1) >> >> >> On Tuesday, March 14, 2017 at 12:39:35 PM UTC-4, Alex Miller wrote: >>> >>> Clojure 1.9.0-alpha15 is now available. >>> >>> Try it via >>> >>> - Download: >>> https://repo1.maven.org/maven2/org/clojure/clojure/1.9.0-alpha15 >>> - Leiningen: [org.clojure/clojure "1.9.0-alpha15"] >>> >>> 1.9.0-alpha15 includes the following changes since 1.9.0-alpha14: >>> >>> - CLJ-1793 - reducer instances hold onto the head of seqs (also applies >>> to a broader set of head-holding cases) >>> - CLJ-2043 - s/form of conformer is broken >>> - CLJ-2035 - s/form of collection specs are broken >>> - CLJ-2100 - s/form of s/nilable should include the original spec, not >>> the resolved spec >>> >>> Specs: >>> >>> - CLJ-2062 - added specs for `import` and `refer-clojure` >>> - CLJ-2114 - ::defn-args spec incorrectly parses map body as a prepost >>> rather than function body >>> - CLJ-2055 - binding-form spec parses symbol-only maps incorrectly >>> >>> Infrastructure: >>> >>> - CLJ-2113 - Clojure maven build updated >>> >> -- 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.9.0-alpha15 is now available
looks like the latest core.async fails Spec validation with alpha15: Caused by: clojure.lang.ExceptionInfo: Call to clojure.core/refer-clojure did not conform to spec: In: [2] val: (quote :as) fails at: [:args :exclude :op :spec] predicate: #{:exclude} In: [2 1] val: :as fails at: [:args :exclude :op :quoted-spec :spec] predicate: #{:exclude} In: [2] val: (quote :as) fails at: [:args :only :op :spec] predicate: #{:only} In: [2 1] val: :as fails at: [:args :only :op :quoted-spec :spec] predicate: #{:only} In: [2] val: (quote :as) fails at: [:args :rename :op :spec] predicate: #{:rename} In: [2 1] val: :as fails at: [:args :rename :op :quoted-spec :spec] predicate: #{:rename} :clojure.spec/args ((quote :exclude) (quote [reduce transduce into merge map take partition partition-by bounded-count]) (quote :as) (quote core)) {:clojure.spec/problems ({:path [:args :exclude :op :spec], :pred #{:exclude}, :val (quote :as), :via [], :in [2]} {:path [:args :exclude :op :quoted-spec :spec], :pred #{:exclude}, :val :as, :via [], :in [2 1]} {:path [:args :only :op :spec], :pred #{:only}, :val (quote :as), :via [], :in [2]} {:path [:args :only :op :quoted-spec :spec], :pred #{:only}, :val :as, :via [], :in [2 1]} {:path [:args :rename :op :spec], :pred #{:rename}, :val (quote :as), :via [], :in [2]} {:path [:args :rename :op :quoted-spec :spec], :pred #{:rename}, :val :as, :via [], :in [2 1]}), :clojure.spec/args ((quote :exclude) (quote [reduce transduce into merge map take partition partition-by bounded-count]) (quote :as) (quote core))}, compiling:(clojure/core/async.clj:9:1) On Tuesday, March 14, 2017 at 12:39:35 PM UTC-4, Alex Miller wrote: > > Clojure 1.9.0-alpha15 is now available. > > Try it via > > - Download: > https://repo1.maven.org/maven2/org/clojure/clojure/1.9.0-alpha15 > - Leiningen: [org.clojure/clojure "1.9.0-alpha15"] > > 1.9.0-alpha15 includes the following changes since 1.9.0-alpha14: > > - CLJ-1793 - reducer instances hold onto the head of seqs (also applies to > a broader set of head-holding cases) > - CLJ-2043 - s/form of conformer is broken > - CLJ-2035 - s/form of collection specs are broken > - CLJ-2100 - s/form of s/nilable should include the original spec, not the > resolved spec > > Specs: > > - CLJ-2062 - added specs for `import` and `refer-clojure` > - CLJ-2114 - ::defn-args spec incorrectly parses map body as a prepost > rather than function body > - CLJ-2055 - binding-form spec parses symbol-only maps incorrectly > > Infrastructure: > > - CLJ-2113 - Clojure maven build updated > -- 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: Luminus in Techempower benchmarks
Sounds fantastic! On Monday, February 29, 2016 at 4:13:53 PM UTC-5, Jim Crossley wrote: > > Sounds good, Dmitri. I'll work up something on a fork in the next few > days and ping you. We can go from there. > > Jim > > > On Mon, Feb 29, 2016 at 2:33 PM, Dmitri <dmitri@gmail.com > > wrote: > > Hi Jim, > > > > I'm the author of Luminus, and I'd love tow work with you to tune up the > > performance. Feel free to ping me via email or on GitHub. > > > > > > On Sunday, February 28, 2016 at 8:17:13 PM UTC-5, Jim Crossley wrote: > >> > >> I just tried a few experiments and realized the :dispatch? option is > >> broken in the latest Immutant release. :( > >> > >> This is a result of some changes we made to better support WebSockets. > >> > >> We were already hoping to get a release out this week, so we'll add > that > >> to the list of fixes. > >> > >> Sorry about that, > >> Jim > >> > >> On Sunday, February 28, 2016 at 1:32:09 PM UTC-5, Jim Crossley wrote: > >>> > >>> Hi, > >>> > >>> Luminus uses Immutant, which uses Undertow, so it should be possible > >>> to tune the Luminus app to approach the performance of the TechEmpower > >>> Undertow app. The relevant options to immutant.web/run [1] are > >>> :dispatch?, :io-threads, and :worker-threads. > >>> > >>> The Undertow app sets IO threads here [2] and worker threads here [3], > >>> so you can easily set those same values in the Luminus app. > >>> > >>> But the real performance bump will come from the :dispatch? option. By > >>> default, :dispatch? is true, i.e. requests handled by threads in the > >>> IO pool are dispatched to a thread in the worker pool. For > >>> compute-bound tasks like the JSON serialization benchmark, that > >>> context switch is far more expensive than just having the IO thread > >>> return the response. So you'd want to set :dispatch? to false in that > >>> case. > >>> > >>> The tricky bit here is that the Luminus app defines all its routes in > >>> a single handler [4]. But for the more io-bound tasks, e.g. > >>> DbSqlHandler [5], you'll want the default true value of :dispatch?. So > >>> in order to get the best results for all the benchmarks, you'll need > >>> to re-organize that app to run two handlers: one that dispatches and > >>> one that doesn't. In Immutant, the simplest way to do this is to > >>> distinguish each handler with a unique :path option. > >>> > >>> I'm happy to assist whoever is maintaining that app with the tuning. > >>> > >>> Thanks, > >>> Jim > >>> > >>> [1] > >>> > http://immutant.org/documentation/current/apidoc/immutant.web.html#var-run > >>> [2] > >>> > https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java#L122 > > >>> [3] > >>> > https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java#L160 > > >>> [4] > >>> > https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Clojure/luminus/hello/src/hello/routes/home.clj#L44 > > >>> [5] > >>> > https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/undertow/src/main/java/hello/DbSqlHandler.java#L38 > > >>> > >>> On Sat, Feb 27, 2016 at 9:40 PM, gvim <gvi...@gmail.com> wrote: > >>> > In the latest round of Techempower benchmarks: > >>> > > >>> > > >>> > > https://www.techempower.com/benchmarks/#section=data-r12=peak=json > >>> > > >>> > ... I was surprised to find Luminus performing no better than Hapi > >>> > (Node) > >>> > and significantly worse than Java frameworks. Figures are > >>> > requests/second: > >>> > > >>> > FORTUNES > >>> > - Hapi: 1.9 > >>> > - Luminus: 0.9 > >>> > - Gemini: 55.5 > >>> > > >>> > JSON SERIALISATION > >>> > - Hapi: 0.3 (Raw db) > >>> > - Luminus: 0.8 > >>> > - Rapidoid: 78.4 > >>> > > >
Re: Luminus in Techempower benchmarks
Hi Jim, I'm the author of Luminus, and I'd love tow work with you to tune up the performance. Feel free to ping me via email or on GitHub. On Sunday, February 28, 2016 at 8:17:13 PM UTC-5, Jim Crossley wrote: > > I just tried a few experiments and realized the :dispatch? option is > broken in the latest Immutant release. :( > > This is a result of some changes we made to better support WebSockets. > > We were already hoping to get a release out this week, so we'll add that > to the list of fixes. > > Sorry about that, > Jim > > On Sunday, February 28, 2016 at 1:32:09 PM UTC-5, Jim Crossley wrote: >> >> Hi, >> >> Luminus uses Immutant, which uses Undertow, so it should be possible >> to tune the Luminus app to approach the performance of the TechEmpower >> Undertow app. The relevant options to immutant.web/run [1] are >> :dispatch?, :io-threads, and :worker-threads. >> >> The Undertow app sets IO threads here [2] and worker threads here [3], >> so you can easily set those same values in the Luminus app. >> >> But the real performance bump will come from the :dispatch? option. By >> default, :dispatch? is true, i.e. requests handled by threads in the >> IO pool are dispatched to a thread in the worker pool. For >> compute-bound tasks like the JSON serialization benchmark, that >> context switch is far more expensive than just having the IO thread >> return the response. So you'd want to set :dispatch? to false in that >> case. >> >> The tricky bit here is that the Luminus app defines all its routes in >> a single handler [4]. But for the more io-bound tasks, e.g. >> DbSqlHandler [5], you'll want the default true value of :dispatch?. So >> in order to get the best results for all the benchmarks, you'll need >> to re-organize that app to run two handlers: one that dispatches and >> one that doesn't. In Immutant, the simplest way to do this is to >> distinguish each handler with a unique :path option. >> >> I'm happy to assist whoever is maintaining that app with the tuning. >> >> Thanks, >> Jim >> >> [1] >> http://immutant.org/documentation/current/apidoc/immutant.web.html#var-run >> [2] >> https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java#L122 >> >> [3] >> https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java#L160 >> >> [4] >> https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Clojure/luminus/hello/src/hello/routes/home.clj#L44 >> >> [5] >> https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/undertow/src/main/java/hello/DbSqlHandler.java#L38 >> >> >> On Sat, Feb 27, 2016 at 9:40 PM, gvimwrote: >> > In the latest round of Techempower benchmarks: >> > >> > >> https://www.techempower.com/benchmarks/#section=data-r12=peak=json >> > >> > ... I was surprised to find Luminus performing no better than Hapi >> (Node) >> > and significantly worse than Java frameworks. Figures are >> requests/second: >> > >> > FORTUNES >> > - Hapi: 1.9 >> > - Luminus: 0.9 >> > - Gemini: 55.5 >> > >> > JSON SERIALISATION >> > - Hapi: 0.3 (Raw db) >> > - Luminus: 0.8 >> > - Rapidoid: 78.4 >> > >> > >> > SINGLE QUERY >> > - Hapi: 2.9 >> > - Luminus: 8.7 >> > - Gemini: 75.8 >> > >> > MULTI-QUERY >> > - Hapi: 33.0 >> > - Luminus: 20.4 >> > - Dropwizard: 65.8 >> > >> > DATA UPDATES >> > - Hapi:20.9 >> > - Luminus: 20.0 >> > - Ninja: 54.7 >> > >> > PLAINTEXT >> > - Hapi:0.7 >> > - Luminus: 0.0 >> > - Rapidoid: 100.0 >> > >> > >> > >> > Any ideas? >> > >> > gvim >> > >> > >> > >> > >> > >> > >> > >> > >> > -- >> > 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 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
Re: Streamlining dev environment startup
The recommended way to manage components in Luminus is using the mount library (https://github.com/tolitius/mount), it's much less intrusive than Component in my opinion and provides most of the same benefits without requiring you to structure your application around it. The latest version of mount has both Clojure and ClojureScript support as well. It's now included in the template by default in recent versions. On Thursday, December 3, 2015 at 5:24:48 AM UTC-5, Sven Richter wrote: > > It definitly is compatible. It just takes some manual work. Like I said, I > started myself with the luminus template and implement components + other > stuff into it. > You can definitly do it and I also recommend it for the sole reason that a > change to the routes in compojure will lead to a restart of the repl. You > can circumvent that by reloading the code base. > It may have changed in the last two years, but then I am not up to date. > > Best Regards, > Sven > > Am Mittwoch, 2. Dezember 2015 22:05:58 UTC+1 schrieb Webdev Tory Anderson: >> >> Maybe I spoke too soon when mentioning incompatibility between Luminus >> and Reloaded. I look forward to taking a closer look at your work! >> >> On Wednesday, December 2, 2015 at 1:49:20 AM UTC-7, Sven Richter wrote: >>> >>> Hi, >>> >>> I based a template on luminus myself and added some stuff. It also >>> contains predefined components so you don't have to add it yourself. >>> You can look how its done here: >>> https://github.com/sveri/closp/tree/master/resources/leiningen/new/closp/clj/components >>> >>> Best Regards, >>> Sven >>> >>> Am Dienstag, 1. Dezember 2015 17:43:41 UTC+1 schrieb Colin Yates: The general idea is to use the ‘reloaded’ pattern, so rather than `lein run` you would have a function which starts and stop the system. You still need to run figwheel and mongo (yay for document databases) as separate processes, although I tend to do those in straight terminals rather than emacs shells as they live longer than my emacs does. You can find more about the reloaded pattern and a prescripted approach to structuring your app here: https://github.com/stuartsierra/component . I think it is fairly common to have: - your major building blocks as components - a specific dev namespace which is only on the :dev profile - fns in that namespace to start/stop components or the entire system There are some libraries which build on the component library: https://github.com/danielsz/system for example. HTH. On 1 Dec 2015, at 16:26, Webdev Tory Andersonwrote: I recently read something hinting at ways of streamlining the startup process for the dev environment, so I'm hoping you good folks can give me some tips. I'm developing a web app in Linux, Clojurescript/Clojure (incidentally using the Luminus architecture). I use emacs (that part's non-negotiable; sorry). The cumbersome startup process I usually have goes like this: M-x shell > mongod # start the mongo daemon > > M-x shell > lein run # start the app and server > > M-x shell > lein figwheel #start CLJS development > > (open a .clj file) > C-c M-c # (cider-connect) > # insert localhost, port num, which proj. to connect to > > This is usually bearable since I only have to do it once or twice a week, but it's definitely the sort of redundancy that would be nice to eliminate. The "lein run" is good to have foregrounded because I can see timbre statements and cleanly reboot when necessary. Figwheel, at the moment, has to be foregrounded because that's where the figwheel prompt ends up (I'd love to have that in Cider somehow, though). Any recommendations on how to chop some of these steps off? -- 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 clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To
Re: [ANN] Let's make clojure.org better!
Just a note that the author of Cryogen is very responsive regarding discussions on improvements and pull requests for additional functionality. If there's a particular feature that's missing it might be worth creating an issue or opening a pr for it. On Tuesday, November 10, 2015 at 10:57:45 AM UTC-5, Alex Miller wrote: > > Hi Hildeberto, > > I built spikes of the site in a number of technologies like Cryogen, > Stasis, Sphinx, Asciidoctor, and some of the other Ruby-based static > generators as well. In the end, I found that JBake was the best match for > our goals at this time. The site build architecture has been decided and > we're not interested in revisiting that at this time. At some point down > the road, based on experience and tool evolution, we may take another look, > but not soon. > > Cryogen is a great tool and I would recommend it to others. One problem I > had with it was its flexibility with respect to the url structure. I > actually think for the purposes of creating a blog etc that is a dimension > that is good to remove, but it was a downside for our use. > > We are working with a designer on the site look and feel and at some point > that will be visible. At the point where that is visible, I expect there > will be some evolution on front page, navigation structure, etc and would > be happy to get feedback on that. > > Right now, we are primarily looking for content ideas and would love > thoughts on that. Or if there is interest in enhancing existing pages, I > would also like to talk about those. > > Thanks, > Alex > > > > On Tuesday, November 10, 2015 at 9:41:40 AM UTC-6, Hildeberto Mendonça > wrote: >> >> That's a great initiative! Thanks! But I'm just sad to see JBake instead >> of Cryogen (https://github.com/cryogen-project/cryogen-core) which is >> written in Clojure :-( Can we send a pull request replacing JBake by >> Cryogen or is JBake a final decision? >> >> -- >> Hildeberto Mendonça, Ph.D >> Blog: http://www.hildeberto.com >> Twitter: https://twitter.com/htmfilho >> > -- 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: Using a dynamic var for my database connection for implicit connections+transactions
What I'm talking about is whether it's a better pattern to leave a repetitive and error prone task to the user or encapsulate it in a single place. The whole discussion boils down to following options. The first option is that we keep functions pure and the connection is passed as a parameter by the person writing the code (the user). With this approach the burden is squarely on the user to remember to pass the correct connection to the function. This becomes error prone for things like transactions where the developer has to pass the transaction connection as opposed to the normal database connection. The worst part in this scenario is that the code will run except it won't run transactionally. This is a bug that is difficult to catch as it only surfaces in cases where the transaction should be rolled back. The alternative is to encapsulate the database connection management in the initialization logic in the namespace managing the connection. This way the query functions can be context aware and ensure that the correct connection is used automatically. I simply disagree that leaving repetitive and error prone tasks to the developer as opposed to encapsulating them centrally is a better pattern. I certainly don't see that as a feature. On Wednesday, August 5, 2015 at 8:19:38 AM UTC-4, James Gatannah wrote: On Monday, August 3, 2015 at 10:21:09 PM UTC-5, Dmitri wrote: My understanding is that the problem is actually caused by the stateless nature of the functions. You're talking about database interactions. By definition, those are not stateless. The trick is to isolate this statefulness as much as possible. Expanding it just compounds the problem. Since the function accepts the connection as a parameter it's up to the user of the function to ensure that it's passed the correct connection. That depends on what you mean by user of the function. If I'm working on the web server front-end, I shouldn't have any idea about the database connection. I should describe what I want to happen. If I have any concept that multiple databases are involved (I shouldn't, but abstractions leak), then, yes, I have to specify which one I mean. This isn't complicated. It's up to the person writing the database back-end code (also possibly me, if we're talking about a start-up, but then we aren't talking about the 200 KLOC scenario) to turn that description into the side-effects. Every functional solution presented in this thread suffers from this same fundamental problem that the function is not aware of the context it's being run in. That isn't a problem: it's a feature. It doesn't matter what language or programming paradigm you're using in this context. This cuts across problem domains and architectures. The actual database interaction code should be as brain-dead simple (not easy) and bullet-proof as you can possibly make it. And it should be as isolated from the front-end code as you can get away with making it. That isn't a right answer. But it's a good rule of thumb. And you should have very hefty reservations (and very good reasons) about violating it. Respectfully, James -- 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: Using a dynamic var for my database connection for implicit connections+transactions
I agree that wrapping the functions is a sensible approach. Using wrap-transaction is precisely how I ended up doing it with the conman yesql wrapper https://github.com/luminus-framework/conman The approach I took there is to have the generated functions use the connection atom, and have with-transaction rebind it to the transactional connection within its scope. However, the functions also accept an explicit connection, and with-transaction also provides explicit access to the transactional connection: (with-transaction [t-conn conn] (jdbc/db-set-rollback-only! t-conn) (create-user! {:id foo :first_name Sam :last_name Smith :email sam.sm...@example.com}) (get-user {:id foo})) This approach works for testing, since the connection can be passed explicitly, but I would argue that in practice it's better to use a separate test database instead of the dev instance. On Wednesday, August 5, 2015 at 11:11:19 AM UTC-4, James Reeves wrote: On 5 August 2015 at 14:03, Dmitri dmitri@gmail.com javascript: wrote: What I'm talking about is whether it's a better pattern to leave a repetitive and error prone task to the user or encapsulate it in a single place. The whole discussion boils down to following options. The first option is that we keep functions pure and the connection is passed as a parameter by the person writing the code (the user). With this approach the burden is squarely on the user to remember to pass the correct connection to the function. This becomes error prone for things like transactions where the developer has to pass the transaction connection as opposed to the normal database connection. The worst part in this scenario is that the code will run except it won't run transactionally. This is a bug that is difficult to catch as it only surfaces in cases where the transaction should be rolled back. It's worth pointing out that you don't need to use dynamic or global vars to avoid this scenario. You could just remove the original database connection from scope: (defn foobar* [tx] (foo tx) (bar tx)) (defn foobar [db] (sql/with-transaction [tx db] (foobar* tx)) Or shadow the original binding: (defn foobar [db] (sql/with-transaction [db db] (foo db) (bar db))) Ideally you also want a way of testing this behaviour, even with dynamic or global scope. If it's critical to your application that database operations run in a transaction, you should have a way of verifying that. For instance, you might use a protocol to factor out the operations on the database: (defprotocol Database (wrap-transaction [db f]) (foo db) (bar db)) (defn foobar [db] (wrap-transaction db (fn [tx] (foo tx) (bar tx This allows tests to be written to verify that foo and bar are called within wrap-transaction, and to verify our production implementation of the protocol correctly wraps the function f in a SQL transaction. If you're writing something that depends upon behaviour that can't be verified, you're going to run into problems no matter how you structure your application. The alternative is to encapsulate the database connection management in the initialization logic in the namespace managing the connection. This way the query functions can be context aware and ensure that the correct connection is used automatically. Do you mean storing the database connection in a global var, not just a dynamically scoped one? In such a case, how do you run tests without wiping the development database? Do you run the tests in a separate process, or shut down the dev server before running tests, or do you not mind if your development database is cleared by your tests? - James -- 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: Using a dynamic var for my database connection for implicit connections+transactions
There are a number of options here depending on your workflow. You could override the dynamic var, create a separate connection for tests and pass it around explicitly in test code, or get the connection from the environment. The last option is what I tend to do, the profiles.clj will contain separate URLs for testing and dev databases: {:profiles/dev {:env {:database-url jdbc:postgresql://localhost/myapp_dev?user=db_user_name_herepassword=db_user_password_here}} :profiles/test {:env {:database-url jdbc:postgresql://localhost/myapp_test?user=db_user_name_herepassword=db_user_password_here}}} The tests run in the test profile and so get the test database connection from the environment. On Wednesday, August 5, 2015 at 2:34:31 PM UTC-4, James Reeves wrote: On 5 August 2015 at 18:04, Dmitri dmitri@gmail.com javascript: wrote: I agree that wrapping the functions is a sensible approach. Using wrap-transaction is precisely how I ended up doing it with the conman yesql wrapper https://github.com/luminus-framework/conman The approach I took there is to have the generated functions use the connection atom, and have with-transaction rebind it to the transactional connection within its scope. However, the functions also accept an explicit connection, and with-transaction also provides explicit access to the transactional connection So when you're testing, presumably you use a dynamic binding to override the global connection to the test database? - James -- 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: Using a dynamic var for my database connection for implicit connections+transactions
While I generally agree that purity is something to strive for, I think it's also important to consider the problem that's being solved in each particular scenario. While creating stateless database query functions and passing the connection round explicitly achieves purity, it's not entirely clear what practical problem that's addressing. However, the practical disadvantages are that you end up with is additional variable being passed around and more opportunities for user error as is the case with transactions. While there is mental overhead in having to understand that the functions use an implicit connection, there's conversely additional mental overhead in having to remember what connection to use when with the explicit approach. In some applications it might be valuable to pass the database around explicitly. Yet, many of the applications in the wild tend to deal with a single database instance where a connection is created when the application is started and retained for the lifecycle of the application. Creating the additional hoops for the user to jump through for purely theoretical benefit seems unwarranted in this scenario. On Monday, August 3, 2015 at 6:48:05 PM UTC-4, Rob Lally wrote: Hey Pablo, Sorry, you are completely correct: I accidentally typed transaction when I meant connection. My bad. I don’t understand what you mean by connections having to be global when dealing with an RDBMS. It is true that you normally want to pool them to conserve resources, and that pooling may be global in nature - but it also may not be. Quality of Service demands often necessitate multiple pools to the same data-source to be created and accessed independently. You also, sometimes, want to access different databases from the same application, that gets much harder - and your code becomes less general if you need to reference specific global connection-pools. I’m also a little confused by your suggestion that it would be impossible to enclose each test in a transaction. The article you point to shows one way. Another way I’ve used often is to declare a var holding a ref and in a fixture initialise/close a connection around the test. The test function then derefences the var holding the connection passing it into the function under test. This does make it impossible to run tests in parallel, but that’s not something I’ve ever tried. Creating tests that access shared resources is a little bit uglier than in a OO language where you could more easily reference an instance variable but it isn’t much worse, and a little macro-pixie dust can make it all go away. I will say that it has been my experience that you don’t find yourself passing database connection pools around everywhere. As your code grows you naturally extract components/protocols that wrap all that up. Your ring-handler doesn’t need a connection it needs some sort of data-access component. That component needs a connection/connection pool but that can be passed in at construction time. I have feared the creation of functions that need an ever increasing number of parameters that need to be passed on, but it isn’t something I find happens in practice. Of course, YMMV. I would respectfully suggest that the solutions are not the same. My way has no global state and functional purity-lite (those connections are rarely idempotent): which are obviously only theoretical benefits. But it does work when I do it; I like my code, I don’t have problems working with it, and I genuinely don’t face any of the challenges you’re struggling with. R. On 3 Aug 2015, at 03:19, J. Pablo Fernández pup...@pupeno.com javascript: wrote: Rob, The transactions are not global, the transactions are local. Connections are global and there's no way around it with the constraints of a traditional RDBMs. Your idea of making the global connection unavailable for code that's in the context of a transaction would prevent the errors I'm trying to prevent but you would still required to pass the connection around, which in a webapp, means that the whole chain of function calls, pretty much everything, would have a database connection. That is ugly in some cases, impossible in others. A piece of code that would be impossible is to enclose each test in a transaction using clojure.test: http://stackoverflow.com/questions/31735423/how-to-pass-a-value-from-a-fixture-to-a-test-with-clojure-test Furthermore, I don't think this solution gains you any purity, you still have a global estate and you are hiding it away when starting a transaction. My proposal was to make it work instead of hiding it. They are rather equivalent from the complexity point of view. -- 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
Re: Using a dynamic var for my database connection for implicit connections+transactions
My understanding is that the problem is actually caused by the stateless nature of the functions. Since the function accepts the connection as a parameter it's up to the user of the function to ensure that it's passed the correct connection. Every functional solution presented in this thread suffers from this same fundamental problem that the function is not aware of the context it's being run in. On Monday, August 3, 2015 at 10:16:28 PM UTC-4, Rob Lally wrote: Everything you say is true. And programming is always about picking the right trade-offs at the right time, making this sort of conversation one that can never come to a *right* answer. But… in this case Pablo was experiencing concrete problems: those problems stemmed from how easy it was to make mistakes having both a global connection pool and the option to pass around specific connections which had transactions open. Having two conflicting ways of doing the same thing was causing problems. Eliminating at least one of them is a solution. Pablo felt that he might want to eliminate both and add a new mechanism. A number of people (including me) felt that Pablo’s proposed solution would, potentially, lead to new problems and that eliminating only one of the original mechanisms would be sufficient to solve his problems. In a very real sense, the pragmatic solution and the most “pure” solution seem - to me at least - to be the same. R. On 3 Aug 2015, at 18:19, Dmitri dmitri@gmail.com javascript: wrote: While I generally agree that purity is something to strive for, I think it's also important to consider the problem that's being solved in each particular scenario. While creating stateless database query functions and passing the connection round explicitly achieves purity, it's not entirely clear what practical problem that's addressing. However, the practical disadvantages are that you end up with is additional variable being passed around and more opportunities for user error as is the case with transactions. While there is mental overhead in having to understand that the functions use an implicit connection, there's conversely additional mental overhead in having to remember what connection to use when with the explicit approach. In some applications it might be valuable to pass the database around explicitly. Yet, many of the applications in the wild tend to deal with a single database instance where a connection is created when the application is started and retained for the lifecycle of the application. Creating the additional hoops for the user to jump through for purely theoretical benefit seems unwarranted in this scenario. On Monday, August 3, 2015 at 6:48:05 PM UTC-4, Rob Lally wrote: Hey Pablo, Sorry, you are completely correct: I accidentally typed transaction when I meant connection. My bad. I don’t understand what you mean by connections having to be global when dealing with an RDBMS. It is true that you normally want to pool them to conserve resources, and that pooling may be global in nature - but it also may not be. Quality of Service demands often necessitate multiple pools to the same data-source to be created and accessed independently. You also, sometimes, want to access different databases from the same application, that gets much harder - and your code becomes less general if you need to reference specific global connection-pools. I’m also a little confused by your suggestion that it would be impossible to enclose each test in a transaction. The article you point to shows one way. Another way I’ve used often is to declare a var holding a ref and in a fixture initialise/close a connection around the test. The test function then derefences the var holding the connection passing it into the function under test. This does make it impossible to run tests in parallel, but that’s not something I’ve ever tried. Creating tests that access shared resources is a little bit uglier than in a OO language where you could more easily reference an instance variable but it isn’t much worse, and a little macro-pixie dust can make it all go away. I will say that it has been my experience that you don’t find yourself passing database connection pools around everywhere. As your code grows you naturally extract components/protocols that wrap all that up. Your ring-handler doesn’t need a connection it needs some sort of data-access component. That component needs a connection/connection pool but that can be passed in at construction time. I have feared the creation of functions that need an ever increasing number of parameters that need to be passed on, but it isn’t something I find happens in practice. Of course, YMMV. I would respectfully suggest that the solutions are not the same. My way has no global state and functional purity-lite (those connections are rarely idempotent): which are obviously only
Re: ANN: ClojureScript 0.0-3255 - pretty printer latest Closure Compiler / Library
Is there possibly anything else missing in the package, figwheel doesn't appear to find the repl ns. lein figwheel Retrieving org/clojure/clojurescript/0.0-3269/clojurescript-0.0-3269.pom from central Retrieving org/clojure/clojurescript/0.0-3269/clojurescript-0.0-3269.jar from central Exception in thread main java.io.FileNotFoundException: Could not locate cljs/repl__init.class or cljs/repl.clj on classpath: , compiling:(figwheel_sidecar/repl.clj:1:1) On Sunday, May 10, 2015 at 10:20:13 AM UTC-4, David Nolen wrote: Just cut 0.0-3269 which adds the missing analysis and source map bits back into the artifacts. It also cleans up :libs support and fixes a related regression with Closure compatible libraries that follow classpath conventions (like transit-js). Both :libs Closure libraries and classpath aware Closure compatible libraries now enjoy REPL support. David On Sun, May 10, 2015 at 9:41 AM, David Nolen dnolen...@gmail.com javascript: wrote: It appears there are still some important bits missing from the artifacts. Working through the issues and will cut a release soon. David On Sun, May 10, 2015 at 12:22 AM, Rangel Spasov rasp...@gmail.com javascript: wrote: Hey guys, 0.0-3264 fails for me with: clojure.lang.ExceptionInfo: failed compiling file:resources/public/js/compiled/out/cljs/core.cljs at clojure.core$ex_info.invoke (core.clj:4591) Caused by: java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil at clojure.core$_cache_protocol_fn.invoke (core_deftype.clj:554) 0.0-3255 seems fine. @raspasov On Saturday, May 9, 2015 at 12:33:52 PM UTC-7, David Nolen wrote: Just released 0.0-3264, it fixes a critical issue where .js files were missing from the artifacts due to the changed build. Also included are a several fixes around the :libs feature, REPLs, and stack trace mapping. David On Fri, May 8, 2015 at 3:23 PM, David Nolen dnolen...@gmail.com wrote: ClojureScript, the Clojure compiler that emits JavaScript source code. README and source code: https://github.com/clojure/clojurescript Leiningen dependency information: [org.clojure/clojurescript 0.0-3255] A big thanks goes out to Jonathan Boston and Shaun Lebron for this release. Thanks to their efforts ClojureScript now includes a full port of clojure.pprint under the cljs.pprint namespace. This was the last major namespace in need of porting to ClojureScript. The release also bumps several dependencies: Clojure 1.7.0-beta2, tools.reader 0.9.2, Closure Compiler v20150505, and Closure Library 0.0-20150505-021ed5b3. This release also fixes some regressions around async testing, docstring REPL support, arglist meta, and more. As always feedback welcome! ## 0.0-3255 ### Changes * Update Closure Library dependency * CLJS-1252: Update Closure Compiler Dependency to v20150505 * .clj - .cljc for important analysis / compilation bits * add public cljs.compiler.api namespace * CLJS-1224: cljs.repl: Memoize stack frame mapping * depend on tools.reader 0.9.2 ### Enhancements * add cljs.pprint/pp macro * CLJS-710: port clojure.pprint * CLJS-1178: Compiler does not know Math ns is not not-native * add getBasis methods to deftype and defrecord ctors a la Clojure JVM * support ^long and ^double type hints ### Fixes * fix cljs-1198 async testing regression * CLJS-1254: Update REPL browser agent detection CLJS-1253: Create/Use new Closure Library Release * CLJS-1225: Variadic function with same name as parent function gives runtime error in advanced compile mode. * CLJS-1246: Add cljs.core/record? predicate. * CLJS-1239: Make eduction variadic. * CLJS-1244: tagged-literal precondition check missing wrapping vector * CLJS-1243: Add TaggedLiteral type related fns * CLJS-1240: Add cljs.core/var? * CLJS-1214: :arglists meta has needless quoting CLJS-1232: bad arglists for doc, regression * CLJS-1212: Error in set ctor for 8-entry map literal * CLJS-1218: Syntax quoting an alias created with :require-macros throws ClassCastException * CLJS-1213: cljs.analyzer incorrectly marks all defs as tests when eliding test metadata * CLJS-742: Compilation with :output-file option set fails -- 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 javascript: 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
Re: Clojure needs a web framework with more momentum
Luminus uses a minimal amount of generated code. It completely embraces the composable library approach. The difference from rolling your own each time is that it provides some structure and it's a curated set of libraries that are known to work well together. On Tuesday, May 5, 2015 at 3:46:09 AM UTC-4, Dan Kersten wrote: On Monday, May 4, 2015 at 4:41:02 AM UTC-4, Sven Richter wrote: One potential problem with this web framework as app template approach is upgrade-ability. When 2.0 of your framework comes out, what happens to an app generated from 1.0 that wants to benefit from the new capabilities? This is the reason I don't use Luminus or Modularity or others that rely heavily on leiningen template-based codegen. Its very difficult to upgrade the generated code, especially if you've had to add to or modify it. I'm experimenting with an approach that would generate only the project.clj file and directory structure (putting everything else into libraries), but don't yet have anything to release (my code is currently very targeted at my own use case, but in time I'd like to generalize it a bit and let others at 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.
Re: Clojure needs a web framework with more momentum
One way I could see this working is having a more opinionated profile like +site or something that sets up an app with authentication, logins, a default model and so on. I would definitely support merging the efforts on this front. Ping me by email, and we can try figure out the details. :) On Tuesday, May 5, 2015 at 1:27:21 AM UTC-4, Sven Richter wrote: Hi Dmitri, When I was building closp I was taking luminus as the base for it with some minor adoptions. I just had a look at the website of luminus and saw the massive amount of work you put into the documentation again. If that sounds reasonable for you I'd like to try to move closp and closp-crud to luminus as an opionated part of it. So if you call lein new luminus projectname +closp you will basically get what you get now with closp. You can look here for the additions: https://github.com/sveri/closp. I would like to maintain that branch. I am not sure if that will work out the way I think, but I'd like to evaluate it at least. It would be nice to have a common base and a common documentation for it. Best Regards, Sven Am Dienstag, 5. Mai 2015 02:38:41 UTC+2 schrieb Dmitri: As others have pointed out the comparison isn't really valid. Luminus intentionally aims to leverage existing libraries that are maintained independently whenever possible. I've been doing web dev with Clojure for the past 4 years and overall I do prefer the approach of using composable libraries over monolithic frameworks. With the Clojure web stack it's much easier to tell what's actually happening during the request/response lifecycle as things tend to be explicit. With frameworks like Rails a lot of stuff happens implicitly and requires a lot of in depth knowledge to work with effectively. However, there are a some downsides to the libraries over frameworks approach as well. The biggest issue is that it's difficult to track what libraries are actively maintained and which ones play nicely together. Since most libraries are maintained by individuals it's common for them to become abandoned. Another problem is that each app becomes a unique snowflake since there aren't a lot of established patterns for structuring them. Finally, security is an issue for Clojure web apps as a lot of it done in rather ad hoc fashion. While this works great for people who are well versed in the Clojure web ecosystem it's a huge barrier for newcomers. I think that the best way to address the problem is via organizations where related projects are maintained by groups of contributors. This helps discovery of projects, and it helps spread the burden of maintenance for them. This approach is already working in the wild on GitHub with Ring, Reagent, and Luminus orgs. Meanwhile, Leiningen templates are a great way to provide reasonable defaults for different types of applications and can be used to address issues such as security. Also, I'm certainly open to contributions for Luminus. I moved it to an org recently and new members would be very welcome. :) On Saturday, May 2, 2015 at 4:43:53 PM UTC-4, g vim wrote: I recently did some research into web frameworks on Github. Here's what I found: FRAMEWORK LANG CONTRIBUTORS COMMITS LuminusClojure28678 CaribouClojure 2275 BeegoGolang991522 PhoenixElixir 1241949 YesodHaskell 1303722 LaravelPHP2684421 PlayScala 4176085 SymfonyPHP113020914 RailsRuby 269151000 One could conclude from this that the Clojure community isn't that interested in web development but the last Clojure survey suggests otherwise. Clojure's library composition approach to everything only goes so far with large web applications, as Aaron Bedra reminded us in March last year: www.youtube.com/watch?v=CBL59w7fXw4 . Less manpower means less momentum and more bugs. Furthermore, I have a hunch that Clojure's poor adoption as indicated by Indeed.com maybe due to this immaturity in the web framework sphere. Why is it that Elixir, with a much smaller community and lifespan than Clojure's, has managed to put 4 times as much mindshare into its main web framework when its module output, as measured by modulecounts.com, is a tiny fraction of Clojure's? gvim -- 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
Re: Clojure needs a web framework with more momentum
As others have pointed out the comparison isn't really valid. Luminus intentionally aims to leverage existing libraries that are maintained independently whenever possible. I've been doing web dev with Clojure for the past 4 years and overall I do prefer the approach of using composable libraries over monolithic frameworks. With the Clojure web stack it's much easier to tell what's actually happening during the request/response lifecycle as things tend to be explicit. With frameworks like Rails a lot of stuff happens implicitly and requires a lot of in depth knowledge to work with effectively. However, there are a some downsides to the libraries over frameworks approach as well. The biggest issue is that it's difficult to track what libraries are actively maintained and which ones play nicely together. Since most libraries are maintained by individuals it's common for them to become abandoned. Another problem is that each app becomes a unique snowflake since there aren't a lot of established patterns for structuring them. Finally, security is an issue for Clojure web apps as a lot of it done in rather ad hoc fashion. While this works great for people who are well versed in the Clojure web ecosystem it's a huge barrier for newcomers. I think that the best way to address the problem is via organizations where related projects are maintained by groups of contributors. This helps discovery of projects, and it helps spread the burden of maintenance for them. This approach is already working in the wild on GitHub with Ring, Reagent, and Luminus orgs. Meanwhile, Leiningen templates are a great way to provide reasonable defaults for different types of applications and can be used to address issues such as security. Also, I'm certainly open to contributions for Luminus. I moved it to an org recently and new members would be very welcome. :) On Saturday, May 2, 2015 at 4:43:53 PM UTC-4, g vim wrote: I recently did some research into web frameworks on Github. Here's what I found: FRAMEWORK LANG CONTRIBUTORS COMMITS LuminusClojure28678 CaribouClojure 2275 BeegoGolang991522 PhoenixElixir 1241949 YesodHaskell 1303722 LaravelPHP2684421 PlayScala 4176085 SymfonyPHP113020914 RailsRuby 269151000 One could conclude from this that the Clojure community isn't that interested in web development but the last Clojure survey suggests otherwise. Clojure's library composition approach to everything only goes so far with large web applications, as Aaron Bedra reminded us in March last year: www.youtube.com/watch?v=CBL59w7fXw4 . Less manpower means less momentum and more bugs. Furthermore, I have a hunch that Clojure's poor adoption as indicated by Indeed.com maybe due to this immaturity in the web framework sphere. Why is it that Elixir, with a much smaller community and lifespan than Clojure's, has managed to put 4 times as much mindshare into its main web framework when its module output, as measured by modulecounts.com, is a tiny fraction of Clojure's? gvim -- 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} Aleph 0.4.0 released, plus Manifold, Dirigiste, and a whole host of other libraries
I'd like to add Aleph to the Luminus template and I was wondering if there's an equivalent of dev mode available for other servers where it watches for changes in source and reloads them. I did a cursory look but didn't spot anything like a -dev option. On Friday, April 17, 2015 at 5:06:30 PM UTC-4, Zach Tellman wrote: Hey all, In preparation for Clojure/West, I'm formally releasing the latest Aleph and the libraries that surround it. Aleph 0.4.0 has been running in production at Factual for half a year now, and across a variety of services is handling at peak 600k HTTP requests/sec (spread across 15-20 machines). Since the landscape of Clojure HTTP servers is pretty crowded these days, it's worth taking some time to explain how Aleph differs. To be clear, most Clojure deployments likely use Jetty, and should continue to do so. However, Aleph has some unique properties: * It uses the Netty library, which is a high-performance and very battle-tested network layer for the JVM * It is the only HTTP server that has *ubiquitous* asynchronous streams wherever data can be received or sent (all other libraries can only represent streaming requests using InputStreams, or like http-kit don't support streaming HTTP requests at all) * It is the only server that has a WebSocket implementation with any support for per-connection backpressure. I won't make this post even longer by going into why this is important, but this will be a central theme of my talk at Clojure/West next week if you're interested in hearing more. * It uses consistent abstractions to represent network connections over a variety of protocols, which makes it straightforward to use the same application logic for all of them. Again, none of these points mean you should immediately drop whatever you're using and move over to Aleph instead. However, I do feel it represents the only (current) good option for using core.async or a similar stream abstraction to represent network data, which is an idea a number of people seem to be playing with lately. Some examples of this can be found at http://ideolalia.com/aleph/literate.html. A full list of the libraries: aleph - https://github.com/ztellman/aleph - uses the excellent Netty library to expose HTTP, TCP, and UDP using a consistent asynchronous stream representation. manifold - https://github.com/ztellman/manifold - an unopinionated stream representation designed to cleanly interoperate with other stream representations (Clojure's seqs, core.async channels, Java's BlockingQueues, and others). This is the base stream representation for all network sources and sinks in Aleph. dirigiste - https://github.com/ztellman/dirigiste - a pure-Java library that provides instrumented, dynamically sized thread and object pools. This is used for thread pools in Aleph's HTTP server, and for connection pools in Aleph's HTTP client. byte-streams - https://github.com/ztellman/byte-streams - a means of translating any byte representation into another. Want to turn a core.async channel that emits byte-arrays into an InputStream, or maybe the other way around? Look no further. The library's conversion mechanism is extensible, which is used in Aleph to make Netty's custom byte representations interoperable with more familiar representations. byte-transforms - https://github.com/ztellman/byte-transforms - a curated collection of byte compression, hashing, and encoding mechanisms, which can work on anything byte-streams can convert. While all these libraries are used in concert to create Aleph, I've been very careful to make sure any of them can be used by themselves. If anyone has questions about them, the best place to get my attention is the Aleph mailing list: https://groups.google.com/forum/#!forum/aleph-lib. I will be mentioning some of these libraries at my upcoming Clojure/West talk (http://clojurewest.org/speakers#ztellman), but I've also set aside an Unsession for specifically discussing these libraries: https://github.com/clojurewest/clojurewest2015/wiki/Unsessions. If you're interested, please add your name to the list. Zach -- 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] ring-access-rules library
https://github.com/yogthos/ring-access-rules Friend is a great library, but it's definitely not easy to get into and I found it can actually make the workflow logic difficult to follow in some cases. My experience has been that for apps I work on all I want is to apply a decision function to a route to see if it should be accessible. The decision logic really tends to be application specific. It's easy to write a custom access control function for a specific scenario, but it's difficult to make a generic one that works well for any scenario. This library provides a simple way to associate access control functions with routes and leaves the workflow up to the user. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] ring-access-rules library
That does look rather similar actually, and it looks like buddy does a lot more as well. I guess that validates the approach, I'll have to see if it fits all my use cases. :) On Tuesday, December 9, 2014 2:43:42 PM UTC-5, Andrey Antukh wrote: Hi Dmitri! If I understand it well, is a very similar system already implemented in buddy: http://niwibe.github.io/buddy/#_access_rules_system http://www.google.com/url?q=http%3A%2F%2Fniwibe.github.io%2Fbuddy%2F%23_access_rules_systemsa=Dsntz=1usg=AFQjCNFhCj_anD1ohvV4MbWGgBmSj3OGng Regards. Andrey. 2014-12-09 19:11 GMT+01:00 Dmitri dmitri@gmail.com javascript:: https://github.com/yogthos/ring-access-rules Friend is a great library, but it's definitely not easy to get into and I found it can actually make the workflow logic difficult to follow in some cases. My experience has been that for apps I work on all I want is to apply a decision function to a route to see if it should be accessible. The decision logic really tends to be application specific. It's easy to write a custom access control function for a specific scenario, but it's difficult to make a generic one that works well for any scenario. This library provides a simple way to associate access control functions with routes and leaves the workflow up to the user. -- 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 javascript: 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. -- Andrey Antukh - Андрей Антух - andrei@kaleidos.net javascript: / ni...@niwi.be javascript: http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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] ring-access-rules library
I'm definitely up for that, if I knew about buddy I wouldn't have started the lib in the first place. :) I found friend to be a bit too complex for what I needed in the apps I was writing as well. I originally added the access restriction logic to lib-noir, but recently I started considering deprecating it in favor of standalone libraries for all the functionality that it bundles. Buddy looks like a perfect solution for web app security. I only see a couple of small differences in functionality. Buddy requires a handler function, while I opted for allowing a static redirect URI as an alternative. I allow specifying a vector of uri patterns for each set of rules. I'm also using Clout (https://github.com/weavejester/clout) for request matching instead of plain regex. All of these are very minor differences however. I think I'll be moving Luminus over to use Buddy instead lib-noir for security. :) On Tuesday, December 9, 2014 4:13:44 PM UTC-5, Andrey Antukh wrote: Would be awesome join forces, and If you miss something that you library is already support, let me know, and we can integrate it in buddy. I have made buddy because I'm little frustrate with friend approach (is good but not convinced me). Regards. Andrey 2014-12-09 21:30 GMT+01:00 Dmitri dmitri@gmail.com javascript:: That does look rather similar actually, and it looks like buddy does a lot more as well. I guess that validates the approach, I'll have to see if it fits all my use cases. :) On Tuesday, December 9, 2014 2:43:42 PM UTC-5, Andrey Antukh wrote: Hi Dmitri! If I understand it well, is a very similar system already implemented in buddy: http://niwibe.github.io/buddy/#_access_rules_system http://www.google.com/url?q=http%3A%2F%2Fniwibe.github.io%2Fbuddy%2F%23_access_rules_systemsa=Dsntz=1usg=AFQjCNFhCj_anD1ohvV4MbWGgBmSj3OGng Regards. Andrey. 2014-12-09 19:11 GMT+01:00 Dmitri dmitri@gmail.com: https://github.com/yogthos/ring-access-rules Friend is a great library, but it's definitely not easy to get into and I found it can actually make the workflow logic difficult to follow in some cases. My experience has been that for apps I work on all I want is to apply a decision function to a route to see if it should be accessible. The decision logic really tends to be application specific. It's easy to write a custom access control function for a specific scenario, but it's difficult to make a generic one that works well for any scenario. This library provides a simple way to associate access control functions with routes and leaves the workflow up to the user. -- 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. -- Andrey Antukh - Андрей Антух - andrei@kaleidos.net / ni...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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 javascript: 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. -- Andrey Antukh - Андрей Антух - andrei@kaleidos.net javascript: / ni...@niwi.be javascript: http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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
Re: [ANN] ring-access-rules library
It really looks fantastic, I'll do the integration in Luminus this weekend and let you know how that goes. :) On Tuesday, December 9, 2014 4:50:51 PM UTC-5, Andrey Antukh wrote: 2014-12-09 22:35 GMT+01:00 Dmitri dmitri@gmail.com javascript:: I'm definitely up for that, if I knew about buddy I wouldn't have started the lib in the first place. :) I found friend to be a bit too complex for what I needed in the apps I was writing as well. I originally added the access restriction logic to lib-noir, but recently I started considering deprecating it in favor of standalone libraries for all the functionality that it bundles. Buddy looks like a perfect solution for web app security. I only see a couple of small differences in functionality. Buddy requires a handler function, while I opted for allowing a static redirect URI as an alternative. I allow specifying a vector of uri patterns for each set of rules. I'm also using Clout (https://github.com/weavejester/clout) for request matching instead of plain regex. All of these are very minor differences however. Are minor differences but if them are useful, maybe them should be implemented in buddy. I'll review in detail the implementation of your library and extract from them that parts for buddy. I'll try to do it this weekend. Until weekend I will stay very busy :( I think I'll be moving Luminus over to use Buddy instead lib-noir for security. :) Oh, great notice! I'm repeating, if you find something missing, let me know! Regards. Andrey. On Tuesday, December 9, 2014 4:13:44 PM UTC-5, Andrey Antukh wrote: Would be awesome join forces, and If you miss something that you library is already support, let me know, and we can integrate it in buddy. I have made buddy because I'm little frustrate with friend approach (is good but not convinced me). Regards. Andrey 2014-12-09 21:30 GMT+01:00 Dmitri dmitri@gmail.com: That does look rather similar actually, and it looks like buddy does a lot more as well. I guess that validates the approach, I'll have to see if it fits all my use cases. :) On Tuesday, December 9, 2014 2:43:42 PM UTC-5, Andrey Antukh wrote: Hi Dmitri! If I understand it well, is a very similar system already implemented in buddy: http://niwibe.github.io/buddy/#_access_rules_system http://www.google.com/url?q=http%3A%2F%2Fniwibe.github.io%2Fbuddy%2F%23_access_rules_systemsa=Dsntz=1usg=AFQjCNFhCj_anD1ohvV4MbWGgBmSj3OGng Regards. Andrey. 2014-12-09 19:11 GMT+01:00 Dmitri dmitri@gmail.com: https://github.com/yogthos/ring-access-rules Friend is a great library, but it's definitely not easy to get into and I found it can actually make the workflow logic difficult to follow in some cases. My experience has been that for apps I work on all I want is to apply a decision function to a route to see if it should be accessible. The decision logic really tends to be application specific. It's easy to write a custom access control function for a specific scenario, but it's difficult to make a generic one that works well for any scenario. This library provides a simple way to associate access control functions with routes and leaves the workflow up to the user. -- 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. -- Andrey Antukh - Андрей Антух - andrei@kaleidos.net / ni...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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. -- Andrey Antukh - Андрей Антух - andrei@kaleidos.net / ni...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe
Re: Releasing Caribou today: Open Source Clojure Web Ecosystem
I notice you're using a fairly old version of markdown-clj [markdown-clj 0.9.19] The current version is [markdown-clj 0.9.35] so that should address a lot of formatting issues. :) On Wednesday, November 13, 2013 2:09:10 PM UTC-5, Ryan Spangler wrote: Brian, Thanks for the heads up! I fixed some of the formatting issues I found, I'll keep a lookout for this issue (using a md-html converter which apparently requires spaces at the end of lines in lists?) And yes, data modeling is one of our main concerns. All models are also data, which means they can be manipulated like any other data structure. This is what enables us to generate the admin and api automatically! (as well as a host of other benefits) On Wednesday, November 13, 2013 8:07:52 AM UTC-8, Brian Craft wrote: Looks very cool. I'm happy to see that data modeling is taken seriously, which in my experience is the biggest piece lacking in other clojure web tools. The docs have a lot of layout problems with words running together, like so: data from oneenvironment. Looks like a string joining operation that's not quite right. On Tuesday, November 12, 2013 3:52:10 PM UTC-8, Ryan Spangler wrote: Hello Clojure, Excited to announce today the release of Caribou! http://let-caribou.in/ We have been building web sites and web applications with it for over two years now and improving it every day. Currently we have four people working on it and another ten using it to build things, so it is getting a lot of real world testing. It has been designed as a collection of independent libraries that could each be useful on their own, but which come together as a meaningful whole. We have been spending the last couple months getting it ready for a full open source release, and I am happy to say it is finally ready. Funded and supported by Instrument in Portland, OR: http://weareinstrument.com/ We have four projects using it in production, and several more about to be launched (as well as over a dozen internal things). Documentation is here: http://caribou.github.io/caribou/docs/outline.html Source is here: http://github.com/caribou/caribou (use this for issues, you don't actually need the source as it is installed through a lein template). Some of the independently useful libraries Caribou is built on are: * Polaris -- Routing with data (not macros) and reverse routing! : https://github.com/caribou/polaris * Lichen -- Image resizing to and from s3 or on disk: https://github.com/caribou/lichen * Schmetterling -- Debugging Clojure processes from the browser: https://github.com/prismofeverything/schmetterling * Antlers -- Useful extensions to mustache templating (helpers and blocks, among other things): https://github.com/caribou/antlers * Groundhog -- Replay http requests: https://github.com/noisesmith/groundhog And many others. Basically this is an Alpha release, and I am announcing it here first in order to get as much feedback from the community as possible. We have made it as useful as we can for our purposes and recognize that for it to improve from here, we really need as many people using it and building things with it as possible. The documentation also needs to be put through its paces: we need to see how well people are able to use it who know nothing about it, based only on the existing docs. All feedback welcome! Thanks for reading! I hope you find it useful. -- -- 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/groups/opt_out.
Re: Full stack Clojure web/REST framework - is there any mileage in it?
I think a lot of the issues can be addressed via a good template which sets up all the boiler plate, demonstrates idiomatic usage, and defaults to some common libraries. I'm actively working on filling this gap with the Luminushttp://www.luminusweb.net/, which aims to make it easy to get rolling, and sets up all the basic things like sessions, static resources, packaging, etc. On Friday, January 11, 2013 11:52:05 AM UTC-5, Paul Umbers wrote: I've been experimenting with Clojure web services recently, and posting the work on GitHub https://github.com/3rddog/doitnow and my bloghttp://internistic.blogspot.ca/search/label/clojure . When putting this test app together, it occurred to me that most other languages have a full-stack API available which makes life easier when it comes to making decisions about which libraries/APIs/frameworks to use. It also reduces the possibility of impedance mismatch between the libraries. For Java, you can use Spring (or any one of a dozen or more other popular frameworks), for Scala there's Typesafe, and so on. Clojure has Compojure, Ring, several logging, validation and database libraries, and they can be used together but they don't constitute a coordinated full stack - and that creates issues. For example, the latest vesion of Compojure (1.1.3) uses Ring 1.1.5 and not the latest version of Ring (1.1.6) which has significantly better util functions available - but I can't use them until Compojure catches up. By the time you add logging, validation, data access, etc the odds of a mismatch between these libraries goes up dramatically. This is a concern, because these mismatches must be worked around in *my*code and are likely to break as the libraries are upgraded in future versions. So, I'm having to spend my time maintaining what are essentially patches for third-party libraries just so that they work together. Now, it may not be the best decision to try to put together a true full-stack framework from scratch, but is it worth choosing a bunch of existing frameworks and coordinating their releases - in much the same way as Eclipse coordinates plugin releases for major releases - so that putting together a full-stack app becomes easier? Projects taking part in the meta-project will work together to harmonize their functionality APIs, and coordinate their development cycles releases so that the meta-framework remains consistent and easily usable. Is this another barrier to adoption the Clojure community can remove? Is this even a barrier? Am I missing something? Thoughts? [Also posted to http://www.reddit.com/r/Clojure] -- 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
CDS tutorials
Hi, I saw the new ClojureDocs site and I'd like to contribute some tutorials I've made on setting up the environment and making web apps. I have a tutorial on using Eclipse and CounterClockwise at https://www.yogthos.net/blog/18-Setting+up+Eclipse+for+Clojure and I've got an extensive Noir tutorial here https://www.yogthos.net/blog/22-Noir+tutorial+-+part+1 if they look useful I'd be glad to add them. Cheers, Dmitri -- 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
Re: clj-pdf for declarative PDF generation (status update)
That's a good point, it would make the API more idiomatic I suppose. On 2012-06-11, at 01:45 , Baishampayan Ghose wrote: On Sun, Jun 10, 2012 at 10:16 PM, Dmitri dmitri.sotni...@gmail.com wrote: The reason I'm using strings for values is to make it easier to work with deserialized JSON. Currently I have it running as a service that our internal applications send a JSON request and get a PDF document back. Internally you can call `name` on the arguments, that way the user can pass in either a string or a keyword. Regards, BG -- Baishampayan Ghose b.ghose at gmail.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 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
Re: clj-pdf for declarative PDF generation (status update)
And it's been updated as per suggestion, thanks for the tip. On 2012-06-11, at 01:45 , Baishampayan Ghose wrote: On Sun, Jun 10, 2012 at 10:16 PM, Dmitri dmitri.sotni...@gmail.com wrote: The reason I'm using strings for values is to make it easier to work with deserialized JSON. Currently I have it running as a service that our internal applications send a JSON request and get a PDF document back. Internally you can call `name` on the arguments, that way the user can pass in either a string or a keyword. Regards, BG -- Baishampayan Ghose b.ghose at gmail.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 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
clj-pdf for declarative PDF generation (status update)
The goal of clj-pdf is to provide a straight forward way to generate PDFs using markup similar to hiccup. It tries to do the right thing by default, so all styling hints are optional. It's getting some production use at the moment, and there don't appear to be any issues so far. https://github.com/yogthos/clj-pdf Any suggestions or feature requests are welcome. :) -- 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
Re: clj-pdf for declarative PDF generation (status update)
The reason I'm using strings for values is to make it easier to work with deserialized JSON. Currently I have it running as a service that our internal applications send a JSON request and get a PDF document back. On Sunday, June 10, 2012 12:25:39 PM UTC-4, Moritz Ulrich wrote: Looks cool! Unfortunately I currently don't have the time to have a deep look at it. However, I have a small comment on the api: Many parameters like 'style', 'size', 'orientation', etc. use strings for their values. I think keywords would be a better fit there. On Sun, Jun 10, 2012 at 5:59 PM, Dmitri dmitri.sotni...@gmail.com wrote: The goal of clj-pdf is to provide a straight forward way to generate PDFs using markup similar to hiccup. It tries to do the right thing by default, so all styling hints are optional. It's getting some production use at the moment, and there don't appear to be any issues so far. https://github.com/yogthos/clj-pdf Any suggestions or feature requests are welcome. :) -- 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 -- Moritz Ulrich -- 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
Re: a library I'm working on for generating PDFs from Clojure
It should be pretty easy to map some basic Hiccup tags to this, headings, paragraphs, lists, and tables, etc. I suspect it's probably easier to go the hiccup-pdf route, as you could simply ignore the html tags that aren't applicable. On Apr 19, 4:45 am, David Jagoe davidja...@gmail.com wrote: Hi Dmitri, This is great, thanks! I have a system where I need to render web reports to nicely formatted PDFs. Currently I maintain separate HTML and TeX templates for this purpose (in a Python system) but wanted to have a system that allows me to write hiccup once and have it output HTML PDF reports. I see that you've used the hiccup syntax but obviously your tags are different because screen and print media have different nature. I suppose it would be possible for me to write HTML-hiccup and have a translator that writes pdf-hiccup subset that contains the same content. Or maybe the other way around - write pdf-hiccup and translate to html-hiccup. Do you have an idea of which would be better? I.e. which has richer semantics that could be dropped during translation? Thanks! David 2012/4/19 Vinzent ru.vinz...@gmail.com: Thank you, I was looking for something exactly like that! I'll give it a try. ÞÅÔ×ÅÒÇ, 19 ÁÐÒÅÌÑ 2012šÇ., 7:34:10 UTC+6 ÐÏÌØÚÏ×ÁÔÅÌØ Dmitri ÎÁÐÉÓÁÌ: I poked around and noticed that there aren't any libraries for creating PDFs, and as I needed to make one for work I decided to open source it. I tried to follow Hiccup syntax as I find it to be nice and flexible. https://github.com/yogthos/clj-pdf The library piggy backs on iText 2.1.7 (the last LGPL release) and JFreeChart, it's able to generate documents with text formatting, lists, tables, and charts. I've also made a proof of concept service which accepts JSON formatted text and serves up PDFs that's built on top of it. https://github.com/yogthos/instant-pdf Feedback and suggestions are welcome. -- 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 -- David Jagoe davidja...@gmail.com +447535268218 -- 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
Re: a convenience idea for test functions
That is an excellent point, and the macro is actually a very nice approach, thanks for the help. On Apr 18, 1:07 am, Sean Corfield seancorfi...@gmail.com wrote: On Tue, Apr 17, 2012 at 9:16 PM, Dmitri dmitri.sotni...@gmail.com wrote: (map? foo bar baz) would return bar if foo is a map and baz otherwise. To elaborate on Alan's response, consider: (if (map? foo) (/ bar 0) baz) If map? were 'merely' a variadic function, (map? foo (/ bar 0) baz) would fail because (/ bar 0) would be evaluated and then passed as an argument, along with foo and baz. So, no, the simple answer is that you can't just make the test functions variadic and get the same behavior as an if form (hence Alan's suggestion of a macro-generating macro to create new macros for the forms you want). (Apologies if I'm laboring the point here) -- Sean A Corfield -- (904) 302-SEAN An Architect's View --http://corfield.org/ World Singles, LLC. --http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- 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
a library I'm working on for generating PDFs from Clojure
I poked around and noticed that there aren't any libraries for creating PDFs, and as I needed to make one for work I decided to open source it. I tried to follow Hiccup syntax as I find it to be nice and flexible. https://github.com/yogthos/clj-pdf The library piggy backs on iText 2.1.7 (the last LGPL release) and JFreeChart, it's able to generate documents with text formatting, lists, tables, and charts. I've also made a proof of concept service which accepts JSON formatted text and serves up PDFs that's built on top of it. https://github.com/yogthos/instant-pdf Feedback and suggestions are welcome. -- 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
a convenience idea for test functions
Often times I find myself writing code like the following (if (map? foo) bar baz) would it make sense to make test functions variadic, so if only passed a single argument it would return true/false, but could also act as an if when passed 3 arguments, eg: (map? foo bar baz) would return bar if foo is a map and baz otherwise. -- 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
Re: Servlet question
Thanks this does seem to solve the problem of the servlet being reinitialized on every run. On Oct 10, 11:10 pm, Adrian Cuthbertson adrian.cuthbert...@gmail.com wrote: Hi Dmitri, The problem is probably related to calling init with args. It requires that super() gets called - I can't remember where I saw the documentation, but here's an example of what works for me. The following is a generic servlet which gets passed a clojure namespace name as an init parameter at init time which is saved in an atom. Then on each service call, it parses the servlet path and uses the ipath (first component of the url after the context), along with the ns name from the atom to load a clj namespace (once) and call a function called ipath passing it the req and rsp. The clj fn cn then handle the method type, GET, POST, etc and has access to all the servlet stuff. This way you have a servlet as a gateway to a clj ns and the function called determined by the req url... (ns svlt.Svlt (import (javax.servlet.http HttpServlet HttpServletRequest HttpServletResponse HttpSession) (javax.servlet ServletConfig) ) (:gen-class :extends javax.servlet.http.HttpServlet :state state :init clinit)) (defn -clinit [] [[] (atom (hash-map))]) (defn -init-void [this] ; NB - careful, must rather call init() (void) than with the cfg args. ; If with args, must call .super() which is problematic (let [;cfg (.getServletConfig this) ns-nm (.getInitParameter this app-ns)] (println :Svlt :init :ns-nm ns-nm) (swap! (.state this) assoc :ns-nm ns-nm))) (defn -service [this #^HttpServletRequest req #^HttpServletRequest rsp] (let [cpath (.getContextPath req) spath (.getServletPath req) ipath (.getPathInfo req) _ (println :Svlt :cpath cpath :spath spath :ipath ipath) ns-nm (get @(.state this) :ns-nm) _ (println :Svlt :ns-nm ns-nm) _ (when (nil? ns-nm) (throw (java.io.IOException. (str No app-ns param found in Svlt config: spath ipath (if (or (nil? ipath) (= ipath )) root ipath) ipath (if (.startsWith ipath /) (.substring ipath 1) ipath) ns-sym (symbol ns-nm) _ (println :ns-sym ns-sym :ipath-now ipath) found-ns (find-ns ns-sym) found-ns (if (nil? found-ns) (let [n (create-ns ns-sym)] (require ns-sym) n) found-ns) _ (when (nil? found-ns) (throw (java.io.IOException. (str Namespace not found for: ns-sym req-fn (get (ns-publics ns-sym) (symbol ipath)) ] (req-fn req rsp))) -Hth, Adrian -- 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
Servlet question
I noticed an odd thing when making a servlet (ns jms.myservlet (import (javax.servlet.http HttpServlet HttpServletRequest HttpServletResponse)) (:gen-class :extends javax.servlet.http.HttpServlet)) (defn -init [ args] (println +++ init ran with args: args)) (defn -doGet [_ #^HttpServletRequest request #^HttpServletResponse response] (println +++ in doGet) (.. response (getWriter) (println (str htmlbodyhello/body/html I've deployed the above on glassfish, and every time the page is hit the init is run: [#|2010-10-10T14:50:20.116-0400|INFO|glassfish3.0.1| javax.enterprise.system.std.com.sun.enterprise.v3.services.impl| _ThreadID=34;_ThreadName=Thread-1;|+++ init ran with args: (#myservlet jms.myserv...@38f2601a #StandardWrapperFacade org.apache.catalina.core.standardwrapperfac...@49d618db) |#] [#|2010-10-10T14:50:20.116-0400|INFO|glassfish3.0.1| javax.enterprise.system.std.com.sun.enterprise.v3.services.impl| _ThreadID=34;_ThreadName=Thread-1;|+++ in doGet |#] [#|2010-10-10T14:50:24.572-0400|INFO|glassfish3.0.1| javax.enterprise.system.std.com.sun.enterprise.v3.services.impl| _ThreadID=34;_ThreadName=Thread-1;|+++ init ran with args: (#myservlet jms.myserv...@38f2601a #StandardWrapperFacade org.apache.catalina.core.standardwrapperfac...@49d618db) |#] [#|2010-10-10T14:50:24.573-0400|INFO|glassfish3.0.1| javax.enterprise.system.std.com.sun.enterprise.v3.services.impl| _ThreadID=34;_ThreadName=Thread-1;|+++ in doGet |#] A servlet is supposed to be run once when the page is loaded and stick around until destroy is called, which is the case with a Java servlet. What am I doing wrong in implementing the servlet, so that the Clojure one is reloaded every time it's accessed? -- 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
Re: date serialization in clojure-contrib json
So I made a change which allows passing a map of deserializers instead of having them initialized globally, it's more or less the same as the previous version otherwise, let me know if you feel it makes the reader too complex http://gist.github.com/565764 here's sample usage with that approach (defn write-date [date #^PrintWriter out] (.print out (str \ (.format (new java.text.SimpleDateFormat MMM dd, hh:mm:ss a) date) \))) (extend Date Write-JSON {:write-json write-date}) (def deserializers {:age #(.parse (new java.text.SimpleDateFormat MMM dd, hh:mm:ss a) %)}) (defn read-json-from-str [input] (read-json input true true nil deserializers)) (let [data {:name John :age (new java.util.Date) :address [:street 1 Bay :city Toronto]} encoded (json-str data)] (println encoded encoded) (println decoded (read-json-from-str encoded))) output: encoded {name:John,age:Sep 05, 2010 01:04:02 AM,address: [street,1 Bay,city,Toronto]} decoded {:name John, :age #Date Sun Sep 05 01:04:02 EDT 2010, :address [street 1 Bay city Toronto]} On Sep 3, 3:17 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: No. I'm talking about collisions when multiple deserialization functions are added from different sources. It cannot be a global setting. -S On Sep 3, 1:28 pm, Dmitri dmitri.sotni...@gmail.com wrote: The problem I was trying to avoid is having to do a second pass over the data after it comes out of the parser, it's more expensive and it's also ugly for nested data structures. Would using defonce- and defmacro- from clojure-contrib address the problem with namespace collisions? On Sep 3, 12:01 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: You can already extend the Write-JSON protocol to any type. But it doesn't work in reverse. JSON has no standardized way to express types beyond Object/Array/String/Number, so any deserialization will always be application-specific. -S On Sep 3, 8:58 am, Baishampayan Ghose b.gh...@gmail.com wrote: Sorry, I can't accept any patch that modifies behavior globally. What happens when two different libraries try to parse JSON with different deserializers? The only thing I would consider is a function that is passed into read- json and invoked in read-json-object. But even that seems like adding unnecessary complication to the library. Just curious, but does using protocols in clojure.contrib.json help? May be people can extend the protocol to their types and make them serializable to JSON and vice versa? Regards, BG -- Baishampayan Ghose b.ghose at gmail.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
Re: date serialization in clojure-contrib json
The problem I was trying to avoid is having to do a second pass over the data after it comes out of the parser, it's more expensive and it's also ugly for nested data structures. Would using defonce- and defmacro- from clojure-contrib address the problem with namespace collisions? On Sep 3, 12:01 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: You can already extend the Write-JSON protocol to any type. But it doesn't work in reverse. JSON has no standardized way to express types beyond Object/Array/String/Number, so any deserialization will always be application-specific. -S On Sep 3, 8:58 am, Baishampayan Ghose b.gh...@gmail.com wrote: Sorry, I can't accept any patch that modifies behavior globally. What happens when two different libraries try to parse JSON with different deserializers? The only thing I would consider is a function that is passed into read- json and invoked in read-json-object. But even that seems like adding unnecessary complication to the library. Just curious, but does using protocols in clojure.contrib.json help? May be people can extend the protocol to their types and make them serializable to JSON and vice versa? Regards, BG -- Baishampayan Ghose b.ghose at gmail.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
Re: date serialization in clojure-contrib json
That's a very good point, I can't think of a good way to address that off top of my head, I agree that passing in a function isn't really great either. On Sep 3, 3:17 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: No. I'm talking about collisions when multiple deserialization functions are added from different sources. It cannot be a global setting. -S On Sep 3, 1:28 pm, Dmitri dmitri.sotni...@gmail.com wrote: The problem I was trying to avoid is having to do a second pass over the data after it comes out of the parser, it's more expensive and it's also ugly for nested data structures. Would using defonce- and defmacro- from clojure-contrib address the problem with namespace collisions? On Sep 3, 12:01 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: You can already extend the Write-JSON protocol to any type. But it doesn't work in reverse. JSON has no standardized way to express types beyond Object/Array/String/Number, so any deserialization will always be application-specific. -S On Sep 3, 8:58 am, Baishampayan Ghose b.gh...@gmail.com wrote: Sorry, I can't accept any patch that modifies behavior globally. What happens when two different libraries try to parse JSON with different deserializers? The only thing I would consider is a function that is passed into read- json and invoked in read-json-object. But even that seems like adding unnecessary complication to the library. Just curious, but does using protocols in clojure.contrib.json help? May be people can extend the protocol to their types and make them serializable to JSON and vice versa? Regards, BG -- Baishampayan Ghose b.ghose at gmail.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
Re: date serialization in clojure-contrib json
I added the *deserializers* atom, converted read-json-object to a macro (def *deserializers* (atom {})) (defn add-deserializer [k deserializer] (swap! *deserializers* #(assoc % k deserializer))) (defn remove-deserializer [k] (swap! *deserializers* #(dissoc % k))) (defmacro get-object-reader [] (let [store '(recur (.read stream) nil (assoc! result (if keywordize? (keyword key) key) element)) deserialize-store '(let [elm-key (if keywordize? (keyword key) key) deserializer (get @*deserializers* elm-key)] (recur (.read stream) nil (assoc! result elm-key (if deserializer (deserializer element) element store-and-recur (if (empty? @*deserializers*) deserialize- store store)] `(fn [#^PushbackReader ~'stream ~'keywordize?] ;; Expects to be called with the head of the stream AFTER the ;; opening bracket. (loop [~'i (.read ~'stream), ~'key nil, ~'result (transient {})] (let [~'c (char ~'i)] (cond (= ~'i -1) (throw (EOFException. JSON error (end-of- file inside object))) (Character/isWhitespace ~'c) (recur (.read ~'stream) ~'key ~'result) (= ~'c \,) (recur (.read ~'stream) nil ~'result) (= ~'c \:) (recur (.read ~'stream) ~'key ~'result) (= ~'c \}) (if (nil? ~'key) (persistent! ~'result) (throw (Exception. JSON error (key missing value in object :else (do (.unread ~'stream ~'i) (let [~'element (read-json-reader ~'stream ~'keywordize? true nil)] (if (nil? ~'key) (if (string? ~'element) (recur (.read ~'stream) ~'element ~'result) (throw (Exception. JSON error (non-string key in object ~store-and-recur) and changed read-json-reader to use get-object-reader at the start of the loop (defn- read-json-reader ([#^PushbackReader stream keywordize? eof-error? eof-value] (loop [i (.read stream) object-reader (get-object-reader)] (let [c (char i)] (cond ;; Handle end-of-stream (= i -1) (if eof-error? (throw (EOFException. JSON error (end-of- file))) eof-value) ;; Ignore whitespace (Character/isWhitespace c) (recur (.read stream) object- reader) these are the only changes that are needed and should preserve the default case, while allowing to extend object reader with custom deserializers, would this solution be acceptable? On Aug 24, 8:21 pm, Dmitri dmitri.sotni...@gmail.com wrote: I understand the desire to keep the parser clean, but at the same time the ability to register custom data deserializers would be very convenient. Would something like the following help with the performance issue, since if no deserializers were registered there would only be a one time penalty for selecting the object reader? (defn- read-json-reader ([#^PushbackReader stream keywordize? eof-error? eof-value] (loop [i (.read stream) object-reader (if (empty? @*deserializers*) read-json- object read-json-object-and-deserialize)] On Aug 24, 6:51 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: On Aug 23, 9:03 pm, Dmitri dmitri.sotni...@gmail.com wrote: Would there be an issue with adding something like that to the contrib? I don't want to add anything that impacts performance in the plain parsing case. -S -- 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
Re: date serialization in clojure-contrib json
I posted the complete file on github here http://gist.github.com/549771 -- 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
Re: date serialization in clojure-contrib json
I understand the desire to keep the parser clean, but at the same time the ability to register custom data deserializers would be very convenient. Would something like the following help with the performance issue, since if no deserializers were registered there would only be a one time penalty for selecting the object reader? (defn- read-json-reader ([#^PushbackReader stream keywordize? eof-error? eof-value] (loop [i (.read stream) object-reader (if (empty? @*deserializers*) read-json- object read-json-object-and-deserialize)] On Aug 24, 6:51 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: On Aug 23, 9:03 pm, Dmitri dmitri.sotni...@gmail.com wrote: Would there be an issue with adding something like that to the contrib? I don't want to add anything that impacts performance in the plain parsing case. -S -- 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
Re: date serialization in clojure-contrib json
Transforming the data after it comes out of the parser can be cumbersome with complex data structures though, it would be nice to have a way for the parser to return the data in the desired format. I updated clojure.contrib.json with the ability to add custom deserializers: (def *deserializers* (atom {})) (defn add-deserializer [k deserializer] (swap! *deserializers* #(assoc % k deserializer))) (defn remove-deserializer [k] (swap! *deserializers* #(dissoc % k))) (defn- read-json-object [#^PushbackReader stream keywordize?] ;; Expects to be called with the head of the stream AFTER the ;; opening bracket. (loop [i (.read stream), key nil, result (transient {})] (let [c (char i)] (cond (= i -1) (throw (EOFException. JSON error (end-of-file inside object))) (Character/isWhitespace c) (recur (.read stream) key result) (= c \,) (recur (.read stream) nil result) (= c \:) (recur (.read stream) key result) (= c \}) (if (nil? key) (persistent! result) (throw (Exception. JSON error (key missing value in object :else (do (.unread stream i) (let [element (read-json-reader stream keywordize? true nil)] (if (nil? key) (if (string? element) (recur (.read stream) element result) (throw (Exception. JSON error (non-string key in object (let [elm-key (if keywordize? (keyword key) key) deserializer (get @*deserializers* elm- key)] (recur (.read stream) nil (assoc! result elm-key (if deserializer (deserializer element) element))) all I had to change was the part where the key and value are put in the map to first check if there is a deserializer registered and use it instead of storing the data directly, then I can use it as follows (defn write-date [date #^PrintWriter out] (.print out (str \ (.format (new java.text.SimpleDateFormat MMM dd, hh:mm:ss a) date) \))) (extend Date Write-JSON {:write-json write-date}) (add-deserializer :age #(.parse (new java.text.SimpleDateFormat MMM dd, hh:mm:ss a) %)) (let [data {:name John :age (new java.util.Date) :address [:street 1 Bay :city Toronto]} encoded (json-str data)] (println encoded) (println decoded (read-json encoded))) Would there be an issue with adding something like that to the contrib? On Aug 21, 1:52 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: I suppose one could override the (private) read-json-object function to transform maps after they are read, based on the presence of certain keys. But that would seriously complicate the reader. It's probably easier to transform the data after it comes back from the JSON parser. -S On Aug 20, 5:06 pm, Dmitri dmitri.sotni...@gmail.com wrote: My concern is more to do with the reader, I think extending writer works quite well, it would be nice if it was possible to do the same thing with the reader, so you could specify how to deserialize specific types of data. Right now it seems to be baked into read-json- reader and there's no easy way to extend it. Maybe it could be possible to specify how to deserialize data based on the key names, then if the reader hits a key with the given name it would try to deserialize it with the given function or something? On Aug 20, 3:32 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: Since there is no standard for how to represent dates in JSON, it is unlikely to be built in. But you can extend the writer with application-specific date formats. -S On Aug 20, 2:15 pm, Dmitri dmitri.sotni...@gmail.com wrote: I'm currently using Dan Larkin's clojure-json, and it provides a way to serialize and deserialize dates, it also provides the option to specify custom serializers, eg: (defn date-encoder [date writer pad current-indent start-token-indent indent- size] (.append writer (str start-token-indent \ date \))) I was looking at switching to using the json implementation in clojure- contrib, but noticed that it doesn't handle dates nor does it provide a way to register custom serializers, is there a plan to implement that in the future, or is the proper approach to simply extend Write- JSON whenever a custom serializer/deserializer is needed. -- 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
date serialization in clojure-contrib json
I'm currently using Dan Larkin's clojure-json, and it provides a way to serialize and deserialize dates, it also provides the option to specify custom serializers, eg: (defn date-encoder [date writer pad current-indent start-token-indent indent- size] (.append writer (str start-token-indent \ date \))) I was looking at switching to using the json implementation in clojure- contrib, but noticed that it doesn't handle dates nor does it provide a way to register custom serializers, is there a plan to implement that in the future, or is the proper approach to simply extend Write- JSON whenever a custom serializer/deserializer is needed. -- 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
Re: date serialization in clojure-contrib json
Extending the writer is pretty trivial (defn write-date [date] (.format (new java.text.SimpleDateFormat MMM dd, hh:mm:ss a) date)) (extend Date Write-JSON {:write-json write-date}) but it seems like deserializing a date wouldn't be quite so trivial. -- 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
Re: date serialization in clojure-contrib json
My concern is more to do with the reader, I think extending writer works quite well, it would be nice if it was possible to do the same thing with the reader, so you could specify how to deserialize specific types of data. Right now it seems to be baked into read-json- reader and there's no easy way to extend it. Maybe it could be possible to specify how to deserialize data based on the key names, then if the reader hits a key with the given name it would try to deserialize it with the given function or something? On Aug 20, 3:32 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote: Since there is no standard for how to represent dates in JSON, it is unlikely to be built in. But you can extend the writer with application-specific date formats. -S On Aug 20, 2:15 pm, Dmitri dmitri.sotni...@gmail.com wrote: I'm currently using Dan Larkin's clojure-json, and it provides a way to serialize and deserialize dates, it also provides the option to specify custom serializers, eg: (defn date-encoder [date writer pad current-indent start-token-indent indent- size] (.append writer (str start-token-indent \ date \))) I was looking at switching to using the json implementation in clojure- contrib, but noticed that it doesn't handle dates nor does it provide a way to register custom serializers, is there a plan to implement that in the future, or is the proper approach to simply extend Write- JSON whenever a custom serializer/deserializer is needed. -- 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
sequence manipulation question
I notice that certain sequence operations such as concat and cons will not retain the original type of sequence, for example if you combine two vectors together a list will be returned: user= (concat [1 2] [3 4]) (1 2 3 4) is this intentional behavior, and would it not be more consistent for concat to retain the original type of the data structures, when both data structures that were passed in are of the same type. Also, why does cons behave differently from conj: user= (conj [1 2] 3) [1 2 3] user= (cons 2 [1 2]) (2 1 2) --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: sequence manipulation question
ah thanks for the clarification, makes perfect sense, didn't notice into. On Oct 20, 1:25 am, Alex Osborne a...@meshy.org wrote: Dmitri wrote: I notice that certain sequence operations such as concat and cons will not retain the original type of sequence, for example if you combine two vectors together a list will be returned: user= (concat [1 2] [3 4]) (1 2 3 4) is this intentional behavior, and would it not be more consistent for concat to retain the original type of the data structures, when both data structures that were passed in are of the same type. It's because concat returns a lazy sequence, the concatenation only happens when you ask for relevant elements (which has the benefit that it doesn't need to do any copying, saving both time and memory). If you want to concatenate two vectors eagerly (so returning another vector) you could use 'into' instead: user= (into [1 2] [3 4]) [1 2 3 4] Also, why does cons behave differently from conj: user= (conj [1 2] 3) [1 2 3] user= (cons 2 [1 2]) (2 1 2) Because cons always creates a list (which construct at the front), while conj adds it in the natural (ie fastest) way for that collection type, vectors add at the end. user (conj '(1 2) 3) (3 1 2) user (conj [1 2] 3) [1 2 3] user (conj #{1 2} 3) #{1 2 3} user (cons 3 '(1 2)) (3 1 2) --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: speed question
thanks a lot, that's really helpful. On Apr 2, 7:25 am, Paul Stadig p...@stadig.name wrote: I got it down to about 3 seconds. I did what William said, but the biggest improvement was from changing the way *width*, *height*, and *max-steps* were defined. I noticed that in the Java version they are constants, but in the Clojure version they are Vars which means that inside your tight inner loops you are dereferencing the vars multiple times. Vars are for thread local values, but these values are not expected to change. I'm not sure the best way to make these vars into constants, but I changed them into macros: (defmacro *width* [] (float 640)) Then replaced instances of *width* with (*width*). The macros will get compiled down to floats instead of resulting in multiple Var.deref calls (and probably Number.floatValue calls) per loop iteration. Here is the code: (ns main (:import (java.awt Color Container Graphics Canvas Dimension) (javax.swing JPanel JFrame) (java.awt.image BufferedImage BufferStrategy))) (set! *warn-on-reflection* true) (defmacro *width* [] (float 640)) (defmacro *height* [] (float 640)) (defmacro *max-steps* [] (float 32)) (defn on-thread [#^Runnable f] (doto (new Thread f) (.start))) (defn check-bounds [x y] (loop [px (float x) py (float y) zx (float 0.0) zy (float 0.0) zx2 (float 0.0) zy2 (float 0.0) value (float 0)] (if (and ( value (*max-steps*)) ( (+ zx2 zy2) (float 4.0))) (let [new-zy (float (+ (* (float 2.0) zx zy) py)) new-zx (float (+ (- zx2 zy2) px)) new-zx2 (float (* new-zx new-zx)) new-zy2 (float (* new-zy new-zy))] (recur px py new-zx new-zy new-zx2 new-zy2 (inc value))) (if (== value (*max-steps*)) 0 value (defn draw-line [#^Graphics g y] (let [dy (- 1.25 (* 2.5 (/ y (*height*] (doseq [x (range 0 (*width*))] (let [dx (- (* 2.5 (/ x (*width*))) 2.0)] (let [value (check-bounds dx dy)] (if ( value 0) (doto g (. setColor (Color. (* value (/ 255 (*max-steps*) (. drawRect x y 0 0 (defn draw-lines ([buffer g] (draw-lines buffer g (*height*))) ([#^BufferStrategy buffer g y] (doseq [y (range 0 y)] (draw-line g y) ;(on-thread (draw-line g y)) (. buffer show (defn draw [#^Canvas canvas] (let [buffer (. canvas getBufferStrategy) g (. buffer getDrawGraphics)] (draw-lines buffer g))) (defn main [] (let [panel (JPanel.) canvas (Canvas.) frame (JFrame. Mandelbrot)] (doto panel (.setPreferredSize (Dimension. (*width*) (*height*))) (.setLayout nil) (.add canvas)) (doto frame (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) (.setBounds 0,0,(*width*) (*height*)) (.setResizable false) (.add panel) (.setVisible true)) (doto canvas (.setBounds 0,0,(*width*) (*height*)) (.setBackground (Color/BLACK)) (.createBufferStrategy 2) (.requestFocus)) (draw canvas))) (time (main)) ~$ clojure /tmp/mandelbrot.clj Elapsed time: 3577.128587 msecs Paul --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: speed question
Thanks a lot, that's really helpful. I never thought of using a macro to define constants like that, it's definitely a good trick and it does seem to result in the biggest performance gain. On Apr 2, 7:25 am, Paul Stadig p...@stadig.name wrote: I got it down to about 3 seconds. I did what William said, but the biggest improvement was from changing the way *width*, *height*, and *max-steps* were defined. I noticed that in the Java version they are constants, but in the Clojure version they are Vars which means that inside your tight inner loops you are dereferencing the vars multiple times. Vars are for thread local values, but these values are not expected to change. I'm not sure the best way to make these vars into constants, but I changed them into macros: (defmacro *width* [] (float 640)) Then replaced instances of *width* with (*width*). The macros will get compiled down to floats instead of resulting in multiple Var.deref calls (and probably Number.floatValue calls) per loop iteration. Here is the code: (ns main (:import (java.awt Color Container Graphics Canvas Dimension) (javax.swing JPanel JFrame) (java.awt.image BufferedImage BufferStrategy))) (set! *warn-on-reflection* true) (defmacro *width* [] (float 640)) (defmacro *height* [] (float 640)) (defmacro *max-steps* [] (float 32)) (defn on-thread [#^Runnable f] (doto (new Thread f) (.start))) (defn check-bounds [x y] (loop [px (float x) py (float y) zx (float 0.0) zy (float 0.0) zx2 (float 0.0) zy2 (float 0.0) value (float 0)] (if (and ( value (*max-steps*)) ( (+ zx2 zy2) (float 4.0))) (let [new-zy (float (+ (* (float 2.0) zx zy) py)) new-zx (float (+ (- zx2 zy2) px)) new-zx2 (float (* new-zx new-zx)) new-zy2 (float (* new-zy new-zy))] (recur px py new-zx new-zy new-zx2 new-zy2 (inc value))) (if (== value (*max-steps*)) 0 value (defn draw-line [#^Graphics g y] (let [dy (- 1.25 (* 2.5 (/ y (*height*] (doseq [x (range 0 (*width*))] (let [dx (- (* 2.5 (/ x (*width*))) 2.0)] (let [value (check-bounds dx dy)] (if ( value 0) (doto g (. setColor (Color. (* value (/ 255 (*max-steps*) (. drawRect x y 0 0 (defn draw-lines ([buffer g] (draw-lines buffer g (*height*))) ([#^BufferStrategy buffer g y] (doseq [y (range 0 y)] (draw-line g y) ;(on-thread (draw-line g y)) (. buffer show (defn draw [#^Canvas canvas] (let [buffer (. canvas getBufferStrategy) g (. buffer getDrawGraphics)] (draw-lines buffer g))) (defn main [] (let [panel (JPanel.) canvas (Canvas.) frame (JFrame. Mandelbrot)] (doto panel (.setPreferredSize (Dimension. (*width*) (*height*))) (.setLayout nil) (.add canvas)) (doto frame (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) (.setBounds 0,0,(*width*) (*height*)) (.setResizable false) (.add panel) (.setVisible true)) (doto canvas (.setBounds 0,0,(*width*) (*height*)) (.setBackground (Color/BLACK)) (.createBufferStrategy 2) (.requestFocus)) (draw canvas))) (time (main)) ~$ clojure /tmp/mandelbrot.clj Elapsed time: 3577.128587 msecs Paul --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: speed question
nifty :) On Apr 2, 5:10 pm, Raffael Cavallaro raffaelcavall...@gmail.com wrote: If you change the color constructor you can get some nice color effects: (. setColor (let [scaled (Math/round (* value color-scale))] (Color. 255 (- 255 scaled) scaled))) will give you yellow and magenta for example --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: speed question
yeah I definitely agree that it would be nice if constants could be used without the parens. On Apr 2, 11:48 am, Paul Stadig p...@stadig.name wrote: Yeah that works the same as defining a function, just more explicit. I was looking for a way to define a constant and just use it as my-const without having to use the parens to call a function or a macro. I guess that would be something like a symbol macro in CL? Paul On Thu, Apr 2, 2009 at 11:08 AM, MikeM michael.messini...@invista.comwrote: There is definline which seems appropriate in place of the constant macros. (definline my-const [] 1) (my-const) ;= 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 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 -~--~~~~--~~--~--~---
speed question
I've been playing around with rendering a mandelbrot set, and using pure java it renders about 2 seconds on my machine, however it runs about 10 times as slow in clojure, I was curious if I'm doing anything obviously wrong, or if it's just life :) I do run it with the -server flag, which does improve it a bit. I've got the java and clojure source below: import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.image.BufferStrategy; import java.awt.image.ImageObserver; import javax.swing.JFrame; import javax.swing.JPanel; public class Mandelbrot extends Canvas implements ImageObserver { public static final int WIDTH = 640; public static final int HEIGHT = 640; private static int BAILOUT = 4; private static int MAX_ITERATIONS = 32; public BufferStrategy strategy; public Mandelbrot () { setBounds(0,0,WIDTH,HEIGHT); setBackground(Color.BLACK); JPanel panel = new JPanel(); panel.setPreferredSize(new Dimension(WIDTH, HEIGHT)); panel.setLayout(null); panel.add(this); JFrame frame = new JFrame(Mandelbrot); frame.add(panel); frame.setBounds(0,0,WIDTH, HEIGHT); frame.setResizable(false); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //create a double buffer createBufferStrategy(2); strategy = getBufferStrategy(); requestFocus(); } private int checkBounds(float x, float y) { float cr = x; float ci = y; float zi = 0.0f; float zr = 0.0f; int i = 0; while (true) { i++; float temp = zr * zi; float zr2 = zr * zr; float zi2 = zi * zi; zr = zr2 - zi2 + cr; zi = temp + temp + ci; if (zi2 + zr2 BAILOUT) return i; if (i MAX_ITERATIONS) return 0; } } private void draw() { float x = -2.1f, y = -1.5f, z = 3.0f; int i, j; Graphics g = strategy.getDrawGraphics(); g.clearRect(0, 0, getWidth(), getHeight()); for (i = 0; i HEIGHT; i++) { for (j = 0; j WIDTH; j++) { int value = checkBounds((x + z*(i/(float)WIDTH)), (y + z*(j/(float) HEIGHT))); if (value 0) { g.setColor(new Color(value*255/MAX_ITERATIONS)); g.drawRect(i, j, 0, 0); } } strategy.show(); } strategy.show(); } public static void main(String args[]) { Mandelbrot m = new Mandelbrot(); long startTime = System.currentTimeMillis(); m.draw(); System.out.println((System.currentTimeMillis() - startTime)/1000); } } Clojure: (ns main (:import (java.awt Color Container Graphics Canvas Dimension) (javax.swing JPanel JFrame) (java.awt.image BufferedImage BufferStrategy))) (def *width* 640) (def *height* 640) (def *max-steps* 32) (defn on-thread [f] (doto (new Thread f) (.start))) (defn check-bounds [x y] (loop [px x py y zx 0.0 zy 0.0 zx2 0.0 zy2 0.0 value 0] (if (and ( value *max-steps*) ( (+ zx2 zy2) 4.0)) (let [new-zy (+ (* 2.0 zx zy) py) new-zx (+ (- zx2 zy2) px) new-zx2 (* new-zx new-zx) new-zy2 (* new-zy new-zy)] (recur px py new-zx new-zy new-zx2 new-zy2 (inc value))) (if (== value *max-steps*) 0 value (defn draw-line [g y] (let [dy (- 1.25 (* 2.5 (/ y *height*)))] (doseq [x (range 0 *width*)] (let [dx (- (* 2.5 (/ x *width*)) 2.0)] (let [value (check-bounds dx dy)] (if ( value 0) (doto g (. setColor (Color. (* value (/ 255 *max- steps* (. drawRect x y 0 0 (defn draw-lines ([buffer g] (draw-lines buffer g *height*)) ([buffer g y] (doseq [y (range 0 y)] (draw-line g y) ;(on-thread (draw-line g y)) (. buffer show (defn draw [canvas] (let [buffer (. canvas getBufferStrategy) g(. buffer getDrawGraphics)]
Re: speed question
I actually tried forcing the type hints and didn't really see a noticeable improvement, just made the code hard to read for the most part. On Apr 1, 9:57 pm, CuppoJava patrickli_2...@hotmail.com wrote: From a quick glance, I think the lack of type hints is what's slowing down your Clojure code. You can set the global variable *warn-on-reflection* to true, to get a sense of where to add your type hints. -Patrick --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
is there a replace-at function
I ran into a situation where I needed to replace an element in a collection at a specific position, I ended up writing the following: (defn replace-at [coll pos value] replaces an element in collection at pos with the value (let [parts (split-at pos coll)] (concat (first parts) (cons value (rest (second parts)) I was wondering if there's a standard function to do 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 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 -~--~~~~--~~--~--~---
Re: sort behavior question
There are two issues here that I'm seeing, first is that the list and vector have different behavior, my understanding is that they are both sequences and one should be able to perform the same operations on them. Second issue is that the behavior is inconsistent, if it is not possible to sort tuples with a list as a second element, then it should never work, as opposed to working sometimes on some data sets. The inconsistency of the behavior is troubling. On Jan 7, 11:47 pm, .Bill Smith william.m.sm...@gmail.com wrote: I wonder if the root cause might be clearer if you were to review the documentation for the sort function and then apply what it says to a smaller dataset, e.g. a pair of lists. Bill --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: sort behavior question
I think the main issue is that sort should behave consistently. Possibly sort could check if the elements implement Comparable before attempting to sort them? I also don't see a reason as to why the lists shouldn't implement Comparable. On Jan 8, 4:17 pm, Mark Engelberg mark.engelb...@gmail.com wrote: Lists are not comparable (i.e., you can't do something like ( '(1 2 3) '(4 5 6))). So you can't sort a collection of lists, but you can sort a collection of vectors (provided the vectors contain comparable things). This is always the case; there is no inconsistency. The reason you are sometimes not getting an error is that when you randomly generate small collections of vectors, often the first element will be enough to sort the collection, so it never tries to compare the second elements, which in this case are lists. I'm not sure why lists don't implement comparable. Offhand I can't think of a reason why they wouldn't, but perhaps there is a reason. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
sort behavior question
I noticed strange behavior in the sort function, I was sorting key value tuples and ran into the following: when sorting 2 item vectors such as [1 [1 2 3]] sort works fine: (println (sort (map (fn [x] [(int (* (Math/random) 10)) x]) (for [x (range 4)] [1 2 3] output: ([6 [1 2 3]] [6 [1 2 3]] [6 [1 2 3]] [6 [1 2 3]]) however, if the second item is a list, e.g: (println (sort (map (fn [x] [(int (* (Math/random) 10)) x]) (for [x (range 100)] `(1 2 3) the following exception can occur, this happens more frequently for larger ranges, for range of 4, it may or may run and produce the result, however with a range of 100 the exception occurs consistently: Exception in thread main java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.LazyCons (gen.clj:60) at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2684) at clojure.lang.Compiler.compile(Compiler.java:4564) at clojure.lang.RT.compile(RT.java:362) at clojure.lang.RT.load(RT.java:404) at clojure.lang.RT.load(RT.java:376) --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
performance question
I wrote a simple word counter described here http://ptrace.fefe.de/wp/ it reads stdin and counts the occurrences of words, however I notice that it runs significantly slower than the java version in the link. I was wondering why there is such a dramatic difference. The approach I took was to create a map keyed on words and use the occurrence count as the value. When each line is read from input it's tokenized and the word counts are updated. The slowdown seems to occur in the inc-count function, where it updates the map using the assoc. Is this not a proper way to approach this in clojure? I've also noticed that there is a significant speed difference between conj and assoc, why is that? If I understand correctly both should only create the delta of the new elements and the old structure, however assoc appears to perform much better. (import '(java.io BufferedReader InputStreamReader)) (defn inc-count [words word] (if (= (. word (length)) 0) words (let [cnt (get words word)] (if cnt (assoc words word (inc cnt)) (assoc words word 1) (defn sort-words [words] (reverse (sort-by (fn [x] (first x)) (map (fn [x] [(get words x) x]) (keys words) (defn print-words [words] (let [head (first words) tail (rest words)] (if head (do (println head) (recur tail) (defn read-words [words line] (let [head (first line) tail (rest line)] (if (nil? tail) words (recur (time (inc-count words head)) tail (defn read-input [] (with-open [stream (System/in)] (let [buf (BufferedReader. (InputStreamReader. stream))] (loop [line (. buf (readLine)) words {}] (if (nil? line) (print-words (sort-words words)) (recur (. buf (readLine)) (read-words words (. line (split ) (time (read-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 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 -~--~~~~--~~--~--~---
Re: performance question
I added the time call later on to find what was taking up the cycles, I also checked the reverse, it's impact is minimal, the print-words part of the program runs fast, but the read-words takes the majority of the time. On Dec 13, 12:38 pm, Jeremy Dunck jdu...@gmail.com wrote: On Dec 13, 9:41 am, Dmitri dmitri.sotni...@gmail.com wrote: ... The slowdown seems to occur in the inc-count function, where it updates the map using the assoc. Is this not a proper way to approach this in clojure? (recur (time (inc-count words head)) tail You're pretty tightly looping here-- are you sure the overhead isn't in this extra (time) call rather than (inc-count) itself? --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: performance question
thanks for pointing this out, and I absolutely appreciate the example. I'm still new to functional approach and I always like to see how things are done properly. On Dec 13, 1:15 pm, Chouser chou...@gmail.com wrote: On Sat, Dec 13, 2008 at 10:41 AM, Dmitri dmitri.sotni...@gmail.com wrote: I wrote a simple word counter described herehttp://ptrace.fefe.de/wp/ it reads stdin and counts the occurrences of words, however I notice that it runs significantly slower than the java version in the link. There are several differences that could be factors. For example, the Java version uses StreamTokenizer, while your Clojure version uses String.split with a regex that gets recompiled for each line read. I've also noticed that there is a significant speed difference between conj and assoc, why is that? If I understand correctly both should only create the delta of the new elements and the old structure, however assoc appears to perform much better. user= (let [c 100 p [1 1]] (time (reduce #(conj % [%2 %2]) {} (range c))) (time (reduce #(assoc % %2 %2) {} (range c))) nil) Elapsed time: 1544.180472 msecs Elapsed time: 1894.318809 msecs nil user= (let [c 100 p [1 1]] (time (reduce #(conj % [%2 %2]) {} (range c))) (time (reduce #(assoc % %2 %2) {} (range c))) nil) Elapsed time: 1549.159812 msecs Elapsed time: 1594.18912 msecs That's a million items added to a hash-map each way in about 1.5 seconds -- not too shabby. And the speeds for conj vs. assoc seem very close, though I'm actually seeing a slight advantage for conj. And I'm sorry for what follows -- it's like a compulsion for me, and I hope it doesn't put you off. Each of these functions takes the same input and produces the same output as your original code, but each is implemented a bit more succinctly: (import '(java.io BufferedReader InputStreamReader)) (defn inc-count [words word] (if (seq word) (assoc words word (inc (words word 0))) words)) (defn sort-words [words] (reverse (sort (map (fn [[k v]] [v k]) words (defn print-words [words] (doseq [head words] (println head))) (defn read-words [words line] (reduce inc-count words line)) (defn read-input [] (with-open [buf (BufferedReader. (InputStreamReader. System/in))] (let [words (for [line (line-seq buf)] (.split line ))] (print-words (sort-words (reduce read-words {} words)) (time (read-input)) --Chouser --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: infix operators
Thanks for the example, the macro is exactly the solution was looking for. On Nov 30, 1:11 am, Jeff Bester [EMAIL PROTECTED] wrote: On Nov 28, 11:11 pm, Dmitri [EMAIL PROTECTED] wrote: Thanks for the comments, the prefix notation may indeed be something that one gets used to. I find it just fine for most cases, just not for mathematical expressions. The example function was not meant as a complete solution, but rather as an example of how trivial it is to switch between the two notations. I do see how the formatting makes it more readable, thanks for pointing that out. It does sound that it's largely a matter of what you're used to. If you are translating formulas it might be worth investing the time to create a macro to convert from infix to prefix with precedence rules, as well as, creating new operators. I think Peter Norvig covers something akin to this in PAIP. This is where any lisp truly shines; that is using macros to express Domain Specific Languages. That is at compile/load time morph the code to allow new syntax in the language. See the following for an example implementation user (formula (3 + 4 * 2) / 3) 11/3 = Example code ;; used for order of evaluation table and for valid infix operators (def +precedence+ {'rem 5, '* 4, '/ 3, '+ 2, '- 1}) ;; highest level of precedence (def +highest-precedence+ (apply max (map val +precedence+))) (defn- operator? Check if is valid operator ([sym] (not (nil? (get +precedence+ sym) (defn- find-lowest-precedence find the operator with lowest precedence; search from left to right ([seq] ;; loop through terms in the sequence (loop [idx 0 seq seq lowest-idx nil lowest-prec +highest-precedence+] ;; nothing left to process (if (empty? seq) ;; return lowest found lowest-idx ;; otherwise check if current term is lower (let [prec (get +precedence+ (first seq))] ;; is of lower or equal precedence (if (and prec (= prec lowest-prec)) (recur (inc idx) (rest seq) idx prec) ;; is of high precedence therefore skip for now (recur (inc idx) (rest seq) lowest-idx lowest-prec))) (defn- infix-to-prefix Convert from infix notation to prefix notation ([seq] (cond ;; handle term only (not (seq? seq)) seq ;; handle sequence containing one term (i.e. handle parens) (= (count seq) 1) (infix-to-prefix (first seq)) ;; handle all other cases true (let [lowest (find-lowest-precedence seq)] (if (nil? lowest) ;; nothing to split seq ;; (a b c) bind a to hd, c to tl, and b to op (let [[hd tl] (split-at lowest seq) op (first tl) tl (rest tl)] ;; recurse (list op (infix-to-prefix hd) (infix-to-prefix tl (defmacro formula Formula macro translates from infix to prefix ([ equation] (infix-to-prefix equation)) --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: infix operators
Thanks for the comments, the prefix notation may indeed be something that one gets used to. I find it just fine for most cases, just not for mathematical expressions. The example function was not meant as a complete solution, but rather as an example of how trivial it is to switch between the two notations. I do see how the formatting makes it more readable, thanks for pointing that out. It does sound that it's largely a matter of what you're used 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
if small syntax change proposal
Allow cond-like specification of expression pairs and allow odd number of expressions. Let odd expressions in last position serve as default return value. There will be no impact on previous reading/writing of if. Stolen from Paul Graham's Arc. (defmacro myif ([x] x) ([x y] (if x y)) ([x y z] (if x y `(myif [EMAIL PROTECTED] --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure Poll 09/2008
Doing: learning, deciding whether clojure is appropriate for my company projects Would like: 1) up to date documentation. Online docs are so far behind SVN it's not funny. Yes yes, SVN is not release, but in the beginning stages of the project as it is things happen very fast and sticking with release is shooting yourself in the foot. 2) more examples in online docs, especially where there are no examples at all. 3) more syntax tricks, like defining partials with arbitrary argument positions. Otherwise, clojure is already good, because it's lispy, does macros and talks with java. On Sep 10, 2:40 pm, Rich Hickey [EMAIL PROTECTED] wrote: As we rapidly approach 500 members on the group (!) I thought it would be a good time to conduct another poll: What are you doing with Clojure? What 3 features would you most like to see added next? Thanks, Rich --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Bug: self require - stack overflow
Whatever you do, don't kill Clojure while trying to save us from ourselves. --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---