By the way, the order of arguments of as-> makes more sense when it’s used
*within* one of the other threading macros. For example:
(-> x
foo
(bar y)
(baz w z)
(as-> mid-x
(log/debug "The intermediate value:" mid-x)
(if (color-requested? mid-x)
(assoc mid-x :color "periwinkle")
(do
(log/warn "skipping the addition of color")
mid-x)))
(update :counter inc))
On Wednesday, September 28, 2016 at 4:11:42 PM UTC-4, [email protected] wrote:
>
> 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 <[email protected]> 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, [email protected] 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, [email protected]
>>> 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 [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.
>>>
>>>
>>> --
>>> 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.
>>>
>>
>>
--
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.