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.