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.