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
<https://github.com/cloojure/tupelo#literate-threading-macro>:

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 <colin.ya...@gmail.com> 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 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.
>

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