emacs + assert + syntax highlighting

2014-05-23 Thread t x
Hi,

  In my code, I have many lines like:

  (assert  )
  (assert  )
  (assert  )

  Now, is there a way to have the entire sexp highlighted in light
grey? (Rather than as normal code).

  The logic being "assertions are meant more like comments", and when
reading, I'd prefer to not see them as normal code.

Thanks!

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


how to define a variable of type collection to keep other functions.

2014-05-23 Thread sorin cristea

Hi all,

do you have any idea how I can define a variable, global or inside a 
function, used to store for example the FutureTask objects resulted from 
ExecutorService submit(fn) call,I want to put all futures in a collection 
and later call 'get' on each of them. bellow is a sample of that code: 

(defn sample-fc
  []
  (def futures '())
  (dotimes [i 3]
(def f (. thread-pool (submit (fn [] ("task result !!!")
(cons f futures)
)
   "shutdown the pool"
  (. thread-pool shutdown)
  (. thread-pool awaitTermination (. Long MAX_VALUE) (. TimeUnit SECONDS))

  "go through all futures an call get on them"
  (doseq [f futures]
(println (. f get))
)
)

 when I do 'dosync' futures collection is empty, even if (def f (. 
thread-pool (submit (fn [] ("task result !!!") is a a non empty object 
of type FutureTask(java.util.concurrent package).

Do you know how to define 'futures' variable such that to keep all returned 
future ?

thanks,
Sorin

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: how to define a variable of type collection to keep other functions.

2014-05-23 Thread Philippe Guillebert
Hello

This is not written as functional code. You have to understand that :

(cons f futures)

creates a new "version" of futures with f in front of it and cons *returns
it to you*. Put another way,* futures is not modified by cons*. In your
dotimes construct, the consed value is lost each loop. Have a look at
loop/recur, map, and reduce, these are the backbone functions when
programming in clojure.

Also, do not use (def) inside a function, this is ugly. use let to define
local bindings instead.

--
Philippe.




On Fri, May 23, 2014 at 10:16 AM, sorin cristea wrote:

>
> Hi all,
>
> do you have any idea how I can define a variable, global or inside a
> function, used to store for example the FutureTask objects resulted from
> ExecutorService submit(fn) call,I want to put all futures in a collection
> and later call 'get' on each of them. bellow is a sample of that code:
>
> (defn sample-fc
>   []
>   (def futures '())
>   (dotimes [i 3]
> (def f (. thread-pool (submit (fn [] ("task result !!!")
> (cons f futures)
> )
>"shutdown the pool"
>   (. thread-pool shutdown)
>   (. thread-pool awaitTermination (. Long MAX_VALUE) (. TimeUnit SECONDS))
>
>   "go through all futures an call get on them"
>   (doseq [f futures]
> (println (. f get))
> )
> )
>
>  when I do 'dosync' futures collection is empty, even if (def f (.
> thread-pool (submit (fn [] ("task result !!!") is a a non empty
> object of type FutureTask(java.util.concurrent package).
>
> Do you know how to define 'futures' variable such that to keep all
> returned future ?
>
> thanks,
> Sorin
>
>  --
> 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.
>



-- 
Philippe

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: how to define a variable of type collection to keep other functions.

2014-05-23 Thread sorin cristea

Thank Philippe for your advices,I came from java environment and seems I 
still remain with some 'bad' habits.

On Friday, May 23, 2014 12:04:52 PM UTC+3, Philippe Guillebert wrote:
>
> Hello
>
> This is not written as functional code. You have to understand that :
>
> (cons f futures)
>
> creates a new "version" of futures with f in front of it and cons *returns 
> it to you*. Put another way,* futures is not modified by cons*. In your 
> dotimes construct, the consed value is lost each loop. Have a look at 
> loop/recur, map, and reduce, these are the backbone functions when 
> programming in clojure.
>
> Also, do not use (def) inside a function, this is ugly. use let to define 
> local bindings instead.
>
> --
> Philippe.
>
>
>
>
> On Fri, May 23, 2014 at 10:16 AM, sorin cristea 
> 
> > wrote:
>
>>
>> Hi all,
>>
>> do you have any idea how I can define a variable, global or inside a 
>> function, used to store for example the FutureTask objects resulted from 
>> ExecutorService submit(fn) call,I want to put all futures in a collection 
>> and later call 'get' on each of them. bellow is a sample of that code: 
>>
>> (defn sample-fc
>>   []
>>   (def futures '())
>>   (dotimes [i 3]
>> (def f (. thread-pool (submit (fn [] ("task result !!!")
>> (cons f futures)
>> )
>>"shutdown the pool"
>>   (. thread-pool shutdown)
>>   (. thread-pool awaitTermination (. Long MAX_VALUE) (. TimeUnit SECONDS))
>>
>>   "go through all futures an call get on them"
>>   (doseq [f futures]
>> (println (. f get))
>> )
>> )
>>
>>  when I do 'dosync' futures collection is empty, even if (def f (. 
>> thread-pool (submit (fn [] ("task result !!!") is a a non empty 
>> object of type FutureTask(java.util.concurrent package).
>>
>> Do you know how to define 'futures' variable such that to keep all 
>> returned future ?
>>
>> thanks,
>> Sorin
>>
>>  -- 
>> 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.
>>
>
>
>
> -- 
> Philippe
>  

-- 
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: Community Interest in a Clojure Application Config Library, using Zookeeper?

2014-05-23 Thread Stathis Sideris
You guys should check stoic:

https://github.com/juxt/stoic

>From the readme:

This library marries Stuart Sierras Component library with distributed 
> config. Feed Stoic a SystemMap and it will ensure that the relevant 
> components are bounced when their config changes. Config-suppliers are 
> pluggable, at present Zookeeper is the sole config supplier implementation.


I've used it without any problems.

On Thursday, 22 May 2014 14:00:03 UTC+1, Daniel Higginbotham wrote:
>
> Yes, please do open source it!
>
> On Tuesday, May 20, 2014 5:33:05 PM UTC-4, Thomas Steffes wrote:
>>
>> Hey folks,
>>
>> At Room Key we're using Apache Zookeeper and a home-grown clojure library 
>> called drcfg for real-time application configuration management. We're 
>> debating open-sourcing drcfg and are trying to gauge community interest in 
>> such a tool. 
>>
>> We think it's got great usage semantics, basically you just def an atom 
>> in any namespace where you'd like a variable that can be changed in 
>> real-time on a running system. When you define the atom, you can also 
>> provide defaults to fall back to if zookeeper is unavailable, a validator 
>> to be run on any value when a change is attempted (to prevent invalid 
>> configuration data), as well as some meta-data about the variable.
>>
>> We've also got a web UI we use to change configuration data, but that 
>> would likely be released separate of drcfg itself.
>>
>> If anyone's interested, could you reply to this post? I can provide more 
>> information as well if need be.
>>
>>
>> -Thomas Steffes @ Room Key
>>
>>
>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: How should I implement an elevator state-machine with loops and core.async?

2014-05-23 Thread Jesse


On Thursday, May 22, 2014 8:17:51 PM UTC+9, Jesse wrote:
>
> Hey guys, I am trying to build a program that can instruct a single 
> elevator, 2 floor system how to behave based on the state of an atom that 
> is being constantly checked for updates by a loop. The state of the atom at 
> a given time is then used to determine the conditional behavior of a 
> move-elevator function. 
>
> It is the first time I have ever written a program like this before, so I 
> am not sure if I am doing it efficiently or not. Everything works fine up 
> until the final *init* loop, where it freezes up my computer or ends 
> prematurely. In Joy of Clojure, I saw a cool program using *case* and* 
> trampoline *that is related to elevators, but somewhat different from 
> what I am doing. I am not sure if those functions, *cond,* or perhaps 
> *condp*, using *recur*, would be better for my use-case.
>
> I run a go-loop in the background that reads inputs from first or second 
> floor button presses, *up* or *down,* from a channel, and updates the 
> state of an atom, that is read by the move-elevator function. I am not sure 
> if/how to call the move-elevator function to have the whole process run 
> continuously, by itself, after I call the *init *function. Right now I 
> have to call the move-function manually. Other than that, the whole things 
> works fine. Could somebody please give me some helpful pointers to make my 
> code more professional and/or sophisticated, or more general advice on 
> using Clojure to design programs that interface with in mechanical systems? 
> Is using an async channel to store presses here a good choice? This article 
> here, creating ATM machine functionality using case and core.async, also 
> inspired me: 
> http://www.neo.com/2014/05/18/using-a-core-async-routine-as-a-state-machine
>
> The code is a little long (80 lines), so below is a link to the github 
> gist. 
>
> https://gist.github.com/gamma235/4ea0d7a0d0efb8d4399f
>
> Thanks ahead of time!
>
> Jesse
>
>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: How should I implement an elevator state-machine with loops and core.async?

2014-05-23 Thread Jesse
I have got in a shape where it works fine, but with slightly unusual 
behavior. I am looking for  advice on refactoring, So if someone could 
please have a look. 

https://gist.github.com/gamma235/4ea0d7a0d0efb8d4399f

Jesse




On Thursday, May 22, 2014 8:25:39 PM UTC+9, Rob Day wrote:
>
> I haven't taken a detailed look yet, but you say you're watching the 
> atom in a background loop - would 
> http://clojuredocs.org/clojure_core/1.2.0/clojure.core/add-watch be 
> more idiomatic and more efficient? 
>
> Best, 
> Rob 
>
> On 22 May 2014 14:17, Jesse > wrote: 
> > Hey guys, I am trying to build a program that can instruct a single 
> > elevator, 2 floor system how to behave based on the state of an atom 
> that is 
> > being constantly checked for updates by a loop. The state of the atom at 
> a 
> > given time is then used to determine the conditional behavior of a 
> > move-elevator function. 
> > 
> > It is the first time I have ever written a program like this before, so 
> I am 
> > not sure if I am doing it efficiently or not. Everything works fine up 
> until 
> > the final init loop, where it freezes up my computer or ends 
> prematurely. In 
> > Joy of Clojure, I saw a cool program using case and trampoline that is 
> > related to elevators, but somewhat different from what I am doing. I am 
> not 
> > sure if those functions, cond, or perhaps condp, using recur, would be 
> > better for my use-case. 
> > 
> > I run a go-loop in the background that reads inputs from first or second 
> > floor button presses, up or down, from a channel, and updates the state 
> of 
> > an atom, that is read by the move-elevator function. I am not sure 
> if/how to 
> > call the move-elevator function to have the whole process run 
> continuously, 
> > by itself, after I call the init function. Right now I have to call the 
> > move-function manually. Other than that, the whole things works fine. 
> Could 
> > somebody please give me some helpful pointers to make my code more 
> > professional and/or sophisticated, or more general advice on using 
> Clojure 
> > to design programs that interface with in mechanical systems? Is using 
> an 
> > async channel to store presses here a good choice? This article here, 
> > creating ATM machine functionality using case and core.async, also 
> inspired 
> > me: 
> > 
> http://www.neo.com/2014/05/18/using-a-core-async-routine-as-a-state-machine 
> > 
> > The code is a little long (80 lines), so below is a link to the github 
> gist. 
> > 
> > https://gist.github.com/gamma235/4ea0d7a0d0efb8d4399f 
> > 
> > Thanks ahead of time! 
> > 
> > Jesse 
> > 
> > 
> > 
> > -- 
> > 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
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.


Code Poetry

2014-05-23 Thread daly
Ok, so I'm a bit over the edge about how good code should be written,
as many of you might have guessed...

but it could be worse:
 http://sourcecodepoetry.com
"good code reads well, best code rhymes"

and, best of all, it is a contest!

Tim Daly
/me mutters about being one-upped :-(

-- 
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: Code Poetry

2014-05-23 Thread Gregg Reynolds
On Fri, May 23, 2014 at 8:23 AM,  wrote:

> Ok, so I'm a bit over the edge about how good code should be written,
> as many of you might have guessed...
>
> but it could be worse:
>  http://sourcecodepoetry.com
> "good code reads well, best code rhymes"
>
> and, best of all, it is a contest!
>
> Tim Daly
> /me mutters about being one-upped :-(


Curse you, Tim Daly!  I don't have time for this stuff!  But now I'll have
no choice but to waste a few who knows how many hours on it. Who can resist
"The dynamic languages are discouraged (too easy!) but may be accepted if
solution is unbelievably cool."

Gregg

-- 
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] core.async (and more) video tutorials

2014-05-23 Thread Juan Manuel Gimeno Illa
The videos look very good and seem very interesting.

One idea: some video about how to create & configure a project in cursive 
would be helpful as well.

Juan Manuel

El viernes, 23 de mayo de 2014 05:56:45 UTC+2, tbc++ escribió:
>
> I'm using Cursive Clojure (Intelij). It has a "Presentation Mode" which is 
> pretty good, but I use Cursive as my main IDE these days. 
>
>
> On Thu, May 22, 2014 at 7:41 PM, Jason Gilman 
> 
> > wrote:
>
>> Thanks for the videos. The first one was good. What text editor are you 
>> using in the videos? I haven't seen that one before.
>>
>> --
>> 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.
>>
>
>
>
> -- 
> “One of the main causes of the fall of the Roman Empire was that–lacking 
> zero–they had no way to indicate successful termination of their C 
> programs.”
> (Robert Firth) 
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: How to refactor data safely?

2014-05-23 Thread Bertrand Dechoux
It's only a reformulation of Ulises comment but I would say:

1) abstract away how the data is accessed
2) introduce change one function at a time by swapping the past accessor 
with the new accessor (really it is like a getter/setter)
3) if you have final consumer(s) you might need to introduce a 
datastructure (a map?) stating which id should be accessed with the new 
implementation of the accessor

Bertrand

Le jeudi 22 mai 2014 10:21:30 UTC+2, Ulises a écrit :
>
> How are you accessing the data?
>
> I suppose that if you were accessing (maybe you are) the data via helper 
> functions, that's where most of the refactoring should happen.
>
>
> On 22 May 2014 09:17, Jakub Holy >wrote:
>
>> I have a nested data structure, used by a bunch of functions that presume 
>> knowledge of its structure, and I wonder how to change a part of the 
>> structure in a safe way, preferably in small incremental steps, rather than 
>> having my code broken until I update all the functions and tests for the 
>> new structure. I believe many of you must have experiences with this, would 
>> you care to share some tips?
>>
>> The data structure is first built incrementally and the collected data is 
>> later summarized. Instead of replacing the raw data with their summary, I 
>> want to keep both, so I want to wrap the data with a map; i.e. from:
>> {  [ data...] }   ;; later replaced with { summary}
>> to
>> { {:data [data...], :summary ...}
>>
>> I have a number of functions operating on the structure and tests for 
>> those functions (with test data that also need to be updated w.r.t. the 
>> refactoring).
>>
>> When I change one of the functions to produce the new data structure 
>> (i.e. data wrapped in a map instead of the data itself), everything else 
>> breaks. So I fix some tests and another function and get even more 
>> failures. This does not feel as a good way to do it as I prefer to have 
>> limited 
>> red  and am 
>> fond of parallel 
>> changefor
>>  that reason.
>>
>> Ideally, I would have an automated refactoring or the possibility to wrap 
>> the data in some kind of a two-faced proxy that could behave both as a 
>> vector (towards the old code) or as a map containing the vector (towards 
>> the updated code) [some thing like lenses/cursor?!]. I haven't either so I 
>> guess the only option remaining is a well-controlled process of updating 
>> the structure and code. Any advice?
>>
>> Thank you! /Jakub
>> -- 
>> *Forget software. Strive to make an impact, deliver a valuable change.*
>>
>> *(**Vær så snill og hjelp meg med å forbedre norsken **min –** skriftlig 
>> og muntlig. Takk!**)*
>>
>> Jakub Holy
>> Solutions Engineer | +47 966 23 666
>> Iterate AS | www.iterate.no
>> The Lean Software Development Consultancy
>> - http://theholyjava.wordpress.com/ -
>>  
>> -- 
>> 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
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: Help with a memory leak

2014-05-23 Thread Pablo Nussembaum
I have been working hard to understand the issue, and it seems to related to 
the creation of lots of functions using eval.
for instance if you run: (for [_ (range 1)] (eval (read-string "(fn [x] 
(inc x))")))
2 or 3 time it will consume all  PermGen. Is there any way to palliate this 
problem?

As regards head retention, I believe it's not the problem because I run all my 
processing in one line[1] the repl without assigning the result to any var, 
then I press "1" four times to avoid the repl
retain references in "*1 *2 *3" variables, after that I run (System/gc) several 
times and then I take the memory snapshot using yourkit. Finally, in the mem 
snapshot there are no live instances inside
mentat.* packages generated by clojure.

[1] (-> (g/build-dot-file [(t/trace-gen ArrayStack sel-fn)]) d/dot (d/save! 
"arrayStack.eps" {:format :eps}))

Regards,
-- 
Pablo

On 05/23/2014 02:04 AM, Mars0i wrote:
>
>
> On Wednesday, May 21, 2014 7:43:41 PM UTC-5, Bauna wrote:
>
> The main loop is here[2] in the function trace-gen that generates a lazy 
> list. I don't care about the memory required during the execution of the 
> function but after it should be GC'd all.
>
>
> Just a quick question: Have you checked to make sure that that you are not 
> keeping a reference to the beginning (or other position) of the lazy list 
> after you're done processing 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.

-- 
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: [RFC] Roundtripping namespaced xml documents for data.xml

2014-05-23 Thread Paul Gearon
Hi Herwig,

I spent some time going through the design, and a email thread
(particularly Chouser and Christophe's responses), plus I spent a bit more
time on my own implementation where it was clear that I'd missed some
things.

I've yet to go through your code in fine detail, so I'll still have some
gaps in my knowledge.

On Thu, May 22, 2014 at 2:44 PM, Herwig Hochleitner
wrote:

> 2014-05-21 21:06 GMT+02:00 Paul Gearon :
>
>
>> Are QNames strictly necessary? Keywords seem to do the trick, and they
>> work in nicely with what already exists.
>>
>> I know that there are some QName forms that are not readable as a
>> keyword, but the XML parsing code will always call (keyword ...) and that
>> holds any kind of QName,
>>
>
> I've argued this at some length on the dev thread. IMO QNames are not
> nessecary, but we want another datatype than keywords.
> I think the main argument for using keywords would be xml literals in code
> and there readability (i.e. not having to use (keyword ..)) counts. A
> reader tag is far better suited for this.
> In the course of that argument, I also came up with a way to represent
> resolved names as keywords in literals. Please check out the design page
> for this.
>

I still argue for using keywords here. The existing API uses them, and
they're a natural fit.

The one real problem is elements would need a special hash/equality check
to deal with namespace contexts (presuming that fn:deep-equal maps to
Object.equals). The keywords would need to be translated according to the
current context. However, that approach still works for fragments that can
be evaluated in different contexts, while storing URIs directly needs
everything to be rebuilt for another context.

Most possible QNames can be directly expressed as a keyword (for instance,
the QName 㑦:㒪 can be represented as the read-able keyword :㑦/㒪). The
keyword function is just a workaround for exotic values. While I know they
can exist (e.g. containing \u000A), I've yet to see any QNames in the wild
that cannot be represented as a read-able keyword.

In case I'm not clear, say I have these two docs:

http://ex.com/"; xmlns:a="http://a.com/";>
  http://b.org"; b:baz="blah"/>


http://something.else.com/";>
  http://b.org"; b:baz="blah"/>


If I compare the a:bar element form both documents with func-deep-equal
then they should compare equal, despite the fact that the a:bar qname
resolves differently in each context.

The representation I've used was only a small extension to the existing one:
#clojure.data.xml.Element{:tag :a/bar, :attrs {:b/baz "blah"}, :namespaces
{:b "http://b.org"}, :content ()}

I agree with the use of meta to handle the namespaces, since it's not
included in equality testing. Namespaces are declared on, and scoped to the
element, so it makes sense to add them as a map there (this is what I've
done). In the first case, the meta-data for the a:bar element is:
{:b "http://b.org";, :a "http://a.com/";, :xmlns "http://ex.com/"}

I didn't follow the discussion for putting URIs into keywords, as I could
not see why we would want this (am I missing something obvious?)

Are the reverse mappings (uri->prefix) definitely necessary? My first look
>> at this made me think that they were (particularly so I could call
>> XMLStreamWriter.getPrefix), but it seemed that the XmlWriter keeps enough
>> state that it isn't necessary. My final code didn't need them at all.
>>
>
> The XmlWriter does keep enough state, but I also want to support tree
> transformers that have the full information without needing to pipe through
> Xml{Reader,Parser}.
> uri->prefix could be reconstructed from prefix->uri in linear time, so
> again, the reason for the reverse mapping is performance.
>

I still don't see why the reverse mapping is needed. Is it because I'm
storing the QName in a keyword and can look up the current namespace for
the URI, while you are storing the fully qualified name?


> I was mostly considering round-tripping the data, and the parser is good
>> at not repeating namespaces for child elements, so the emitter didn't need
>> to either. As a result I didn't need to filter out prefix->uri bindings
>> from parent elements when emitting namespaces, though that should be easy.
>>
>
> What I meant are redundant prefixes, e.g. binding xmlns:D="DAV:" at the
> root element, xmlns:E="DAV:" in a child element.
>

Sorry, I'm not following what you were getting at with this. In this
example D and E both get mapped to the same namespace, meaning that
 and  can be made to resolve the same way. But in a
different context they could be different values.

If both the explicit declarations of namespaces on elements and current
context are stored with the element (one in the :namespaces field, the
other in metadata), then this allows resolution to be handled correctly,
while also maintaining where each namespace needs to be emitted.

If uri->prefix is needed, then a simple map would need that, yes. However,
>> if I needed the reverse mapp

Re: Help with a memory leak

2014-05-23 Thread Andy Fingerhut
I haven't looked into the details, but you might want to check out this
Clojure ticket to see if it is related:

http://dev.clojure.org/jira/browse/CLJ-1152

Andy


On Fri, May 23, 2014 at 8:53 AM, Pablo Nussembaum  wrote:

>  I have been working hard to understand the issue, and it seems to related
> to the creation of lots of functions using eval.
> for instance if you run: (for [_ (range 1)] (eval (read-string "(fn
> [x] (inc x))")))
> 2 or 3 time it will consume all  PermGen. Is there any way to palliate
> this problem?
>
> As regards head retention, I believe it's not the problem because I run
> all my processing in one line[1] the repl without assigning the result to
> any var, then I press "1" four times to avoid the repl retain references in
> "*1 *2 *3" variables, after that I run (System/gc) several times and then I
> take the memory snapshot using yourkit. Finally, in the mem snapshot there
> are no live instances inside mentat.* packages generated by clojure.
>
> [1] (-> (g/build-dot-file [(t/trace-gen ArrayStack sel-fn)]) d/dot
> (d/save! "arrayStack.eps" {:format :eps}))
>
> Regards,
> --
> Pablo
>
>
> On 05/23/2014 02:04 AM, Mars0i wrote:
>
>
>
> On Wednesday, May 21, 2014 7:43:41 PM UTC-5, Bauna wrote:
>>
>> The main loop is here[2] in the function trace-gen that generates a lazy
>> list. I don't care about the memory required during the execution of the
>> function but after it should be GC'd all.
>>
>
> Just a quick question: Have you checked to make sure that that you are not
> keeping a reference to the beginning (or other position) of the lazy list
> after you're done processing 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.
>
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Help with a memory leak

2014-05-23 Thread Pablo Nussembaum
It should be related somehow. Although, in my case I'm not dynamically 
generating protocols or multimethods, the app only generates a plain old 
functions.

In the ticket it says that there is a way to clear the protocols internal 
cache. So I'll try to switch my code to generate protocols and test if cleaning 
internal protocol cache works better.

-- 
Pablo

On 05/23/2014 02:24 PM, Andy Fingerhut wrote:
> I haven't looked into the details, but you might want to check out this 
> Clojure ticket to see if it is related:
>
> http://dev.clojure.org/jira/browse/CLJ-1152
>
> Andy
>
>
> On Fri, May 23, 2014 at 8:53 AM, Pablo Nussembaum  > wrote:
>
> I have been working hard to understand the issue, and it seems to related 
> to the creation of lots of functions using eval.
> for instance if you run: (for [_ (range 1)] (eval (read-string "(fn 
> [x] (inc x))")))
> 2 or 3 time it will consume all  PermGen. Is there any way to palliate 
> this problem?
>
> As regards head retention, I believe it's not the problem because I run 
> all my processing in one line[1] the repl without assigning the result to any 
> var, then I press "1" four times to avoid
> the repl retain references in "*1 *2 *3" variables, after that I run 
> (System/gc) several times and then I take the memory snapshot using yourkit. 
> Finally, in the mem snapshot there are no live
> instances inside mentat.* packages generated by clojure.
>
> [1] (-> (g/build-dot-file [(t/trace-gen ArrayStack sel-fn)]) d/dot 
> (d/save! "arrayStack.eps" {:format :eps}))
>
> Regards,
> -- 
> Pablo
>
>
> On 05/23/2014 02:04 AM, Mars0i wrote:
>>
>>
>> On Wednesday, May 21, 2014 7:43:41 PM UTC-5, Bauna wrote:
>>
>> The main loop is here[2] in the function trace-gen that generates a 
>> lazy list. I don't care about the memory required during the execution of 
>> the function but after it should be GC'd all.
>>
>>
>> Just a quick question: Have you checked to make sure that that you are 
>> not keeping a reference to the beginning (or other position) of the lazy 
>> list after you're done processing 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.
>
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com 
> 
> Note that posts from new members are moderated - please be patient with 
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com 
> 
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com 
> .
> For more options, visit https://groups.google.com/d/optout.
>
>
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com 
> .
> For more options, visit https://groups.google.com/d/optout.

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

Re: Question regarding tools.analyzer.jvm and the :tag, :o-tag, and :class entries

2014-05-23 Thread guns
On Fri 23 May 2014 at 01:29:54AM +0200, Bronsa wrote:

> When using tools.analyzer.jvm you have to remember that its primary
> use-case is as a front-end for a compiler, in this case :tag and
> :o-tag serve to inform tools.emitter.jvm when to emit a cast thus
> might not always reflect the :tag meta of the expression :form.

I see, that makes sense. In that case I will attempt to preserve the
type hints in a namespaced metadata entry before calling the analyzer.

> Regarding the :tag/:o-tag difference, :o-tag (you can read it as
> "original tag") holds the static type of the node known at that point
> and might be either inferred by the :tag of some children nodes or from
> the class of the :form of the node in case it's a literal, :tag on the
> other hand can be either the same of :o-tag or hold the Class that node
> needs to be cast to, usually because of an explicit type-hint.
>
> For example, ^IPersistentCollection [] will have :o-tag PersistentVector
> and :tag IPersistentCollection.
>
> :class is an attribute of some nodes that deal with host interop forms,
> like :new, :instance-call and others and holds the Class that node deals
> with; for example it might hold the Class a :new node is going to
> instantiate, the Class an :instance-method belongs to etc.

This is very helpful, thank you very much.

> BTW, you don't need to roll your own `analyze` function providing those
> bindings, jvm/analyze already sets up the right bindings for you.

Ah, I should have looked at the source of jvm/analyze. That's much
friendlier.

Thank you for the reply!

guns


pgpp_1NFoctow.pgp
Description: PGP signature


Using records as handles vs. complete representations

2014-05-23 Thread Elliot
There seem to be two kinds of definitions of what a record could be:

1. A full representation of a resource,e.g. (defrecord User [id name age 
gender address])
2. A *handle* to a resource, e.g. (defrecord User [id]), e.g. [wikipedia] 
below

Some protocols only ever need a handle, not the full resource, e.g.:

(retrieve-from-datomic (->User 42)

But other protocols need a complete representation, e.g.:

(produce-edn-for-api (->User 42 "John Doe" 64 ...)

Is there an idiomatic approach to solving this problem?  It seems like the 
options are:

A. Define complete representations (#1 above) everywhere, and only 
partially fill them in when used as handles (e.g. (->User 42 nil nil nil 
nil).  This seems somewhat annoying and worse, makes it unclear what 
exactly is the data expected as I/O for a given function, which was 
original point of making a named, well-defined data structure.

B. Define two separate but related records (e.g. UserHandle vs. User).  
This is also somewhat annoyingly duplicative, especially since every 
protocol implemented by UserHandle will need to be re-implemented by User 
(though it could be a simple delegation thereto).

Is there a standard and/or satisfying way to solve this?  Thanks.

- Elliot


[wikipedia] http://en.wikipedia.org/wiki/Handle_%28computing%29


-- 
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 records as handles vs. complete representations

2014-05-23 Thread Stuart Sierra
I would say do one of:

- define your own constructor functions like (defn user [id] ...)
- use the map->User constructors created by defrecord
- do not specify the non-required keys as fields in the defrecord
- use plain maps



On Friday, May 23, 2014 4:47:43 PM UTC-4, Elliot wrote:
>
> There seem to be two kinds of definitions of what a record could be:
>
> 1. A full representation of a resource,e.g. (defrecord User [id name age 
> gender address])
> 2. A *handle* to a resource, e.g. (defrecord User [id]), e.g. [wikipedia] 
> below
>
> Some protocols only ever need a handle, not the full resource, e.g.:
>
> (retrieve-from-datomic (->User 42)
>
> But other protocols need a complete representation, e.g.:
>
> (produce-edn-for-api (->User 42 "John Doe" 64 ...)
>
> Is there an idiomatic approach to solving this problem?  It seems like the 
> options are:
>
> A. Define complete representations (#1 above) everywhere, and only 
> partially fill them in when used as handles (e.g. (->User 42 nil nil nil 
> nil).  This seems somewhat annoying and worse, makes it unclear what 
> exactly is the data expected as I/O for a given function, which was 
> original point of making a named, well-defined data structure.
>
> B. Define two separate but related records (e.g. UserHandle vs. User).  
> This is also somewhat annoyingly duplicative, especially since every 
> protocol implemented by UserHandle will need to be re-implemented by User 
> (though it could be a simple delegation thereto).
>
> Is there a standard and/or satisfying way to solve this?  Thanks.
>
> - Elliot
>
>
> [wikipedia] http://en.wikipedia.org/wiki/Handle_%28computing%29
>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: How to refactor data safely?

2014-05-23 Thread Armando Blancas
Jakub,

I'll be interested to learn how you work this out. I also work with data 
whose structure is known to functions in various modules, thus its very 
shape is a contract. This is coming from the other end of encapsulating 
everything in Java classes and interfaces. Also, I write test cases at a 
high level and not really as unit tests, which prevents rewriting test 
after a refactoring but will like to know how you handle that too so as to 
reduce any rework there or else whether it's worth the maintenance. 

Short of a massive refactoring of data and code, maybe writing 
data-transform function? Not sure about the proxy concept (is that data?) 
but if a function can produce the new format from the old you may start 
changing one consumer function at a time; then work on the producers until 
you can switch and remove the transform.

On Thursday, May 22, 2014 1:17:52 AM UTC-7, Jakub Holy wrote:
>
> I have a nested data structure, used by a bunch of functions that presume 
> knowledge of its structure, and I wonder how to change a part of the 
> structure in a safe way, preferably in small incremental steps, rather than 
> having my code broken until I update all the functions and tests for the 
> new structure. I believe many of you must have experiences with this, would 
> you care to share some tips?
>
> The data structure is first built incrementally and the collected data is 
> later summarized. Instead of replacing the raw data with their summary, I 
> want to keep both, so I want to wrap the data with a map; i.e. from:
> {  [ data...] }   ;; later replaced with { summary}
> to
> { {:data [data...], :summary ...}
>
> I have a number of functions operating on the structure and tests for 
> those functions (with test data that also need to be updated w.r.t. the 
> refactoring).
>
> When I change one of the functions to produce the new data structure (i.e. 
> data wrapped in a map instead of the data itself), everything else breaks. 
> So I fix some tests and another function and get even more failures. This 
> does not feel as a good way to do it as I prefer to have limited 
> redand am fond of 
> parallel 
> changefor
>  that reason.
>
> Ideally, I would have an automated refactoring or the possibility to wrap 
> the data in some kind of a two-faced proxy that could behave both as a 
> vector (towards the old code) or as a map containing the vector (towards 
> the updated code) [some thing like lenses/cursor?!]. I haven't either so I 
> guess the only option remaining is a well-controlled process of updating 
> the structure and code. Any advice?
>
> Thank you! /Jakub
> -- 
> *Forget software. Strive to make an impact, deliver a valuable change.*
>
> *(**Vær så snill og hjelp meg med å forbedre norsken **min –** skriftlig 
> og muntlig. Takk!**)*
>
> Jakub Holy
> Solutions Engineer | +47 966 23 666
> Iterate AS | www.iterate.no
> The Lean Software Development Consultancy
> - http://theholyjava.wordpress.com/ -
>  

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: how to define a variable of type collection to keep other functions.

2014-05-23 Thread Sean Corfield
On May 23, 2014, at 2:19 AM, sorin cristea  wrote:
> Thank Philippe for your advices,I came from java environment and seems I 
> still remain with some 'bad' habits.

Coming from Java, the main thing to bear in mind in Clojure is that you do not 
have "variables" in the sense you are used to and you generally avoid "loops" 
in favor of operations on whole collections (such as map/reduce).

`def` and `defn` create global bindings - they are not variable assignments - 
and you don't want `def` nested into `defn`.

You can use `let` to create local bindings (again, not variables).

Clojure has `future` built-in so you might consider something like this:

(defn sample-fc
  []
  (let [futures (repeatedly 3 (fn [] (future "task result !!!")))]
(doseq [f futures]
  (println (deref f)

Or just:

(defn sample-fc
  []
  (doseq [f (repeatedly 3 (fn [] (future "task result !!!")))]
(println @f))) ;; @f is short for (deref f)

`repeatedly` takes a count and a no-arg function and return a sequence of 
results of calling that function.

Or if you want to see the results differ:

(defn sample-fc
  []
  (doseq [f (for [i (range 3)] (future (str "task result " i "!!!")))]
(println @f)))

But all of these are still procedural in that they loop over the data and print 
results, rather than constructing data structures and transforming them (and 
ultimately printing the result).

Consider:

(defn make-tasks
  [inputs]
  (for [i inputs]
(future (str "task result " i "!!!"

(defn join-tasks
  [tasks]
  (clojure.string/join "\n" (map deref tasks)))

(println (join-tasks (make-tasks (range 3

Here we've separated out task creation (based on a sequence of inputs), task 
completion (gathering the results as a single string), and printing the result. 
Note that `map` is lazy so the actual task completion - deref - is forced by 
joining the results together since that is an eager operation.

At this point you could also do:

(-> (range 3)
make-tasks
join-tasks
println)

which makes the "pipeline" sequence of steps more obvious.

Since we've broken things down into small steps - and I mentioned `map` being 
lazy - it's instructive to see what happens if we don't "force" the mapped 
sequence to be used:

(do (map deref (make-tasks (range 3))) (println "DONE"))

This will just print DONE (and nil, the result of calling `println`) but the 
tasks will not even be created because nothing uses them. You can prove this to 
your self by adding a `println` inside the `future` call like this:

(future (do (println "RUNNING " i) (str "task result " i "!!!")))

There are several ways to "force" the mapped sequence to be used (realized). 
You could wrap it in a call to `doall`:

(do (doall (map deref (make-tasks (range 3 (println "DONE"))

This realizes the mapped sequence (but still throws away the result). You could 
use `dorun`:

(do (dorun (map deref (make-tasks (range 3 (println "DONE"))

This realizes the mapped sequence and returns nil (which is then thrown away). 
Or you could use `mapv` which produces a vector and is not lazy:

(do (mapv deref (make-tasks (range 3))) (println "DONE"))

Or you could simply loop over the tasks, calling deref and throwing the result 
away via `doseq` (which is why this is kind of procedural):

(doseq [f (make-tasks (range 3))]
  (deref f))

`doseq` returns nil.

Which you choose depends on what, if anything, you want to do with the result.

Hope that helps?

Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)





signature.asc
Description: Message signed with OpenPGP using GPGMail