Re: Idiom question

2016-09-30 Thread Alan Thompson
The idea of the `it->` operator in the Tupelo library
 is basically
just a combination of the explicitness of swiss arrows and the pronoun `it`
from Groovy.
Alan

On Fri, Sep 30, 2016 at 2:00 PM, Stephen Spalding 
wrote:

> The semantic of the swiss-arrows 
> -<> macro are nice. It's like as-> except that the operator is
> automatically specified as <>, and it has a default position.
>
> Your original example would become:
>
> (-<> blah
>  (do-this)
>  (do-that arg)
>  (do-the-other a1 <> a2))
>
> The combination of a pre-specified operator and a default position  makes
> it so handy that I often wish there were a built-in equivalent.
>
> On Wednesday, September 28, 2016 at 6:10:05 PM UTC-4, pa...@pwjw.com
> wrote:
>>
>> All very interesting, and Sean that first/or threading pattern is very
>> helpful.
>>
>> @puzzler - totally get that the language is extensible yup and appreciate
>> the mainstream warning. When I read your cond-better version I got it; and
>> I also thought "a return statement like thing could be useful in a
>> construct something like this" and then remembered just how far the macro
>> system in lisps lets you go, which was really instructive.
>>
>> The patterns here are very useful. Thanks again to all of you who offered
>> up tips so far.
>>
>> On Wednesday, September 28, 2016 at 5:53:10 PM UTC-4, Sean Corfield wrote:
>>>
>>> Ooops, should be:
>>>
>>> (defn has-transmitters
>>>   [^MidiDevice device]
>>>   (<= 0 (.getMaxTransmitters device)))
>>>
>>> And if we made a helper for open-device, we could make it return the
>>> now-open device and then you wouldn’t need the doto – just call
>>> (open-device).
>>>
>>> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
>>> An Architect's View -- http://corfield.org/
>>>
>>> "If you're not annoying somebody, you're not really alive."
>>> -- Margaret Atwood
>>>
>>> On 9/28/16, 2:48 PM, "Sean Corfield"  wrote:
>>>
>>> And for comparison, here’s a threaded version that uses -> (with ->>
>>> embedded, and doto):
>>>
>>>   (-> (MidiSystem/getMidiDeviceInfo)
>>>   (->> (filter #(= (.getName ^MidiDevice$Info %) name))
>>>(map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
>>>(filter #(>= (.getMaxTransmitters ^MidiDevice %) 0)))
>>>   (first)
>>>   (or (throw (ex-info "No midi devices with recievers" {:name
>>> name})))
>>>   (doto (.open))
>>>   (.getReceiver))
>>>
>>> Note that I replaced the empty? check by just calling first followed
>>> by or/throw. Calling first on an empty sequence produces nil and (or x
>>> (throw …)) will yield x if it is not nil (else throw the exception).
>>>
>>> Also note that you lose the type hints here which may affect
>>> performance and/or method resolution (if the calls are ambiguous without
>>> the type hints).
>>>
>>> If the code isn’t performance critical and the calls are still
>>> resolvable without type hint, I’d probably omit them just to make the code
>>> cleaner. If the hints are needed, then I’d probably defn helpers for the
>>> interop calls (with type hinted arguments) to make the code cleaner:
>>>
>>>   (-> (MidiSystem/getMidiDeviceInfo)
>>>   (->> (filter #(= (get-device-name %) name))
>>>(map get-midi-device)
>>>(filter #(>= (get-max-transmitters %) 0)))
>>>   (first)
>>>   (or (throw (ex-info "No midi devices with recievers" {:name
>>> name})))
>>>   (doto (open-device))
>>>   (get-receiver))
>>>
>>> I’d probably make predicates for the two filter calls:
>>>
>>> (defn matches-device-name
>>>   [name]
>>>   (fn [^MidiDevice$Info info]
>>> (= name (.getName info
>>>
>>> (defn has-transmitters
>>>   [^MidiDevice$Info info]
>>>   (<= 0 (.getMaxTransmitters info)))
>>>
>>>   (-> (MidiSystem/getMidiDeviceInfo)
>>>   (->> (filter (matches-device-name name))
>>>(map get-midi-device)
>>>(filter has-transmitters))
>>>   (first)
>>>   (or (throw (ex-info "No midi devices with recievers" {:name
>>> name})))
>>>   (doto (open-device))
>>>   (get-receiver))
>>>
>>> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
>>> An Architect's View -- http://corfield.org/
>>>
>>> "If you're not annoying somebody, you're not really alive."
>>> -- Margaret Atwood
>>>
>>> On 9/28/16, 2:12 PM, "clo...@googlegroups.com on behalf of
>>> pa...@pwjw.com" 
>>> wrote:
>>>
>>> This is a super interesting thread. Thank you all for your input
>>>
>>> I think you are right, @puzzler, that for my case a let may be
>>> better. The original code is above. Using as-> it looks like this (using
>>> 'it' as the name)
>>>
>>>   (as-> (MidiSystem/getMidiDeviceInfo) it
>>>  (filter #(= (.getName ^MidiDevice$Inf

Re: Idiom question

2016-09-30 Thread Stephen Spalding
The semantic of the swiss-arrows  
-<> macro are nice. It's like as-> except that the operator is 
automatically specified as <>, and it has a default position.

Your original example would become:

(-<> blah
 (do-this)
 (do-that arg)
 (do-the-other a1 <> a2))

The combination of a pre-specified operator and a default position  makes 
it so handy that I often wish there were a built-in equivalent.

On Wednesday, September 28, 2016 at 6:10:05 PM UTC-4, pa...@pwjw.com wrote:
>
> All very interesting, and Sean that first/or threading pattern is very 
> helpful.
>
> @puzzler - totally get that the language is extensible yup and appreciate 
> the mainstream warning. When I read your cond-better version I got it; and 
> I also thought "a return statement like thing could be useful in a 
> construct something like this" and then remembered just how far the macro 
> system in lisps lets you go, which was really instructive.
>
> The patterns here are very useful. Thanks again to all of you who offered 
> up tips so far.
>
> On Wednesday, September 28, 2016 at 5:53:10 PM UTC-4, Sean Corfield wrote:
>>
>> Ooops, should be: 
>>
>> (defn has-transmitters 
>>   [^MidiDevice device] 
>>   (<= 0 (.getMaxTransmitters device))) 
>>
>> And if we made a helper for open-device, we could make it return the 
>> now-open device and then you wouldn’t need the doto – just call 
>> (open-device). 
>>
>> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN 
>> An Architect's View -- http://corfield.org/ 
>>
>> "If you're not annoying somebody, you're not really alive." 
>> -- Margaret Atwood 
>>
>> On 9/28/16, 2:48 PM, "Sean Corfield"  wrote: 
>>
>> And for comparison, here’s a threaded version that uses -> (with ->> 
>> embedded, and doto): 
>> 
>>   (-> (MidiSystem/getMidiDeviceInfo) 
>>   (->> (filter #(= (.getName ^MidiDevice$Info %) name)) 
>>(map #(MidiSystem/getMidiDevice ^MidDevice$Info %)) 
>>(filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))) 
>>   (first) 
>>   (or (throw (ex-info "No midi devices with recievers" {:name 
>> name}))) 
>>   (doto (.open)) 
>>   (.getReceiver)) 
>> 
>> Note that I replaced the empty? check by just calling first followed 
>> by or/throw. Calling first on an empty sequence produces nil and (or x 
>> (throw …)) will yield x if it is not nil (else throw the exception). 
>> 
>> Also note that you lose the type hints here which may affect 
>> performance and/or method resolution (if the calls are ambiguous without 
>> the type hints). 
>> 
>> If the code isn’t performance critical and the calls are still 
>> resolvable without type hint, I’d probably omit them just to make the code 
>> cleaner. If the hints are needed, then I’d probably defn helpers for the 
>> interop calls (with type hinted arguments) to make the code cleaner: 
>> 
>>   (-> (MidiSystem/getMidiDeviceInfo) 
>>   (->> (filter #(= (get-device-name %) name)) 
>>(map get-midi-device) 
>>(filter #(>= (get-max-transmitters %) 0))) 
>>   (first) 
>>   (or (throw (ex-info "No midi devices with recievers" {:name 
>> name}))) 
>>   (doto (open-device)) 
>>   (get-receiver)) 
>> 
>> I’d probably make predicates for the two filter calls: 
>> 
>> (defn matches-device-name 
>>   [name] 
>>   (fn [^MidiDevice$Info info] 
>> (= name (.getName info 
>> 
>> (defn has-transmitters 
>>   [^MidiDevice$Info info] 
>>   (<= 0 (.getMaxTransmitters info))) 
>> 
>>   (-> (MidiSystem/getMidiDeviceInfo) 
>>   (->> (filter (matches-device-name name)) 
>>(map get-midi-device) 
>>(filter has-transmitters)) 
>>   (first) 
>>   (or (throw (ex-info "No midi devices with recievers" {:name 
>> name}))) 
>>   (doto (open-device)) 
>>   (get-receiver)) 
>> 
>> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN 
>> An Architect's View -- http://corfield.org/ 
>> 
>> "If you're not annoying somebody, you're not really alive." 
>> -- Margaret Atwood 
>> 
>> On 9/28/16, 2:12 PM, "clo...@googlegroups.com on behalf of 
>> pa...@pwjw.com"  
>> wrote: 
>> 
>> This is a super interesting thread. Thank you all for your input 
>> 
>> I think you are right, @puzzler, that for my case a let may be 
>> better. The original code is above. Using as-> it looks like this (using 
>> 'it' as the name) 
>> 
>>   (as-> (MidiSystem/getMidiDeviceInfo) it 
>>  (filter #(= (.getName ^MidiDevice$Info %) name) it) 
>>  (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) it) 
>>  (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) it) 
>>  (if (empty? it) (throw (ex-info "No midi devices with recievers" 
>> {:name name})) it) 
>>

Re: Idiom question

2016-09-28 Thread paul
All very interesting, and Sean that first/or threading pattern is very 
helpful.

@puzzler - totally get that the language is extensible yup and appreciate 
the mainstream warning. When I read your cond-better version I got it; and 
I also thought "a return statement like thing could be useful in a 
construct something like this" and then remembered just how far the macro 
system in lisps lets you go, which was really instructive.

The patterns here are very useful. Thanks again to all of you who offered 
up tips so far.

On Wednesday, September 28, 2016 at 5:53:10 PM UTC-4, Sean Corfield wrote:
>
> Ooops, should be: 
>
> (defn has-transmitters 
>   [^MidiDevice device] 
>   (<= 0 (.getMaxTransmitters device))) 
>
> And if we made a helper for open-device, we could make it return the 
> now-open device and then you wouldn’t need the doto – just call 
> (open-device). 
>
> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN 
> An Architect's View -- http://corfield.org/ 
>
> "If you're not annoying somebody, you're not really alive." 
> -- Margaret Atwood 
>
> On 9/28/16, 2:48 PM, "Sean Corfield" > 
> wrote: 
>
> And for comparison, here’s a threaded version that uses -> (with ->> 
> embedded, and doto): 
> 
>   (-> (MidiSystem/getMidiDeviceInfo) 
>   (->> (filter #(= (.getName ^MidiDevice$Info %) name)) 
>(map #(MidiSystem/getMidiDevice ^MidDevice$Info %)) 
>(filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))) 
>   (first) 
>   (or (throw (ex-info "No midi devices with recievers" {:name 
> name}))) 
>   (doto (.open)) 
>   (.getReceiver)) 
> 
> Note that I replaced the empty? check by just calling first followed 
> by or/throw. Calling first on an empty sequence produces nil and (or x 
> (throw …)) will yield x if it is not nil (else throw the exception). 
> 
> Also note that you lose the type hints here which may affect 
> performance and/or method resolution (if the calls are ambiguous without 
> the type hints). 
> 
> If the code isn’t performance critical and the calls are still 
> resolvable without type hint, I’d probably omit them just to make the code 
> cleaner. If the hints are needed, then I’d probably defn helpers for the 
> interop calls (with type hinted arguments) to make the code cleaner: 
> 
>   (-> (MidiSystem/getMidiDeviceInfo) 
>   (->> (filter #(= (get-device-name %) name)) 
>(map get-midi-device) 
>(filter #(>= (get-max-transmitters %) 0))) 
>   (first) 
>   (or (throw (ex-info "No midi devices with recievers" {:name 
> name}))) 
>   (doto (open-device)) 
>   (get-receiver)) 
> 
> I’d probably make predicates for the two filter calls: 
> 
> (defn matches-device-name 
>   [name] 
>   (fn [^MidiDevice$Info info] 
> (= name (.getName info 
> 
> (defn has-transmitters 
>   [^MidiDevice$Info info] 
>   (<= 0 (.getMaxTransmitters info))) 
> 
>   (-> (MidiSystem/getMidiDeviceInfo) 
>   (->> (filter (matches-device-name name)) 
>(map get-midi-device) 
>(filter has-transmitters)) 
>   (first) 
>   (or (throw (ex-info "No midi devices with recievers" {:name 
> name}))) 
>   (doto (open-device)) 
>   (get-receiver)) 
> 
> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN 
> An Architect's View -- http://corfield.org/ 
> 
> "If you're not annoying somebody, you're not really alive." 
> -- Margaret Atwood 
> 
> On 9/28/16, 2:12 PM, "clo...@googlegroups.com  on behalf 
> of pa...@pwjw.com "  
> on behalf of pa...@pwjw.com > wrote: 
> 
> This is a super interesting thread. Thank you all for your input 
> 
> I think you are right, @puzzler, that for my case a let may be better. 
> The original code is above. Using as-> it looks like this (using 'it' as 
> the name) 
> 
>   (as-> (MidiSystem/getMidiDeviceInfo) it 
>  (filter #(= (.getName ^MidiDevice$Info %) name) it) 
>  (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) it) 
>  (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) it) 
>  (if (empty? it) (throw (ex-info "No midi devices with recievers" 
> {:name name})) it) 
>  (first it) 
>  (do (.open ^MidiDevice it) it) 
>  (.getReceiver ^MidiDevice it) 
>  ) 
>) 
> 
> using let it looks like this 
> 
> (let [device-info   (MidiSystem/getMidiDeviceInfo) 
>  named-device-info (filter #(= (.getName ^MidiDevice$Info %) 
> name) device-info) 
>  devices   (map #(MidiSystem/getMidiDevice 
> ^MidDevice$Info %) named-device-info) 
>  receivables   (filter #(>= (.getMaxTransmitters 
> ^MidiDevice %) 0) devices) 
>  _ (when (empty? receivables) (throw (ex-info 
>

Re: Idiom question

2016-09-28 Thread Sean Corfield
Ooops, should be:

(defn has-transmitters
  [^MidiDevice device]
  (<= 0 (.getMaxTransmitters device)))

And if we made a helper for open-device, we could make it return the now-open 
device and then you wouldn’t need the doto – just call (open-device).

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

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

On 9/28/16, 2:48 PM, "Sean Corfield"  wrote:

And for comparison, here’s a threaded version that uses -> (with ->> 
embedded, and doto):

  (-> (MidiSystem/getMidiDeviceInfo)
  (->> (filter #(= (.getName ^MidiDevice$Info %) name))
   (map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
   (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0)))
  (first)
  (or (throw (ex-info "No midi devices with recievers" {:name name})))
  (doto (.open))
  (.getReceiver))

Note that I replaced the empty? check by just calling first followed by 
or/throw. Calling first on an empty sequence produces nil and (or x (throw …)) 
will yield x if it is not nil (else throw the exception).

Also note that you lose the type hints here which may affect performance 
and/or method resolution (if the calls are ambiguous without the type hints).

If the code isn’t performance critical and the calls are still resolvable 
without type hint, I’d probably omit them just to make the code cleaner. If the 
hints are needed, then I’d probably defn helpers for the interop calls (with 
type hinted arguments) to make the code cleaner:

  (-> (MidiSystem/getMidiDeviceInfo)
  (->> (filter #(= (get-device-name %) name))
   (map get-midi-device)
   (filter #(>= (get-max-transmitters %) 0)))
  (first)
  (or (throw (ex-info "No midi devices with recievers" {:name name})))
  (doto (open-device))
  (get-receiver))

I’d probably make predicates for the two filter calls:

(defn matches-device-name
  [name]
  (fn [^MidiDevice$Info info]
(= name (.getName info

(defn has-transmitters
  [^MidiDevice$Info info]
  (<= 0 (.getMaxTransmitters info)))

  (-> (MidiSystem/getMidiDeviceInfo)
  (->> (filter (matches-device-name name))
   (map get-midi-device)
   (filter has-transmitters))
  (first)
  (or (throw (ex-info "No midi devices with recievers" {:name name})))
  (doto (open-device))
  (get-receiver))

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

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

On 9/28/16, 2:12 PM, "clojure@googlegroups.com on behalf of p...@pwjw.com" 
 wrote:

This is a super interesting thread. Thank you all for your input

I think you are right, @puzzler, that for my case a let may be better. The 
original code is above. Using as-> it looks like this (using 'it' as the name)

  (as-> (MidiSystem/getMidiDeviceInfo) it
 (filter #(= (.getName ^MidiDevice$Info %) name) it)
 (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) it)
 (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) it)
 (if (empty? it) (throw (ex-info "No midi devices with recievers" 
{:name name})) it)
 (first it)
 (do (.open ^MidiDevice it) it)
 (.getReceiver ^MidiDevice it)
 )
   )

using let it looks like this

(let [device-info   (MidiSystem/getMidiDeviceInfo) 
 named-device-info (filter #(= (.getName ^MidiDevice$Info %) name) 
device-info)
 devices   (map #(MidiSystem/getMidiDevice ^MidDevice$Info 
%) named-device-info)
 receivables   (filter #(>= (.getMaxTransmitters ^MidiDevice %) 
0) devices)
 _ (when (empty? receivables) (throw (ex-info "No 
midi devices with recievers" {:name name})))
 receivable(first receivables)
 result(do 
 (.open ^MidiDevice receivable)
 (.getReceiver ^MidiDevice receivable))]
 result)

and if I were doing a code review, I think I would like the last one better.

How very interesting. Thanks all for your constructive answers. What a 
great community.







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

Re: Idiom question

2016-09-28 Thread Sean Corfield
And for comparison, here’s a threaded version that uses -> (with ->> embedded, 
and doto):

  (-> (MidiSystem/getMidiDeviceInfo)
  (->> (filter #(= (.getName ^MidiDevice$Info %) name))
   (map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
   (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0)))
  (first)
  (or (throw (ex-info "No midi devices with recievers" {:name name})))
  (doto (.open))
  (.getReceiver))

Note that I replaced the empty? check by just calling first followed by 
or/throw. Calling first on an empty sequence produces nil and (or x (throw …)) 
will yield x if it is not nil (else throw the exception).

Also note that you lose the type hints here which may affect performance and/or 
method resolution (if the calls are ambiguous without the type hints).

If the code isn’t performance critical and the calls are still resolvable 
without type hint, I’d probably omit them just to make the code cleaner. If the 
hints are needed, then I’d probably defn helpers for the interop calls (with 
type hinted arguments) to make the code cleaner:

  (-> (MidiSystem/getMidiDeviceInfo)
  (->> (filter #(= (get-device-name %) name))
   (map get-midi-device)
   (filter #(>= (get-max-transmitters %) 0)))
  (first)
  (or (throw (ex-info "No midi devices with recievers" {:name name})))
  (doto (open-device))
  (get-receiver))

I’d probably make predicates for the two filter calls:

(defn matches-device-name
  [name]
  (fn [^MidiDevice$Info info]
(= name (.getName info

(defn has-transmitters
  [^MidiDevice$Info info]
  (<= 0 (.getMaxTransmitters info)))

  (-> (MidiSystem/getMidiDeviceInfo)
  (->> (filter (matches-device-name name))
   (map get-midi-device)
   (filter has-transmitters))
  (first)
  (or (throw (ex-info "No midi devices with recievers" {:name name})))
  (doto (open-device))
  (get-receiver))

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

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

On 9/28/16, 2:12 PM, "clojure@googlegroups.com on behalf of p...@pwjw.com" 
 wrote:

This is a super interesting thread. Thank you all for your input

I think you are right, @puzzler, that for my case a let may be better. The 
original code is above. Using as-> it looks like this (using 'it' as the name)

  (as-> (MidiSystem/getMidiDeviceInfo) it
     (filter #(= (.getName ^MidiDevice$Info %) name) it)
     (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) it)
     (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) it)
     (if (empty? it) (throw (ex-info "No midi devices with recievers" {:name 
name})) it)
     (first it)
     (do (.open ^MidiDevice it) it)
     (.getReceiver ^MidiDevice it)
     )
   )

using let it looks like this

(let [device-info       (MidiSystem/getMidiDeviceInfo) 
         named-device-info (filter #(= (.getName ^MidiDevice$Info %) name) 
device-info)
         devices           (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) 
named-device-info)
         receivables       (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) 
devices)
         _                 (when (empty? receivables) (throw (ex-info "No midi 
devices with recievers" {:name name})))
         receivable        (first receivables)
         result            (do 
                             (.open ^MidiDevice receivable)
                             (.getReceiver ^MidiDevice receivable))]
     result)

and if I were doing a code review, I think I would like the last one better.

How very interesting. Thanks all for your constructive answers. What a great 
community.




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


Re: Idiom question

2016-09-28 Thread Mark Engelberg
Right, and just to take this one step farther, imagine that instead of
throwing an error, you wanted to actually return a value.  And imagine that
your call to MidiSystem/getMidiDeviceInfo might return nil as well, and
this is something that needs to be protected against and a value returned
accordingly.  These sorts of intertwinings of conditional logic and chains
of computations is exactly when I reach for better-cond, which would make
it look like this:
(cond
  :let [device-info   (MidiSystem/getMidiDeviceInfo)]

  (nil? device-info) :device-not-available

  :let [named-device-info (filter #(= (.getName ^MidiDevice$Info %) name)
device-info)
devices   (map #(MidiSystem/getMidiDevice ^MidDevice$Info
%) named-device-info)
receivables   (filter #(>= (.getMaxTransmitters ^MidiDevice %)
0) devices)]

  (empty? receivables) :no-receivers

  :let [receivable(first receivables)]
  (do
(.open ^MidiDevice receivable)
(.getReceiver ^MidiDevice receivable)))

Since you're new to the community, I want to be sure not to mislead you --
the above example is not mainstream Clojure code.  But it's a great example
of how you can mold the language to suit your own taste of what is
readable.  The above example is my preferred way to write these sorts of
things.

On Wed, Sep 28, 2016 at 2:12 PM,  wrote:

> This is a super interesting thread. Thank you all for your input
>
> I think you are right, @puzzler, that for my case a let may be better. The
> original code is above. Using as-> it looks like this (using 'it' as the
> name)
>
>   (as-> (MidiSystem/getMidiDeviceInfo) it
>  (filter #(= (.getName ^MidiDevice$Info %) name) it)
>  (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) it)
>  (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) it)
>  (if (empty? it) (throw (ex-info "No midi devices with recievers"
> {:name name})) it)
>  (first it)
>  (do (.open ^MidiDevice it) it)
>  (.getReceiver ^MidiDevice it)
>  )
>)
>
> using let it looks like this
>
> (let [device-info   (MidiSystem/getMidiDeviceInfo)
>  named-device-info (filter #(= (.getName ^MidiDevice$Info %) name)
> device-info)
>  devices   (map #(MidiSystem/getMidiDevice ^MidDevice$Info
> %) named-device-info)
>  receivables   (filter #(>= (.getMaxTransmitters ^MidiDevice
> %) 0) devices)
>  _ (when (empty? receivables) (throw (ex-info "No
> midi devices with recievers" {:name name})))
>  receivable(first receivables)
>  result(do
>  (.open ^MidiDevice receivable)
>  (.getReceiver ^MidiDevice receivable))]
>  result)
>
> and if I were doing a code review, I think I would like the last one
> better.
>
> How very interesting. Thanks all for your constructive answers. What a
> great community.
>
> On Wednesday, September 28, 2016 at 4:47:22 PM UTC-4, puzzler wrote:
>>
>> A common convention with as-> is to use the symbol $ because it is
>> recognized as a Clojure identifier but looks distinctive, so it stands out
>> as the placeholder of where to thread.
>>
>> Personally, when reading code, I don't really like to see long uses of
>> the threading operator, and I'd argue that if you find yourself using such
>> long chains of computations that the "important" argument is switching to
>> different positions, that's a sign that maybe you shouldn't be using
>> threading operators in the first place, because it can be hard to mentally
>> follow what intermediate data structure you have at each stage of the
>> computation.  Instead, I'd argue that you should be using `let`, because
>> `let` allows you to give each stage of computation a meaningful name,
>> making it easy for others (or yourself in two months) to read and reason
>> about your code.  `let` allows you to communicate intent.
>>
>> I think one reason people sometimes shy away from using `let` is that it
>> can't easily be used at all positions within one's code.  For example, if
>> you are inside a `cond`  doing some conditional logic, adding a `let` means
>> you have to also start a new `cond`, and your code ends up awkwardly nested
>> and indented, drifting to the right.   The better-cond library removes this
>> limitation, making it easy to write clear functions which intermingle long
>> chains of computations with conditional logic:
>> https://github.com/Engelberg/better-cond
>>
> --
> 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 Go

Re: Idiom question

2016-09-28 Thread Josh Tilles
By the way, the order of arguments of as-> makes more sense when it’s used 
*within* one of the other threading macros. For example:
(-> x
  foo
  (bar y)
  (baz w z)
  (as-> mid-x
(log/debug "The intermediate value:" mid-x)
(if (color-requested? mid-x)
  (assoc mid-x :color "periwinkle")
  (do
(log/warn "skipping the addition of color")
mid-x)))
  (update :counter inc))


On Wednesday, September 28, 2016 at 4:11:42 PM UTC-4, pa...@pwjw.com wrote:
>
> Wow yes that's exactly the -%> macro I imagined just with "%" replaced 
> with "it". And it exists!  Plus I just converted my fragment to use as-> 
> and thought "aren't the first two arguments backwards (vs, say, "let"); and 
> what name should I use (I chose 's')". Thank you. Reading the tupelo docs 
> now.
>
> On Wednesday, September 28, 2016 at 4:02:38 PM UTC-4, Alan Thompson wrote:
>>
>> Hi Paul,
>>
>> Since you are interested in the threading macros, you might like to take 
>> a look at one of my favorite variants from the Tupelo library 
>> :
>>
>> Literate Threading Macro
>>
>> We all love to use the threading macros -> and ->> for certain tasks, 
>> but they only work if all of the forms should be threaded into the first or 
>> last argument.
>>
>> The built-in threading macro as-> can avoid this requirement, but the 
>> order of the first expression and the placeholder symbol is arguably 
>> backwards from what users would expect. Also, there is often no obvious 
>> name to use for the placeholder symbol. Re-using a good idea from Groovy, 
>> we simply use the symbol it as the placeholder symbol in each expression 
>> to represent the value of the previous result.
>>
>> (it-> 1
>>   (inc it)  ; thread-first or thread-last
>>   (+ it 3)  ; thread-first
>>   (/ 10 it) ; thread-last
>>   (str "We need to order " it " items." )   ; middle of 3 arguments;=> 
>> "We need to order 2 items." )
>>
>> Here is a more complicated example. Note that we can assign into a local 
>> let block from the it placeholder value:
>>
>> (it-> 3
>>   (spy :msg :initial it)
>>   (let [x it]
>> (inc x))
>>   (spy it :msg 222)
>>   (* it 2)
>>   (spyx it)); :initial => 3; 222 => 4; it => 88   ; return value
>>
>> Note that the :msg argument does not need to be a string. As shown 
>> above, keywords, integers, etc may be used.
>> Alan
>>
>>
>> On Wed, Sep 28, 2016 at 11:36 AM, Colin Yates  wrote:
>>
>>> Welcome to one of the best things about Clojure - the community. 
>>> However, if anyone starts using the phrase 'Clojurian' then it is time to 
>>> leave :-).
>>>
>>>
>>>
>>> On Wed, 28 Sep 2016, at 07:17 PM, pa...@pwjw.com wrote:
>>>
>>> Wow thank you all for the really useful responses. How great. I 
>>> appreciate the time.
>>>
>>> as-> cleans up a couple of ugly bits of my code already, yes. And I'm 
>>> sort of irritated with myself for not thinking of _ (if (throw)) in my let 
>>> but yes that's a perfect idiom.
>>>
>>>
>>> I totally get the minimalist approach in clojure.test and like it. In 
>>> fact, the ease of testing (and how easy it is to get coverage running with 
>>> cloverage) is one of the things I find the most impressive. expectations 
>>> looks interesting though too for a lot of my tests and I'll spend some time 
>>> with it too.
>>>
>>> The idiom of "most important is first unless its a sequence then it is 
>>> last" is really natural too; but I think it's what makes me end up 
>>> switching from ->> to ->. Putting a "first" in the middle of a ->> 
>>> expression is, I suppose, a hint that I'm switching.  Looking at my code, 
>>> it really seems to be a mix of ->> and "doto" that I'm looking for. Here's 
>>> a fragment, for instance, that returns me an opened instance of the first 
>>> core midi device with a name that can receive messages. (and I know I 
>>> should error check that there is one after that filter... that's on my todo 
>>> list). An "as-> doto" pair would help and I'll get right on that later on 
>>> this week.
>>>
>>> (->> (MidiSystem/getMidiDeviceInfo)
>>>
>>> (filter #(= (.getName ^MidiDevice$Info %) name))
>>>
>>> (map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
>>>
>>> (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))
>>>
>>> first
>>>
>>> (#(do (.open ^MidiDevice %) %))
>>>
>>> (#(.getReceiver ^MidiDevice %))
>>>
>>> )
>>>
>>> Anyway, wow thanks again for all the responses!
>>>
>>>
>>>
>>>
>>>
>>> On Wednesday, September 28, 2016 at 10:31:37 AM UTC-4, pa...@pwjw.com 
>>> wrote:
>>>
>>> Hi.
>>>
>>> I'm new to clojure, and it is quite lovely. The threading model is 
>>> great, the emacs integration is super, and the tasteful lisp extensions are 
>>> good. A very nice programming environment all around. 
>>>
>>> But as I write more code I f

Re: Idiom question

2016-09-28 Thread paul
This is a super interesting thread. Thank you all for your input

I think you are right, @puzzler, that for my case a let may be better. The 
original code is above. Using as-> it looks like this (using 'it' as the 
name)

  (as-> (MidiSystem/getMidiDeviceInfo) it
 (filter #(= (.getName ^MidiDevice$Info %) name) it)
 (map #(MidiSystem/getMidiDevice ^MidDevice$Info %) it)
 (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0) it)
 (if (empty? it) (throw (ex-info "No midi devices with recievers" 
{:name name})) it)
 (first it)
 (do (.open ^MidiDevice it) it)
 (.getReceiver ^MidiDevice it)
 )
   )

using let it looks like this

(let [device-info   (MidiSystem/getMidiDeviceInfo) 
 named-device-info (filter #(= (.getName ^MidiDevice$Info %) name) 
device-info)
 devices   (map #(MidiSystem/getMidiDevice ^MidDevice$Info 
%) named-device-info)
 receivables   (filter #(>= (.getMaxTransmitters ^MidiDevice %) 
0) devices)
 _ (when (empty? receivables) (throw (ex-info "No 
midi devices with recievers" {:name name})))
 receivable(first receivables)
 result(do 
 (.open ^MidiDevice receivable)
 (.getReceiver ^MidiDevice receivable))]
 result)

and if I were doing a code review, I think I would like the last one better.

How very interesting. Thanks all for your constructive answers. What a 
great community.

On Wednesday, September 28, 2016 at 4:47:22 PM UTC-4, puzzler wrote:
>
> A common convention with as-> is to use the symbol $ because it is 
> recognized as a Clojure identifier but looks distinctive, so it stands out 
> as the placeholder of where to thread.
>
> Personally, when reading code, I don't really like to see long uses of the 
> threading operator, and I'd argue that if you find yourself using such long 
> chains of computations that the "important" argument is switching to 
> different positions, that's a sign that maybe you shouldn't be using 
> threading operators in the first place, because it can be hard to mentally 
> follow what intermediate data structure you have at each stage of the 
> computation.  Instead, I'd argue that you should be using `let`, because 
> `let` allows you to give each stage of computation a meaningful name, 
> making it easy for others (or yourself in two months) to read and reason 
> about your code.  `let` allows you to communicate intent.
>
> I think one reason people sometimes shy away from using `let` is that it 
> can't easily be used at all positions within one's code.  For example, if 
> you are inside a `cond`  doing some conditional logic, adding a `let` means 
> you have to also start a new `cond`, and your code ends up awkwardly nested 
> and indented, drifting to the right.   The better-cond library removes this 
> limitation, making it easy to write clear functions which intermingle long 
> chains of computations with conditional logic: 
> https://github.com/Engelberg/better-cond
>

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


Re: Idiom question

2016-09-28 Thread Mark Engelberg
A common convention with as-> is to use the symbol $ because it is
recognized as a Clojure identifier but looks distinctive, so it stands out
as the placeholder of where to thread.

Personally, when reading code, I don't really like to see long uses of the
threading operator, and I'd argue that if you find yourself using such long
chains of computations that the "important" argument is switching to
different positions, that's a sign that maybe you shouldn't be using
threading operators in the first place, because it can be hard to mentally
follow what intermediate data structure you have at each stage of the
computation.  Instead, I'd argue that you should be using `let`, because
`let` allows you to give each stage of computation a meaningful name,
making it easy for others (or yourself in two months) to read and reason
about your code.  `let` allows you to communicate intent.

I think one reason people sometimes shy away from using `let` is that it
can't easily be used at all positions within one's code.  For example, if
you are inside a `cond`  doing some conditional logic, adding a `let` means
you have to also start a new `cond`, and your code ends up awkwardly nested
and indented, drifting to the right.   The better-cond library removes this
limitation, making it easy to write clear functions which intermingle long
chains of computations with conditional logic:
https://github.com/Engelberg/better-cond

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


Re: Idiom question

2016-09-28 Thread paul
Wow yes that's exactly the -%> macro I imagined just with "%" replaced with 
"it". And it exists!  Plus I just converted my fragment to use as-> and 
thought "aren't the first two arguments backwards (vs, say, "let"); and 
what name should I use (I chose 's')". Thank you. Reading the tupelo docs 
now.

On Wednesday, September 28, 2016 at 4:02:38 PM UTC-4, Alan Thompson wrote:
>
> Hi Paul,
>
> Since you are interested in the threading macros, you might like to take a 
> look at one of my favorite variants from the Tupelo library 
> :
>
> Literate Threading Macro
>
> We all love to use the threading macros -> and ->> for certain tasks, but 
> they only work if all of the forms should be threaded into the first or 
> last argument.
>
> The built-in threading macro as-> can avoid this requirement, but the 
> order of the first expression and the placeholder symbol is arguably 
> backwards from what users would expect. Also, there is often no obvious 
> name to use for the placeholder symbol. Re-using a good idea from Groovy, 
> we simply use the symbol it as the placeholder symbol in each expression 
> to represent the value of the previous result.
>
> (it-> 1
>   (inc it)  ; thread-first or thread-last
>   (+ it 3)  ; thread-first
>   (/ 10 it) ; thread-last
>   (str "We need to order " it " items." )   ; middle of 3 arguments;=> 
> "We need to order 2 items." )
>
> Here is a more complicated example. Note that we can assign into a local 
> let block from the it placeholder value:
>
> (it-> 3
>   (spy :msg :initial it)
>   (let [x it]
> (inc x))
>   (spy it :msg 222)
>   (* it 2)
>   (spyx it)); :initial => 3; 222 => 4; it => 88   ; return value
>
> Note that the :msg argument does not need to be a string. As shown above, 
> keywords, integers, etc may be used.
> Alan
>
>
> On Wed, Sep 28, 2016 at 11:36 AM, Colin Yates  > wrote:
>
>> Welcome to one of the best things about Clojure - the community. However, 
>> if anyone starts using the phrase 'Clojurian' then it is time to leave :-).
>>
>>
>>
>> On Wed, 28 Sep 2016, at 07:17 PM, pa...@pwjw.com  wrote:
>>
>> Wow thank you all for the really useful responses. How great. I 
>> appreciate the time.
>>
>> as-> cleans up a couple of ugly bits of my code already, yes. And I'm 
>> sort of irritated with myself for not thinking of _ (if (throw)) in my let 
>> but yes that's a perfect idiom.
>>
>>
>> I totally get the minimalist approach in clojure.test and like it. In 
>> fact, the ease of testing (and how easy it is to get coverage running with 
>> cloverage) is one of the things I find the most impressive. expectations 
>> looks interesting though too for a lot of my tests and I'll spend some time 
>> with it too.
>>
>> The idiom of "most important is first unless its a sequence then it is 
>> last" is really natural too; but I think it's what makes me end up 
>> switching from ->> to ->. Putting a "first" in the middle of a ->> 
>> expression is, I suppose, a hint that I'm switching.  Looking at my code, 
>> it really seems to be a mix of ->> and "doto" that I'm looking for. Here's 
>> a fragment, for instance, that returns me an opened instance of the first 
>> core midi device with a name that can receive messages. (and I know I 
>> should error check that there is one after that filter... that's on my todo 
>> list). An "as-> doto" pair would help and I'll get right on that later on 
>> this week.
>>
>> (->> (MidiSystem/getMidiDeviceInfo)
>>
>> (filter #(= (.getName ^MidiDevice$Info %) name))
>>
>> (map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
>>
>> (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))
>>
>> first
>>
>> (#(do (.open ^MidiDevice %) %))
>>
>> (#(.getReceiver ^MidiDevice %))
>>
>> )
>>
>> Anyway, wow thanks again for all the responses!
>>
>>
>>
>>
>>
>> On Wednesday, September 28, 2016 at 10:31:37 AM UTC-4, pa...@pwjw.com 
>> wrote:
>>
>> Hi.
>>
>> I'm new to clojure, and it is quite lovely. The threading model is great, 
>> the emacs integration is super, and the tasteful lisp extensions are good. 
>> A very nice programming environment all around. 
>>
>> But as I write more code I find a couple of structures I'm using a lot 
>> which seem related to me not knowing idioms for a couple of uses cases. So 
>> thought I'd ask and see if you have any suggestions. 
>>
>> Apologies if this is covered elsewhere. And if I should read some 
>> existing documentation I didn't find, I apologize for missing it. And 
>> thanks in advance for your time reading!
>>
>> First the thrush operators (-> and ->>) are super handy. But I find 
>> myself needing to 'move' arguments every now and then. So I get code which 
>> looks like
>>
>> (->> blah
>>  (do-this)
>>  (do-that arg)
>>  ((fn [s

Re: Idiom question

2016-09-28 Thread Alan Thompson
Hi Paul,

Since you are interested in the threading macros, you might like to take a
look at one of my favorite variants from the Tupelo library
:

Literate Threading Macro

We all love to use the threading macros -> and ->> for certain tasks, but
they only work if all of the forms should be threaded into the first or
last argument.

The built-in threading macro as-> can avoid this requirement, but the order
of the first expression and the placeholder symbol is arguably backwards
from what users would expect. Also, there is often no obvious name to use
for the placeholder symbol. Re-using a good idea from Groovy, we simply use
the symbol it as the placeholder symbol in each expression to represent the
value of the previous result.

(it-> 1
  (inc it)  ; thread-first or thread-last
  (+ it 3)  ; thread-first
  (/ 10 it) ; thread-last
  (str "We need to order " it " items." )   ; middle of 3
arguments;=> "We need to order 2 items." )

Here is a more complicated example. Note that we can assign into a
local let block
from the it placeholder value:

(it-> 3
  (spy :msg :initial it)
  (let [x it]
(inc x))
  (spy it :msg 222)
  (* it 2)
  (spyx it)); :initial => 3; 222 => 4; it => 88   ; return value

Note that the :msg argument does not need to be a string. As shown above,
keywords, integers, etc may be used.
Alan


On Wed, Sep 28, 2016 at 11:36 AM, Colin Yates  wrote:

> Welcome to one of the best things about Clojure - the community. However,
> if anyone starts using the phrase 'Clojurian' then it is time to leave :-).
>
>
>
> On Wed, 28 Sep 2016, at 07:17 PM, p...@pwjw.com wrote:
>
> Wow thank you all for the really useful responses. How great. I appreciate
> the time.
>
> as-> cleans up a couple of ugly bits of my code already, yes. And I'm sort
> of irritated with myself for not thinking of _ (if (throw)) in my let but
> yes that's a perfect idiom.
>
>
> I totally get the minimalist approach in clojure.test and like it. In
> fact, the ease of testing (and how easy it is to get coverage running with
> cloverage) is one of the things I find the most impressive. expectations
> looks interesting though too for a lot of my tests and I'll spend some time
> with it too.
>
> The idiom of "most important is first unless its a sequence then it is
> last" is really natural too; but I think it's what makes me end up
> switching from ->> to ->. Putting a "first" in the middle of a ->>
> expression is, I suppose, a hint that I'm switching.  Looking at my code,
> it really seems to be a mix of ->> and "doto" that I'm looking for. Here's
> a fragment, for instance, that returns me an opened instance of the first
> core midi device with a name that can receive messages. (and I know I
> should error check that there is one after that filter... that's on my todo
> list). An "as-> doto" pair would help and I'll get right on that later on
> this week.
>
> (->> (MidiSystem/getMidiDeviceInfo)
>
> (filter #(= (.getName ^MidiDevice$Info %) name))
>
> (map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
>
> (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))
>
> first
>
> (#(do (.open ^MidiDevice %) %))
>
> (#(.getReceiver ^MidiDevice %))
>
> )
>
> Anyway, wow thanks again for all the responses!
>
>
>
>
>
> On Wednesday, September 28, 2016 at 10:31:37 AM UTC-4, pa...@pwjw.com
> wrote:
>
> Hi.
>
> I'm new to clojure, and it is quite lovely. The threading model is great,
> the emacs integration is super, and the tasteful lisp extensions are good.
> A very nice programming environment all around.
>
> But as I write more code I find a couple of structures I'm using a lot
> which seem related to me not knowing idioms for a couple of uses cases. So
> thought I'd ask and see if you have any suggestions.
>
> Apologies if this is covered elsewhere. And if I should read some existing
> documentation I didn't find, I apologize for missing it. And thanks in
> advance for your time reading!
>
> First the thrush operators (-> and ->>) are super handy. But I find myself
> needing to 'move' arguments every now and then. So I get code which looks
> like
>
> (->> blah
>  (do-this)
>  (do-that arg)
>  ((fn [s] (rearrange arg s arg
>
> quite a lot.The alternate is a big nested let like
>
>  (let  [ first   (blah)
>   second  (do-this first)
>   ...
>   result  (wrap-it-up fourteenth) ]
> result)
>
> for sort of sequential application where arguments fall in different
> 'spots'. So I sort of find myself wanting to write a 'positional-thrush'
> macro like
>
> (-%> blah
>  (do-this %)
>  (do-that arg %)
>  (do-the-other a1 % a2))
>
> where % is replaced with the output of the prior. But no such operator
> exists as far as I can see. So eit

Re: Idiom question

2016-09-28 Thread Colin Yates
Welcome to one of the best things about Clojure - the community.
However, if anyone starts using the phrase 'Clojurian' then it is time
to leave :-).



On Wed, 28 Sep 2016, at 07:17 PM, p...@pwjw.com wrote:
> Wow thank you all for the really useful responses. How great. I
> appreciate the time.
>
> as-> cleans up a couple of ugly bits of my code already, yes. And I'm
> sort of irritated with myself for not thinking of _ (if (throw)) in my
> let but yes that's a perfect idiom.
>
>
> I totally get the minimalist approach in clojure.test and like it. In
> fact, the ease of testing (and how easy it is to get coverage running
> with cloverage) is one of the things I find the most impressive.
> expectations looks interesting though too for a lot of my tests and
> I'll spend some time with it too.
>
> The idiom of "most important is first unless its a sequence then it is
> last" is really natural too; but I think it's what makes me end up
> switching from ->> to ->. Putting a "first" in the middle of a ->>
> expression is, I suppose, a hint that I'm switching.  Looking at my
> code, it really seems to be a mix of ->> and "doto" that I'm looking
> for. Here's a fragment, for instance, that returns me an opened
> instance of the first core midi device with a name that can receive
> messages. (and I know I should error check that there is one after
> that filter... that's on my todo list). An "as-> doto" pair would help
> and I'll get right on that later on this week.
>
> (->> (MidiSystem/getMidiDeviceInfo)
> (filter #(= (.getName ^MidiDevice$Info %) name))
> (map #(MidiSystem/getMidiDevice ^MidDevice$Info %))
> (filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))
> first
> (#(do (.open ^MidiDevice %) %))
> (#(.getReceiver ^MidiDevice %))
> )
>
> Anyway, wow thanks again for all the responses!
>
>
>
>
>
> On Wednesday, September 28, 2016 at 10:31:37 AM UTC-4,
> pa...@pwjw.com wrote:
>> Hi.
>>
>> I'm new to clojure, and it is quite lovely. The threading model is
>> great, the emacs integration is super, and the tasteful lisp
>> extensions are good. A very nice programming environment all around.
>>
>> But as I write more code I find a couple of structures I'm using a
>> lot which seem related to me not knowing idioms for a couple of uses
>> cases. So thought I'd ask and see if you have any suggestions.
>>
>> Apologies if this is covered elsewhere. And if I should read some
>> existing documentation I didn't find, I apologize for missing it. And
>> thanks in advance for your time reading!
>>
>> First the thrush operators (-> and ->>) are super handy. But I find
>> myself needing to 'move' arguments every now and then. So I get code
>> which looks like
>>
>> (->> blah
>>  (do-this)
>>  (do-that arg)
>>  ((fn [s] (rearrange arg s arg
>>
>> quite a lot.The alternate is a big nested let like
>>
>>  (let  [ first   (blah)
>>   second  (do-this first)
>>   ...
>>   result  (wrap-it-up fourteenth) ]
>> result)
>>
>> for sort of sequential application where arguments fall in different
>> 'spots'. So I sort of find myself wanting to write a 'positional-
>> thrush' macro like
>>
>> (-%> blah
>>  (do-this %)
>>  (do-that arg %)
>>  (do-the-other a1 % a2))
>>
>> where % is replaced with the output of the prior. But no such
>> operator exists as far as I can see. So either I've had a good idea
>> (which is unlikely since I'm super new to the language) or there's
>> some other idiom you all use for this pattern which I've missed.
>>
>> The second is smaller, but is more a question. clojure.test seems to
>> only have 'is' so for things like equality I end up writing (is (=
>> (...) (...))) a lot. Or to test if an exception is thrown (is
>> (thrown? ...)). That's OK, but I'm wondering what led to that
>> decision rather than having is-eq and is-thrown and so on
>> (considering the core language has shortcuts like when and unless and
>> if-not so the compound macros seem idiomatic).
>>
>> The last is sort of related to the first. Sometimes I'm assembling a
>> data structure in a set of operators and I write them with a let or a
>> -> and half way through I have an error condition I want to check. In
>> a mutable procedural language you would do something like
>>
>>   x = blah
>>   y = bim
>>   if (! (condition (y))) throw "y doesn't meet condition"
>>   z = blob
>>
>> I don't see a good idiom for this. I have to split and nest lets for
>> instance
>>
>> (let [x (blah) y (bim) ]
>>   (if (condition (y)) (throw ...)
>>  (let [ z (blob) ]
>>   ))
>>
>> which seems a bit ugly.  I sort of want a let-with-test or a thrush-with-
>> test so something which looks like
>>
>> (-%?>  (init)
>>  (operator-1 %)  (post-condition)
>>  (operator-2 %)  (post-condition) )
>>
>> where if I don't have a post condition I could just use 'true'. Then
>> this expands to doing a quick '(if (not (postcondition (intermedia-
>> result))

Re: Idiom question

2016-09-28 Thread paul
Wow thank you all for the really useful responses. How great. I appreciate 
the time.

as-> cleans up a couple of ugly bits of my code already, yes. And I'm sort 
of irritated with myself for not thinking of _ (if (throw)) in my let but 
yes that's a perfect idiom.


I totally get the minimalist approach in clojure.test and like it. In fact, 
the ease of testing (and how easy it is to get coverage running with 
cloverage) is one of the things I find the most impressive. expectations 
looks interesting though too for a lot of my tests and I'll spend some time 
with it too.

The idiom of "most important is first unless its a sequence then it is 
last" is really natural too; but I think it's what makes me end up 
switching from ->> to ->. Putting a "first" in the middle of a ->> 
expression is, I suppose, a hint that I'm switching.  Looking at my code, 
it really seems to be a mix of ->> and "doto" that I'm looking for. Here's 
a fragment, for instance, that returns me an opened instance of the first 
core midi device with a name that can receive messages. (and I know I 
should error check that there is one after that filter... that's on my todo 
list). An "as-> doto" pair would help and I'll get right on that later on 
this week.

(->> (MidiSystem/getMidiDeviceInfo)

(filter #(= (.getName ^MidiDevice$Info %) name))

(map #(MidiSystem/getMidiDevice ^MidDevice$Info %))

(filter #(>= (.getMaxTransmitters ^MidiDevice %) 0))

first

(#(do (.open ^MidiDevice %) %))

(#(.getReceiver ^MidiDevice %))

)

Anyway, wow thanks again for all the responses!





On Wednesday, September 28, 2016 at 10:31:37 AM UTC-4, pa...@pwjw.com wrote:
>
> Hi.
>
> I'm new to clojure, and it is quite lovely. The threading model is great, 
> the emacs integration is super, and the tasteful lisp extensions are good. 
> A very nice programming environment all around. 
>
> But as I write more code I find a couple of structures I'm using a lot 
> which seem related to me not knowing idioms for a couple of uses cases. So 
> thought I'd ask and see if you have any suggestions. 
>
> Apologies if this is covered elsewhere. And if I should read some existing 
> documentation I didn't find, I apologize for missing it. And thanks in 
> advance for your time reading!
>
> First the thrush operators (-> and ->>) are super handy. But I find myself 
> needing to 'move' arguments every now and then. So I get code which looks 
> like
>
> (->> blah
>  (do-this)
>  (do-that arg)
>  ((fn [s] (rearrange arg s arg
>
> quite a lot.The alternate is a big nested let like
>
>  (let  [ first   (blah)
>   second  (do-this first)
>   ...
>   result  (wrap-it-up fourteenth) ]
> result)
>
> for sort of sequential application where arguments fall in different 
> 'spots'. So I sort of find myself wanting to write a 'positional-thrush' 
> macro like
>
> (-%> blah
>  (do-this %)
>  (do-that arg %)
>  (do-the-other a1 % a2))
>
> where % is replaced with the output of the prior. But no such operator 
> exists as far as I can see. So either I've had a good idea (which is 
> unlikely since I'm super new to the language) or there's some other idiom 
> you all use for this pattern which I've missed.
>
> The second is smaller, but is more a question. clojure.test seems to only 
> have 'is' so for things like equality I end up writing (is (= (...) (...))) 
> a lot. Or to test if an exception is thrown (is (thrown? ...)). That's OK, 
> but I'm wondering what led to that decision rather than having is-eq and 
> is-thrown and so on (considering the core language has shortcuts like when 
> and unless and if-not so the compound macros seem idiomatic).
>
> The last is sort of related to the first. Sometimes I'm assembling a data 
> structure in a set of operators and I write them with a let or a -> and 
> half way through I have an error condition I want to check. In a mutable 
> procedural language you would do something like
>
>   x = blah
>   y = bim
>   if (! (condition (y))) throw "y doesn't meet condition"
>   z = blob
>
> I don't see a good idiom for this. I have to split and nest lets for 
> instance
>
> (let [x (blah) y (bim) ]
>   (if (condition (y)) (throw ...)
>  (let [ z (blob) ] 
>   ))
>
> which seems a bit ugly.  I sort of want a let-with-test or a 
> thrush-with-test so something which looks like
>
> (-%?>  (init)
>  (operator-1 %)  (post-condition)
>  (operator-2 %)  (post-condition) )
>
> where if I don't have a post condition I could just use 'true'. Then this 
> expands to doing a quick '(if (not (postcondition (intermedia-result 
> throw...)
>
> but that's a crazy thing to want. So curious how you all tackle this.
>
> Thank you all for your consideration. And apologies again if this is 
> covered elsewhere or I should have asked in a different forum.
>
> Best,
>
>   Paul
>

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

Re: Idiom question

2016-09-28 Thread Sean Corfield
Welcome to Clojure!

As others have noted, there are quite a few threading macros so your example 
could become:

(-> blah
(do-this)
(->> (do-that arg))
(as-> s (do-the-other a1 s a2)))

Or:

(-> (->> blah
 (do-this)
 (do-that arg))
(as-> s (do-the-other a1 s a2)))

How elegant the result ends up being will depend on exactly how many first 
position, last position, and “in the middle” position your expressions are. One 
thing to be aware of is that, idiomatically, Clojure tries to follow the 
pattern that the “important” argument is always the first one (the thing being 
“operated on”), except for collection functions where it is always the last 
one. The former lends itself to -> and the latter to ->> (and partial) so if 
you have an expression that seems to be a mixture of both, think hard about 
whether the functions are following that idiom.

In your example, if blah is a collection, then do-the-other probably ought to 
be:

(do-the-other a1 a2 coll)
   ;; and use ->> blah across all three calls

If blah is the “important” argument, then maybe do-that and do-the-other should 
have it consistently in the first position:

(do-that s arg)
(do-the-other s a1 a2)
;; and use -> blah across all three calls

If you still need to mix -> and ->> perhaps break the expression up and use let 
to bind appropriate names to the subexpressions for clarity of intent.

For the conditional throw code, I’d suggest two possible alternatives:

(let [x blah
  y bim
  _ (when-not (condition y) (throw …))
  z blob]
  …)

The _ is just a convention for “this is unused”. Or, if your blob does not 
depend on y, simply reorder things:

(let [x blah
  y bim
  z blob]
  (when-not (condition y) (throw …))
  …)

As for clojure.test/is – if you want something a bit more expressive that is 
still concise, I’d recommend Expectations http://jayfields.com/expectations/ -- 
we switched to this from clojure.test several years ago and we’ve been very 
happy with it:

(expect value expression)
(expect predicate? expression)
(expect SomeException expression)

To us, that’s a very natural way to write tests. clojure.test feels a bit 
“imperative” since it’s “assert this, assert that”. Mind you, testing is very 
subjective and I know there are folks who won’t like the opinionated way 
Expectations wants you to write your tests.

Hope that helps?

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

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

On 9/28/16, 7:26 AM, "clojure@googlegroups.com on behalf of p...@pwjw.com" 
 wrote:

Hi.

I'm new to clojure, and it is quite lovely. The threading model is great, the 
emacs integration is super, and the tasteful lisp extensions are good. A very 
nice programming environment all around. 

But as I write more code I find a couple of structures I'm using a lot which 
seem related to me not knowing idioms for a couple of uses cases. So thought 
I'd ask and see if you have any suggestions. 

Apologies if this is covered elsewhere. And if I should read some existing 
documentation I didn't find, I apologize for missing it. And thanks in advance 
for your time reading!

First the thrush operators (-> and ->>) are super handy. But I find myself 
needing to 'move' arguments every now and then. So I get code which looks like

(->> blah
     (do-this)
     (do-that arg)
     ((fn [s] (rearrange arg s arg

quite a lot.The alternate is a big nested let like

 (let  [ first   (blah)
          second  (do-this first)
          ...
          result  (wrap-it-up fourteenth) ]
    result)

for sort of sequential application where arguments fall in different 'spots'. 
So I sort of find myself wanting to write a 'positional-thrush' macro like

(-%> blah
     (do-this %)
     (do-that arg %)
     (do-the-other a1 % a2))

where % is replaced with the output of the prior. But no such operator exists 
as far as I can see. So either I've had a good idea (which is unlikely since 
I'm super new to the language) or there's some other idiom you all use for this 
pattern which I've missed.

The second is smaller, but is more a question. clojure.test seems to only have 
'is' so for things like equality I end up writing (is (= (...) (...))) a lot. 
Or to test if an exception is thrown (is (thrown? ...)). That's OK, but I'm 
wondering what led to that decision rather than having is-eq and is-thrown and 
so on (considering the core language has shortcuts like when and unless and 
if-not so the compound macros seem idiomatic).

The last is sort of related to the first. Sometimes I'm assembling a data 
structure in a set of operators and I write them with a let or a -> and half 
way through I have an error condi

Re: Idiom question

2016-09-28 Thread Stuart Sierra
I will answer the clojure.test question, since I wrote it.

You can call clojure.test/is with *any* Clojure expression: if the 
expression returns logical true, the assertion passes. Having just the one 
expression keeps the scope of the testing library small.

The `clojure.test/is` macro was designed to be extensible, based on the 
syntax of the expression you pass it, but in a really convoluted way 
involving multimethods and macroexpansion. It was an experiment that did 
not turn out well, and I don't recommend it.

–Stuart S.


On Wednesday, September 28, 2016 at 10:31:37 AM UTC-4, paul wrote:
>
> The second is smaller, but is more a question. clojure.test seems to only 
> have 'is' so for things like equality I end up writing (is (= (...) (...))) 
> a lot. Or to test if an exception is thrown (is (thrown? ...)). That's OK, 
> but I'm wondering what led to that decision rather than having is-eq and 
> is-thrown and so on (considering the core language has shortcuts like when 
> and unless and if-not so the compound macros seem idiomatic).
>

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


Re: Idiom question

2016-09-28 Thread Colin Yates
You might want to checkout 'cond->', 'condp' and 'as->'. Checkout the
excellent clojuredocs.org website for examples of their usage
(https://clojuredocs.org/clojure.core/condp for example).

Sorry to be so succinct - deadlines etc.

On Wed, 28 Sep 2016, at 03:26 PM, p...@pwjw.com wrote:
> Hi.
>
> I'm new to clojure, and it is quite lovely. The threading model is
> great, the emacs integration is super, and the tasteful lisp
> extensions are good. A very nice programming environment all around.
>
> But as I write more code I find a couple of structures I'm using a lot
> which seem related to me not knowing idioms for a couple of uses
> cases. So thought I'd ask and see if you have any suggestions.
>
> Apologies if this is covered elsewhere. And if I should read some
> existing documentation I didn't find, I apologize for missing it. And
> thanks in advance for your time reading!
>
> First the thrush operators (-> and ->>) are super handy. But I find
> myself needing to 'move' arguments every now and then. So I get code
> which looks like
>
> (->> blah
>  (do-this)
>  (do-that arg)
>  ((fn [s] (rearrange arg s arg
>
> quite a lot.The alternate is a big nested let like
>
>  (let  [ first   (blah)
>   second  (do-this first)
>   ...
>   result  (wrap-it-up fourteenth) ]
> result)
>
> for sort of sequential application where arguments fall in different
> 'spots'. So I sort of find myself wanting to write a 'positional-
> thrush' macro like
>
> (-%> blah
>  (do-this %)
>  (do-that arg %)
>  (do-the-other a1 % a2))
>
> where % is replaced with the output of the prior. But no such operator
> exists as far as I can see. So either I've had a good idea (which is
> unlikely since I'm super new to the language) or there's some other
> idiom you all use for this pattern which I've missed.
>
> The second is smaller, but is more a question. clojure.test seems to
> only have 'is' so for things like equality I end up writing (is (=
> (...) (...))) a lot. Or to test if an exception is thrown (is (thrown?
> ...)). That's OK, but I'm wondering what led to that decision rather
> than having is-eq and is-thrown and so on (considering the core
> language has shortcuts like when and unless and if-not so the compound
> macros seem idiomatic).
>
> The last is sort of related to the first. Sometimes I'm assembling a
> data structure in a set of operators and I write them with a let or a
> -> and half way through I have an error condition I want to check. In
> a mutable procedural language you would do something like
>
>   x = blah
>   y = bim
>   if (! (condition (y))) throw "y doesn't meet condition"
>   z = blob
>
> I don't see a good idiom for this. I have to split and nest lets for
> instance
>
> (let [x (blah) y (bim) ]
>   (if (condition (y)) (throw ...)
>  (let [ z (blob) ]
>   ))
>
> which seems a bit ugly.  I sort of want a let-with-test or a thrush-with-
> test so something which looks like
>
> (-%?>  (init)
>  (operator-1 %)  (post-condition)
>  (operator-2 %)  (post-condition) )
>
> where if I don't have a post condition I could just use 'true'. Then
> this expands to doing a quick '(if (not (postcondition (intermedia-
> result throw...)
>
> but that's a crazy thing to want. So curious how you all tackle this.
>
> Thank you all for your consideration. And apologies again if this is
> covered elsewhere or I should have asked in a different forum.
>
> Best,
>
>   Paul
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient
> with your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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


Re: Idiom question

2016-09-28 Thread Alex Miller
Hi Paul, there is a rich history of people extending the thread macros. For 
things in core, check out some of the other threading operators: as->, 
cond->, some-> etc as they handle more of your cases below. This is a good 
overview of what they do:

http://clojure.org/guides/threading_macros

Additionally, there are a bunch of libraries that provide other variants 
like synthread , swiss-arrows 
, and even core.incubator 
. 


On Wednesday, September 28, 2016 at 9:31:37 AM UTC-5, p...@pwjw.com wrote:
>
> Hi.
>
> I'm new to clojure, and it is quite lovely. The threading model is great, 
> the emacs integration is super, and the tasteful lisp extensions are good. 
> A very nice programming environment all around. 
>
> But as I write more code I find a couple of structures I'm using a lot 
> which seem related to me not knowing idioms for a couple of uses cases. So 
> thought I'd ask and see if you have any suggestions. 
>
> Apologies if this is covered elsewhere. And if I should read some existing 
> documentation I didn't find, I apologize for missing it. And thanks in 
> advance for your time reading!
>
> First the thrush operators (-> and ->>) are super handy. But I find myself 
> needing to 'move' arguments every now and then. So I get code which looks 
> like
>
> (->> blah
>  (do-this)
>  (do-that arg)
>  ((fn [s] (rearrange arg s arg
>
> quite a lot.The alternate is a big nested let like
>
>  (let  [ first   (blah)
>   second  (do-this first)
>   ...
>   result  (wrap-it-up fourteenth) ]
> result)
>
> for sort of sequential application where arguments fall in different 
> 'spots'. So I sort of find myself wanting to write a 'positional-thrush' 
> macro like
>
> (-%> blah
>  (do-this %)
>  (do-that arg %)
>  (do-the-other a1 % a2))
>
> where % is replaced with the output of the prior. But no such operator 
> exists as far as I can see. So either I've had a good idea (which is 
> unlikely since I'm super new to the language) or there's some other idiom 
> you all use for this pattern which I've missed.
>
> The second is smaller, but is more a question. clojure.test seems to only 
> have 'is' so for things like equality I end up writing (is (= (...) (...))) 
> a lot. Or to test if an exception is thrown (is (thrown? ...)). That's OK, 
> but I'm wondering what led to that decision rather than having is-eq and 
> is-thrown and so on (considering the core language has shortcuts like when 
> and unless and if-not so the compound macros seem idiomatic).
>
> The last is sort of related to the first. Sometimes I'm assembling a data 
> structure in a set of operators and I write them with a let or a -> and 
> half way through I have an error condition I want to check. In a mutable 
> procedural language you would do something like
>
>   x = blah
>   y = bim
>   if (! (condition (y))) throw "y doesn't meet condition"
>   z = blob
>
> I don't see a good idiom for this. I have to split and nest lets for 
> instance
>
> (let [x (blah) y (bim) ]
>   (if (condition (y)) (throw ...)
>  (let [ z (blob) ] 
>   ))
>
> which seems a bit ugly.  I sort of want a let-with-test or a 
> thrush-with-test so something which looks like
>
> (-%?>  (init)
>  (operator-1 %)  (post-condition)
>  (operator-2 %)  (post-condition) )
>
> where if I don't have a post condition I could just use 'true'. Then this 
> expands to doing a quick '(if (not (postcondition (intermedia-result 
> throw...)
>
> but that's a crazy thing to want. So curious how you all tackle this.
>
> Thank you all for your consideration. And apologies again if this is 
> covered elsewhere or I should have asked in a different forum.
>
> Best,
>
>   Paul
>

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


Idiom question

2016-09-28 Thread paul
Hi.

I'm new to clojure, and it is quite lovely. The threading model is great, 
the emacs integration is super, and the tasteful lisp extensions are good. 
A very nice programming environment all around. 

But as I write more code I find a couple of structures I'm using a lot 
which seem related to me not knowing idioms for a couple of uses cases. So 
thought I'd ask and see if you have any suggestions. 

Apologies if this is covered elsewhere. And if I should read some existing 
documentation I didn't find, I apologize for missing it. And thanks in 
advance for your time reading!

First the thrush operators (-> and ->>) are super handy. But I find myself 
needing to 'move' arguments every now and then. So I get code which looks 
like

(->> blah
 (do-this)
 (do-that arg)
 ((fn [s] (rearrange arg s arg

quite a lot.The alternate is a big nested let like

 (let  [ first   (blah)
  second  (do-this first)
  ...
  result  (wrap-it-up fourteenth) ]
result)

for sort of sequential application where arguments fall in different 
'spots'. So I sort of find myself wanting to write a 'positional-thrush' 
macro like

(-%> blah
 (do-this %)
 (do-that arg %)
 (do-the-other a1 % a2))

where % is replaced with the output of the prior. But no such operator 
exists as far as I can see. So either I've had a good idea (which is 
unlikely since I'm super new to the language) or there's some other idiom 
you all use for this pattern which I've missed.

The second is smaller, but is more a question. clojure.test seems to only 
have 'is' so for things like equality I end up writing (is (= (...) (...))) 
a lot. Or to test if an exception is thrown (is (thrown? ...)). That's OK, 
but I'm wondering what led to that decision rather than having is-eq and 
is-thrown and so on (considering the core language has shortcuts like when 
and unless and if-not so the compound macros seem idiomatic).

The last is sort of related to the first. Sometimes I'm assembling a data 
structure in a set of operators and I write them with a let or a -> and 
half way through I have an error condition I want to check. In a mutable 
procedural language you would do something like

  x = blah
  y = bim
  if (! (condition (y))) throw "y doesn't meet condition"
  z = blob

I don't see a good idiom for this. I have to split and nest lets for 
instance

(let [x (blah) y (bim) ]
  (if (condition (y)) (throw ...)
 (let [ z (blob) ] 
  ))

which seems a bit ugly.  I sort of want a let-with-test or a 
thrush-with-test so something which looks like

(-%?>  (init)
 (operator-1 %)  (post-condition)
 (operator-2 %)  (post-condition) )

where if I don't have a post condition I could just use 'true'. Then this 
expands to doing a quick '(if (not (postcondition (intermedia-result 
throw...)

but that's a crazy thing to want. So curious how you all tackle this.

Thank you all for your consideration. And apologies again if this is 
covered elsewhere or I should have asked in a different forum.

Best,

  Paul

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


Re: idiom question: infinite sequence as data source for many threads?

2010-02-01 Thread free_variation
Urp yes thanks!  Remainder of a previous version of the function.

jds

On Feb 1, 3:57 pm, Daniel Werner 
wrote:
> On Jan 30, 7:07 am, free_variation  wrote:
>
> > (defn init-features [stream]
> >         (let [feature-stream (ref stream)]
> >                 (dosync (ref-set feature-stream stream))
>
> The call to ref-set seems redundant here since you already initialize
> the ref with stream as its value.

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-02-01 Thread Daniel Werner
On Jan 30, 7:07 am, free_variation  wrote:
> (defn init-features [stream]
> (let [feature-stream (ref stream)]
> (dosync (ref-set feature-stream stream))

The call to ref-set seems redundant here since you already initialize
the ref with stream as its value.

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-02-01 Thread Daniel Werner
On Jan 30, 8:09 am, Timothy Pratley  wrote:
> Below I present 'submit-future' which is similar to the existing
> 'future' call in that it spawns a thread to execute a task, but
> differs in that it will block if n submitted futures are already
> running, where n is the number of available processors. I think this
> could be quite handy for the producer-consumer model which lazy-seq
> lends itself to, allowing one to write:

This looks like it could become really useful in the future (no pun
intended), thanks for sharing! Instead of enforcing its own thread
count limit, however, it might be worthwhile to interface with the
Agent thread pool. Otherwise, in the worst case a machine with N cores
could try to run N+2 agent threads and N+2 future-submit threads at
once. That said, I'm not sure about the consequences of the Agent
thread pool being saturated by copious use of future-submit.

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-31 Thread Timothy Pratley
On 1 February 2010 15:21, free_variation  wrote:
> Mind if I use it?

Of course I don't mind. It is intended for your use. :)



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 
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: idiom question: infinite sequence as data source for many threads?

2010-01-31 Thread free_variation
Excellent, very nice.  Mind if I use it?

jds

On Jan 30, 2:09 am, Timothy Pratley  wrote:
> Below I present 'submit-future' which is similar to the existing
> 'future' call in that it spawns a thread to execute a task, but
> differs in that it will block if n submitted futures are already
> running, where n is the number of available processors. I think this
> could be quite handy for the producer-consumer model which lazy-seq
> lends itself to, allowing one to write:
>
> (doseq [d data-seq]
>   (submit-future (foo d)))
>
> where data-seq is some feed of CPU bound tasks which you want to
> process as quickly as possible. This is diverging from the OP, but
> thought it might be of interest:
>
> (let [limit (.availableProcessors (Runtime/getRuntime))
>       sem (java.util.concurrent.Semaphore. limit)]
>   (defn submit-future-call
>     "Takes a function of no args and yields a future object that will
>     invoke the function in another thread, and will cache the result and
>     return it on all subsequent calls to deref/@. If the computation has
>     not yet finished, calls to deref/@ will block.
>     If n futures have already been submitted, then submit-future blocks
>     until the completion of another future, where n is the number of
>     available processors."
>     [#^Callable task]
>     ; take a slot (or block until a slot is free)
>     (.acquire sem)
>     (try
>       ; create a future that will free a slot on completion
>       (future (try (task) (finally (.release sem
>       (catch java.util.concurrent.RejectedExecutionException e
>         ; no task was actually submitted
>         (.release sem)
>         (throw e)
>
> (defmacro submit-future
>   "Takes a body of expressions and yields a future object that will
>   invoke the body in another thread, and will cache the result and
>   return it on all subsequent calls to deref/@. If the computation has
>   not yet finished, calls to deref/@ will block.
>   If n futures have already been submitted, then submit-future blocks
>   until the completion of another future, where n is the number of
>   available processors."
>   [& body] `(submit-future-call (fn [] ~...@body)))
>
> #_(example
>     user=> (submit-future (reduce + (range 1)))
>     #
>     user=> (submit-future (reduce + (range 1)))
>     #
>     user=> (submit-future (reduce + (range 1)))
>     ;; blocks at this point for a 2 processor PC until the previous
>     ;; two futures complete
>     #)

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-29 Thread Timothy Pratley
Below I present 'submit-future' which is similar to the existing
'future' call in that it spawns a thread to execute a task, but
differs in that it will block if n submitted futures are already
running, where n is the number of available processors. I think this
could be quite handy for the producer-consumer model which lazy-seq
lends itself to, allowing one to write:

(doseq [d data-seq]
  (submit-future (foo d)))

where data-seq is some feed of CPU bound tasks which you want to
process as quickly as possible. This is diverging from the OP, but
thought it might be of interest:


(let [limit (.availableProcessors (Runtime/getRuntime))
  sem (java.util.concurrent.Semaphore. limit)]
  (defn submit-future-call
"Takes a function of no args and yields a future object that will
invoke the function in another thread, and will cache the result and
return it on all subsequent calls to deref/@. If the computation has
not yet finished, calls to deref/@ will block.
If n futures have already been submitted, then submit-future blocks
until the completion of another future, where n is the number of
available processors."
[#^Callable task]
; take a slot (or block until a slot is free)
(.acquire sem)
(try
  ; create a future that will free a slot on completion
  (future (try (task) (finally (.release sem
  (catch java.util.concurrent.RejectedExecutionException e
; no task was actually submitted
(.release sem)
(throw e)

(defmacro submit-future
  "Takes a body of expressions and yields a future object that will
  invoke the body in another thread, and will cache the result and
  return it on all subsequent calls to deref/@. If the computation has
  not yet finished, calls to deref/@ will block.
  If n futures have already been submitted, then submit-future blocks
  until the completion of another future, where n is the number of
  available processors."
  [& body] `(submit-future-call (fn [] ~...@body)))

#_(example
user=> (submit-future (reduce + (range 1)))
#
user=> (submit-future (reduce + (range 1)))
#
user=> (submit-future (reduce + (range 1)))
;; blocks at this point for a 2 processor PC until the previous
;; two futures complete
#)

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-29 Thread free_variation
Thank you Meikel, I was aware of the nil issue but it's good that you
made that explicit.

I got rid of the 'symbol per your suggestion, and factored the closure
to take the stream as an input:

(defn init-features [stream]
(let [feature-stream (ref stream)]
(dosync (ref-set feature-stream stream))
(fn []
(dosync
(let [f (first @feature-stream)]
(alter feature-stream rest)
f)

It's amazing to me how concise this is.  I'm really loving Clojure!  I
kinda miss typing 'lambda' instead of 'fn' or '#(', but I suppose a
macro can fix that.  Must have been done already :)

On Jan 29, 1:42 am, Meikel Brandmeyer  wrote:
> Hi,
>
> On Jan 29, 5:05 am, free_variation  wrote:
>
>
>
> > You people are terrific, thanks so much.
>
> > I basically went with what Michal and Konrad worked out:
>
> > (let [feature-stream (ref nil)]
> >         (defn init-features [stream]
> >                 (dosync (ref-set feature-stream stream))
> >                 'ready)
> >         (defn get-feature []
> >                 (dosync
> >                         (let [f (first @feature-stream)]
> >                                 (alter feature-stream rest)
> >                                 f
>
> > Works like a charm.  Are the ref to nil (as initial value) and the
> > constructor-like "init-features" in the closure idiomatic to Clojure?
> > I realize I'm writing scheme here :)
>
> Please note, that you cannot distinguish a nil in the stream from an
> exhausted stream. That's the reason I returned the whole seq in my
> solution and not only the first element. Maybe this doesn't apply in
> your case, but you should keep it in mind for other occasions.
>
> For the idiomatic question (and personal taste): Use :keywords instead
> of 'quoted-symbols. I would not hard-wire the ref. I would make it
> explicit as an argument. You can spice this more general function for
> convenience with partial.
>
> 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: idiom question: infinite sequence as data source for many threads?

2010-01-29 Thread cburroughs
java.util.concurrent.LinkedBlockingQueue

Check out the put() method.  That what I used for a program similar to
the original poster when I needed control over the number of threads.

On Jan 28, 7:15 pm, Paul  Mooser  wrote:
> This is something I run into with executors in Java periodically - I
> have never understood why there isn't a default implementation
> provided which has a blocking queue for tasks which will block on
> submission to the queue if it is full. If I'm not mistaken, the
> default ones which use bounded blocking queues throw rejected
> execution exceptions if you submit too many tasks, or just let the
> queue grow without bounds.
>
> It should be relatively easy to set up an executor with that behavior,
> which would make it fairly easy to not produce things "too far" ahead
> of consumption.
>
> On Jan 28, 6:53 am, Timothy Pratley  wrote:
>
> > pooledExecutor is just a standard java fixed size thread pool based
> > upon the number of processors available, so it will only create X
> > threads at a time. However I believe that submitted jobs are queued so
> > if your seq processing can get too far ahead you would end up with a
> > very full queue. I'm sure there must be a way to limit the submission
> > rate but can't think of it right now maybe someone else will chime in

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Michael Wood
On 28 January 2010 23:30, Timothy Pratley  wrote:
> 2010/1/29 Michael Wood :
>>> (doseq [d data-seq]
>>>  (.submit clojure.lang.Agent/pooledExecutor (cast Callable #(foo d
>>
>> What's the purpose of the cast here?
>>
>> #(...) is an fn, which is Callable by definition, isn't it?  So
>> wouldn't that line be equivalent to:
>> (.submit clojure.lang.Agent/pooledExecutor #(foo d)))
>
> Yes and no... submit is overloaded on Callable and Runnable and #(foo
> d) implements both.
> user=> (.submit clojure.lang.Agent/pooledExecutor #(inc 1))
> java.lang.IllegalArgumentException: More than one matching method found: 
> submit
>
> The cast was just a quick hack to make the example work.

Ah, OK.  Thanks for the explanation.

-- 
Michael Wood 

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Meikel Brandmeyer
Hi,

On Jan 29, 5:05 am, free_variation  wrote:

> You people are terrific, thanks so much.
>
> I basically went with what Michal and Konrad worked out:
>
> (let [feature-stream (ref nil)]
>         (defn init-features [stream]
>                 (dosync (ref-set feature-stream stream))
>                 'ready)
>         (defn get-feature []
>                 (dosync
>                         (let [f (first @feature-stream)]
>                                 (alter feature-stream rest)
>                                 f
>
> Works like a charm.  Are the ref to nil (as initial value) and the
> constructor-like "init-features" in the closure idiomatic to Clojure?
> I realize I'm writing scheme here :)

Please note, that you cannot distinguish a nil in the stream from an
exhausted stream. That's the reason I returned the whole seq in my
solution and not only the first element. Maybe this doesn't apply in
your case, but you should keep it in mind for other occasions.

For the idiomatic question (and personal taste): Use :keywords instead
of 'quoted-symbols. I would not hard-wire the ref. I would make it
explicit as an argument. You can spice this more general function for
convenience with partial.

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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread free_variation
You people are terrific, thanks so much.

I basically went with what Michal and Konrad worked out:

(let [feature-stream (ref nil)]
(defn init-features [stream]
(dosync (ref-set feature-stream stream))
'ready)
(defn get-feature []
(dosync
(let [f (first @feature-stream)]
(alter feature-stream rest)
f

Works like a charm.  Are the ref to nil (as initial value) and the
constructor-like "init-features" in the closure idiomatic to Clojure?
I realize I'm writing scheme here :)

jds

On Jan 28, 2:39 am, Michał Marczyk  wrote:
> 2010/1/28 Konrad Hinsen :
>
> > The Clojure solution for your problem is an agent, which makes the access
> > thread-safe:
>
> > user> (def data-source (agent (cycle [1 2 3])))
> > #'user/data-source
> > user> (defn get-some-data [] (let [v (first @data-source)] (send data-source
> > rest) v))
>
> Wouldn't this make it possible for two threads to obtain the same
> value of (first @data-source), then send two rest messages to the
> agent?
>
> A ref would not have this problem, though:
>
> (def data-source (ref the_sequence))
> (defn get-some-data [] (dosync (let [v (first @data-source)] (alter
> data-source rest) v)))
>
> Sincerely,
> Michal

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Paul Mooser
This is something I run into with executors in Java periodically - I
have never understood why there isn't a default implementation
provided which has a blocking queue for tasks which will block on
submission to the queue if it is full. If I'm not mistaken, the
default ones which use bounded blocking queues throw rejected
execution exceptions if you submit too many tasks, or just let the
queue grow without bounds.

It should be relatively easy to set up an executor with that behavior,
which would make it fairly easy to not produce things "too far" ahead
of consumption.

On Jan 28, 6:53 am, Timothy Pratley  wrote:
> pooledExecutor is just a standard java fixed size thread pool based
> upon the number of processors available, so it will only create X
> threads at a time. However I believe that submitted jobs are queued so
> if your seq processing can get too far ahead you would end up with a
> very full queue. I'm sure there must be a way to limit the submission
> rate but can't think of it right now maybe someone else will chime in

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Timothy Pratley
2010/1/29 Michael Wood :
>> (doseq [d data-seq]
>>  (.submit clojure.lang.Agent/pooledExecutor (cast Callable #(foo d
>
> What's the purpose of the cast here?
>
> #(...) is an fn, which is Callable by definition, isn't it?  So
> wouldn't that line be equivalent to:
> (.submit clojure.lang.Agent/pooledExecutor #(foo d)))

Yes and no... submit is overloaded on Callable and Runnable and #(foo
d) implements both.
user=> (.submit clojure.lang.Agent/pooledExecutor #(inc 1))
java.lang.IllegalArgumentException: More than one matching method found: submit

The cast was just a quick hack to make the example work.

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Michael Wood
Hi

On 28 January 2010 16:53, Timothy Pratley  wrote:
[...]
> eg: if you had a file which you read as a lazy sequence you could
> create worker tasks like this:
> (doseq [d data-seq]
>  (.submit clojure.lang.Agent/pooledExecutor (cast Callable #(foo d

What's the purpose of the cast here?

#(...) is an fn, which is Callable by definition, isn't it?  So
wouldn't that line be equivalent to:
(.submit clojure.lang.Agent/pooledExecutor #(foo d)))

-- 
Michael Wood 

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Timothy Pratley
2010/1/28 free_variation :
> I have an infinite sequence.  I'd like to have the sequence be a
> source for N parallel worker threads that now and then will show up to
> grab a few elements from the sequence, then go off and crunch on the
> data.  The sequence should be traversed only once per execution of the
> software.

Who's in charge here? :) The other way to look at this problem is an
executor handing out the tasks (as opposed to threads asking for
work). That way there is no need to coordinate between workers.

eg: if you had a file which you read as a lazy sequence you could
create worker tasks like this:
(doseq [d data-seq]
  (.submit clojure.lang.Agent/pooledExecutor (cast Callable #(foo d

pooledExecutor is just a standard java fixed size thread pool based
upon the number of processors available, so it will only create X
threads at a time. However I believe that submitted jobs are queued so
if your seq processing can get too far ahead you would end up with a
very full queue. I'm sure there must be a way to limit the submission
rate but can't think of it right now maybe someone else will chime in
:)


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 
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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Meikel Brandmeyer
Hi,

On Jan 28, 5:21 am, free_variation  wrote:

> Is the solution to have my-seq somehow
> refer to the next element to be retrieved, i.e. to the head of the
> infinite sequence that has yet to be fed to the workers?

You probably want a Ref here to coordinate the changes on the
sequence.

(defn get-step
  [queue]
  (dosync
(let [q @queue]
  (alter queue rest)
  q)))

; Or for convenience if you like...
(def get-step-c
  (let [queue (ref your-seq-here)]
(partial get-item queue)))

Each worker can call get-step on your seq Ref. Then the current step
in the seq is returned and the Ref is updated to contain the next
step. The seq is returned, so you can do nil-checking of (seq q) or
working with (first q) and what you normally do with seqs.

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: idiom question: infinite sequence as data source for many threads?

2010-01-28 Thread Christophe Grand
Hi!

On Thu, Jan 28, 2010 at 8:39 AM, Michał Marczyk
 wrote:
> 2010/1/28 Konrad Hinsen :
>> The Clojure solution for your problem is an agent, which makes the access
>> thread-safe:
>>
>> user> (def data-source (agent (cycle [1 2 3])))
>> #'user/data-source
>> user> (defn get-some-data [] (let [v (first @data-source)] (send data-source
>> rest) v))
>
> Wouldn't this make it possible for two threads to obtain the same
> value of (first @data-source), then send two rest messages to the
> agent?
>
> A ref would not have this problem, though:
>
> (def data-source (ref the_sequence))
> (defn get-some-data [] (dosync (let [v (first @data-source)] (alter
> data-source rest) v)))

Right, or you could also use an atom:
(def data-source (atom (cons nil the_sequence)))
(defn get-some-data [] (first (swap! data-source rest)))

But this retains the last read value until next call to get-some-data.
I recently realized that one can work around this problem:
(def data-source (atom (cons nil the_sequence)))
(defn get-some-data []
  (let [s (swap! data-source rest)]
(swap! data-source #(if (identical? s %) (cons nil (rest %)) %))
(first s)))

This make me think that one could optimize Atom/swap by avoiding the
CAS and the validation (but not the watches) when (identical?
new-value old-value).

Christophe

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-27 Thread Konrad Hinsen

On 28 Jan 2010, at 08:39, Michał Marczyk wrote:


Wouldn't this make it possible for two threads to obtain the same
value of (first @data-source), then send two rest messages to the
agent?

A ref would not have this problem, though:


You are right. Refs provide synchronous access to the data source.

Konrad.

--
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: idiom question: infinite sequence as data source for many threads?

2010-01-27 Thread Michał Marczyk
2010/1/28 Konrad Hinsen :
> The Clojure solution for your problem is an agent, which makes the access
> thread-safe:
>
> user> (def data-source (agent (cycle [1 2 3])))
> #'user/data-source
> user> (defn get-some-data [] (let [v (first @data-source)] (send data-source
> rest) v))

Wouldn't this make it possible for two threads to obtain the same
value of (first @data-source), then send two rest messages to the
agent?

A ref would not have this problem, though:

(def data-source (ref the_sequence))
(defn get-some-data [] (dosync (let [v (first @data-source)] (alter
data-source rest) v)))

Sincerely,
Michal

-- 
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: idiom question: infinite sequence as data source for many threads?

2010-01-27 Thread Konrad Hinsen

On 28 Jan 2010, at 05:21, free_variation wrote:


I'm not clear on how to implement this without keeping a reference to
the sequence, say in a closure.  In scheme I might solve the problem
using a continuation.  But in clojure if I do, say:

(let [my-seq (lazy-seq ...)]
   (defn get-some-data ...))

won't I run out of memory?  Is the solution to have my-seq somehow
refer to the next element to be retrieved, i.e. to the head of the
infinite sequence that has yet to be fed to the workers?


Your approach won't work for another reason: you can't change my-seq  
inside get-some-data, unlike in Scheme. Moreover, you have the problem  
of thread safety. A closure is not sufficient to protect the sequence  
against uncoordinated requests from multiple threads.


The Clojure solution for your problem is an agent, which makes the  
access thread-safe:


user> (def data-source (agent (cycle [1 2 3])))
#'user/data-source
user> (defn get-some-data [] (let [v (first @data-source)] (send data- 
source rest) v))

#'user/get-some-data
user> (get-some-data)
1
user> (get-some-data)
2
user> (get-some-data)
3
user> (get-some-data)
1
user> (get-some-data)
2
user> (get-some-data)
3

Konrad.

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


idiom question: infinite sequence as data source for many threads?

2010-01-27 Thread free_variation
Hi,

I'm a clojure noob, with a background in scheme (and functional
languages).

I'm looking for the "clojure way" to solve the following problem:

I have an infinite sequence.  I'd like to have the sequence be a
source for N parallel worker threads that now and then will show up to
grab a few elements from the sequence, then go off and crunch on the
data.  The sequence should be traversed only once per execution of the
software.

I'm not clear on how to implement this without keeping a reference to
the sequence, say in a closure.  In scheme I might solve the problem
using a continuation.  But in clojure if I do, say:

(let [my-seq (lazy-seq ...)]
(defn get-some-data ...))

won't I run out of memory?  Is the solution to have my-seq somehow
refer to the next element to be retrieved, i.e. to the head of the
infinite sequence that has yet to be fed to the workers?

Thanks,

jds

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