Re: Synchronous watches

2009-03-01 Thread mikel



On Feb 27, 8:57 am, Rich Hickey richhic...@gmail.com wrote:
 I've added (back) synchronous watches (svn 1309+), which used to exist
 for agents, now for all reference types.

[...]

 Please try them out for your latest Cells-like and other reactive
 programs. I'd like to move this out of the experimental category.

 Feedback and questions welcome

I hope this works out well. I've folded it into my app, and am finding
it useful. They facilitate factoring out application state into a
repository object whose sole job is to keep track of such state; I can
use watches to pass updated state to a synch agent that periodically
writes the changed state to a store, or to a UI agent that updates
views. That makes for a nice decomposition of concerns.

--~--~-~--~~~---~--~~
You 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: Opinions on - macro? (was Re: Extensive use of let?)

2009-03-01 Thread Meikel Brandmeyer

Hi,

Am 01.03.2009 um 02:19 schrieb Belfabius:


I quickly learned the - macro can't be used in the same way for one
simple reason; the value that is threaded through to the forms is
always placed in the first argument position.  How about adding a
macro -- it could be called | just as in F# -- that places the value
in the last argument position?  (It's dead simple to write -- I just
copied and modified the - macro.)


See here for a in-depth discussion of the pipe macro. :)

http://groups.google.com/group/clojure/browse_frm/thread/66ff0b89229be894/c3d4a6dae45d4852

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


Re: time complexity for immutable priority queue?

2009-03-01 Thread Achim Passen

Hi,

that's a nice example of using closures to store data!

(f)first and rest look like constant time to me. count is linear time,  
but could easily be made constant time by storing the counts instead  
of recursing.

Insertion is linear time though, plus it recurses, resulting in stack  
sizes in the order of the length of the queue.

Here's a version that's roughly equivalent (including the recursion  
problem), but uses maps instead of closures:


(defn prio-insert [queue elem prio]
   (if ( prio (:prio queue (Integer/MIN_VALUE)))
 {:first elem
  :prio  prio
  :count (inc (:count queue 0))
  :rest  queue}
 (let [new-rest (prio-insert (:rest queue) elem prio)]
   (assoc queue
 :rest  new-rest
 :count (inc (:count new-rest))


user= (def pq (prio-insert nil 3 4))
#'user/pq
user= pq
{:first 3, :prio 4, :count 1, :rest nil}
user= (def pq (prio-insert pq 2 10))
#'user/pq
user= pq
{:first 2, :prio 10, :count 2, :rest {:first 3, :prio 4, :count  
1, :rest nil}}
user= (def pq (prio-insert pq 4 1))
#'user/pq
user= pq
{:first 2, :prio 10, :count 3, :rest {:first 3, :prio 4, :count  
2, :rest {:first 4, :prio 1, :count 1, :rest nil}}}
user= (:first (:rest pq))
3


Kind regards,
achim


Am 01.03.2009 um 06:31 schrieb zoglma...@gmail.com:


 After helping tutor some students earlier in the week on the subject
 of priority queues, I ended up implementing it in Clojure as a mutable
 data structure. It was straight forward, but curiosity struck and I
 implemented the priority queue as an immutable data structure. I'm
 pretty sure that 'ffirst 'first 'count and 'rest have a constant time
 complexity, but it is a little hard to wrap my mind around this code.
 Is it really constant time?

 ;- immutiable priority queue -

 (defn priority-cons [priority data queue]
  (defstruct element :priority :data)
  (let [elem (struct element priority data)
   queue-first
(if (nil? queue)
  nil
  (queue 'ffirst))
   queue-rest
  (cond
  (nil? queue)
 nil
  (nil? elem)
 (queue 'rest)
  (= priority (queue-first :priority))
 queue
  :else
 (priority-cons priority data (queue 'rest)))]
  (fn [op]
(cond (= op 'count)
(cond
 (nil? queue)
   1
 (nil? elem)
   (queue 'count)
 :else
   (inc (queue 'count)))
  (= op 'first)
(cond
 (nil? queue)
data
 (nil? elem)
nil
 (= priority (queue-first :priority))
 data
 :else
 (queue-first :data))
  (= op 'ffirst)
(cond
 (nil? queue)
elem
 (nil? elem)
nil
 (= priority (queue-first :priority))
 elem
 :else
 queue-first)
 (= op 'rest)
queue-rest
 

 ;--- testing code

 (defn print-priority-queue [queue]
  (loop [queue queue]
(if (nil? queue)
  nil
  (do
   (println (queue 'first))
   (recur (queue 'rest))

 (def a (priority-cons 10 hello nil))
 (print-priority-queue a)
 (a 'count)

 (def b (priority-cons 20 hello2 a))
 (print-priority-queue b)
 (b 'count)

 (def c (priority-cons 15 hello-m b))
 (print-priority-queue c)
 (c 'count)

 ((c 'rest) 'count)
 (((c 'rest) 'rest) 'first)
 (((c 'rest) 'rest) 'count)
 (((c 'rest) 'rest) 'rest)

 


--~--~-~--~~~---~--~~
You 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: Opinions on - macro?

2009-03-01 Thread Joshua Fox
Meikel and eyeris,
Thanks, that clarifies the usage of - even multiple parameters.

IMHO, - simplifies things where unary functions are involved and where the
list-parens are absent, so that - creates the list.

In the other cases, the standard syntax is easier on the eye.

Joshua

On Sun, Mar 1, 2009 at 12:17 AM, eyeris drewpvo...@gmail.com wrote:


 You are wrong. Many writings use ,, as a place-holder for where - is
 placing the argument. Take Meikel's example above:

(foo (bar (baz (frobnicate a-thing)) bla))

 Becomes

(- a-thing frobnicate baz (bar bla) foo)

 So bar is a function of more than one argument. Re-written with place-
 holders it would be:

(- a-thing (frobnicate ,,) (baz ,,) (bar ,, bla) (foo ,,))

 Does that make it more clear?

 -Drew

 On Feb 28, 9:39 pm, Joshua Fox joshuat...@gmail.com wrote:
  -  confuses me: Does it treat functions with multiple parameters
 different
  from functions with one parameter? Am I right that it can only be used
 with
  the latter?
  Joshua
 


--~--~-~--~~~---~--~~
You 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: Clojure + Terracotta = Yeah, Baby!

2009-03-01 Thread Paul Stadig

I've started work on a Terracotta Integration Module for Clojure
already. As I understand it, we can package up the Terracotta config
as well as any replacement classes. This way we can patch Clojure
temporarily until either Terracotta supports the features we need, or
Clojure can be rewritten so that it doesn't use classes that are
unsupported by Terracotta (if prudent and possible), and there would
be no need to fracture the Clojure code base.

I'll keep everyone apprised of my progress.


Paul

On Sat, Feb 28, 2009 at 11:35 PM, Nabib El-Rahman nabi...@gmail.com wrote:
 Its a way to package integration details into a module.  For example, if I
 want to cluster EHCache, I can drive through the code and figure out what
 data structure to share and subsequently lock on.  All that work can be
 packaged into a module for terracotta, so that way people who just want to
 use ehcache + terracotta change just include tim-ehache in terracotta
 configuration and that's it.

 the same can be done for clojure. the details can be abstract to a
 tim-clojure.

 http://www.terracotta.org/web/display/docs/Terracotta+Integration+Modules+Manual

 -Nabib

 On Sat, Feb 28, 2009 at 8:16 PM, hank williams hank...@gmail.com wroote:

   Writing a TIM is definitely the way to go, It's a place to hide the
 glue until both Terracotta and Clojure catches up with each other.

 uhhh what is a TIM?

 Thanks
 Hank


 --
 blog: whydoeseverythingsuck.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
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
-~--~~~~--~~--~--~---



could someone explain the difference between these two error messages

2009-03-01 Thread Martin DeMello

Playing with readFileToByteArray in the repl:

user= (import '(org.apache.commons.io FileUtils))
nil

user= (def dawg (FileUtils/readFileToByteArray words.dawg))
java.lang.ClassCastException (NO_SOURCE_FILE:10)

user= (FileUtils/readFileToByteArray words.dawg)
java.lang.ClassCastException: java.lang.String cannot be cast to
java.io.File (NO_SOURCE_FILE:0)

The second error message was a lot more helpful than the first - why
was the message lost en route? It doesn't always happen:

user= (/ 1 0)
java.lang.ArithmeticException: Divide by zero (NO_SOURCE_FILE:0)

user= (def a (/ 1 0))
java.lang.ArithmeticException: Divide by zero (NO_SOURCE_FILE:18)

martin

--~--~-~--~~~---~--~~
You 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: (rest ())

2009-03-01 Thread Rich Hickey


On Feb 28, 2009, at 5:45 PM, Mark Engelberg wrote:


 As Rich explained in one post, in Lisp-like languages, there is a
 certain amount of intertwining between two views of a sequence which
 is a series of linked nodes.  One way is to think about these nodes as
 just nodes with a first and rest.  Another way is to think about each
 node as representing an entire chain from this node onward to the end.
 He explained that next is more like the move from one node to
 another view, and rest is more like the view of these things as
 collections, where rest gives you the collection of everything but the
 first.

 (rest []) translates in my mind to everything but the first item of
 [].  There is no first item of [], and there isn't an
 everything-but-the-first-item of it.  It's empty.  You can't take
 something out of it.


One way to think of it is as the sequence version of:

;a set of the things other than first
(disj #{} first) = #{}

;a sequence of the things other than first
(rest ()) = ()

i.e. it's an empty container of a particular type.

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 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: If/cond thoughts..

2009-03-01 Thread GS

On Feb 25, 10:19 pm, glow glo...@gmail.com wrote:
 Hi everyone!
 I am currently learning Lisp and Clojure. A few days ago i read how
 if in Arc works and I wonder why it is not the same in Clojure:
 (if a b       ; if a then b
     c d       ; elseif c then d
       e)      ; else e.

(cond
   pred1 form1
   pred2 form2
   :else  form3)

seems pretty good to me.  I prefer that to the Arc code above.

Gavin
--~--~-~--~~~---~--~~
You 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: Clojure Continuous Integration on Tapestry360

2009-03-01 Thread Paul Stadig

If I want to install maven into my local repository from a working
copy (with local changes), how would I do so?

I would expect to be able to do mvn install, but it does not work.
The pom.xml has been gutted of any source directory definitions, so it
only builds an empty JAR. Assuming I have the maven-ant-tasks library
installed, is there an ant task to install to my local repo?


Paul

On Feb 22, 12:48 pm, Howard Lewis Ship hls...@gmail.com wrote:
 I've set up two Clojure builds on the Tapestry360 Continuous Integration Site:

 http://tapestry.formos.com/bamboo

 A trunk build runs after any changes to clojure.

 The nightly build runs every morning.

 Clojure now producesMavenartifacts in 
 thehttp://tapestry.formos.com/maven-snapshot-repositoryMavenrepository
 as part of the nightly build.

 To access the nightly snapshot inMaven, you must update your
 pom.xml's repositories element (creating it as necessary):

   repositories
         repository
             idtapestry-snapshots/id
             urlhttp://tapestry.formos.com/maven-snapshot-repository//url
         /repository
   /respositories

 You can then add a dependency for Clojure:

   dependency
      groupIdorg.clojure/groupId
      artifactIdclojure-lang/artifactId
      version1.0-SNAPSHOT/version
   /dependency

 Note that the repository includes a sources JAR (most IDEs will
 download it automatically, which may help with debugging).  In
 addition, there's a slim variant, where the core library Clojure
 sources are NOT pre-compiled:

   dependency
      groupIdorg.clojure/groupId
      artifactIdclojure-lang/artifactId
      version1.0-SNAPSHOT/version
      classifierslim/classifier
   /dependency

 The slim JAR is about half the size of the standard JAR but will,
 obviously, start up more slowly as all the scripts need to be compiled
 at runtime.

 I'd be interested in setting up the same thing for the Clojure contrib
 library ... we can set it up as a dependent build of Clojure, so that
 any change to Clojure forces a rebuild of contrib.

 --
 Howard M. Lewis Ship

 Creator Apache Tapestry and Apache HiveMind
--~--~-~--~~~---~--~~
You 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: If/cond thoughts..

2009-03-01 Thread glow

Thanks everyone for the response! As a Lisp newbie i may sound naive
but:

1) Why is cond and condp syntax inconsistent (necessity of :else)?

2) On page 1 of introduction to Lisp I read (+ 1 2) but also (+ 1 2
3). Wow prefix notation is cool. But imagine for a moment
that in an new exciting language you can write (* 1 2) but not (* 1 2
3)! You must use (cond* 1 2 3 4) and what is worse (cond* 1 2 3
4 :else 5)! Moreover since :else is necessary in cond why not (if a
b :else c)?! That looks sooo bad.

3) That Arc syntax is not colliding with current well known cond and
if (maybe except of the possibility of catching some arity
exceptions). Who is used to them might still use traditional syntax
and new players might prefer Arc's (and I believe they would).
--~--~-~--~~~---~--~~
You 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: If/cond thoughts..

2009-03-01 Thread Meikel Brandmeyer

Hi,

Am 01.03.2009 um 15:23 schrieb glow:


1) Why is cond and condp syntax inconsistent (necessity of :else)?


The syntax of cond is

  (cond
test1 clause1
test2 clause2
...)

That is the first argument will be evaluated. If it is logically true,
the second argument is evaluated and its result returned. If the
test is logically false, cond goes on with test2 and clause2 etc.
:else is simply a trick to provide an always true test. You could
also write true, 5 or Hello World! instead of :else. This is the
same eg. in Scheme.

The syntax of condp is

  (condp test-fn thing
candidate1 clause1
candidate2 clause2
...)

Here the first and second arguments are a test function and the
thing to test. condp takes the third argument and checks, whether
(test-fn candidate1 thing) returns logically true. If so clause1 is
evaluated and its result returned. Otherwise it goes on with
candidate2 and clause2. How do you specify here the :else?
So the convention is an odd clause at the end, which is then
interpreted at as else-clause if no candidate yields logically
true.

Every syntax by itself is consistent. Although the :else could
be considered a hack. Maybe cond should be adjusted to
allow an odd else-clause?

Note also, that condp throws if no candidate yields true and
no else-clause is provided. And it supports a form, where the
test-fn result is passed to the clause which is expected to be
a function.

  (condp some coll
set1 : (fn [hit] ...)
set2 : (fn [hit] ...)
...)


2) On page 1 of introduction to Lisp I read (+ 1 2) but also (+ 1 2
3). Wow prefix notation is cool. But imagine for a moment
that in an new exciting language you can write (* 1 2) but not (* 1 2
3)! You must use (cond* 1 2 3 4) and what is worse (cond* 1 2 3
4 :else 5)! Moreover since :else is necessary in cond why not (if a
b :else c)?! That looks sooo bad.


The reasons why it is like that are outlined above. And for
the case file: In almost all languages you cannot say (* 1 2 3).
You have to say (* (* 1 2) 3) aka 1 * 2 * 3.

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


Re: new Clojure article

2009-03-01 Thread panozzaj

Looks very nice.  I like the code to text ratio, it's denser than most
texts that I see of this nature.  Great job!

On Feb 28, 1:27 pm, Mark Volkmann r.mark.volkm...@gmail.com wrote:
 I've written anarticleonClojure. Seehttp://ociweb.com/jnb/jnbMar2009.html.

 The goal of thisarticleis to provide a fairly comprehensive
 introduction to theClojureprogramming language. A large number of
 features are covered, each in a fairly brief manner. Check out the
 hyperlinked table of contents.

 Thanks to all of you that have patiently answered my questions 
 aboutClojureover that past couple of months!

 While reading this, if you spot errors or just have ideas for better
 ways to explain certain concepts, please email me. I plan to make
 updates to thearticlefrequently in order to make it as valuable a
 resource as possible.

 --
 R. Mark Volkmann
 Object Computing, Inc.

--~--~-~--~~~---~--~~
You 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: Synchronous watches

2009-03-01 Thread Stuart Sierra

On Feb 27, 9:57 am, Rich Hickey richhic...@gmail.com wrote:
 I've added (back) synchronous watches (svn 1309+), which used to exist
 for agents, now for all reference types.

Cool.  I won't have much time to play with this until next week, but I
look forward to experimenting with it.

-Stuart Sierra
--~--~-~--~~~---~--~~
You 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
-~--~~~~--~~--~--~---



updated cfa

2009-03-01 Thread MikeM

I've updated cfa.clj (original thread:
http://groups.google.com/group/clojure/browse_frm/thread/ce795dd1fb646df1/e211230f5e230bc5?lnk=gstq=cfa#e211230f5e230bc5)
in the user files for SVN 1315, also many changes to (hopefully) use
more idiomatic code.

Comments 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
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: functional programming idiom

2009-03-01 Thread Michel S.

On Feb 28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote:
 hello,
 what's the common idiom in functional programming regarding checking
 the validity of arguments to functions. i think this is called
 defensive programming vs contract programming.

Mostly defensive, I think. Some languages (e.g. PLT Scheme) have
contracts:
http://docs.plt-scheme.org/guide/contracts.html

There's a new tech report on contract checking for Haskell that might
be interesting too -- I've just started reading it:
www.cl.cam.ac.uk/techreports/UCAM-CL-TR-737.pdf

Regards,

--
Michel 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
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: functional programming idiom

2009-03-01 Thread Michel S.



On Mar 1, 11:02 am, Michel S. michel.syl...@gmail.com wrote:
 On Feb 28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello,
  what's the common idiom in functional programming regarding checking
  the validity of arguments to functions. i think this is called
  defensive programming vs contract programming.

 Mostly defensive, I think. Some languages (e.g. PLT Scheme) have
 contracts:http://docs.plt-scheme.org/guide/contracts.html

Also, constructs such as Haskell's Maybe monad (available in clojure-
contrib) simplifies doing defensive programming on a chain of
computation.

Which reminds me. We have no error monad yet (not as important since
Clojure has Java exceptions, though).

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



Utility / Reflection functions

2009-03-01 Thread Kearsley Schieder-Wethy

I'm trying to get back into using Clojure a bit.  This time around
with actual package management and builds, so that I'm able to easily
import Java classes and build a Windows / Linux / Mac OS X application
in a single step.

However, I'll freely admit that I'm a Java newbie.  I get the basic
gist of the language, but find myself stalling when it comes to
finding methods and fields on an object.  One thing that I found
myself missing, deeply, was an equivalent to Python's dir function,
but for Java objects.

Essentially, I wanted a set of functions that would let me list and
search through methods, constructors and fields on a Java object.  So
I set up a few and dropped them in ~/.cljrc (My shell scripts to
launch Clojure load this, so it's a handy place to put reader
functions.

===.cljrc

(in-ns 'user)

(import '(java.util.regex Pattern Matcher)
'(java.lang.reflect Modifier))

(defn #^{:doc Takes a sequence of strings as arguments and joins them
  with the string `ch'.  If `ch' is omitted, a space (\ \) will be
  used.

  If only one string is supplied, it will be returned unchanged.  If
  no strings are supplied, an empty string (\\) is returned.
 :test (fn []
 (assert (=  (join-strings nil)))
 (assert (= a (join-strings '(a
 (assert (= a1b (join-strings 1 (list a b
 (assert (= a b c (join-strings [a b c]
 } join-strings
  ([strings]
 (join-strings   strings))
  ([ch strings]
 (let [strings (seq strings)]
   (if (empty? strings)
 
 (if (= (.size strings) 1)
   (reduce str
   
   strings)
   (reduce (fn [a b] (str a ch b))
   strings))

(defn #^{:doc Takes as arguments a regular expression and a list.
  Returns the elements of the list for which the regular expression is
  a match.

  The comparison is done against (str element), but the returned
  values are the actual elements.

  The optional `prefix' argument is passed as a prefix to all elements
  in `li', but the elements are returned without the prefix.}
  filter-list-by-re
  ([] nil)
  ([li] li)
  ([re li]
 (filter-list-by-re re  li))
  ([re prefix li]
 (let [regex (. Pattern (compile re
 (. Pattern CASE_INSENSITIVE)))]
   (filter (fn [x] (.. regex (matcher (str prefix x)) (find)))
   li


(defn #^{:doc Returns a listing of the methods, constructors and
fields of an object as a hashmap.}
  dir
  ([ob]
 (let [methods (.. ob (getClass) (getMethods))
   constructors (.. ob (getClass) (getConstructors))
   fields (.. ob (getClass) (getFields))]
   (hash-map method (seq methods)
 constructor (seq constructors)
 field (seq fields
  ([re ob]
 (let [old-map (dir ob)]
   (reduce merge
   (map (fn [key]
  (hash-map key
(filter-list-by-re re
   key
   (get old-map key
nil
(keys old-map))

(defn #^{:doc Tests if the object `ob' has a method with the name
`method-name'.  Returns true if yes, false otherwise.
 :test (fn []
 (assert (has-method? size (list 1)))
 (assert (not (has-method? ize (list 1)}
  has-method? [method-name ob]
  ( 0 (.size (get (dir (str \\W method-name \\() ob) method

(defn #^{:doc Returns the methods, constructors and fields on an
object as a single list. } list-dir
  ([ob] (list-dir  ob))
  ([re ob]
 (reduce concat
 (vals (dir re ob)

(defn #^{:doc Prints the methods, constructors and fields on an
  object, one per line.

  If the optional `re' option is specified, only methods matching that
  regular expression will be printed.

  Note that the regular expression is case insensitive and can match
  the prefixes, so (print-dir \^field\ \\) will match only fields
  for the String class }
  print-dir
  ([ob] (print-dir  ob))
  ([re ob]
 (let [old-map (dir re ob)]
   (println
(join-strings \n
  (mapcat (fn [key] (map (fn [val] (str key : 
val))
 (get old-map key)))
  (keys old-map)))

(defn #^{:doc Prints fields of `ob', one per line, showing field name
  and value.

  If the optional argument `re' is supplied, only fields matching that
  regular expression are printed.}
  print-fields
  ([ob]
 (print-fields  ob))
  ([re ob]
 (let [fields (get (dir re ob) field)]
   (println
(join-strings \n
  (map (fn [field]
 (join-strings
   
  (list (. Modifier
   (toString (. field
   

Re: Clojure + Terracotta = Yeah, Baby!

2009-03-01 Thread Luc Prefontaine
We will go for a TIM. Just looked at the doc and tes that would simplify
our work a lot.

Thank you,

Luc

On Sat, 2009-02-28 at 18:48 -0800, Nabib El-Rahman wrote:

 Hi guys,
 
 I work for Terracotta ( on the server side ) and find this work with
 Clojure + Terracotta very exciting.  Writing a TIM is definitely the
 way to go, It's a place to hide the glue until both Terracotta and
 Clojure catches up with each other. If you have any questions feel
 free to post on our forums
 http://forums.terracotta.org/forums/forums/list.page
 
 If you check out our trunk version, theres also an effort to make a
 common-api which will help writing a TIM easier for you guys.
 
 Good luck!
 
 -Nabib
 
 
 On Sat, Feb 28, 2009 at 12:02 PM, Luc Prefontane
 lprefonta...@softaddicts.ca wrote:
 
 We think the same way. Our first implementation of an
 alternative to AtomicReference
 is straightforward, we will look at improving it if the need
 arises.
 
 It will be easier to do so when we get stats from Terracotta
 after running some benchmarks.
 There's much to do before getting there.
 
 Luc
 
 
 
 
 
 On Sat, 2009-02-28 at 14:33 -0500, Paul Stadig wrote: 
 
  In the Namespace case, it might be premature optimization to worry
  about AtomicReference being replaced. If there is a way to rewrite
  that code with, say, synchronized blocks, and it will work better 
 with
  Terracotta, I think it would be worth doing. I don't think it would 
 be
  normal usage to be updating the mappings and aliases in a namespace
  1,000 times a second.
  
  AtomicReference is also used in Atom and Agent. Those cases may not 
 be
  as straight forward.
  
  
  Paul
  
  On Sat, Feb 28, 2009 at 11:51 AM, Luc Prefontaine
  lprefonta...@softaddicts.ca wrote:
  
   1) AtomicReference is used in several places. Instead of changing 
 it, we
   think we can keep
   it when Clojure runs locally and provide an alternative when 
 running in
   shared mode.
  
   AtomicReference is optimized to be efficient in a standalone JVM. 
 We would
   like to
   keep it that way. Eventually Terracotta will provide 
 instrumentation on this
   class
   by default so the shared implementation could be thrown away in 
 the near
   future.
   We see the double implementations as a transition period until 
 Terracotta
   supports
   it directly.
  
   2) Noted
  
   Shared versus local mode:
  
   That's what we have in mind, getting Clojure to work in a 
 shared mode
   versus a
   local/standalone mode. We want 0 impacts on the user code. 
 Eventually we
   could use meta data to provide some hints that would allow us to 
 fine tune
   shared interactions from user code. This would not impact local 
 mode
   behaviours.
   We're not there yet but we know that this possibility exists so 
 that's
   reassuring
   for the future.
  
   Integration is pretty simple once the common code base integrates 
 the
   necessary
   changes. We need a shell script, a Terracotta configuration that 
 will be
   maintained
   as part of the Clojure code base and some documentation.
  
   As of now we use a system property to toggle the modes, we will 
 implement a
   transparent way (testing the presence of a terracotta property 
 most
   probably).
  
  
   Luc
  
  
 
 
 
 
 -- 
 
 Luc Préfontaine
 
 Off.:(514) 993-0320
 Fax.:(514) 993-0325
 
 Armageddon was yesterday, today we have a real problem...
 
 
 
 
 
 
 
 
  

-- 

Luc Préfontaine

Off.:(514) 993-0320
Fax.:(514) 993-0325

Armageddon was yesterday, today we have a real problem...

--~--~-~--~~~---~--~~
You 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: Early registration for International Lisp Conference (Cambridge, MA, 22-25 March 2009)

2009-03-01 Thread Jeff Rose

Anyone know if they will be filming the ILC 2009?  I can't fly to 
Boston, but I'd pay to get a quality stream.

-Jeff

Stephen C. Gilardi wrote:
 Rich will be presenting a Clojure in Depth tutorial session on Sunday, 
 22 March 2009 at the International Lisp Conference taking place at MIT 
 in Cambridge, MA:
 
 http://www.international-lisp-conference.org/2009/tutorials#clojure
 
 It's scheduled in 3 parts for a total of 5 hours:
 
 http://www.international-lisp-conference.org/2009/schedule
 
 The conference agenda contains a lot more interesting Lisp-related 
 content as well:
 
 http://www.international-lisp-conference.org/2009/index
 
 I'm writing to mention this today because the early registration 
 deadline is nearly upon us.
 
 The conference fee for an individual participant is $210 on or before 1 
 March 2009 and rises to $250 after that:
 
 http://www.regonline.com/builder/site/Default.aspx?eventid=688757
 
 If you've been on the fence about attending, now is a good time to 
 conclude: There's no way I'm missing that!
 
 Cheers,
 
 --Steve
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
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: functional programming idiom

2009-03-01 Thread linh

thank you for the information

On Mar 1, 5:09 pm, Michel S. michel.syl...@gmail.com wrote:
 On Mar 1, 11:02 am, Michel S. michel.syl...@gmail.com wrote: On Feb 28, 
 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello,
   what's the common idiom in functional programming regarding checking
   the validity of arguments to functions. i think this is called
   defensive programming vs contract programming.

  Mostly defensive, I think. Some languages (e.g. PLT Scheme) have
  contracts:http://docs.plt-scheme.org/guide/contracts.html

 Also, constructs such as Haskell's Maybe monad (available in clojure-
 contrib) simplifies doing defensive programming on a chain of
 computation.

 Which reminds me. We have no error monad yet (not as important since
 Clojure has Java exceptions, though).

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



IntelliJ Clojure Plugin - Minor Indentation Issues.

2009-03-01 Thread CuppoJava

After using La Clojure a bit more, I noticed a few minor issues with
the indentation system.

Inside a let form binding, the next line should be indented to one
character past the opening bracket.

eg. should be like:
(let [i hi
  j hi])
where j lines up with i.

current behavior:
(let [i hi
 j hi])
where j lines up with [


Also
Nested forms, IMO, should be indented to be two spaces past the last
opening parenthesis.

eg. should be like:
(let [i (fn [a]
(println a))]

current behavior:
(let [i (fn [a]
   (fn [a]
  (println a)))]

Those are the only two issues I've noticed so far. Everything else is
working perfectly.
--~--~-~--~~~---~--~~
You 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
-~--~~~~--~~--~--~---



Making agents able to temporarily yield place on thread pool

2009-03-01 Thread Anand Patil

Hi all,

My concurrent dabblings in Clojure have been a real pleasure so far.
In terms of concurrency, it's just in a completely different league
from any other language I've tried. However, I think agents could be
made even more friendly by allowing them to temporarily surrender
their place in the thread pool pending another computation.

Specifically, I'm thinking of a function 'yield' called as (yield
other-agent msg-fn args) from within agent actions. If agent a yields
to agent b, a gets off the thread pool and msg is sent to b with given
args. When b finishes executing the message, the yield call returns
b's new value, and a gets back on the thread pool.

I _think_ the language could prevent deadlocks by:
- making agents not take any messages while they are 'yielded'
- keeping a 'yield stack' and checking that no cycles happen.

Here are two use cases for yield:

1) Say an 'auto-agent' cell needs to run an expensive, parallelizable
computation to update its value. Without yield you could do this by
dispatching the action with send-off, or by splitting the cell up into
multiple cells, each handling a chunk of the computation. Yield would
be nicer than both: send-off spawns an expensive kernel thread (as I
understand it) and breaking up the cell complicates the dataflow model
unnecessarily.

2) Currently this program, which creates a tree of dependent futures,
deadlocks on my 8-core mac pro:

(def breadth 4)

(defn with-deref [fun]
(fn [ x] (apply fun (map deref x

(defn future-tree [depth]
(if (= depth 0) (future 1)
(let [new-futures (map future-tree (repeat breadth (- depth
1)))]
(future (apply (with-deref +)  new-futures)

; WARNING: This deadlocks on 8-core Mac Pro!
(future-tree 4)

I'm guessing it deadlocks because the thread pool fills up with
futures that aren't ready to go, but it feels like the language should
be able to avoid the deadlock without requiring the programmer to
think about how many threads are actually in the thread pool. If
futures were based on agents, which yielded when deref-ing other
futures, the deadlock wouldn't happen.

I have no idea how hard it would be to implement yield, as I have very
little practice with Java. Thoughts?

Anand
--~--~-~--~~~---~--~~
You 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: functional programming idiom

2009-03-01 Thread Berlin Brown



On Mar 1, 12:19 pm, linh nguyenlinh.m...@gmail.com wrote:
 thank you for the information

 On Mar 1, 5:09 pm, Michel S. michel.syl...@gmail.com wrote:

  On Mar 1, 11:02 am, Michel S. michel.syl...@gmail.com wrote: On Feb 
  28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello,
what's the common idiom in functional programming regarding checking
the validity of arguments to functions. i think this is called
defensive programming vs contract programming.

   Mostly defensive, I think. Some languages (e.g. PLT Scheme) have
   contracts:http://docs.plt-scheme.org/guide/contracts.html

  Also, constructs such as Haskell's Maybe monad (available in clojure-
  contrib) simplifies doing defensive programming on a chain of
  computation.

  Which reminds me. We have no error monad yet (not as important since
  Clojure has Java exceptions, though).

  --
  Michel S.


Good that you brought this up.  I was considering of writing more
design by contract code.  It is definitely a good coding style
--~--~-~--~~~---~--~~
You 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
-~--~~~~--~~--~--~---



[PATCH] Getting substrings counting from the end

2009-03-01 Thread Phil Hagelberg

Phil Hagelberg p...@hagelb.org writes:

 It's a pretty common idiom in other languages for substring functions
 to count from the end if given a negative index.

   (substring hello world! 6 -1) ;; = world

 I'd be glad if Clojure's subs function could work like this. Should
 I create an issue and patch to implement it?

Haven't heard any response on this positive or negative.

Here's the new function definition:

(defn subs
  Returns the substring of s beginning at start inclusive, and ending
  at end (defaults to length of string), exclusive. Negative arguments
  count from the end.
  ([#^String s start] (subs s start (count s)))
  ([#^String s start end]
 (let [count-back #(if ( 0 %) (+ (count s) %) %)]
   (.substring s (count-back start) (count-back end)

Am I the only one who finds this useful? Perhaps if it's not suited for
core it could go in str-utils in contrib as substring.

Thoughts?

-Phil

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



Internal structure of evaluation results

2009-03-01 Thread David

Every now and again I try to get serious about learning Clojure and
every time I quit due to its documentation. I find it confusing.
Nothing seems to be where it should be, there are almost no examples
etc. So, every time I end up writing (in Java, I might add) a
documentation browser with index, full-text search support, bookmarks
(something similar to Eclipses help system or kchmviewer) and maybe a
possibility of adding custom examples to meta :doc with aspiration of
building a personal tutorial as I go along.

I can't seem to find a way of obtaining that information from Clojures
runtime in a standard manner, however. I tried tackling the
'problem' with evaluating a (map meta (reduce concat (map vals (map ns-
publics (all-ns) and then parsing the result using Clojures java
classes. I can do that without major problems. But I'm tired of doing
it every time when some (sub)results type gets changed (the last one
was from LazyCons to LazySeq) and I naively update everything from the
SVN.

Is there any guarantee with regard to the internal structure of
evaluation results (speaking in Java terms)? If not, is there
something planed to that effect for official release(s)?

Alternatively, what's the best (quickest, most robust, ...) way of
obtaining Clojures runtime info in a manner similar to this:

MapString, interns
// keys == distinct namespace names

interns: MapString, meta
// keys == distinct intern or public names

meta: MapString, String (or MapString, ListString for the sake
of arguments ;-) )
// keys == meta names

in a sentence: something that could be parsed from within Java using
java.lang.String and Java collection classes?

Regards,
David
--~--~-~--~~~---~--~~
You 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: [PATCH] Getting substrings counting from the end

2009-03-01 Thread Mark Volkmann

On Sun, Mar 1, 2009 at 2:13 PM, Phil Hagelberg p...@hagelb.org wrote:

 Phil Hagelberg p...@hagelb.org writes:

 It's a pretty common idiom in other languages for substring functions
 to count from the end if given a negative index.

   (substring hello world! 6 -1) ;; = world

 I'd be glad if Clojure's subs function could work like this. Should
 I create an issue and patch to implement it?

 Haven't heard any response on this positive or negative.

 Here's the new function definition:

 (defn subs
  Returns the substring of s beginning at start inclusive, and ending
  at end (defaults to length of string), exclusive. Negative arguments
  count from the end.
  ([#^String s start] (subs s start (count s)))
  ([#^String s start end]
     (let [count-back #(if ( 0 %) (+ (count s) %) %)]
       (.substring s (count-back start) (count-back end)

 Am I the only one who finds this useful? Perhaps if it's not suited for
 core it could go in str-utils in contrib as substring.

 Thoughts?

I'd like to see it added. I'm used to having that available in Ruby.

-- 
R. Mark Volkmann
Object Computing, Inc.

--~--~-~--~~~---~--~~
You 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: [PATCH] Getting substrings counting from the end

2009-03-01 Thread Michael Wood

On Sun, Mar 1, 2009 at 10:13 PM, Phil Hagelberg p...@hagelb.org wrote:

 Phil Hagelberg p...@hagelb.org writes:

 It's a pretty common idiom in other languages for substring functions
 to count from the end if given a negative index.

   (substring hello world! 6 -1) ;; = world

 I'd be glad if Clojure's subs function could work like this. Should
 I create an issue and patch to implement it?

 Haven't heard any response on this positive or negative.

 Here's the new function definition:

 (defn subs
  Returns the substring of s beginning at start inclusive, and ending
  at end (defaults to length of string), exclusive. Negative arguments
  count from the end.
  ([#^String s start] (subs s start (count s)))
  ([#^String s start end]
     (let [count-back #(if ( 0 %) (+ (count s) %) %)]
       (.substring s (count-back start) (count-back end)

 Am I the only one who finds this useful? Perhaps if it's not suited for
 core it could go in str-utils in contrib as substring.

Makes sense to me, but there's a bug in your function.  You want ( %
0) instead of ( 0 %).

-- 
Michael Wood esiot...@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
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: Internal structure of evaluation results

2009-03-01 Thread Joshua Fox
 I find it confusing. Nothing seems to be where it should be, there are
almost no examples
Just my opinion, but I think that  Clojure is very well documented, both  on
clojure.org and on various online articles.

 But I'm tired of doing it every time when some (sub)results type gets
changed
In good encapsulated fashion, Clojure guarantees the interface of its
returned objects, but not the implementation class   to its documentation
How about   doc and find-doc
user= (doc +)
user= (find-doc vec)

... namespace names
...distinct intern or public names
Take a look at fnuctions mentioned here
http://clojure.org/namespaces

like ns-name http://clojure.org/api#ns-name
ns-aliaseshttp://clojure.org/api#ns-aliases
 ns-imports http://clojure.org/api#ns-imports
ns-internshttp://clojure.org/api#ns-interns
 ns-map http://clojure.org/api#ns-map
ns-publicshttp://clojure.org/api#ns-publics
 ns-refers http://clojure.org/api#ns-refers

Joshua

On Sun, Mar 1, 2009 at 10:15 PM, David david.ra...@gmail.com wrote:


 Every now and again I try to get serious about learning Clojure and
 every time I quit due to its documentation. I find it confusing.
 Nothing seems to be where it should be, there are almost no examples
 etc. So, every time I end up writing (in Java, I might add) a
 documentation browser with index, full-text search support, bookmarks
 (something similar to Eclipses help system or kchmviewer) and maybe a
 possibility of adding custom examples to meta :doc with aspiration of
 building a personal tutorial as I go along.

 I can't seem to find a way of obtaining that information from Clojures
 runtime in a standard manner, however. I tried tackling the
 'problem' with evaluating a (map meta (reduce concat (map vals (map ns-
 publics (all-ns) and then parsing the result using Clojures java
 classes. I can do that without major problems. But I'm tired of doing
 it every time when some (sub)results type gets changed (the last one
 was from LazyCons to LazySeq) and I naively update everything from the
 SVN.

 Is there any guarantee with regard to the internal structure of
 evaluation results (speaking in Java terms)? If not, is there
 something planed to that effect for official release(s)?

 Alternatively, what's the best (quickest, most robust, ...) way of
 obtaining Clojures runtime info in a manner similar to this:

 MapString, interns
 // keys == distinct namespace names

 interns: MapString, meta
 // keys == distinct intern or public names

 meta: MapString, String (or MapString, ListString for the sake
 of arguments ;-) )
 // keys == meta names

 in a sentence: something that could be parsed from within Java using
 java.lang.String and Java collection classes?

 Regards,
 David
 


--~--~-~--~~~---~--~~
You 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: [PATCH] Getting substrings counting from the end

2009-03-01 Thread Phil Hagelberg

Michael Wood esiot...@gmail.com writes:

 Makes sense to me, but there's a bug in your function.  You want ( %
 0) instead of ( 0 %).

Quite right; good catch.

thanks,
Phil

--~--~-~--~~~---~--~~
You 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: letfn - mutually recursive local functions

2009-03-01 Thread Rich Hickey


On Mar 1, 2009, at 4:18 PM, Konrad Hinsen wrote:


 On 01.03.2009, at 01:38, Rich Hickey wrote:

 I've added letfn, which lets you define mutually recursive local
 functions a la CL's labels.

 (defn ring [n]
  (letfn [(a [n] (if (zero? n) n (b (dec n
  (b [n] (if (zero? n) n (c (dec n
  (c [n] (if (zero? n) n (a (dec n]
 (c n)))

 I noticed that letfn does not permit destructuring in its argument
 lists:

   (letfn [(a [[f  r]] f)]
 (a [1 2 3]))

   java.lang.IllegalArgumentException: fn params must be Symbols
 (NO_SOURCE_FILE:2)

 Is this intentional?


Fixed in svn 1317 - thanks for the report.

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 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Clojure + Terracotta = Yeah, Baby!

2009-03-01 Thread Amit Rathore

Are any of the folks on this thread in/around the bay area? (I know
Nabib is).
We're having a clojure user-group meeting on the 12th of March - and
the clojure/terracotta topic is of interest to a lot of people...
It would be wonderful if someone would come and talk about the
progress...

Regards,
Amit.

http://www.meetup.com/The-Bay-Area-Clojure-User-Group/

On Mar 1, 8:37 am, Luc Prefontaine lprefonta...@softaddicts.ca
wrote:
 We will go for a TIM. Just looked at the doc and tes that would simplify
 our work a lot.

 Thank you,

 Luc





 On Sat, 2009-02-28 at 18:48 -0800, Nabib El-Rahman wrote:
  Hi guys,

  I work for Terracotta ( on the server side ) and find this work with
  Clojure + Terracotta very exciting.  Writing a TIM is definitely the
  way to go, It's a place to hide the glue until both Terracotta and
  Clojure catches up with each other. If you have any questions feel
  free to post on our forums
 http://forums.terracotta.org/forums/forums/list.page

  If you check out our trunk version, theres also an effort to make a
  common-api which will help writing a TIM easier for you guys.

  Good luck!

  -Nabib

  On Sat, Feb 28, 2009 at 12:02 PM, Luc Prefontane
  lprefonta...@softaddicts.ca wrote:

          We think the same way. Our first implementation of an
          alternative to AtomicReference
          is straightforward, we will look at improving it if the need
          arises.

          It will be easier to do so when we get stats from Terracotta
          after running some benchmarks.
          There's much to do before getting there.

          Luc

          On Sat, 2009-02-28 at 14:33 -0500, Paul Stadig wrote:

           In the Namespace case, it might be premature optimization to worry
           about AtomicReference being replaced. If there is a way to rewrite
           that code with, say, synchronized blocks, and it will work better 
  with
           Terracotta, I think it would be worth doing. I don't think it 
  would be
           normal usage to be updating the mappings and aliases in a 
  namespace
           1,000 times a second.

           AtomicReference is also used in Atom and Agent. Those cases may 
  not be
           as straight forward.

           Paul

           On Sat, Feb 28, 2009 at 11:51 AM, Luc Prefontaine
           lprefonta...@softaddicts.ca wrote:

            1) AtomicReference is used in several places. Instead of 
  changing it, we
            think we can keep
            it when Clojure runs locally and provide an alternative when 
  running in
            shared mode.

            AtomicReference is optimized to be efficient in a standalone 
  JVM. We would
            like to
            keep it that way. Eventually Terracotta will provide 
  instrumentation on this
            class
            by default so the shared implementation could be thrown away 
  in the near
            future.
            We see the double implementations as a transition period until 
  Terracotta
            supports
            it directly.

            2) Noted

            Shared versus local mode:

            That's what we have in mind, getting Clojure to work in a 
  shared mode
            versus a
            local/standalone mode. We want 0 impacts on the user code. 
  Eventually we
            could use meta data to provide some hints that would allow us 
  to fine tune
            shared interactions from user code. This would not impact 
  local mode
            behaviours.
            We're not there yet but we know that this possibility exists so 
  that's
            reassuring
            for the future.

            Integration is pretty simple once the common code base 
  integrates the
            necessary
            changes. We need a shell script, a Terracotta configuration 
  that will be
            maintained
            as part of the Clojure code base and some documentation.

            As of now we use a system property to toggle the modes, we will 
  implement a
            transparent way (testing the presence of a terracotta property 
  most
            probably).

            Luc

          --

          Luc Préfontaine

          Off.:(514) 993-0320
          Fax.:(514) 993-0325

          Armageddon was yesterday, today we have a real problem...

 --

 Luc Préfontaine

 Off.:(514) 993-0320
 Fax.:(514) 993-0325

 Armageddon was yesterday, today we have a real problem...

--~--~-~--~~~---~--~~
You 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: IntelliJ Clojure Plugin - Minor Indentation Issues.

2009-03-01 Thread Ilya Sergey

Patrick,

Please, create a ticket in our bugtracker for this issue:
http://jetbrains.net/jira/browse/CLJ

With best regards,
Ilya Sergey

On Mar 1, 7:22 pm, CuppoJava patrickli_2...@hotmail.com wrote:
 After using La Clojure a bit more, I noticed a few minor issues with
 the indentation system.

 Inside a let form binding, the next line should be indented to one
 character past the opening bracket.

 eg. should be like:
 (let [i hi
       j hi])
 where j lines up with i.

 current behavior:
 (let [i hi
      j hi])
 where j lines up with [

 Also
 Nested forms, IMO, should be indented to be two spaces past the last
 opening parenthesis.

 eg. should be like:
 (let [i (fn [a]
             (println a))]

 current behavior:
 (let [i (fn [a]
    (fn [a]
       (println a)))]

 Those are the only two issues I've noticed so far. Everything else is
 working perfectly.
--~--~-~--~~~---~--~~
You 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: IntelliJ Clojure Plugin - Minor Indentation Issues.

2009-03-01 Thread Ilya Sergey

Patrick,

Please, create a ticket in our bugtracker for this issue:
http://jetbrains.net/jira/browse/CLJ

With best regards,
Ilya Sergey

On Mar 1, 7:22 pm, CuppoJava patrickli_2...@hotmail.com wrote:
 After using La Clojure a bit more, I noticed a few minor issues with
 the indentation system.

 Inside a let form binding, the next line should be indented to one
 character past the opening bracket.

 eg. should be like:
 (let [i hi
       j hi])
 where j lines up with i.

 current behavior:
 (let [i hi
      j hi])
 where j lines up with [

 Also
 Nested forms, IMO, should be indented to be two spaces past the last
 opening parenthesis.

 eg. should be like:
 (let [i (fn [a]
             (println a))]

 current behavior:
 (let [i (fn [a]
    (fn [a]
       (println a)))]

 Those are the only two issues I've noticed so far. Everything else is
 working perfectly.
--~--~-~--~~~---~--~~
You 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: Clojure + Terracotta = Yeah, Baby!

2009-03-01 Thread Luc Prefontaine
I'm in Montreal Quebec, we have several feet of snow here and still have
a month of snow storms to go.
Having some spare time I would love to visit you but there's too much
work here
and you area is a bit too far away :)))

Luc

On Sun, 2009-03-01 at 12:21 -0800, Amit Rathore wrote:

 Are any of the folks on this thread in/around the bay area? (I know
 Nabib is).
 We're having a clojure user-group meeting on the 12th of March - and
 the clojure/terracotta topic is of interest to a lot of people...
 It would be wonderful if someone would come and talk about the
 progress...
 
 Regards,
 Amit.
 
 http://www.meetup.com/The-Bay-Area-Clojure-User-Group/
 
 On Mar 1, 8:37 am, Luc Prefontaine lprefonta...@softaddicts.ca
 wrote:
  We will go for a TIM. Just looked at the doc and tes that would simplify
  our work a lot.
 
  Thank you,
 
  Luc
 
 
 
 
 
  On Sat, 2009-02-28 at 18:48 -0800, Nabib El-Rahman wrote:
   Hi guys,
 
   I work for Terracotta ( on the server side ) and find this work with
   Clojure + Terracotta very exciting.  Writing a TIM is definitely the
   way to go, It's a place to hide the glue until both Terracotta and
   Clojure catches up with each other. If you have any questions feel
   free to post on our forums
  http://forums.terracotta.org/forums/forums/list.page
 
   If you check out our trunk version, theres also an effort to make a
   common-api which will help writing a TIM easier for you guys.
 
   Good luck!
 
   -Nabib
 
   On Sat, Feb 28, 2009 at 12:02 PM, Luc Prefontane
   lprefonta...@softaddicts.ca wrote:
 
   We think the same way. Our first implementation of an
   alternative to AtomicReference
   is straightforward, we will look at improving it if the need
   arises.
 
   It will be easier to do so when we get stats from Terracotta
   after running some benchmarks.
   There's much to do before getting there.
 
   Luc
 
   On Sat, 2009-02-28 at 14:33 -0500, Paul Stadig wrote:
 
In the Namespace case, it might be premature optimization to 
   worry
about AtomicReference being replaced. If there is a way to 
   rewrite
that code with, say, synchronized blocks, and it will work 
   better with
Terracotta, I think it would be worth doing. I don't think it 
   would be
normal usage to be updating the mappings and aliases in a 
   namespace
1,000 times a second.
 
AtomicReference is also used in Atom and Agent. Those cases may 
   not be
as straight forward.
 
Paul
 
On Sat, Feb 28, 2009 at 11:51 AM, Luc Prefontaine
lprefonta...@softaddicts.ca wrote:
 
 1) AtomicReference is used in several places. Instead of 
   changing it, we
 think we can keep
 it when Clojure runs locally and provide an alternative 
   when running in
 shared mode.
 
 AtomicReference is optimized to be efficient in a standalone 
   JVM. We would
 like to
 keep it that way. Eventually Terracotta will provide 
   instrumentation on this
 class
 by default so the shared implementation could be thrown 
   away in the near
 future.
 We see the double implementations as a transition period 
   until Terracotta
 supports
 it directly.
 
 2) Noted
 
 Shared versus local mode:
 
 That's what we have in mind, getting Clojure to work in a 
   shared mode
 versus a
 local/standalone mode. We want 0 impacts on the user code. 
   Eventually we
 could use meta data to provide some hints that would allow us 
   to fine tune
 shared interactions from user code. This would not impact 
   local mode
 behaviours.
 We're not there yet but we know that this possibility exists 
   so that's
 reassuring
 for the future.
 
 Integration is pretty simple once the common code base 
   integrates the
 necessary
 changes. We need a shell script, a Terracotta configuration 
   that will be
 maintained
 as part of the Clojure code base and some documentation.
 
 As of now we use a system property to toggle the modes, we 
   will implement a
 transparent way (testing the presence of a terracotta 
   property most
 probably).
 
 Luc
 
   --
 
   Luc Préfontaine
 
   Off.:(514) 993-0320
   Fax.:(514) 993-0325
 
   Armageddon was yesterday, today we have a real problem...
 
  --
 
  Luc Préfontaine
 
  Off.:(514) 993-0320
  Fax.:(514) 993-0325
 
  Armageddon was yesterday, today we have a real problem...
 
  
 

-- 

Luc Préfontaine

Off.:(514) 993-0320
Fax.:(514) 993-0325

Armageddon was yesterday, today we have a 

Clojure desktop wallpaper request/discussion

2009-03-01 Thread Rayne

I've been wishing I had one for a while now, to replace my Haskell
wallpaper ;). Me and blbrown were talking in #Clojure and he suggested
I make this post requesting that if anyone here has skill in image
editing they could make a Clojure wallpaper. He said he wouldn't mind
having one himself. My guess would be to enlarge the Clojure icon and
go from there. I really don't care how it looks, I just suck at image
editing and would love to have a Clojure wallpaper. Anyone got any
ideas?

-Rayne
--~--~-~--~~~---~--~~
You 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: IntelliJ Clojure Plugin - Minor Indentation Issues.

2009-03-01 Thread CuppoJava

Ticket submitted.

Thanks a lot
  -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
-~--~~~~--~~--~--~---



Re: Algebraic data types in clojure.contrib

2009-03-01 Thread Rich Hickey



On Feb 26, 4:06 pm, Konrad Hinsen konrad.hin...@laposte.net wrote:
 On 26.02.2009, at 10:00, Konrad Hinsen wrote:

  I know, but as I said, my current implementation is just a proof of
  concept. It is not viable for production use for a variety of
  reasons. I was planning to replace it by something based on gen-class
  and proxy, but I will first try to get away with the new type
  function.

 I just committed a completely new implementation to clojure.contrib.
 It uses a vector with type metadata for representingalgebraicdata
 types. Overall I am rather happy with this version. It is used almost
 exactly like the previous one.

 There is probably still room for improvement, but I don't expect the
 interface to change significantly any more, so I'd say it's safe for
 adoption by adventurous Clojurians :-)


I was wondering if you considered using maps or struct-maps for this.
One of my pet peeves with algebraic data types is the unnamed,
positional nature of the components/fields. It always bothers me you
have to rename the fields in every pattern match, skip fields with _
etc.

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 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: IntelliJ Clojure Plugin - Minor Indentation Issues.

2009-03-01 Thread Asbjørn Bjørnstad


I'm not an Intellij user, but:

On Mar 2, 2:22 am, CuppoJava patrickli_2...@hotmail.com wrote:
 After using La Clojure a bit more, I noticed a few minor issues with
 the indentation system.

 Inside a let form binding, the next line should be indented to one
 character past the opening bracket.

 eg. should be like:
 (let [i hi
       j hi])
 where j lines up with i.

Agree on this.

 Also
 Nested forms, IMO, should be indented to be two spaces past the last
 opening parenthesis.

 eg. should be like:
 (let [i (fn [a]
             (println a))]

That's three spaces...

I'd say use the common indentation rules, which I thought was on space
past the last opening parenthesis. But I just looked at one of the
source files, and it's not consistent.

When a pretty-printer is in place, I guess that could become the
definition of the indentation rules.
--
  -asbjxrn
--~--~-~--~~~---~--~~
You 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: Making agents able to temporarily yield place on thread pool

2009-03-01 Thread MikeM

Not sure if I understand what you need, but could you build on the
existing capability to send to the current agent: (send *agent* ...) ?
You could have the agent send to itself, then exit the function with
some work left to do that would be restarted on the next go-around.
--~--~-~--~~~---~--~~
You 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: Making agents able to temporarily yield place on thread pool

2009-03-01 Thread Timothy Pratley

A non-important follow up question too:
When I initially implemented without a type-hint for 'pool', it didn't
work at all (deref would always be nil). I'm just curious why.
--~--~-~--~~~---~--~~
You 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
-~--~~~~--~~--~--~---



Concatenating many lists (stack overflow problem)

2009-03-01 Thread Zededarian

My ultimate goal is to get a list of all the words in a file in
order.  I have a function that will get a list of all the words on one
line of this file in order, and I want to efficiently concatenate
these lists to end up with one large list.  I'm working with about
12000 lines right now, but in a perfect world I'd like to scale much
higher.

I started off just using concat.  Basically my code looks like:
(defn getstrlist
  ([file]
 (loop [x (getline file) worklst '()]
   (if x
 (recur (getline file) (concat worklst (splitstr x)))
 worklst

Then in the REPL, if I type (def a (getstrlist FILE)), it works fine.
But if I try to output a or take (first a), I get a stack overflow
error.  I don't know why this is.  I remember hearing somewhere that
Clojure had lazy sequences, so my best guess is that it isn't actually
concatenating anything, but is storing pointers to the start of all
the lists on a stack that overflows when I try to evaluate one of
these pointers.

I know in Scheme I would write this using metalists that keep track of
the location of their last element:
(define (concat metalst1 metalst2)
  (set-cdr! (car metalst1) (cdr metalst2))
  (set-car! metalst1 (car metalst2))
  metalst1)

(define (make-metalst lst)
  (cons (get-end lst) lst))

(define (get-end lst)
  (if (null? lst)
  '()
  (if (null? (cdr lst))
  lst
  (get-end (cdr lst)

Which would be fairly efficient.  But since Clojure doesn't seem to
have real lists, I'm not quite sure how I could port this over.  I
suppose I could implement my own cons pairs like an idiot and do all
of this manually, but I figure I'm just not understanding the Clojure
solution to this problem.

--~--~-~--~~~---~--~~
You 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: Concatenating many lists (stack overflow problem)

2009-03-01 Thread Jason Wolfe

Hi,

The problem is that you end up with the front of your worklist being
wrapped in n-lines nested calls to lazy-seq, one per each call to
concat.  Then, realizing the first element causes a stack overflow.
This wouldn't happen if you reversed the arguments to concat, but then
you wouldn't get what you want.  Some possibilities (untested):

; probably the shortest, most idiomatic solution?

(defn getstrlist [file]
  (apply concat
(take-while identity
  (repeatedly #(getline file)

;or, using vectors, and written more like your solution:

(defn getstrlist [file]
  (loop [worklst []]
   (if-let [x (getline file)]
  (recur (into worklst x))
 worklst)))

Cheers,
Jason


On Mar 1, 4:53 pm, Zededarian zededar...@gmail.com wrote:
 My ultimate goal is to get a list of all the words in a file in
 order.  I have a function that will get a list of all the words on one
 line of this file in order, and I want to efficiently concatenate
 these lists to end up with one large list.  I'm working with about
 12000 lines right now, but in a perfect world I'd like to scale much
 higher.

 I started off just using concat.  Basically my code looks like:
 (defn getstrlist
   ([file]
      (loop [x (getline file) worklst '()]
        (if x
          (recur (getline file) (concat worklst (splitstr x)))
          worklst

 Then in the REPL, if I type (def a (getstrlist FILE)), it works fine.
 But if I try to output a or take (first a), I get a stack overflow
 error.  I don't know why this is.  I remember hearing somewhere that
 Clojure had lazy sequences, so my best guess is that it isn't actually
 concatenating anything, but is storing pointers to the start of all
 the lists on a stack that overflows when I try to evaluate one of
 these pointers.

 I know in Scheme I would write this using metalists that keep track of
 the location of their last element:
 (define (concat metalst1 metalst2)
   (set-cdr! (car metalst1) (cdr metalst2))
   (set-car! metalst1 (car metalst2))
   metalst1)

 (define (make-metalst lst)
   (cons (get-end lst) lst))

 (define (get-end lst)
   (if (null? lst)
       '()
       (if (null? (cdr lst))
           lst
           (get-end (cdr lst)

 Which would be fairly efficient.  But since Clojure doesn't seem to
 have real lists, I'm not quite sure how I could port this over.  I
 suppose I could implement my own cons pairs like an idiot and do all
 of this manually, but I figure I'm just not understanding the Clojure
 solution to this problem.
--~--~-~--~~~---~--~~
You 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: time complexity for immutable priority queue?

2009-03-01 Thread zoglma...@gmail.com

(for those browsing.. there is an immutable priority queue in constant
time when favorable, but not unrealistic conditions)

I woke up this morning dreaming about this queue and also recognized
that count is linear. I have changed it to be constant.

(defn priority-cons [priority data queue]
  (defstruct element :priority :data)
  (let [elem (struct element priority data)
queue-first
 (if (nil? queue)
   nil
   (queue 'ffirst))
queue-rest
   (cond
   (nil? queue)
  nil
   (nil? elem)
  (queue 'rest)
   (= priority (queue-first :priority))
  queue
   :else
  (priority-cons priority data (queue 'rest)))
count
   (cond
   (nil? queue)
  0
   (nil? elem)
  (queue 'count)
   :else
  (inc (queue 'count)))]
  (fn [op]
(cond (= op 'count)
 count
  (= op 'first)
 (cond
  (nil? queue)
 data
  (nil? elem)
 nil
  (= priority (queue-first :priority))
  data
  :else
  (queue-first :data))
  (= op 'ffirst)
 (cond
  (nil? queue)
 elem
  (nil? elem)
 nil
  (= priority (queue-first :priority))
  elem
  :else
  queue-first)
  (= op 'rest)
 queue-rest


I am beginning to wonder about insertion though. You say that
insertion is linear and it recurses, but I'm seeing exponential time
in practice. For instance, because the argument queue is a function
that has been fully evaluated (meaning that calling any op on it is
constant time), each of the function calls should be constant in
helping to build the new function. The time to insert seems to be
bogged down simply by the creation of the function which grows in size
exponentially. Maybe I'm mistaken?

(def rnd (java.util.Random.))
(time (loop [count 10]
  (if (= count 0)
nil
(do
  (.nextInt rnd 100)
  (priority-cons 10 hello nil)
  (recur (dec count))

(time (loop [queue nil count 3200]
  (if (= count 0)
nil
(do
  (recur
   (priority-cons (.nextInt rnd 100) hello queue)
   (dec count))

In playing with depth of the queue it is obvious that no one would
ever use this. :) It appears that in practice the queue takes up
exponentially amounts of memory. It seems to reach nearly 1GB with
3200 elements. I'm also guessing that the exponential amount of space
is why for every doubling of length it takes roughly 4 times as long.
This is definitely worse than linear.

best run times for increasing length of x
x  time
25.786
502.2
100  6
200  27
400  101
800  571
1600 3426
3200 11842


And to be through I wrote an implementation that is similar to your
answer. This one does not grow exponentially in space. It still
suffers from terrible performance with any large number of entries.

(defstruct element :priority :data)
(defn priq-add [priority data queue]
  (let [elem (struct element priority data)]
(loop [queue queue acc []]
  (cond (nil? queue)
   (conj acc elem)
(= priority ((first queue) :priority))
   (if (nil? acc)
 (cons elem queue)
 (concat acc (cons elem queue)))
:else
   (recur (rest queue) (conj acc (first queue)))

(def rnd (java.util.Random.))
(time (loop [queue nil count 12800]
  (if (= count 0)
nil
(do
  (let [nextInt (.nextInt rnd 100)]
(recur
 (priq-add nextInt hello queue)
 (dec count)))

And to be really through, I finally found a solution that is basically
linear in insertion and removal assuming the span of priorities is
around n/100 and evenly dispersed.

(defn priq-add [priority data queue]
  (let [priority (* -1 priority)
[cnt queue] queue]
(if (nil? queue)
  (list 1 (sorted-map priority (list data)))
  (let [pri-list (queue priority)
new-pri-list
(if (nil? pri-list)
  (list data)
  (lazy-cons data pri-list))]
(list (inc cnt) (assoc queue priority new-pri-list))

; returns list of (data, new-queue)
(defn priq-remove [queue]
  (if (nil? queue)
nil
(let [[cnt queue] queue
  key (first (keys queue))
  value (queue key)
  data (first value)
  new-queue
  (if (= (count value) 1)
(dissoc queue key)
(assoc queue key (rest value)))
  ]
  (if (= cnt 1)
(list data nil)
(list data (list (dec cnt) new-queue))

(defn priq-count [queue]
  (if (nil? queue)
0
(first queue)))


(def rnd (java.util.Random.))
(def big-q (time 

Laziness madness

2009-03-01 Thread max3000

Hi,

I find the laziness in clojure very hard to wrap my head around. I
understand the idea and it's probably nice in theory. However, in real
life it doesn't seem really useful beyond hardcore mathematical
problems.

Case in point, I just spent 2 hours debugging a piece of code (shown
below) that seemed simple enough. This is the 3rd time this week that
I've lost substantial time to laziness. I'm pretty pissed to tell the
truth and I find myself wrapping things in doseq more and more just to
be sure. I rarely use 'for' anymore, what's the point?

Here is the code that gave me trouble:

(map #(add-watch % watcher callback-fn) all-agents)

This was not executing. I had to change it to the below expression:

(doseq [agent all-labor-agents]
  (add-watch agent total-labor-agent callback-fn))

This second expression seems less elegant than the map above. Why
doesn't clojure realize that an add-watch really should actually loop
over all-agents? Why is it that Java calls are not made in similar
expressions?

Is laziness so useful that we should waste time investigating and
fixing errors like this? Sure, there could be special constructs for
laziness when we really need it. However, clojure shouldn't default to
it IMO. At this point, laziness is a nice concept but it feels
somewhat removed from reality to tell the truth. Of course I want to
iterate over my collection when I'm doing an add-watch!

What am I missing?

Thanks,

Max

--~--~-~--~~~---~--~~
You 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: Laziness madness

2009-03-01 Thread Mibu

doseq is the idiomatic way to write imperative code segments like this
(add-watch generates a side-effect). Nevertheless, I too love using
map for stuff like that. All you need to do is surround the map with
dorun (or doall if you need the return value) and it will force the
computation.

see: (doc dorun) and (doc doall)


On Mar 2, 7:06 am, max3000 maxime.lar...@gmail.com wrote:
 Hi,

 I find the laziness in clojure very hard to wrap my head around. I
 understand the idea and it's probably nice in theory. However, in real
 life it doesn't seem really useful beyond hardcore mathematical
 problems.

 Case in point, I just spent 2 hours debugging a piece of code (shown
 below) that seemed simple enough. This is the 3rd time this week that
 I've lost substantial time to laziness. I'm pretty pissed to tell the
 truth and I find myself wrapping things in doseq more and more just to
 be sure. I rarely use 'for' anymore, what's the point?

 Here is the code that gave me trouble:

     (map #(add-watch % watcher callback-fn) all-agents)

 This was not executing. I had to change it to the below expression:

     (doseq [agent all-labor-agents]
       (add-watch agent total-labor-agent callback-fn))

 This second expression seems less elegant than the map above. Why
 doesn't clojure realize that an add-watch really should actually loop
 over all-agents? Why is it that Java calls are not made in similar
 expressions?

 Is laziness so useful that we should waste time investigating and
 fixing errors like this? Sure, there could be special constructs for
 laziness when we really need it. However, clojure shouldn't default to
 it IMO. At this point, laziness is a nice concept but it feels
 somewhat removed from reality to tell the truth. Of course I want to
 iterate over my collection when I'm doing an add-watch!

 What am I missing?

 Thanks,

 Max
--~--~-~--~~~---~--~~
You 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: Concatenating many lists (stack overflow problem)

2009-03-01 Thread Zededarian

Thanks!

One follow up question, though: will the first solution take O(n^2)
time, or is clojure clever enough to keep track of where the end of a
sequence is on its own (or, alternately, to start by concatenating the
last two elements and working backward)?  Or does it do some other
cool magic to make this quick?

On Mar 1, 9:07 pm, Jason Wolfe jawo...@berkeley.edu wrote:
 Hi,

 The problem is that you end up with the front of your worklist being
 wrapped in n-lines nested calls to lazy-seq, one per each call to
 concat.  Then, realizing the first element causes a stack overflow.
 This wouldn't happen if you reversed the arguments to concat, but then
 you wouldn't get what you want.  Some possibilities (untested):

 ; probably the shortest, most idiomatic solution?

 (defn getstrlist [file]
   (apply concat
     (take-while identity
       (repeatedly #(getline file)

 ;or, using vectors, and written more like your solution:

 (defn getstrlist [file]
   (loop [worklst []]
    (if-let [x (getline file)]
       (recur (into worklst x))
      worklst)))

 Cheers,
 Jason

 On Mar 1, 4:53 pm, Zededarian zededar...@gmail.com wrote:

  My ultimate goal is to get a list of all the words in a file in
  order.  I have a function that will get a list of all the words on one
  line of this file in order, and I want to efficiently concatenate
  these lists to end up with one large list.  I'm working with about
  12000 lines right now, but in a perfect world I'd like to scale much
  higher.

  I started off just using concat.  Basically my code looks like:
  (defn getstrlist
    ([file]
       (loop [x (getline file) worklst '()]
         (if x
           (recur (getline file) (concat worklst (splitstr x)))
           worklst

  Then in the REPL, if I type (def a (getstrlist FILE)), it works fine.
  But if I try to output a or take (first a), I get a stack overflow
  error.  I don't know why this is.  I remember hearing somewhere that
  Clojure had lazy sequences, so my best guess is that it isn't actually
  concatenating anything, but is storing pointers to the start of all
  the lists on a stack that overflows when I try to evaluate one of
  these pointers.

  I know in Scheme I would write this using metalists that keep track of
  the location of their last element:
  (define (concat metalst1 metalst2)
    (set-cdr! (car metalst1) (cdr metalst2))
    (set-car! metalst1 (car metalst2))
    metalst1)

  (define (make-metalst lst)
    (cons (get-end lst) lst))

  (define (get-end lst)
    (if (null? lst)
        '()
        (if (null? (cdr lst))
            lst
            (get-end (cdr lst)

  Which would be fairly efficient.  But since Clojure doesn't seem to
  have real lists, I'm not quite sure how I could port this over.  I
  suppose I could implement my own cons pairs like an idiot and do all
  of this manually, but I figure I'm just not understanding the Clojure
  solution to this problem.
--~--~-~--~~~---~--~~
You 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: Laziness madness

2009-03-01 Thread David Nolen
Remember that you can force lazy sequences if you need to as you are with
doseq with doall (retains head) and dorun (does not) as well.
You probably want

(dorun (map #(add-watch % watcher callback-fn) all-agents))

I think it's pretty clear here what's going on.  Your code needs
side-effects. In Clojure side-effect code tends to stands out.

I sympathize with your frustration, I remember getting excited about Lisp
macros but spending many many long hours trying to understand how to write
even a simple one.

Similarly I think lazy sequences are worth the initial frustration ;)

On Mon, Mar 2, 2009 at 12:06 AM, max3000 maxime.lar...@gmail.com wrote:


 Hi,

 I find the laziness in clojure very hard to wrap my head around. I
 understand the idea and it's probably nice in theory. However, in real
 life it doesn't seem really useful beyond hardcore mathematical
 problems.

 Case in point, I just spent 2 hours debugging a piece of code (shown
 below) that seemed simple enough. This is the 3rd time this week that
 I've lost substantial time to laziness. I'm pretty pissed to tell the
 truth and I find myself wrapping things in doseq more and more just to
 be sure. I rarely use 'for' anymore, what's the point?

 Here is the code that gave me trouble:

(map #(add-watch % watcher callback-fn) all-agents)

 This was not executing. I had to change it to the below expression:

(doseq [agent all-labor-agents]
  (add-watch agent total-labor-agent callback-fn))

 This second expression seems less elegant than the map above. Why
 doesn't clojure realize that an add-watch really should actually loop
 over all-agents? Why is it that Java calls are not made in similar
 expressions?

 Is laziness so useful that we should waste time investigating and
 fixing errors like this? Sure, there could be special constructs for
 laziness when we really need it. However, clojure shouldn't default to
 it IMO. At this point, laziness is a nice concept but it feels
 somewhat removed from reality to tell the truth. Of course I want to
 iterate over my collection when I'm doing an add-watch!

 What am I missing?

 Thanks,

 Max

 


--~--~-~--~~~---~--~~
You 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: Concatenating many lists (stack overflow problem)

2009-03-01 Thread Jason Wolfe

No, it will be O(n), where the cool magic is in the use of lazy  
sequences.

Here's a very simple way to write an O(n) lazy concat:

user (defn my-concat [ seqs]
(when-first [s seqs]
  (if (seq s)
  (lazy-seq (cons (first s) (apply my-concat (rest s) (rest  
seqs
  (recur (rest seqs)

user (my-concat '(1 2 3) [4 5] '(6 7))
(1 2 3 4 5 6 7)

This is not proper lazy programming style, but it should give you the  
basic idea.

The actual definition of concat is significantly more complicated:

user (source concat)
(defn concat
   Returns a lazy seq representing the concatenation of the elements  
in the supplied colls.
   ([] (lazy-seq nil))
   ([x] (lazy-seq x))
   ([x y]
  (lazy-seq
   (let [s (seq x)]
 (if s
   (cons (first s) (concat (rest s) y))
   y
   ([x y  zs]
  (let [cat (fn cat [xys zs]
  (lazy-seq
   (let [xys (seq xys)]
 (if xys
   (cons (first xys) (cat (rest xys) zs))
   (when zs
 (cat (first zs) (next zs)))]
(cat (concat x y) zs

-Jason



On Mar 1, 2009, at 9:47 PM, Zededarian wrote:


 Thanks!

 One follow up question, though: will the first solution take O(n^2)
 time, or is clojure clever enough to keep track of where the end of a
 sequence is on its own (or, alternately, to start by concatenating the
 last two elements and working backward)?  Or does it do some other
 cool magic to make this quick?

 On Mar 1, 9:07 pm, Jason Wolfe jawo...@berkeley.edu wrote:
 Hi,

 The problem is that you end up with the front of your worklist being
 wrapped in n-lines nested calls to lazy-seq, one per each call to
 concat.  Then, realizing the first element causes a stack overflow.
 This wouldn't happen if you reversed the arguments to concat, but  
 then
 you wouldn't get what you want.  Some possibilities (untested):

 ; probably the shortest, most idiomatic solution?

 (defn getstrlist [file]
   (apply concat
 (take-while identity
   (repeatedly #(getline file)

 ;or, using vectors, and written more like your solution:

 (defn getstrlist [file]
   (loop [worklst []]
(if-let [x (getline file)]
   (recur (into worklst x))
  worklst)))

 Cheers,
 Jason

 On Mar 1, 4:53 pm, Zededarian zededar...@gmail.com wrote:

 My ultimate goal is to get a list of all the words in a file in
 order.  I have a function that will get a list of all the words on  
 one
 line of this file in order, and I want to efficiently concatenate
 these lists to end up with one large list.  I'm working with about
 12000 lines right now, but in a perfect world I'd like to scale much
 higher.

 I started off just using concat.  Basically my code looks like:
 (defn getstrlist
   ([file]
  (loop [x (getline file) worklst '()]
(if x
  (recur (getline file) (concat worklst (splitstr x)))
  worklst

 Then in the REPL, if I type (def a (getstrlist FILE)), it works  
 fine.
 But if I try to output a or take (first a), I get a stack overflow
 error.  I don't know why this is.  I remember hearing somewhere that
 Clojure had lazy sequences, so my best guess is that it isn't  
 actually
 concatenating anything, but is storing pointers to the start of all
 the lists on a stack that overflows when I try to evaluate one of
 these pointers.

 I know in Scheme I would write this using metalists that keep  
 track of
 the location of their last element:
 (define (concat metalst1 metalst2)
   (set-cdr! (car metalst1) (cdr metalst2))
   (set-car! metalst1 (car metalst2))
   metalst1)

 (define (make-metalst lst)
   (cons (get-end lst) lst))

 (define (get-end lst)
   (if (null? lst)
   '()
   (if (null? (cdr lst))
   lst
   (get-end (cdr lst)

 Which would be fairly efficient.  But since Clojure doesn't seem to
 have real lists, I'm not quite sure how I could port this over.  I
 suppose I could implement my own cons pairs like an idiot and do all
 of this manually, but I figure I'm just not understanding the  
 Clojure
 solution to this problem.
 


--~--~-~--~~~---~--~~
You 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: Laziness madness

2009-03-01 Thread max3000

Thanks for the pointers. I was indeed able to make it work with
dorun. ;)

Still, I'm not sure I understand what all the fuss is about regarding
laziness. I'll take your word for it for now but I hope to grock it
eventually.

Thanks!

Max


On Mar 2, 12:30 am, David Nolen dnolen.li...@gmail.com wrote:
 Remember that you can force lazy sequences if you need to as you are with
 doseq with doall (retains head) and dorun (does not) as well.
 You probably want

 (dorun (map #(add-watch % watcher callback-fn) all-agents))

 I think it's pretty clear here what's going on.  Your code needs
 side-effects. In Clojure side-effect code tends to stands out.

 I sympathize with your frustration, I remember getting excited about Lisp
 macros but spending many many long hours trying to understand how to write
 even a simple one.

 Similarly I think lazy sequences are worth the initial frustration ;)

 On Mon, Mar 2, 2009 at 12:06 AM, max3000 maxime.lar...@gmail.com wrote:

  Hi,

  I find the laziness in clojure very hard to wrap my head around. I
  understand the idea and it's probably nice in theory. However, in real
  life it doesn't seem really useful beyond hardcore mathematical
  problems.

  Case in point, I just spent 2 hours debugging a piece of code (shown
  below) that seemed simple enough. This is the 3rd time this week that
  I've lost substantial time to laziness. I'm pretty pissed to tell the
  truth and I find myself wrapping things in doseq more and more just to
  be sure. I rarely use 'for' anymore, what's the point?

  Here is the code that gave me trouble:

     (map #(add-watch % watcher callback-fn) all-agents)

  This was not executing. I had to change it to the below expression:

     (doseq [agent all-labor-agents]
       (add-watch agent total-labor-agent callback-fn))

  This second expression seems less elegant than the map above. Why
  doesn't clojure realize that an add-watch really should actually loop
  over all-agents? Why is it that Java calls are not made in similar
  expressions?

  Is laziness so useful that we should waste time investigating and
  fixing errors like this? Sure, there could be special constructs for
  laziness when we really need it. However, clojure shouldn't default to
  it IMO. At this point, laziness is a nice concept but it feels
  somewhat removed from reality to tell the truth. Of course I want to
  iterate over my collection when I'm doing an add-watch!

  What am I missing?

  Thanks,

  Max
--~--~-~--~~~---~--~~
You 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: Laziness madness

2009-03-01 Thread Laurent PETIT
Hello,

The way I think about it is am I in a portion of code that does pure
functional stuff, or am I doing side effects ?
A pure functional stuff resembles a computation, but not the storage part,
or the part that gets the stuff from the outside (that is, no input / output
stuff).

doing side effects is when your function not only responds to a call to it
by reading its input data and computing a new one that it returns, but also
when it reads the input data, does some stuff to change the world (by
accessing functions that will permanently change the world), and also
(maybe) return a value.
In this case, generally, comes with the non pure stuff the need to control
the flow of execution of your program. That is : function A must be called
before function B, and the effects of A on the world must have been
realized before function B can run.

In your case, you're calling add-watch which is clearly (to me) a
side-effect function because it adds watchers to a long list of watchees by
modifying them in place (side-effect).

Generally speaking, if this talk about side-effect free function is still
a little bit unclear to you, here are some smells to guess if a given
function is pure or not :

- does the function return a value (different from nil) ? If no - probably
a function with side effect .. or a function that really does nothing !
- does the function return newly computed values ? If no - probably a
function with side effect .. or a function that really does nothing !
(please note that the inverse is not true : you can't say that a function is
pure just because it returns a new computed value of something)

I would like to add a third rule to this list, but currently you will not
encounter it for a lot of cases, yet it is correct in a number of case and I
think it applies correctly to those cases :
- does the function implementation use calls to functions ending with a !  (
e.g. set!) : those functions are performing side effects by permanently
changing the value of something in the world.

HTH,

-- 
Laurent

2009/3/2 max3000 maxime.lar...@gmail.com


 Hi,

 I find the laziness in clojure very hard to wrap my head around. I
 understand the idea and it's probably nice in theory. However, in real
 life it doesn't seem really useful beyond hardcore mathematical
 problems.

 Case in point, I just spent 2 hours debugging a piece of code (shown
 below) that seemed simple enough. This is the 3rd time this week that
 I've lost substantial time to laziness. I'm pretty pissed to tell the
 truth and I find myself wrapping things in doseq more and more just to
 be sure. I rarely use 'for' anymore, what's the point?

 Here is the code that gave me trouble:

(map #(add-watch % watcher callback-fn) all-agents)

 This was not executing. I had to change it to the below expression:

(doseq [agent all-labor-agents]
  (add-watch agent total-labor-agent callback-fn))

 This second expression seems less elegant than the map above. Why
 doesn't clojure realize that an add-watch really should actually loop
 over all-agents? Why is it that Java calls are not made in similar
 expressions?

 Is laziness so useful that we should waste time investigating and
 fixing errors like this? Sure, there could be special constructs for
 laziness when we really need it. However, clojure shouldn't default to
 it IMO. At this point, laziness is a nice concept but it feels
 somewhat removed from reality to tell the truth. Of course I want to
 iterate over my collection when I'm doing an add-watch!

 What am I missing?

 Thanks,

 Max

 


--~--~-~--~~~---~--~~
You 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: Laziness madness

2009-03-01 Thread Timothy Pratley

Quite a frequent occurrence, welcome to the club!

One simple check that the Clojure compiler could make is to produce a
warning if any lazy result is discarded. I think that would catch 90%
of the problems and give the user an immediate clue what to
investigate. Well it sounds simple, but I have no idea where to start
implementing it.

To me the big win of laziness is dealing with large collections, which
would otherwise break.

Regards,
Tim.




On Mar 2, 4:06 pm, max3000 maxime.lar...@gmail.com wrote:
 Hi,

 I find the laziness in clojure very hard to wrap my head around. I
 understand the idea and it's probably nice in theory. However, in real
 life it doesn't seem really useful beyond hardcore mathematical
 problems.

 Case in point, I just spent 2 hours debugging a piece of code (shown
 below) that seemed simple enough. This is the 3rd time this week that
 I've lost substantial time to laziness. I'm pretty pissed to tell the
 truth and I find myself wrapping things in doseq more and more just to
 be sure. I rarely use 'for' anymore, what's the point?

 Here is the code that gave me trouble:

     (map #(add-watch % watcher callback-fn) all-agents)

 This was not executing. I had to change it to the below expression:

     (doseq [agent all-labor-agents]
       (add-watch agent total-labor-agent callback-fn))

 This second expression seems less elegant than the map above. Why
 doesn't clojure realize that an add-watch really should actually loop
 over all-agents? Why is it that Java calls are not made in similar
 expressions?

 Is laziness so useful that we should waste time investigating and
 fixing errors like this? Sure, there could be special constructs for
 laziness when we really need it. However, clojure shouldn't default to
 it IMO. At this point, laziness is a nice concept but it feels
 somewhat removed from reality to tell the truth. Of course I want to
 iterate over my collection when I'm doing an add-watch!

 What am I missing?

 Thanks,

 Max
--~--~-~--~~~---~--~~
You 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: Laziness madness

2009-03-01 Thread Stu Hood
Laziness hit home for me in Clojure when I noticed that one of our Java
library functions, looking for a Collection, had happily accepted a Clojure
(map ...) object which was going to expand a small set of integers into much
larger objects. Because Clojure deferred the work, they were only generated
when they were actually needed, and saved memory the rest of the time.

Thanks,
Stu


On Mon, Mar 2, 2009 at 1:17 AM, Laurent PETIT laurent.pe...@gmail.comwrote:

 Hello,

 The way I think about it is am I in a portion of code that does pure
 functional stuff, or am I doing side effects ?
 A pure functional stuff resembles a computation, but not the storage
 part, or the part that gets the stuff from the outside (that is, no input /
 output stuff).

 doing side effects is when your function not only responds to a call to
 it by reading its input data and computing a new one that it returns, but
 also when it reads the input data, does some stuff to change the world (by
 accessing functions that will permanently change the world), and also
 (maybe) return a value.
 In this case, generally, comes with the non pure stuff the need to
 control the flow of execution of your program. That is : function A must be
 called before function B, and the effects of A on the world must have been
 realized before function B can run.

 In your case, you're calling add-watch which is clearly (to me) a
 side-effect function because it adds watchers to a long list of watchees by
 modifying them in place (side-effect).

 Generally speaking, if this talk about side-effect free function is still
 a little bit unclear to you, here are some smells to guess if a given
 function is pure or not :

 - does the function return a value (different from nil) ? If no - probably
 a function with side effect .. or a function that really does nothing !
 - does the function return newly computed values ? If no - probably a
 function with side effect .. or a function that really does nothing !
 (please note that the inverse is not true : you can't say that a function is
 pure just because it returns a new computed value of something)

 I would like to add a third rule to this list, but currently you will not
 encounter it for a lot of cases, yet it is correct in a number of case and I
 think it applies correctly to those cases :
 - does the function implementation use calls to functions ending with a !
 ( e.g. set!) : those functions are performing side effects by permanently
 changing the value of something in the world.

 HTH,

 --
 Laurent

 2009/3/2 max3000 maxime.lar...@gmail.com


 Hi,

 I find the laziness in clojure very hard to wrap my head around. I
 understand the idea and it's probably nice in theory. However, in real
 life it doesn't seem really useful beyond hardcore mathematical
 problems.

 Case in point, I just spent 2 hours debugging a piece of code (shown
 below) that seemed simple enough. This is the 3rd time this week that
 I've lost substantial time to laziness. I'm pretty pissed to tell the
 truth and I find myself wrapping things in doseq more and more just to
 be sure. I rarely use 'for' anymore, what's the point?

 Here is the code that gave me trouble:

(map #(add-watch % watcher callback-fn) all-agents)

 This was not executing. I had to change it to the below expression:

(doseq [agent all-labor-agents]
  (add-watch agent total-labor-agent callback-fn))

 This second expression seems less elegant than the map above. Why
 doesn't clojure realize that an add-watch really should actually loop
 over all-agents? Why is it that Java calls are not made in similar
 expressions?

 Is laziness so useful that we should waste time investigating and
 fixing errors like this? Sure, there could be special constructs for
 laziness when we really need it. However, clojure shouldn't default to
 it IMO. At this point, laziness is a nice concept but it feels
 somewhat removed from reality to tell the truth. Of course I want to
 iterate over my collection when I'm doing an add-watch!

 What am I missing?

 Thanks,

 Max





 


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