Re: [ANN] Clojure 1.9.0-alpha15 is now available

2017-03-14 Thread Dmitri
 <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

2017-03-14 Thread Dmitri
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

2016-02-29 Thread Dmitri
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

2016-02-29 Thread Dmitri
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  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 
>> > 
>> > 
>> > 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

2015-12-11 Thread Dmitri
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 Anderson  
 wrote:

 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!

2015-11-10 Thread Dmitri
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

2015-08-05 Thread Dmitri
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

2015-08-05 Thread Dmitri
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

2015-08-05 Thread Dmitri
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

2015-08-03 Thread Dmitri
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

2015-08-03 Thread Dmitri
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

2015-05-10 Thread Dmitri
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

2015-05-05 Thread Dmitri
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

2015-05-05 Thread Dmitri
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

2015-05-04 Thread 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
--- 
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

2015-04-17 Thread Dmitri
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

2014-12-09 Thread Dmitri
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

2014-12-09 Thread Dmitri
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

2014-12-09 Thread Dmitri
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

2014-12-09 Thread Dmitri
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

2013-11-13 Thread Dmitri
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?

2013-01-11 Thread Dmitri
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

2012-10-10 Thread Dmitri
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)

2012-06-11 Thread Dmitri Sotnikov
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)

2012-06-11 Thread Dmitri

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)

2012-06-10 Thread Dmitri
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)

2012-06-10 Thread Dmitri
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

2012-04-19 Thread Dmitri
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

2012-04-18 Thread Dmitri
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

2012-04-18 Thread 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


a convenience idea for test functions

2012-04-17 Thread Dmitri
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

2010-10-11 Thread Dmitri
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

2010-10-10 Thread Dmitri
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

2010-09-04 Thread Dmitri
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

2010-09-03 Thread Dmitri
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

2010-09-03 Thread Dmitri
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

2010-08-25 Thread Dmitri
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

2010-08-25 Thread Dmitri
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

2010-08-24 Thread Dmitri
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

2010-08-23 Thread Dmitri
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

2010-08-20 Thread Dmitri
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

2010-08-20 Thread Dmitri
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

2010-08-20 Thread Dmitri
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

2009-10-19 Thread Dmitri

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

2009-10-19 Thread Dmitri

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

2009-04-02 Thread Dmitri

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

2009-04-02 Thread Dmitri

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

2009-04-02 Thread Dmitri

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

2009-04-02 Thread Dmitri

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

2009-04-01 Thread Dmitri

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

2009-04-01 Thread Dmitri

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

2009-01-25 Thread Dmitri

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

2009-01-08 Thread Dmitri

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

2009-01-08 Thread Dmitri

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

2009-01-07 Thread Dmitri

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

2008-12-13 Thread Dmitri

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

2008-12-13 Thread Dmitri

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

2008-12-13 Thread Dmitri

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

2008-11-30 Thread Dmitri

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

2008-11-28 Thread Dmitri

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

2008-10-09 Thread Dmitri P

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

2008-09-12 Thread Dmitri P

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

2008-09-09 Thread Dmitri P

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
-~--~~~~--~~--~--~---