Wow yes that's exactly the -%> macro I imagined just with "%" replaced with 
"it". And it exists!  Plus I just converted my fragment to use as-> and 
thought "aren't the first two arguments backwards (vs, say, "let"); and 
what name should I use (I chose 's')". Thank you. Reading the tupelo docs 
now.

On Wednesday, September 28, 2016 at 4:02:38 PM UTC-4, Alan Thompson wrote:
>
> 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...@gmail.com 
> <javascript:>> 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, pa...@pwjw.com <javascript:> 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 clo...@googlegroups.com 
>> <javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> 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+u...@googlegroups.com <javascript:>.
>> 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 clo...@googlegroups.com 
>> <javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> 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+u...@googlegroups.com <javascript:>.
>> 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