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, pa...@pwjw.com 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 <colin...@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, pa...@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 clo...@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+u...@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+u...@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 clo...@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+u...@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+u...@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.