There is a command in Calva for making a thread-last of a bunch of nested calls like you have there in the beginning. And a command for unwinding the thread again. Not suggesting you should have used that in the video, the way you showed it now was very nice and step by step so that it is easy to understand what the thread does. Just FYI for anyone watching this.
At 6:00 in order to move the whole form starting with thread-first macro into let binding form, you may simply place cursor before opening bracket of line 56 (ie. just before "(->")) and use Ctrl+I (Calva forma: Indent Line). Similarly, there's Ctrl+Shift+I to do the opposite. I usually automatically also press Tab just after Ctrl+Shift+I to fix formatting. BWT great tutorial as always!
You can also slurp it from within the let form. Or have the cursor before or after the form you want to move into the let and ”Drag Sexpr Backward Down” (shift+ctrl+alt+j).
The cool part about threading in Clojure is that if you have an infinite or a long long loooong collection you still can use threading and be really efficient since map and filter are lazy. This code (->> collection (filter even?) (map str) (take 5)) calculates and return only 5 elements without filtering and mapping entire collection.
Also if you keep the first part (def foo (->> collection (filter even?) (map str))) and then run (take 5 foo) (take 4 foo) (take 2 foo) the functions will run only once since first 5 results will be memoized. See memoize function.
When it comes to threading macros (and their debugging), I'd also also add following tips: 1) sometimes it helps to wrap the threading macro inside macroexpand. You also need to quote the threading form with either ' or (quote). This will spit out the actual final form, which you would normally have to write if you wouldn't use the threading macro. Good for checking whether the threading macro is doing what you intended it to do. (macroexpand '(->> [1 2 3] (filter #( (first (filter (fn* [p1__20623#] (
@@RepertoireSix Thanks. But it's this channel that's really awesome IMO. Looking at 8 months old videos it seems that Daniel (at least I hope it's his name according to github :-)) was probably more or less starting with clojure. Since then, it has been a a joy to watch his videos/tutorials. You can see the fast progress and improvements in how easily he's writing/understanding the code he's writing. You can feel that he's enjoying the language/ecosystem. Moreover, he has a gift of being able to pass the knowledge to others in very accessible way. Big thumbs up!
@@TomasBrejla Thanks a lot for the kind words! The comments section on the recent videos has been an excellent place to get more insight, which is so rad! thanks for watching + contributing
Great content, and much appreciated. Small bit of feedback - since you have so much screen real estate available, perhaps increase the font size so viewers watching this on a laptop can see it more easily. Also, I know dark mode is what people like to _use_ quite often, but it's less good for screen recordings for many reasons. For viewers who may be watching this in a bright environment, the dark mode content just cannot be made bright enough to clearly see. Further, video compression favors dark text on light backgrounds. With dark mode, it can muddle the content since it has less contrast room to work with. The point of all this is to say, if you're making good content, you don't want to lose half your viewers because they can't consume it :)
@@onthecodeagain Also handy: if for some reason you needed the new keys to be variable (ie.: passed as an argument to your function), there is also merge which takes a map as a second argument: (merge my-map {:key-a 42 :key-b "elephant" :key-c nil})
Sometimes, when building these pipelines you want to build them in slightly smaller steps. You can for example hold off defining a function for a bit, and put the thread in a comment form. Then you can use the command fro evaluating up to cursor (ctrl+alt+enter) to see the result of each step in the thread. Then when the thread is done, wrap it in a function and define it. Rinse, repeat. (Not doing it this way may end you up in a crash of the app during live demo. Haha.)
There is a command in Calva for making a thread-last of a bunch of nested calls like you have there in the beginning. And a command for unwinding the thread again. Not suggesting you should have used that in the video, the way you showed it now was very nice and step by step so that it is easy to understand what the thread does. Just FYI for anyone watching this.
Thats handy!
At 6:00 in order to move the whole form starting with thread-first macro into let binding form, you may simply place cursor before opening bracket of line 56 (ie. just before "(->")) and use Ctrl+I (Calva forma: Indent Line). Similarly, there's Ctrl+Shift+I to do the opposite.
I usually automatically also press Tab just after Ctrl+Shift+I to fix formatting.
BWT great tutorial as always!
Thank you!!! For the compliment and for the shortcut :)
You can also slurp it from within the let form. Or have the cursor before or after the form you want to move into the let and ”Drag Sexpr Backward Down” (shift+ctrl+alt+j).
The cool part about threading in Clojure is that if you have an infinite or a long long loooong collection you still can use threading and be really efficient since map and filter are lazy.
This code (->> collection (filter even?) (map str) (take 5)) calculates and return only 5 elements without filtering and mapping entire collection.
Also if you keep the first part (def foo (->> collection (filter even?) (map str))) and then run (take 5 foo) (take 4 foo) (take 2 foo) the functions will run only once since first 5 results will be memoized. See memoize function.
@@eugenej.5584 I was thinking of showing memoize in a video 🤔 the lazyness of Clojure is amazing
Many thanks for providing this kind of content! Such a great tempo you have. Fast paced, yet easy to follow steps making things clear.
I absolutely agree. The tempo is just about right and the editing is very well done.
I appreciate that!
My new favorite channel 💗
Woah! Thanks so much!
These are such clear tutorials. Thanks
Thanks a lot :)
When it comes to threading macros (and their debugging), I'd also also add following tips:
1) sometimes it helps to wrap the threading macro inside macroexpand. You also need to quote the threading form with either ' or (quote). This will spit out the actual final form, which you would normally have to write if you wouldn't use the threading macro. Good for checking whether the threading macro is doing what you intended it to do.
(macroexpand '(->> [1 2 3]
(filter #( (first (filter (fn* [p1__20623#] (
Really nice addition to the video!
@@RepertoireSix Thanks. But it's this channel that's really awesome IMO. Looking at 8 months old videos it seems that Daniel (at least I hope it's his name according to github :-)) was probably more or less starting with clojure. Since then, it has been a a joy to watch his videos/tutorials. You can see the fast progress and improvements in how easily he's writing/understanding the code he's writing. You can feel that he's enjoying the language/ecosystem. Moreover, he has a gift of being able to pass the knowledge to others in very accessible way. Big thumbs up!
@@TomasBrejla Thanks a lot for the kind words! The comments section on the recent videos has been an excellent place to get more insight, which is so rad! thanks for watching + contributing
Great content, and much appreciated. Small bit of feedback - since you have so much screen real estate available, perhaps increase the font size so viewers watching this on a laptop can see it more easily. Also, I know dark mode is what people like to _use_ quite often, but it's less good for screen recordings for many reasons. For viewers who may be watching this in a bright environment, the dark mode content just cannot be made bright enough to clearly see. Further, video compression favors dark text on light backgrounds. With dark mode, it can muddle the content since it has less contrast room to work with. The point of all this is to say, if you're making good content, you don't want to lose half your viewers because they can't consume it :)
Thanks for the feedback! The text is much larger in my following videos, I get flamed either way for using light/dark themes :p
Instead of calling assoc twice, you can also call it once with more than one key value pairs:
(assoc my-map
:key-a 42
:key-b "elephant"
:key-c nil)
Handy!
@@onthecodeagain Also handy: if for some reason you needed the new keys to be variable (ie.: passed as an argument to your function), there is also merge which takes a map as a second argument:
(merge my-map
{:key-a 42
:key-b "elephant"
:key-c nil})
@@epgui yeah! I think I should make a video all about maps and how to manipulate them :)
Sometimes, when building these pipelines you want to build them in slightly smaller steps. You can for example hold off defining a function for a bit, and put the thread in a comment form. Then you can use the command fro evaluating up to cursor (ctrl+alt+enter) to see the result of each step in the thread. Then when the thread is done, wrap it in a function and define it. Rinse, repeat. (Not doing it this way may end you up in a crash of the app during live demo. Haha.)
hahaha, I knew this worked because I filmed it 4 times 😅 I agree with you though!
Even cond covered!
I wanted to go over everything!
Really good!
Thank you! :D
that's lit mahn.... !!
Thanks!!
#(do(not(->> % (filter :me) seq)))