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, [email protected] 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" <[email protected]> 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, "[email protected] on behalf of
>> [email protected]" <[email protected] on behalf of [email protected]>
>> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.