The semantic of the swiss-arrows <https://github.com/rplevy/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" <se...@corfield.org> 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" <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) 
>>          (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.

Reply via email to