Re: Can I make this faster?

2010-02-18 Thread Jason Wolfe
Hey Aria,

If you really want a mutable Counter, IMO you might as well do things
your "Java" way with a HashMap ... or at least that's how I would do
it.

A more Clojure way would be a totally safe, functional counter:

(deftype ClojureCounter2 [counts total]
  Counter
(getCount [k] (get counts k 0.0))
(incCount! [k v] (ClojureCounter2. (assoc counts k (+ v (get
counts k 0.0))) (+ total v)))
(totalCount [] total))

(defn make-cc2 []
  (ClojureCounter2 {} 0.0))

And, by my measurements, it's twice as fast as your mutable Clojure
version when run in the following harness:

(defn testFunctionalCounter [counter]
  (let [r (java.util.Random. 0)]
(loop [counter counter i (int 100)]
  (when-not (== i (int 0))
(recur (incCount! counter (.nextInt r 10) (.nextDouble r))
(dec i))

If you want to keep to a functional style but don't care if old copies
of the counter get trashed (be careful!), you can easily switch to
transients:

(deftype ClojureCounter3 [counts total]
  Counter
(getCount [k] (get counts k 0.0))
(incCount! [k v] (ClojureCounter3. (assoc! counts k (+ v (get
counts k 0.0))) (+ total v)))
(totalCount [] total))

(defn make-cc3 []
  (ClojureCounter3 (transient {}) 0.0))

which gives you another > 2x speedup, bringing it to within ~50% of
the Java version.

HTH, Jason


On Feb 17, 2:40 am, aria42  wrote:
> Hi all, I was playing with the defprotocol/deftype/reify stuff in 1.2,
> and I wanted to test how a common abstraction I use would look if I
> did with java data structures vs. clojure ones. I've pasted the code
> below. I'll wait for you to take a lookSo on my test, I have the
> Clojure version about 5x slower than the Java one only one cpu. Now I
> know that JavaMapCounter isn't thread safe, while ClojureCounter is,
> and that if I had sufficiently many cpus, the clojure version would be
> faster. But is there a better way to do what I'm doing with clojure to
> get the performance a bit more up to par with javas?
>
> Thanks, Aria
>
> (defprotocol Counter
>   (getCount [_ k])
>   (incCount! [_ k v])
>   (totalCount [_]))
>
> (defn JavaMapCounter []
>   (let [counts (java.util.HashMap.)
>         total (org.apache.commons.lang.mutable.MutableDouble.)]
>     (reify :as self
>      Counter
>      (getCount [k] (.get counts k))
>      (incCount! [k v]
>        (let [cur-v (if-let [x (getCount self k)] x 0.0)]
>         (.put counts k (+ v cur-v)))
>        (.setValue total (+ (.doubleValue total) v)))
>      (totalCount [] (.doubleValue total)
>
> (defn ClojureCounter []
>   (let [state (atom {:counts (hash-map) :total 0.0})]
>     (reify :as self
>      Counter
>      (getCount [k] (if-let [x (get-in @state [:counts,k])] x 0.0))
>      (incCount! [k v]
>        (swap! state
>          (fn [data]
>            (let [add-v (fn [x] (if x (+ x v) v))]
>               (-> data (update-in  [:counts,k] add-v)
>                        (update-in [:total] add-v))
>      (totalCount [] (:total @state)
>
> (defn testCounter [counter]
>   (let [r (java.util.Random. 0)]
>     (dotimes  [_ 100]
>       (incCount! counter (.nextInt r 10) (.nextDouble r)
>
> (time (testCounter (JavaMapCounter)))
> (time (testCounter (ClojureCounter)))

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


Re: jmx with auth

2010-02-18 Thread Stuart Halloway

Hi Drz,

Just pushed a fix, let me know if it works for you. 
http://github.com/richhickey/clojure-contrib/commit/6f2b1d73b50b7b9f0d753aa0f5fd343b67f75bf6

Stu


I am just starting to play around with clojure.  I was trying to use
the clojure.contrib.jmx library to connect to remote java vms that
require auth (-Dcom.sun.management.jmxremote.password.file=blah -
Dcom.sun.management.jmxremote.access.file=blah).  Looking at the java
docs, I need to add "jmx.remote.credentials" into the environment map
with the value of ["username" "password"].  I tested this out by
creating a with-connection macro in my own namespace and changing the
{} to {"jmx.remote.credentials" (into-array ["username"
"password"])}.  That worked just fine for testing, but is not a long
term solution.  Does anyone have a suggestion as to how I could get
this kind of functionality integrated into jmx library?  I tried to
contact Stuart Halloway via github with no luck.  If getting this into
the library isn't an option, does anyone have any suggestions on an
elegant way to add this without essentially duplicating with-
connection macro?

 Drz

--  
You received this message because you are subscribed to the Google

Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


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


side effects in fn passed to filter

2010-02-18 Thread Rowdy Rednose
The filter documentation reads:

"Returns a lazy sequence of the items in coll for which (pred item)
returns true. pred must be free of side-effects."

So that means I should not write a function like this:

(defn unique [sc]
  "Returns a lazy sequence with all consecutive duplicates removed"
  (let [last (atom (Object.))]
(filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))

user=> (unique [1 2 3 3 4 5 5 6])
(1 2 3 4 5 6)

But in contrast to functions that can be retried (compare-and-swap
etc.), I don't immediately see why having side effects in filter would
be bad. Can anybody enlighten me? And how should I do this instead?

Thanks

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


Re: side effects in fn passed to filter

2010-02-18 Thread Rowdy Rednose
I just noticed I put the doc string in the wrong place. So this would
be the correct way:

(defn unique
  "Returns a lazy sequence with all consecutive duplicates removed"
  [sc]
  (let [last (atom (Object.))]
(filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))

On Feb 18, 11:04 pm, Rowdy Rednose  wrote:
> The filter documentation reads:
>
> "Returns a lazy sequence of the items in coll for which (pred item)
> returns true. pred must be free of side-effects."
>
> So that means I should not write a function like this:
>
> (defn unique [sc]
>   "Returns a lazy sequence with all consecutive duplicates removed"
>   (let [last (atom (Object.))]
> (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> user=> (unique [1 2 3 3 4 5 5 6])
> (1 2 3 4 5 6)
>
> But in contrast to functions that can be retried (compare-and-swap
> etc.), I don't immediately see why having side effects in filter would
> be bad. Can anybody enlighten me? And how should I do this instead?
>
> Thanks

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


Re: side effects in fn passed to filter

2010-02-18 Thread Sean Devlin
The first thing I can think of is that filter is lazy.  You side
effects won't occur when you think they will.  Generally if you're
dealing with side-effects over a sequence, it's time to think about
using a macro, such as doseq.

In your specific case, I'd recommend using a custom form of reduce,
something that returned

[your-filtered-seq last-element]

HTH,
Sean

On Feb 18, 9:04 am, Rowdy Rednose  wrote:
> The filter documentation reads:
>
> "Returns a lazy sequence of the items in coll for which (pred item)
> returns true. pred must be free of side-effects."
>
> So that means I should not write a function like this:
>
> (defn unique [sc]
>   "Returns a lazy sequence with all consecutive duplicates removed"
>   (let [last (atom (Object.))]
>     (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> user=> (unique [1 2 3 3 4 5 5 6])
> (1 2 3 4 5 6)
>
> But in contrast to functions that can be retried (compare-and-swap
> etc.), I don't immediately see why having side effects in filter would
> be bad. Can anybody enlighten me? And how should I do this instead?
>
> Thanks

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


Re: side effects in fn passed to filter

2010-02-18 Thread Stuart Halloway

(use 'clojure.contrib.seq-utils)

(def by-pairs
  (partial partition-all 2 1))

; ignores possibility of nil (exercise for reader)
(defn matched-pair?
  [[a b]]
  (= a b))

; I think this is very literate
(println (let [x [1 2 3 4 5 5 5 6]]
   (->> (by-pairs x)
(remove matched-pair?)
(map first


The first thing I can think of is that filter is lazy.  You side
effects won't occur when you think they will.  Generally if you're
dealing with side-effects over a sequence, it's time to think about
using a macro, such as doseq.

In your specific case, I'd recommend using a custom form of reduce,
something that returned

[your-filtered-seq last-element]

HTH,
Sean

On Feb 18, 9:04 am, Rowdy Rednose  wrote:

The filter documentation reads:

"Returns a lazy sequence of the items in coll for which (pred item)
returns true. pred must be free of side-effects."

So that means I should not write a function like this:

(defn unique [sc]
  "Returns a lazy sequence with all consecutive duplicates removed"
  (let [last (atom (Object.))]
(filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))

user=> (unique [1 2 3 3 4 5 5 6])
(1 2 3 4 5 6)

But in contrast to functions that can be retried (compare-and-swap
etc.), I don't immediately see why having side effects in filter  
would

be bad. Can anybody enlighten me? And how should I do this instead?

Thanks


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


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


Re: side effects in fn passed to filter

2010-02-18 Thread Meikel Brandmeyer
Hi,

On Feb 18, 3:04 pm, Rowdy Rednose  wrote:

> "Returns a lazy sequence of the items in coll for which (pred item)
> returns true. pred must be free of side-effects."
>
> So that means I should not write a function like this:
>
> (defn unique [sc]
>   "Returns a lazy sequence with all consecutive duplicates removed"
>   (let [last (atom (Object.))]
>     (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> user=> (unique [1 2 3 3 4 5 5 6])
> (1 2 3 4 5 6)
>
> But in contrast to functions that can be retried (compare-and-swap
> etc.), I don't immediately see why having side effects in filter would
> be bad. Can anybody enlighten me? And how should I do this instead?

Besides the other suggestions: clojure.core/distinct and its
implementation.

Sincerely
Meikel

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


Re: side effects in fn passed to filter

2010-02-18 Thread Stuart Halloway
Rowdy's question asks for less than what core/distinct delivers--he  
only wanted to remove *adjacent* duplicates.


That said, core/distinct is a better demo of "how do I maintain state  
across a lazy sequence without requiring any mutation?"


Stu


Hi,

On Feb 18, 3:04 pm, Rowdy Rednose  wrote:


"Returns a lazy sequence of the items in coll for which (pred item)
returns true. pred must be free of side-effects."

So that means I should not write a function like this:

(defn unique [sc]
  "Returns a lazy sequence with all consecutive duplicates removed"
  (let [last (atom (Object.))]
(filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))

user=> (unique [1 2 3 3 4 5 5 6])
(1 2 3 4 5 6)

But in contrast to functions that can be retried (compare-and-swap
etc.), I don't immediately see why having side effects in filter  
would

be bad. Can anybody enlighten me? And how should I do this instead?


Besides the other suggestions: clojure.core/distinct and its
implementation.

Sincerely
Meikel

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


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


bug? #'separate in seq-utils

2010-02-18 Thread reynard

ok, the following works as expected.

user> (separate (fn [n]
  (= n 2))
'(1 2 3 4 5))
[(2) (1 3 4 5)]


now, I want to randomly select a number from '(1 2 3 4 5), I change
the function to the following, and the result is NOT expected.

user> (separate (fn [n]
  (= n (inc (int (rand 5)
'(1 2 3 4 5))
[() (2 3 4)]


Is it a bug in the separate function or do I use it incorrectly?

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


http-agent usage in subsequent agent action question

2010-02-18 Thread sim
I have been using http-agents to grab a bunch of pages and then
process them, my initial solutions involved partitioning a sequence of
urls and then awaiting for that group before moving on.

(I'm using clojure-1.1.0 and clojure-contrib-1.1.0)

However the problem with that approach is that when one of the
responses is slow they all have to wait.  To get around that I can
loop and query each running agent with done? etc, but that is a
hassle.

I figured I'd use the :handler function instead, when the handler is
called I can deal with the response body and then fire off another
agent.  However the agent's state hasn't changed internally to ::done
yet so not all the accessors work (like status, for example).

No problem I thought just queue another action behind the initial
http-agent request.  As I am sending the actions from the same thread
they are guaranteed to run sequentially so my second action will have
access to the final agent state and then all the accessors will work,
etc.

However there is another wrinkle; both string and result call await
and you can't await in an action.

I want to do the following;

(let [agnt (http-agent "http://slashdot.org/";)]
(send agnt
  (fn [state]
;; printing for demonstration but could write to file,
post to another queue, etc.
(println  "Done:" (done? *agent*) "Status:" (status
*agent*))
;; the following causes an error as string calls await
which is bad in an action
(println (string *agent*))
state)))

This seems fairly idiomatic to me but I end up with agnt having the
"can't await in action" error.  After I redefine result and string
(the only two that await in http-agent) to be the following;

(in-ns clojure.contrib.http.agent)

(defn string
  "Returns the HTTP response body as a string, using the given
  encoding.

  If no encoding is given, uses the encoding specified in the server
  headers, or clojure.contrib.duck-streams/*default-encoding* if it is
  not specified."
  ([http-agnt]
 ;; may have to wait for Content-Encoding
 (if (not (done? http-agnt))
   (await http-agnt))

 (string http-agnt (or (.getContentEncoding
#^HttpURLConnection (::connection @http-
agnt))
   duck/*default-encoding*)))

  ([http-agnt #^String encoding]
 (.toString (get-byte-buffer http-agnt) encoding)))

(defn result
  "Returns the value returned by the :handler function of the HTTP
  agent; blocks until the HTTP request is completed.  The default
  handler function returns a ByteArrayOutputStream."
  [http-agnt]
  (if (not (done? http-agnt))
(await http-agnt))
  (::result @http-agnt))

Then everything is fine and the code above works.  Interestingly this
doesn't change the documented behaviour of result as result still
blocks until complete but now only if it needs to which means I am
free to call result in a later action.

Finally my question, is my usage of actions idiomatic and I have just
stumbled onto an unusual usage pattern for http-agent or is there some
reason that await is always called in string and result that I am
unaware of?

-- sim

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


Re: jmx with auth

2010-02-18 Thread Drz
Stu,

Works for me.  Thanks for the quick turn around.

  Drz

On Feb 18, 5:27 am, Stuart Halloway  wrote:
> Hi Drz,
>
> Just pushed a fix, let me know if it works for 
> you.http://github.com/richhickey/clojure-contrib/commit/6f2b1d73b50b7b9f0...
>
> Stu
>
>
>
> > I am just starting to play around with clojure.  I was trying to use
> > the clojure.contrib.jmx library to connect to remote java vms that
> > require auth (-Dcom.sun.management.jmxremote.password.file=blah -
> > Dcom.sun.management.jmxremote.access.file=blah).  Looking at the java
> > docs, I need to add "jmx.remote.credentials" into the environment map
> > with the value of ["username" "password"].  I tested this out by
> > creating a with-connection macro in my own namespace and changing the
> > {} to {"jmx.remote.credentials" (into-array ["username"
> > "password"])}.  That worked just fine for testing, but is not a long
> > term solution.  Does anyone have a suggestion as to how I could get
> > this kind of functionality integrated into jmx library?  I tried to
> > contact Stuart Halloway via github with no luck.  If getting this into
> > the library isn't an option, does anyone have any suggestions on an
> > elegant way to add this without essentially duplicating with-
> > connection macro?
>
> >  Drz
>
> > --  
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient  
> > with your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en

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


Re: side effects in fn passed to filter

2010-02-18 Thread Sean Devlin
Well, if it's golf...

(use 'clojure.contrib.seq-utils)

(map first (partition-by identity [1 2 3 4 5 5 5 6]))

On Feb 18, 9:34 am, Stuart Halloway  wrote:
> Rowdy's question asks for less than what core/distinct delivers--he  
> only wanted to remove *adjacent* duplicates.
>
> That said, core/distinct is a better demo of "how do I maintain state  
> across a lazy sequence without requiring any mutation?"
>
> Stu
>
> > Hi,
>
> > On Feb 18, 3:04 pm, Rowdy Rednose  wrote:
>
> >> "Returns a lazy sequence of the items in coll for which (pred item)
> >> returns true. pred must be free of side-effects."
>
> >> So that means I should not write a function like this:
>
> >> (defn unique [sc]
> >>   "Returns a lazy sequence with all consecutive duplicates removed"
> >>   (let [last (atom (Object.))]
> >>     (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> >> user=> (unique [1 2 3 3 4 5 5 6])
> >> (1 2 3 4 5 6)
>
> >> But in contrast to functions that can be retried (compare-and-swap
> >> etc.), I don't immediately see why having side effects in filter  
> >> would
> >> be bad. Can anybody enlighten me? And how should I do this instead?
>
> > Besides the other suggestions: clojure.core/distinct and its
> > implementation.
>
> > Sincerely
> > Meikel
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient  
> > with your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en

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


Re: bug? #'separate in seq-utils

2010-02-18 Thread Stuart Halloway
You are using it incorrectly. Separate returns a vector of things that  
match, and a vector of things that don't match. Every time you call  
the function it matches against a different random number. Take a look  
at rand-elt in clojure.contrib.seq-utils.


Maybe the docstring for separate should say that fn should be side- 
effect-free...


Stu


ok, the following works as expected.

user> (separate (fn [n]
  (= n 2))
'(1 2 3 4 5))
[(2) (1 3 4 5)]


now, I want to randomly select a number from '(1 2 3 4 5), I change
the function to the following, and the result is NOT expected.

user> (separate (fn [n]
  (= n (inc (int (rand 5)
'(1 2 3 4 5))
[() (2 3 4)]


Is it a bug in the separate function or do I use it incorrectly?

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


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


Re: bug? #'separate in seq-utils

2010-02-18 Thread reynard


On Feb 18, 10:51 pm, Stuart Halloway 
wrote:
> You are using it incorrectly. Separate returns a vector of things that  
> match, and a vector of things that don't match. Every time you call  
> the function it matches against a different random number. Take a look  
> at rand-elt in clojure.contrib.seq-utils.

Yes, the problem is solved by first binding the result of the random
number, before applying it inside #'separate, as follows, thanks

user> (let [rand-num (inc (int (rand 5)))]
(separate (fn [n]
   (= n rand-num))
   '(1 2 3 4 5)))
[(4) (1 2 3 5)]

> Maybe the docstring for separate should say that fn should be side-
> effect-free...

I concur.

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


Re: side effects in fn passed to filter

2010-02-18 Thread Rowdy Rednose
Various interesting approaches to this problem... thanks guys!

Stu, you're right, distinct builds up a set of all items encountered,
which I don't need, and it's costly. But that function it is indeed a
good model. So here's a side effects free version modeled after
distinct:

(defn better-unique
  [coll]
(let [step (fn step [xs last]
   (lazy-seq
((fn [[f :as xs] last]
  (when-let [s (seq xs)]
(if (= last f)
  (recur (rest s) f)
  (cons f (step (rest s) f)
 xs last)))]
  (step coll (Object.

Doing some micro-benchmarking, it turns out my initial version is the
fastest, but better-unique is comparable.

This one

(defn parti-by-unique [sc] (map first (partition-by identity sc)))

is much slower, and distinct is the slowest of the ones I tried, as it
does much more than I need. Here are the numbers (and I don't wanna
hear anybody laugh about the absolute values I achieve on my box ;)

user=> (time (count (unique (range 100
"Elapsed time: 1070.535608 msecs"
100
user=> (time (count (better-unique (range 100
"Elapsed time: 1510.92021 msecs"
100
user=> (time (count (parti-by-unique (range 100
"Elapsed time: 3344.861758 msecs"
100
user=> (time (count (distinct (range 100
"Elapsed time: 6724.705348 msecs"
100

And yes, for a generic function like this, that I want to use
everywhere and anywhere, I do consider performance.

better-unique is not too far off from my initial approach, but still,
why no side effects?
Even though I do not know when the side-effects happen (lazily,
eagerly), shouldn't the order be fixed in case of filter?

At least I'm assuming that every reset! of the last atom will happen
at a time so that the result of unique will not be affected.

On Feb 18, 11:34 pm, Stuart Halloway 
wrote:
> Rowdy's question asks for less than what core/distinct delivers--he
> only wanted to remove *adjacent* duplicates.
>
> That said, core/distinct is a better demo of "how do I maintain state
> across a lazy sequence without requiring any mutation?"
>
> Stu
>
> > Hi,
>
> > On Feb 18, 3:04 pm, Rowdy Rednose  wrote:
>
> >> "Returns a lazy sequence of the items in coll for which (pred item)
> >> returns true. pred must be free of side-effects."
>
> >> So that means I should not write a function like this:
>
> >> (defn unique [sc]
> >>   "Returns a lazy sequence with all consecutive duplicates removed"
> >>   (let [last (atom (Object.))]
> >> (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> >> user=> (unique [1 2 3 3 4 5 5 6])
> >> (1 2 3 4 5 6)
>
> >> But in contrast to functions that can be retried (compare-and-swap
> >> etc.), I don't immediately see why having side effects in filter
> >> would
> >> be bad. Can anybody enlighten me? And how should I do this instead?
>
> > Besides the other suggestions: clojure.core/distinct and its
> > implementation.
>
> > Sincerely
> > Meikel
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient
> > with your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en

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


Re: side effects in fn passed to filter

2010-02-18 Thread Meikel Brandmeyer
Hi,

On Feb 18, 4:34 pm, Rowdy Rednose  wrote:

> better-unique is not too far off from my initial approach, but still,
> why no side effects?

Here an example, where side-effects are the gotcha:
http://groups.google.com/group/clojure/browse_thread/thread/d8fe58489e913433

(filter #(mod % (rand-int 10)) (range 100))

I think side-effects should be read as in transients: if no one sees
the side effect, is there one? "Your" side-effect is local to your
predicate. However the side-effect in rand-int is not!

Maybe as a rule of thumb?

Sincerely
Meikel

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


Re: side effects in fn passed to filter

2010-02-18 Thread fra
You can try the following

(defn unique[s]
"Returns a lazy sequence with all consecutive duplicates removed"
 (filter identity
   (map #(when (not= %1 %2) %1)
   s (cons nil s) )))




On Feb 18, 3:04 pm, Rowdy Rednose  wrote:
> The filter documentation reads:
>
> "Returns a lazy sequence of the items in coll for which (pred item)
> returns true. pred must be free of side-effects."
>
> So that means I should not write a function like this:
>
> (defn unique [sc]
>   "Returns a lazy sequence with all consecutive duplicates removed"
>   (let [last (atom (Object.))]
>     (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> user=> (unique [1 2 3 3 4 5 5 6])
> (1 2 3 4 5 6)
>
> But in contrast to functions that can be retried (compare-and-swap
> etc.), I don't immediately see why having side effects in filter would
> be bad. Can anybody enlighten me? And how should I do this instead?
>
> Thanks

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


Re: side effects in fn passed to filter

2010-02-18 Thread eyeris
On Feb 18, 9:34 am, Rowdy Rednose  wrote:

> better-unique is not too far off from my initial approach, but still,
> why no side effects?
> Even though I do not know when the side-effects happen (lazily,
> eagerly), shouldn't the order be fixed in case of filter?

I think the term "must" in the documentation refers to side-effects on
the seq. General advice would say that the predicate must be free of
side effects if you want to keep your sanity and not die at the hands
of an angry mob of programmers who are later forced to use your
code :)

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


Re: side effects in fn passed to filter

2010-02-18 Thread Sean Devlin
Rowdy,
Does your profiling test do any work?  There aren't any duplicates in
(range 100)  Perhaps you should run a few more benchmarks to get a
better idea of what is going on.

Sean

On Feb 18, 10:34 am, Rowdy Rednose  wrote:
> Various interesting approaches to this problem... thanks guys!
>
> Stu, you're right, distinct builds up a set of all items encountered,
> which I don't need, and it's costly. But that function it is indeed a
> good model. So here's a side effects free version modeled after
> distinct:
>
> (defn better-unique
>   [coll]
>     (let [step (fn step [xs last]
>                    (lazy-seq
>                     ((fn [[f :as xs] last]
>                       (when-let [s (seq xs)]
>                         (if (= last f)
>                           (recur (rest s) f)
>                           (cons f (step (rest s) f)
>                      xs last)))]
>       (step coll (Object.
>
> Doing some micro-benchmarking, it turns out my initial version is the
> fastest, but better-unique is comparable.
>
> This one
>
> (defn parti-by-unique [sc] (map first (partition-by identity sc)))
>
> is much slower, and distinct is the slowest of the ones I tried, as it
> does much more than I need. Here are the numbers (and I don't wanna
> hear anybody laugh about the absolute values I achieve on my box ;)
>
> user=> (time (count (unique (range 100
> "Elapsed time: 1070.535608 msecs"
> 100
> user=> (time (count (better-unique (range 100
> "Elapsed time: 1510.92021 msecs"
> 100
> user=> (time (count (parti-by-unique (range 100
> "Elapsed time: 3344.861758 msecs"
> 100
> user=> (time (count (distinct (range 100
> "Elapsed time: 6724.705348 msecs"
> 100
>
> And yes, for a generic function like this, that I want to use
> everywhere and anywhere, I do consider performance.
>
> better-unique is not too far off from my initial approach, but still,
> why no side effects?
> Even though I do not know when the side-effects happen (lazily,
> eagerly), shouldn't the order be fixed in case of filter?
>
> At least I'm assuming that every reset! of the last atom will happen
> at a time so that the result of unique will not be affected.
>
> On Feb 18, 11:34 pm, Stuart Halloway 
> wrote:
>
> > Rowdy's question asks for less than what core/distinct delivers--he
> > only wanted to remove *adjacent* duplicates.
>
> > That said, core/distinct is a better demo of "how do I maintain state
> > across a lazy sequence without requiring any mutation?"
>
> > Stu
>
> > > Hi,
>
> > > On Feb 18, 3:04 pm, Rowdy Rednose  wrote:
>
> > >> "Returns a lazy sequence of the items in coll for which (pred item)
> > >> returns true. pred must be free of side-effects."
>
> > >> So that means I should not write a function like this:
>
> > >> (defn unique [sc]
> > >>   "Returns a lazy sequence with all consecutive duplicates removed"
> > >>   (let [last (atom (Object.))]
> > >>     (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> > >> user=> (unique [1 2 3 3 4 5 5 6])
> > >> (1 2 3 4 5 6)
>
> > >> But in contrast to functions that can be retried (compare-and-swap
> > >> etc.), I don't immediately see why having side effects in filter
> > >> would
> > >> be bad. Can anybody enlighten me? And how should I do this instead?
>
> > > Besides the other suggestions: clojure.core/distinct and its
> > > implementation.
>
> > > Sincerely
> > > Meikel
>
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Clojure" group.
> > > To post to this group, send email to clojure@googlegroups.com
> > > Note that posts from new members are moderated - please be patient
> > > with your first post.
> > > To unsubscribe from this group, send email to
> > > clojure+unsubscr...@googlegroups.com
> > > For more options, visit this group at
> > >http://groups.google.com/group/clojure?hl=en

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


ANN: byte-spec-0.1

2010-02-18 Thread Jeff Rose
Just a quick announcement for a small library recently extracted from
Project Overtone.  It lets you specify binary formats and then
serialize to and from clojure data structures.  This was created to
read and write SuperCollider synthesizer definition files, but it
could be used for other binary file formats also.

You can check it out on github here:

http://github.com/rosejn/byte-spec

or you can use it in your project.clj and let lein pull it from
clojars using this identifier:

[byte-spec "0.1"]

Here is a snip from the tests to give you a sense for how it works:

(defspec rhythm-spec
 :name :string
 :length :int16
 :n-triggers :int32
 :triggers [:int8])

(defspec melody-spec
 :name :string
 :n-notes :int32
 :notes  [:int16])

(defspec song-spec
 :name   :string
 :bpm:int8
 :rhythm rhythm-spec
 :melody melody-spec)

(defn bytes-and-back [spec obj]
  (spec-read-bytes spec (spec-write-bytes spec obj)))

(deftest nested-spec-test []
  (let [r (spec rhythm-spec "test rhythm" 100 (short 5) [1 2 3 4 5])
m (spec melody-spec "test melody" (int 12) [2 3 4 54 23 43 98
23 98 54 87 23])
s (spec song-spec "test song" 234 r m)
s2 (bytes-and-back song-spec s)
m2 (:melody s2)
r2 (:rhythm s2)]
(is (= 5 (:n-triggers r2)))
(is (= 12 (:n-notes m2)))
(is (= r2))
(is (= m2))
(is (= s s

Let me know if you have any questions.

Cheers,
Jeff Rose

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


Re: side effects in fn passed to filter

2010-02-18 Thread Rowdy Rednose
Yeah, the numbers depend a bit on the data, so distinct will look
better if there are many dupes, and running tests against

(mapcat vector (range 50) (range 50))

so we have 50% dupes, gave me these numbers:

user=> (time (count (unique (mapcat vector (range 50) (range
50)
"Elapsed time: 4319.796441 msecs"
50
user=> (time (count (better-unique (mapcat vector (range 50)
(range 50)
"Elapsed time: 4107.580937 msecs"
50
user=> (time (count (distinct (mapcat vector (range 50) (range
50)
"Elapsed time: 7279.815677 msecs"
50
user=> (time (count (parti-by-unique (mapcat vector (range 50)
(range 50)
"Elapsed time: 5889.013135 msecs"
50

So now my original unique is actually a little bit slower than better-
unique in all the runs I did. I guess this is due to the overhead of
atoms?

Still distinct will never be faster than better-unique, as it has to
do more.

On Feb 19, 1:26 am, Sean Devlin  wrote:
> Rowdy,
> Does your profiling test do any work?  There aren't any duplicates in
> (range 100)  Perhaps you should run a few more benchmarks to get a
> better idea of what is going on.
>
> Sean
>
> On Feb 18, 10:34 am, Rowdy Rednose  wrote:
>
> > Various interesting approaches to this problem... thanks guys!
>
> > Stu, you're right, distinct builds up a set of all items encountered,
> > which I don't need, and it's costly. But that function it is indeed a
> > good model. So here's a side effects free version modeled after
> > distinct:
>
> > (defn better-unique
> >   [coll]
> > (let [step (fn step [xs last]
> >(lazy-seq
> > ((fn [[f :as xs] last]
> >   (when-let [s (seq xs)]
> > (if (= last f)
> >   (recur (rest s) f)
> >   (cons f (step (rest s) f)
> >  xs last)))]
> >   (step coll (Object.
>
> > Doing some micro-benchmarking, it turns out my initial version is the
> > fastest, but better-unique is comparable.
>
> > This one
>
> > (defn parti-by-unique [sc] (map first (partition-by identity sc)))
>
> > is much slower, and distinct is the slowest of the ones I tried, as it
> > does much more than I need. Here are the numbers (and I don't wanna
> > hear anybody laugh about the absolute values I achieve on my box ;)
>
> > user=> (time (count (unique (range 100
> > "Elapsed time: 1070.535608 msecs"
> > 100
> > user=> (time (count (better-unique (range 100
> > "Elapsed time: 1510.92021 msecs"
> > 100
> > user=> (time (count (parti-by-unique (range 100
> > "Elapsed time: 3344.861758 msecs"
> > 100
> > user=> (time (count (distinct (range 100
> > "Elapsed time: 6724.705348 msecs"
> > 100
>
> > And yes, for a generic function like this, that I want to use
> > everywhere and anywhere, I do consider performance.
>
> > better-unique is not too far off from my initial approach, but still,
> > why no side effects?
> > Even though I do not know when the side-effects happen (lazily,
> > eagerly), shouldn't the order be fixed in case of filter?
>
> > At least I'm assuming that every reset! of the last atom will happen
> > at a time so that the result of unique will not be affected.
>
> > On Feb 18, 11:34 pm, Stuart Halloway 
> > wrote:
>
> > > Rowdy's question asks for less than what core/distinct delivers--he
> > > only wanted to remove *adjacent* duplicates.
>
> > > That said, core/distinct is a better demo of "how do I maintain state
> > > across a lazy sequence without requiring any mutation?"
>
> > > Stu
>
> > > > Hi,
>
> > > > On Feb 18, 3:04 pm, Rowdy Rednose  wrote:
>
> > > >> "Returns a lazy sequence of the items in coll for which (pred item)
> > > >> returns true. pred must be free of side-effects."
>
> > > >> So that means I should not write a function like this:
>
> > > >> (defn unique [sc]
> > > >>   "Returns a lazy sequence with all consecutive duplicates removed"
> > > >>   (let [last (atom (Object.))]
> > > >> (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> > > >> user=> (unique [1 2 3 3 4 5 5 6])
> > > >> (1 2 3 4 5 6)
>
> > > >> But in contrast to functions that can be retried (compare-and-swap
> > > >> etc.), I don't immediately see why having side effects in filter
> > > >> would
> > > >> be bad. Can anybody enlighten me? And how should I do this instead?
>
> > > > Besides the other suggestions: clojure.core/distinct and its
> > > > implementation.
>
> > > > Sincerely
> > > > Meikel
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > > > Groups "Clojure" group.
> > > > To post to this group, send email to clojure@googlegroups.com
> > > > Note that posts from new members are moderated - please be patient
> > > > with your first post.
> > > > To unsubscribe from this group, send email to
> > > > clojure+unsubscr...@googlegroups.com
> > > > For more options, visit this gro

Re: ANN: byte-spec-0.1

2010-02-18 Thread David Nolen
Nice, overtone  also looks really
interesting :)

On Thu, Feb 18, 2010 at 11:59 AM, Jeff Rose  wrote:

> Just a quick announcement for a small library recently extracted from
> Project Overtone.  It lets you specify binary formats and then
> serialize to and from clojure data structures.  This was created to
> read and write SuperCollider synthesizer definition files, but it
> could be used for other binary file formats also.
>
> You can check it out on github here:
>
> http://github.com/rosejn/byte-spec
>
> or you can use it in your project.clj and let lein pull it from
> clojars using this identifier:
>
> [byte-spec "0.1"]
>
> Here is a snip from the tests to give you a sense for how it works:
>
> (defspec rhythm-spec
> :name :string
> :length :int16
> :n-triggers :int32
> :triggers [:int8])
>
> (defspec melody-spec
> :name :string
> :n-notes :int32
> :notes  [:int16])
>
> (defspec song-spec
> :name   :string
> :bpm:int8
> :rhythm rhythm-spec
> :melody melody-spec)
>
> (defn bytes-and-back [spec obj]
>  (spec-read-bytes spec (spec-write-bytes spec obj)))
>
> (deftest nested-spec-test []
>  (let [r (spec rhythm-spec "test rhythm" 100 (short 5) [1 2 3 4 5])
>m (spec melody-spec "test melody" (int 12) [2 3 4 54 23 43 98
> 23 98 54 87 23])
>s (spec song-spec "test song" 234 r m)
>s2 (bytes-and-back song-spec s)
>m2 (:melody s2)
>r2 (:rhythm s2)]
>(is (= 5 (:n-triggers r2)))
>(is (= 12 (:n-notes m2)))
>(is (= r2))
>(is (= m2))
>(is (= s s
>
> Let me know if you have any questions.
>
> Cheers,
> Jeff Rose
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

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

Re: side effects in fn passed to filter

2010-02-18 Thread Sean Devlin
Thanks for running the second experiment.

The more I think about it, getting "typical" performance numbers for
something like this is very difficult, just like getting "typical"
numbers for sorting algorithms is difficult.  Beware the evils of
micro-benchmarking.

Does anyone have some ideas on how to perform a more rigorous
experiment?

Sean

On Feb 18, 12:44 pm, Rowdy Rednose  wrote:
> Yeah, the numbers depend a bit on the data, so distinct will look
> better if there are many dupes, and running tests against
>
> (mapcat vector (range 50) (range 50))
>
> so we have 50% dupes, gave me these numbers:
>
> user=> (time (count (unique (mapcat vector (range 50) (range
> 50)
> "Elapsed time: 4319.796441 msecs"
> 50
> user=> (time (count (better-unique (mapcat vector (range 50)
> (range 50)
> "Elapsed time: 4107.580937 msecs"
> 50
> user=> (time (count (distinct (mapcat vector (range 50) (range
> 50)
> "Elapsed time: 7279.815677 msecs"
> 50
> user=> (time (count (parti-by-unique (mapcat vector (range 50)
> (range 50)
> "Elapsed time: 5889.013135 msecs"
> 50
>
> So now my original unique is actually a little bit slower than better-
> unique in all the runs I did. I guess this is due to the overhead of
> atoms?
>
> Still distinct will never be faster than better-unique, as it has to
> do more.
>
> On Feb 19, 1:26 am, Sean Devlin  wrote:
>
> > Rowdy,
> > Does your profiling test do any work?  There aren't any duplicates in
> > (range 100)  Perhaps you should run a few more benchmarks to get a
> > better idea of what is going on.
>
> > Sean
>
> > On Feb 18, 10:34 am, Rowdy Rednose  wrote:
>
> > > Various interesting approaches to this problem... thanks guys!
>
> > > Stu, you're right, distinct builds up a set of all items encountered,
> > > which I don't need, and it's costly. But that function it is indeed a
> > > good model. So here's a side effects free version modeled after
> > > distinct:
>
> > > (defn better-unique
> > >   [coll]
> > >     (let [step (fn step [xs last]
> > >                    (lazy-seq
> > >                     ((fn [[f :as xs] last]
> > >                       (when-let [s (seq xs)]
> > >                         (if (= last f)
> > >                           (recur (rest s) f)
> > >                           (cons f (step (rest s) f)
> > >                      xs last)))]
> > >       (step coll (Object.
>
> > > Doing some micro-benchmarking, it turns out my initial version is the
> > > fastest, but better-unique is comparable.
>
> > > This one
>
> > > (defn parti-by-unique [sc] (map first (partition-by identity sc)))
>
> > > is much slower, and distinct is the slowest of the ones I tried, as it
> > > does much more than I need. Here are the numbers (and I don't wanna
> > > hear anybody laugh about the absolute values I achieve on my box ;)
>
> > > user=> (time (count (unique (range 100
> > > "Elapsed time: 1070.535608 msecs"
> > > 100
> > > user=> (time (count (better-unique (range 100
> > > "Elapsed time: 1510.92021 msecs"
> > > 100
> > > user=> (time (count (parti-by-unique (range 100
> > > "Elapsed time: 3344.861758 msecs"
> > > 100
> > > user=> (time (count (distinct (range 100
> > > "Elapsed time: 6724.705348 msecs"
> > > 100
>
> > > And yes, for a generic function like this, that I want to use
> > > everywhere and anywhere, I do consider performance.
>
> > > better-unique is not too far off from my initial approach, but still,
> > > why no side effects?
> > > Even though I do not know when the side-effects happen (lazily,
> > > eagerly), shouldn't the order be fixed in case of filter?
>
> > > At least I'm assuming that every reset! of the last atom will happen
> > > at a time so that the result of unique will not be affected.
>
> > > On Feb 18, 11:34 pm, Stuart Halloway 
> > > wrote:
>
> > > > Rowdy's question asks for less than what core/distinct delivers--he
> > > > only wanted to remove *adjacent* duplicates.
>
> > > > That said, core/distinct is a better demo of "how do I maintain state
> > > > across a lazy sequence without requiring any mutation?"
>
> > > > Stu
>
> > > > > Hi,
>
> > > > > On Feb 18, 3:04 pm, Rowdy Rednose  wrote:
>
> > > > >> "Returns a lazy sequence of the items in coll for which (pred item)
> > > > >> returns true. pred must be free of side-effects."
>
> > > > >> So that means I should not write a function like this:
>
> > > > >> (defn unique [sc]
> > > > >>   "Returns a lazy sequence with all consecutive duplicates removed"
> > > > >>   (let [last (atom (Object.))]
> > > > >>     (filter #(let [ok (not= @last %)] (reset! last %) ok) sc)))
>
> > > > >> user=> (unique [1 2 3 3 4 5 5 6])
> > > > >> (1 2 3 4 5 6)
>
> > > > >> But in contrast to functions that can be retried (compare-and-swap
> > > > >> etc.), I don't immediately see why having side effects in filter
> > > > >> would
> > > > >> be bad. Can anybody enlighten me? And ho

Re: side effects in fn passed to filter

2010-02-18 Thread Meikel Brandmeyer
Hi,

On Thu, Feb 18, 2010 at 09:44:52AM -0800, Rowdy Rednose wrote:

> Yeah, the numbers depend a bit on the data, so distinct will look
> better if there are many dupes, and running tests against
> 
> (mapcat vector (range 50) (range 50))
> 
> so we have 50% dupes, gave me these numbers:

You have to sort the collections with your unique. This is not counted
in the current benchmark.

Any reason why not to use (concat (range ..) (range ..))? ;)

Sincerely
Meikel

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


Re: side effects in fn passed to filter

2010-02-18 Thread Sean Devlin
Wait... what's the problem we're trying to solve?

On Feb 18, 1:56 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On Thu, Feb 18, 2010 at 09:44:52AM -0800, Rowdy Rednose wrote:
> > Yeah, the numbers depend a bit on the data, so distinct will look
> > better if there are many dupes, and running tests against
>
> > (mapcat vector (range 50) (range 50))
>
> > so we have 50% dupes, gave me these numbers:
>
> You have to sort the collections with your unique. This is not counted
> in the current benchmark.
>
> Any reason why not to use (concat (range ..) (range ..))? ;)
>
> Sincerely
> Meikel

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


Re: side effects in fn passed to filter

2010-02-18 Thread Meikel Brandmeyer
On Thu, Feb 18, 2010 at 07:56:02PM +0100, Meikel Brandmeyer wrote:

> You have to sort the collections with your unique. This is not counted
> in the current benchmark.

Forget that.

> Any reason why not to use (concat (range ..) (range ..))? ;)

There is a reason

Sincerely
Meikel

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


Re: REST library

2010-02-18 Thread Brandon Mason
This is also worth taking a look at:
http://code.google.com/p/implementing-rest/wiki/ByLanguage
Thanks for the link.  I'm also starting a RESTful Clojure project.
This looks like good reading for me.

On Feb 17, 4:10 am, Shantanu Kumar  wrote:
> On Feb 17, 3:05 pm, Roman Roelofsen 
> wrote:
>
> > Hi,
>
> > does someone knows a good Clojure REST framework? It should help with
> > URL destructuring and maybe creating JSON return data etc.
>
> You can take a look at Taimen (in Alpha now) 
> -http://code.google.com/p/bitumenframework/
>
> Taimen doesn't do serialization for you, but you can use clojure.json
> for that.
>
> This is also worth taking a look 
> at:http://code.google.com/p/implementing-rest/wiki/ByLanguage
>
> Regards,
> Shantanu

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


Does the Logo have a name?

2010-02-18 Thread mcpeterson
If not, I propose "the lambyang".

- mcpeterson

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


commute misunderstanding

2010-02-18 Thread Аркадий Рост
Hi!
I don't understand difference between commute and alter. In fact I
don't understand how can I get different results by changing alter to
commute in code.I've read that the in-transaction value with commute
is that it may differ from the post-commit value, as the effect of
commute is a function of the value of the ref at commit time, but I
don't understand in what situations it can happen.

Please show a code example in which changing alter to commute will
cause different results.

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


Re: side effects in fn passed to filter

2010-02-18 Thread Meikel Brandmeyer
Hi,

> Wait... what's the problem we're trying to solve?

My mistake. I was confused.

Sincerely
Meikel

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


Re: commute misunderstanding

2010-02-18 Thread Laurent PETIT
2010/2/18 Аркадий Рост :
> Hi!
> I don't understand difference between commute and alter. In fact I
> don't understand how can I get different results by changing alter to
> commute in code.I've read that the in-transaction value with commute
> is that it may differ from the post-commit value, as the effect of
> commute is a function of the value of the ref at commit time, but I
> don't understand in what situations it can happen.
>
> Please show a code example in which changing alter to commute will
> cause different results.

Hi,

just in the situation of trying to increment a counter :

with alter: maybe the transaction will have to retry, because you'll
try to change, say a 4 in a 5, but in the mean time, somebody else has
already done this change, and your transaction will retry, now
hopefully changing a 5 in a 6 ... or maybe not if somebody else
already did this ...

now with commute: you say "inc the value". This cannot fail. And
whatever value held by the ref at transaction commit time will be
incremented. Note that this means the incremented in-transaction value
of your "counter" may not be equal to the after the transaction commit
value, of course.

HTH,

-- 
Laurent

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


Re: commute misunderstanding

2010-02-18 Thread Аркадий Рост
hmm..but in what way I can write code to demonstrate the difference?

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


Re: ANN: byte-spec-0.1

2010-02-18 Thread Jeff Rose
Yeah, Overtone is our real focus, but its in rapid development and
there is minimal documentation so it hasn't gotten a real release
yet.  Feel free to mail the Overtone list if you need help getting
setup though.

-Jeff

On Feb 18, 6:50 pm, David Nolen  wrote:
> Nice, overtone  also looks really
> interesting :)
>
> On Thu, Feb 18, 2010 at 11:59 AM, Jeff Rose  wrote:
> > Just a quick announcement for a small library recently extracted from
> > Project Overtone.  It lets you specify binary formats and then
> > serialize to and from clojure data structures.  This was created to
> > read and write SuperCollider synthesizer definition files, but it
> > could be used for other binary file formats also.
>
> > You can check it out on github here:
>
> >http://github.com/rosejn/byte-spec
>
> > or you can use it in your project.clj and let lein pull it from
> > clojars using this identifier:
>
> > [byte-spec "0.1"]
>
> > Here is a snip from the tests to give you a sense for how it works:
>
> > (defspec rhythm-spec
> >         :name :string
> >         :length :int16
> >         :n-triggers :int32
> >         :triggers [:int8])
>
> > (defspec melody-spec
> >         :name :string
> >         :n-notes :int32
> >         :notes  [:int16])
>
> > (defspec song-spec
> >         :name   :string
> >         :bpm    :int8
> >         :rhythm rhythm-spec
> >         :melody melody-spec)
>
> > (defn bytes-and-back [spec obj]
> >  (spec-read-bytes spec (spec-write-bytes spec obj)))
>
> > (deftest nested-spec-test []
> >  (let [r (spec rhythm-spec "test rhythm" 100 (short 5) [1 2 3 4 5])
> >        m (spec melody-spec "test melody" (int 12) [2 3 4 54 23 43 98
> > 23 98 54 87 23])
> >        s (spec song-spec "test song" 234 r m)
> >        s2 (bytes-and-back song-spec s)
> >        m2 (:melody s2)
> >        r2 (:rhythm s2)]
> >    (is (= 5 (:n-triggers r2)))
> >    (is (= 12 (:n-notes m2)))
> >    (is (= r2))
> >    (is (= m2))
> >    (is (= s s
>
> > Let me know if you have any questions.
>
> > Cheers,
> > Jeff Rose
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en

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


Re: commute misunderstanding

2010-02-18 Thread Laurent PETIT
2010/2/18 Аркадий Рост :
> hmm..but in what way I can write code to demonstrate the difference?

You must reproduce the race conditions.
An idea is to start 2 transactions in 2 different threads, while
making the first one sleep sufficiently so you're sure the second one
will commit first.

Simply said: you create deterministic race conditions.

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

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


Clojure box

2010-02-18 Thread Zeynel
Hello,

I am totally new to Clojure. Do you recommend using Clojure Box for
windows installation? I am not an expert user or programmer. Thank you.

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


Re: clojure-contrib on Windows

2010-02-18 Thread Ram
I was considering doing that, but I didn't know if people were aware
of the compilation issue on Windows so I posted it.

On Feb 17, 9:50 pm, kkw  wrote:
> Hi Ram,
>
>     If you all you want is the latest .jar file, and don't feel the
> need to compile, consider bypassing the compilation and grab the
> latest successfully compiled .jar from build.clojure.org. This is what
> I now do.
>
> Kev
>
> On Feb 17, 9:51 am, Ram  wrote:
>
> > I'm having an issue compilingclojure-contrib onWindows.
>
> > I downloaded the code from the git repository and when I run Maven,
> > after compilation it runs through the test suite fails in test-io:
>
> > FAIL in (test-as-url) (run-test5405918110152723544.clj:47)
> > expected: (= (URL. "file:/foo") (as-url (File. "/foo")))
> >   actual: (not (= # #))
>
> > I'm guessing someone expected UNIX style filenames in this test case
> > and notWindowsfilenames, but that is besides the issue. The issue is
> > that the jars aren't actually generating themselves. Am I missing
> > something? If I am, its probably something really dumb.

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


Re: http-agent usage in subsequent agent action question

2010-02-18 Thread Timothy Pratley
On 18 February 2010 23:12, sim  wrote:
> I have been using http-agents to grab a bunch of pages and then
> process them, my initial solutions involved partitioning a sequence of
> urls and then awaiting for that group before moving on.

Consider this alternative:

(use 'clojure.contrib.duck-streams)
(doall
  (apply pcalls
 (map #(fn [] (println (slurp* %)))
 ["http://slashdot.org"; "http://www.reddit.com/";])))

Where println can be replaced with processing.


> (I'm using clojure-1.1.0 and clojure-contrib-1.1.0)
>
> However the problem with that approach is that when one of the
> responses is slow they all have to wait.  To get around that I can
> loop and query each running agent with done? etc, but that is a
> hassle.
>
> I figured I'd use the :handler function instead, when the handler is
> called I can deal with the response body and then fire off another
> agent.  However the agent's state hasn't changed internally to ::done
> yet so not all the accessors work (like status, for example).

I'm confused here whether you want the requests to happen in parallel
or sequentially, or do you want some sort of mixture?


> No problem I thought just queue another action behind the initial
> http-agent request.  As I am sending the actions from the same thread
> they are guaranteed to run sequentially so my second action will have
> access to the final agent state and then all the accessors will work,
> etc.
>
> However there is another wrinkle; both string and result call await
> and you can't await in an action.
>
> I want to do the following;
>
> (let [agnt (http-agent "http://slashdot.org/";)]
>    (send agnt
>          (fn [state]
>            ;; printing for demonstration but could write to file,
> post to another queue, etc.
>            (println  "Done:" (done? *agent*) "Status:" (status
> *agent*))
>            ;; the following causes an error as string calls await
> which is bad in an action
>            (println (string *agent*))
>            state)))

"If you don't provide a handler function, the default handler will
buffer the entire response body in memory, which you can retrieve
with the 'bytes', 'string', or 'stream' functions. Like 'result',
these functions will block until the HTTP request is completed.
A single GET request could be as simple as:
(string (http-agent "http://www.stuartsierra.com/";))"

so why do you have all the other stuff?
If you wanted to use multiple http-agents in parallel you might want
to specify a handler function that operates when the response is
received.

(ns foo (:require [clojure.contrib.http.agent :as a]
  [clojure.contrib.duck-streams :as d]))
(a/http-agent "http://slashdot.org";
  :handler #(println (d/slurp* (a/stream %
(a/http-agent "http://www.reddit.com";
  :handler #(println (d/slurp* (a/stream %

Will do two url retrievals in parallel and print the results when they arrive.


> This seems fairly idiomatic to me but I end up with agnt having the
> "can't await in action" error.  After I redefine result and string
> (the only two that await in http-agent) to be the following;
>
> (in-ns clojure.contrib.http.agent)
>
> (defn string
>  "Returns the HTTP response body as a string, using the given
>  encoding.
>
>  If no encoding is given, uses the encoding specified in the server
>  headers, or clojure.contrib.duck-streams/*default-encoding* if it is
>  not specified."
>  ([http-agnt]
>     ;; may have to wait for Content-Encoding
>     (if (not (done? http-agnt))
>       (await http-agnt))
>
>     (string http-agnt (or (.getContentEncoding
>                            #^HttpURLConnection (::connection @http-
> agnt))
>                           duck/*default-encoding*)))
>
>  ([http-agnt #^String encoding]
>     (.toString (get-byte-buffer http-agnt) encoding)))
>
> (defn result
>  "Returns the value returned by the :handler function of the HTTP
>  agent; blocks until the HTTP request is completed.  The default
>  handler function returns a ByteArrayOutputStream."
>  [http-agnt]
>  (if (not (done? http-agnt))
>    (await http-agnt))
>  (::result @http-agnt))
>
> Then everything is fine and the code above works.  Interestingly this
> doesn't change the documented behaviour of result as result still
> blocks until complete but now only if it needs to which means I am
> free to call result in a later action.
>
> Finally my question, is my usage of actions idiomatic and I have just
> stumbled onto an unusual usage pattern for http-agent or is there some
> reason that await is always called in string and result that I am
> unaware of?

Please let me know if I've misunderstood your aim here, but I think
you can achieve your goals with a much simpler approach as described
above.


Regards,
Tim.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 

Re: Clojure box

2010-02-18 Thread Brian Wolf

Zeynel wrote:

Hello,

I am totally new to Clojure. Do you recommend using Clojure Box for
windows installation? I am not an expert user or programmer. Thank you.

  

I use it all the time.  And its a gentle introduction to emacs

Brian

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


Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread John Williams
I'm no Clojure guru myself, but one approach you may want to consider is
nest all your auxiliary functions inside the main function, and use ordinary
let-bindings the same way you've been trying to use global bindings:

(defn sell-or-rent [{:keys [supplied-1 supplied-2]}]
  (let [derived-1 (+ 1 supplied-1)
derived-2 (* 2 supplied-2)]
(letfn [(f [x y z] ...)
(g [x] ...)]
  ...)))

This has the disadvantage of indenting all your helper functions much more
than they would be otherwise, but it gets the job done without any messy
global variables or thunks.  If you want to expose more functions than just
sell-or-rent, you could write some very OO-flavored code:

;; Define a function to create objects.
(defn pseudo-constructor [{:keys [supplied-1 supplied-2]}]
  (let [member-var-1 (+ 1 supplied-1)
member-var-2 (* 2 supplied-2)]
(letfn [(private-method-1 [] "priv1")
(private-method-2 [] "priv2")]
  {:public-method-1 (fn [x y z] "pub1")
   :public-method-2 (fn [x y] "pub2")})))

;; Use the object.
(let [obj (pseudo-constructor {:supplied-1 1
   :supplied-2 2})]
  (println ((:public-method-1 obj) "x" "y" "z"))
  (println ((:public-method-2 obj) "x" "y")))

--jw

On Mon, Feb 15, 2010 at 11:24 AM, Yaron  wrote:

> I am writing a calculator to figure out if I should sell or rent my
> home using Clojure. This is my first Clojure program so I'm about as
> wet behind the ears as it gets. So far everything is actually going
> really well (reminds me of the fun I had with Scheme in college) but
> for one thing. My calculator needs 30+ arguments from the user in
> order to run. Furthermore I have a bunch of secondary values that are
> derived from the arguments the user submits.
>
> So imagine the user submits a value A. I will have a value B whose
> definition will be something like (+ 1 A) (yes, more complex in
> reality, but you get the idea).
>
> If I were back in Java or C# I would define a class, submit A (and
> it's 29+ friends) in the constructor and then create a property on the
> class B.
>
> In Clojure I have taken a different approach. I first create (def *A*
> 3) where 3 is a completely bogus value I just made up. Then at run
> time I use bindings to re-bind A to the actual value the user passed
> in.
>
> But my problem is, what to do about B? I thought of doing something
> like (def *B* 3) and then in the binding passing in a function like
> (defn B-Gen [] (+ *A* 1)) to create a new binding to B but I quickly
> realized this would be a bug inducing nightmare. If I forget to
> include one of the derived values in the binding or put them in the
> wrong order then I would get the wrong value.
>
> So what I currently do is:
> (def *A* 3) ; A bogus value that will later be rebound
> (defn B [] (+ *A* 3))
>
> The good news is, that this works and doesn't require any book
> keeping.
>
> The bad news is that it's ugly. If I want to do something trivial like
> divide B by 2 I have to call B as a function(/ (B) 2) instead of the
> more natural (/ B 2). And of course this approach is pretty
> unfortunate from a performance perspective as I'm constantly having to
> recalculate what are effectively static values. Yes, I could use
> memoization but many of these values are pretty trivial (usually just
> algebra equations) and I suspect the overhead of memoization exceeds
> the perf improvement.
>
> But in any case the whole approach of having to take what really are
> static values and turn them into functions feels really hacky. So my
> guess is that I'm thinking about this problem the wrong way. I'm stuck
> in my old imperative/OO constructor world.
>
> What's the right way to think about primary values that will be
> rebound (once) that then have dependent values that need to be
> recalculated when that rebinding happens?
>
>  Thanks,
>
>  Yaron
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

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

Re: http-agent usage in subsequent agent action question

2010-02-18 Thread sim
Yes there are other alternatives, but consider this.

(doseq [url urls]
  (let [agt (http-agent url)]
(send-off agt some-action)))

I think that some-action should be able to use string and result as
the HTTP request is complete at this stage.  However some-action
can't as both string and result call await without first checking if
the HTTP request is complete and you can't await in an action.

If my understanding is correct the code above would start as many
agents as there are urls and clojure is free to distribute those
agents in whatever manner it sees fit.  The only guarantee clojure
makes is that some-action will be called after all the previous
actions sent from the same thread are complete (which includes the
ones sent by http-agent itself).  In other words some-action can rely
on the fact that the HTTP request has finished by the time it gets
called.

In my case it is important to the code in some-action that http-agent
has finished as not all of the http-agent accessors return results
when the :handler is called, eg status returns NIL during the
:handler.

I guess the real question is this, is this a bug in http-agent or an
http-agent usage error on my part?

-- sim




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


Re: http-agent usage in subsequent agent action question

2010-02-18 Thread Timothy Pratley
On 19 February 2010 13:35, sim  wrote:
> Yes there are other alternatives, but consider this.
>
> (doseq [url urls]
>  (let [agt (http-agent url)]
>    (send-off agt some-action)))

Ok I understand better where you are coming from now... you want
some-action to occur after http-agent tasks have run. Which seems
reasonable to me!

However perhaps (some-action) should just use ::result to extract the
result instead of (result) etc seeing that is really all it is
happening behind the scenes?

(ns foo (:require [clojure.contrib.http.agent :as a]))
(def urls ["http://slashdot.org"; "http://www.reddit.com";])
(defn some-action [x] (println "FOO:" (:clojure.contrib.http.agent/result x)))
(doseq [url urls] (send-off (a/http-agent url) some-action))

Works as you describe for me.


> I think that some-action should be able to use string and result as
> the HTTP request is complete at this stage.  However some-action
> can't as both string and result call await without first checking if
> the HTTP request is complete and you can't await in an action.
>
> If my understanding is correct the code above would start as many
> agents as there are urls and clojure is free to distribute those
> agents in whatever manner it sees fit.  The only guarantee clojure
> makes is that some-action will be called after all the previous
> actions sent from the same thread are complete (which includes the
> ones sent by http-agent itself).  In other words some-action can rely
> on the fact that the HTTP request has finished by the time it gets
> called.
>
> In my case it is important to the code in some-action that http-agent
> has finished as not all of the http-agent accessors return results
> when the :handler is called, eg status returns NIL during the
> :handler.
>
> I guess the real question is this, is this a bug in http-agent or an
> http-agent usage error on my part?

I think it is just an oversight that someone would want to use it in this way.

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


Common Lisp's append

2010-02-18 Thread Mike K
Hey Clojurians,

I'm a Clojure and Common Lisp newbie. I heard that Norvig's PAIP was a
good book to study idiomatic CL code, so I've embarked on a project to
translate the examples to / work the exercises in Clojure.  I hope to
complete this project before the end of this century :-)

Regarding "append" from CL: ISTM that this is similar to "concat" in
Clojure.  I tried the following definition:

(defn append [& parts] (concat parts))

but it is not quite correct:

(concat '(a b c) '(d e f) '(g))

-> (a b c d e f g)

(append '(a b c) '(d e f) '(g))

-> ((a b c) (d e f) (g))

What is the correct way to do this?  Is it possible to code the idea
that append == concat two ways, one explicitly defining a parameter
list like "parts" and one just aliasing the concat symbol somehow?

Also, is the following definition closer to the CL semantics?

(use '[clojure.contrib.seq-utils :only (flatten)])
(defn append2 [& parts] (flatten (list parts)))

(append2 '((a) b c) '(d e f) '() '(g))

-> (a b c d e f g)

Finally, can anyone recommend a good free common lisp implementation
that runs well with slime / emacs under Windows?

   Thanks,
   Mike

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


Re: Common Lisp's append

2010-02-18 Thread Timothy Pratley
On 19 February 2010 15:18, Mike K  wrote:
> Hey Clojurians,
>
> I'm a Clojure and Common Lisp newbie. I heard that Norvig's PAIP was a
> good book to study idiomatic CL code, so I've embarked on a project to
> translate the examples to / work the exercises in Clojure.  I hope to
> complete this project before the end of this century :-)
>
> Regarding "append" from CL: ISTM that this is similar to "concat" in
> Clojure.  I tried the following definition:
>
> (defn append [& parts] (concat parts))
>
> but it is not quite correct:
>
> (concat '(a b c) '(d e f) '(g))
>
> -> (a b c d e f g)
>
> (append '(a b c) '(d e f) '(g))
>
> -> ((a b c) (d e f) (g))
>
> What is the correct way to do this?  Is it possible to code the idea
> that append == concat two ways, one explicitly defining a parameter
> list like "parts" and one just aliasing the concat symbol somehow?

parts is a collection of the arguments. so you need to use apply to
supply them individually to concat:

foo=> (defn append [& parts] (apply concat parts))
#'foo/append
foo=> (append '(a b c) '(d e f) '(g))
(a b c d e f g)

But as you rightly noted, you could just alias append as concat:

foo=> (def append concat)
#'foo/append
foo=> (append '(a b c) '(d e f) '(g))
(a b c d e f g)

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


noobie library load

2010-02-18 Thread Brian Wolf

Hi,

I have a self contained library let me call it "http_example.jar" (i 
assume the name of the jar file is irrelevant)


and contains this is the root resource:

com.example.clojure.http__init.class (I know its there)

The file, "http_example.jar", to the best I can tell sits squarely in my 
classpath when I start the repl


however when I try to load it, I get this

user=> (require ['com.example.clojure.http :as 'http])
java.lang.NoClassDefFoundError: Could not initialize class 
com.example.clojure.ht

tp__init (NO_SOURCE_FILE:0)


Thanks
Brian



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


Re: Clojure box

2010-02-18 Thread Sean Devlin
Do you need to do a lot of Java work as well?  If so, take a look at
Enclojure (Netbeans) or Counter Clockwise (Eclipse).

On Feb 18, 4:58 pm, Zeynel  wrote:
> Hello,
>
> I am totally new to Clojure. Do you recommend using Clojure Box for
> windows installation? I am not an expert user or programmer. Thank you.

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


Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread Yaron
Way back when I was a wee lad I had been taught that a thunk is any
function that takes no arguments. My definition for my derived values
never took any arguments because they exclusively relied on global
variables.

For example:

(defn months_actively_renting
"The number of months during the time we are in the rental business
that we are either trying to rent the house out or have rented it out"
[]
(* (+ *Months_To_Find_Tenant* *Months_In_Lease*) *Lease_Cycles*))

That's all I meant by the term thunk.

On Feb 17, 10:20 pm, Richard Newman  wrote:
> > I'm just trying to figure out what the right pattern is
> > because the fact that I'm forced to make the derived values into
> > thunks feels really wrong but I honestly don't know what's right in
> > the context of Clojure.
>
> I don't think you're using the term "thunk" correctly.
>
> A thunk is (usually) a no-argument function, typically used for things  
> like delayed evaluation, and typically capturing some environment. E.g.,
>
> (defn hello [thunk]
>    (println "Hello, " (thunk)))
>
> (defn make-name-thunk [name]
>    (fn [] name))
>
> (let [n (make-name-thunk "Jim")]
>    (println "Calling hello...")
>    (hello n))
>
> You are not making your derived values into thunks by this definition.  
> Your derived values are just that: values, computed by functions.  
> Compute them when you need them by invoking the appropriate functions  
> with the appropriate arguments.
>
> Can you explain what you mean by "thunk"?

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


Re: noobie library load

2010-02-18 Thread Meikel Brandmeyer
Hi,

On Feb 19, 5:26 am, Brian Wolf  wrote:

> I have a self contained library let me call it "http_example.jar" (i
> assume the name of the jar file is irrelevant)
>
> and contains this is the root resource:
>
> com.example.clojure.http__init.class (I know its there)

The file should be called com/example/clojure/http__init.class. In
subdirectories. Without dots.

> The file, "http_example.jar", to the best I can tell sits squarely in my
> classpath when I start the repl

You can check with (System/getProperty "java.class.path") at the Repl.
To be sure.

Sincerely
Meikel

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


Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread Yaron
I spent a bunch of time reading and re-reading your mails.

Michal Marczyk's mail (which I read every line of, thank you for
taking the time to write it) was the one that made me get what
Richard Newman has with utmost patience (THANK YOU!), I believe,
been trying to gently beat into my head from the start.

Richard, your mails were extremely clear (and at this point I've read
them all at least 2 or 3 times) but my head was so far away from the
problem space that I needed a sufficient amount of beating before I
could finally even begin to grok anything. It took me forever to get
over the idea that I needed global variables. It was a stupid idee
fixe on my part.

I just took a piece of my code and re-worked it and made it available
at http://www.goland.org/rent_or_sell_refactor.clj.

My approach is as follows:

#1 - I removed all globally scoped defs (well, I left one, but it's
Months-In-Year and is just there for readability purposes). And per
Jarkko Oranen's mail I fixed the dashes. :)

#2 - I created a function called derived-args. It takes as input a map
that is to contain all the arguments provided by the user. It then
adds to that map all the derived values. This means that the derived
values get calculated exactly one time. It is the output of derived-
args that will be put at the very top of the function chain and passed
on down.

#3 - For some functions I explicitly just list out the arguments they
need. But I made a conscious decision not to do that in all cases. I
have a number of functions that I call a lot and constantly having to
break out their arguments when I call them would quickly grow tedious.
So instead I pass those functions the args map and then let them use
keys to break out the values. Probably the most egregious example of
this pattern is valid-month? I use this in preconditions all over the
place. So rather than passing its second argument, months-in-business,
as a separate argument I just pass in the whole args map and break out
the value inside of valid-month? The benefit of this approach is that
all the functions that call valid-month don't themselves have to break
out months-in-business in their keys, they can just pass in args.

Does http://www.goland.org/rent_or_sell_refactor.clj work more or less
the way y'all have been suggesting? In other words have I finally
created something that is heading in the 'right' direction? I realize
you can't properly judge it until I'm done but I wanted to find out if
I was roughly heading in the right direction.

   Thanks

 Yaron

On Feb 17, 10:36 pm, Richard Newman  wrote:
> > I don't expect anyone to actually read, rather I was hoping some folks
> > who know Clojure might just glance at it to get the rhythm of the
> > math. It's the pattern, not the detail that matters. How should what
> > is essentially a monster algebra equation be codified in Clojure?
>
> I looked at your PDF.
>
> You express the equations as functions. Turning your equation notation  
> into function notation -- I'll use Haskell's as an example:
>
> OpportunityCost = Rent - Sell
>
> becomes
>
> opportunityCost r s = r - s
>
> or in Clojure:
>
> (defn opportunity-cost [r s]
>(- r s))
>
> Note that the implicit arguments in your equational notation become  
> explicit arguments in the functional version.
>
> How do I compute r and s? Why, with functions of course! Let's take  
> Sell as an example.
>
> Sell = HouseSaleProfit0(1 +  
> RealMonthlyOpportunityCost)^MonthsInBusiness
>
> which becomes
>
> (defn sell [hsp-zero rmoc mib]
>(* hsp-zero
>   (exp (+ 1 rmoc) mib))); Assuming exp defined.
>
> Now, assuming that we have Rent, HSP0, RMOC, and MIB calculated (which  
> follows the same pattern), we compute our OpportunityCost:
>
> (defn -main []
>   ;; TODO: extract user arguments.
>   ;; ...
>   (let [hsp-zero (...)   ; More calculation.
>  rmoc (...)
> mib (...)]
> (println "Opportunity Cost: "
>   (opportunity-cost rent (sell hsp-zero rmoc mib
>
> To turn this into your final code, you need only:
>
> * Keep walking through your formulae until you've expressed everything  
> as functions;
> * Grab the nineteen or so "leaf" values you need from the user, and  
> plug them into your calls.
>
> When you have intermediate values, bind them with let, as I show above.
>
> Note that:
>
> * Each of the functions stands alone, defined in terms of its  
> arguments, and follows naturally from your equations
> * You can compute any intermediate stage, and print them out, log  
> them, whatever
> * There are no global values or bindings
> * You can name each intermediate value using let; your main function  
> can essentially be a sequential set of intermediate calculations, just  
> like your PDF.

-- 
You received this message because you are subscribed to the Google
Groups "Cl

Clojure function varargs (not Java interop varargs)

2010-02-18 Thread Julien
Dear Clojurists,

Two questions:

Question #1

I want to write a vararg function that does something like this:

(map vector [1 2 3] [4 5 6])
which yields
([1 4] [2 5] [3 6])

I try to capture this as a function:

(defn rotate[& x] (map vector x))

but

(rotate [1 2 3] [4 5 6])

yields

([[1 2 3]] [[4 5 6]]) instead of ([1 4] [2 5] [3 6])

What am I doing wrong?

Question #2

Question #1 was somewhat of a diversion. What I actually want my
function to look like is something like this:

(defn rotate[x] (map vector x))

where the x passed in is a vector of vectors e.g. [[4 2 3] [ 9 8 7]]

so

(rotate [[1 2 3] [4 5 6]])

would yield

([1 4] [2 5] [3 6])

How can I achieve this?

Many thanks for this great language.

-Julien

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


Re: Clojure function varargs (not Java interop varargs)

2010-02-18 Thread Timothy Pratley
On 19 February 2010 18:04, Julien  wrote:
> Question #1
>
> I want to write a vararg function that does something like this:
>
> (map vector [1 2 3] [4 5 6])
> which yields
> ([1 4] [2 5] [3 6])
>
> I try to capture this as a function:
>
> (defn rotate[& x] (map vector x))
>
> but
>
> (rotate [1 2 3] [4 5 6])
>
> yields
>
> ([[1 2 3]] [[4 5 6]]) instead of ([1 4] [2 5] [3 6])
>
> What am I doing wrong?

You want apply...

clojure.core/apply
([f args* argseq])
  Applies fn f to the argument list formed by prepending args to argseq.

foo=> (defn rotate [& x] (apply map vector x))
#'foo/rotate
foo=> (rotate [1 2 3] [4 5 6])
([1 4] [2 5] [3 6])


> Question #2
>
> Question #1 was somewhat of a diversion. What I actually want my
> function to look like is something like this:
>
> (defn rotate[x] (map vector x))
>
> where the x passed in is a vector of vectors e.g. [[4 2 3] [ 9 8 7]]
>
> so
>
> (rotate [[1 2 3] [4 5 6]])
>
> would yield
>
> ([1 4] [2 5] [3 6])
>
> How can I achieve this?

same answer :)

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


Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread Richard Newman

Richard Newman has with utmost patience (THANK YOU!), I believe,
been trying to gently beat into my head from the start.


No problem. Happy to help.



Richard, your mails were extremely clear (and at this point I've read
them all at least 2 or 3 times) but my head was so far away from the
problem space that I needed a sufficient amount of beating before I
could finally even begin to grok anything. It took me forever to get
over the idea that I needed global variables. It was a stupid idee
fixe on my part.


These things take time! Props for not giving up in disgust :)



I just took a piece of my code and re-worked it and made it available
at http://www.goland.org/rent_or_sell_refactor.clj.


Looks pretty good to me. I like your use of preconditions and the  
number of tests. I think your indentation is a little deep (I go for  
two spaces, myself), and I never use :Capital keywords, but otherwise  
great.


You might be interested in the `are` macro to make your test code  
simpler:


user=> (doc are)
-
clojure.test/are
([argv expr & args])
Macro
  Checks multiple assertions with a template expression.
  See clojure.template/do-template for an explanation of
  templates.

  Example: (are [x y] (= x y)
2 (+ 1 1)
4 (* 2 2))
  Expands to:
   (do (is (= 2 (+ 1 1)))
   (is (= 4 (* 2 2



#2 - I created a function called derived-args. It takes as input a map
that is to contain all the arguments provided by the user. It then
adds to that map all the derived values. This means that the derived
values get calculated exactly one time. It is the output of derived-
args that will be put at the very top of the function chain and passed
on down.


That seems like a reasonable approach.


Does http://www.goland.org/rent_or_sell_refactor.clj work more or less
the way y'all have been suggesting? In other words have I finally
created something that is heading in the 'right' direction? I realize
you can't properly judge it until I'm done but I wanted to find out if
I was roughly heading in the right direction.


Pretty much!

One suggestion:

Rather than having two phases of derived args, and calling functions  
with arguments like:


 (total-house-depreciation args-and-mib)

I'd save that step and adjust total-house-depreciation, year-sold,  
etc. to take an additional months-in-business argument:


(defn total-house-depreciation
   "The total amount of depreciation on the rental property taken  
over the period we were in business"

   [args months-in-business]
   ...)

Then you can change your derived-args function to:

(defn derived-args
	[{:keys [months-to-find-tenant months-in-lease lease-cycles months-to- 
sell] :as args}]

  (assoc args
:months-in-business (months-in-business months-to-find-tenant  
months-in-lease lease-cycles months-to-sell)
:total-house-depreciation (total-house-depreciation args months- 
in-business)

:year-sold (year-sold args months-in-business)
:months-actively-renting (months-actively-renting months-to-find- 
tenant months-in-lease lease-cycles)))


No lets at all.
You'll see then that it's a small step from there to my suggested  
"functional" end game, which eliminates the passing of the args map  
altogether: derived-args would extract all the named arguments and  
pass just the specific ones to each function. No big deal, though;  
there are advantages to the map approach.


Looking good!

-R

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