PurelyFunctional.tv Newsletter 352: Tip: use the right kind of comment for the job
Issue 352 - November 18, 2019 ยท Archives ยท Subscribe
First Annual PurelyFunctional.tv Survey! ๐
I'm happy to announce the first annual PurelyFunctional.tv Survey. Your answer to this quick survey will help me understand how to improve my videos and help you master Clojure faster and more deeply.
There are only four questions. If you've watched any of my video content, please take a few minutes to fill this out. I appreciate any answer you can give.
The survey will run for a few weeks.
Clojure Tip ๐ก
use the right comment for the job
Let's face it: sometimes commenting out code is useful. Sometimes you want to test a large piece of code without launching the missile just yet. Comment out the code! And many Clojurists keep snippets of code in a comment at the end of a file to facilitate Repl-Driven Development. And then, of course, there are comments that are actually comments on the code.
Clojure has three ways to ignore input. Each is different in significant ways. Each has found a use in the community. Let's go over each of them.
Line comments
If you put a semicolon in your code (anywhere outside of a string or a character literal) it starts a comment that goes till the end of the line. Anything characters are allowed in that comment. It won't be read or parsed, just ignored. People use these for two purposes:
1. To add a note in natural language to the code.
;; 1002 works. I don't know why. Change at your own risk.
(run-me 1002) ; here is the magic number
As a community, and in many editors, double semicolons indicate comments that shouldn't be grossly indented. Single semicolons are for comments that come after other code on the same line.
2. To comment out a single line of code.
Sometimes the code you want to comment out is all on one line at the end
of the line, and you just want to insert a single ;
. Go for it.
(doseq [task tasks]
;;(println task)
(run-task task))
comment
macro
There's a macro called comment
that will comment out any number of
forms. All you have to do is surround the forms with the comment
macro. There are some gotchas:
- It's a macro, so the forms inside have to be valid for the Clojure reader. That means you have to obey all the syntax rules for numbers, symbols, and braces matching.
- The
comment
form itself is still an expression in your program. It evaluates tonil
. That could have an effect on any surrounding forms.
In short, it's just a way to avoid executing code, but not useful for
text. It's also not very useful for commenting out sub-expressions since
it evaluates to nil
.
So what do people use this for? Mostly for code they want to run during
development but not in the normal flow of production code. It's common
to put a comment
block at the end of a file with expressions to
evaluate for testing.
It sounds weird, but it's better than typing in the same expressions
over and over into the REPL prompt. Most editors have a setting so you
can evaluate expressions inside the comment
just like top-level
expressions.
#_
reader macro
Clojure's reader has a reader macro (different from a regular macro) that directs the reader to ignore the next form. That is, it reads a form and then throws it away. It's a nice way to ignore an entire expression.
#_(println a
b
c
d)
Notice that this one works really well for multi-line expressions.
Unlike ;
, which ignores everything up to the end of the line, #_
ignores the entire next expression. It's the perfect way to "turn off"
one expression. It even works for sub-expressions---it is truly ignored
by the reader, not replaced with nil
. It's great for dropping an
argument, for instance.
But get this: they stack. Often, we want to ignore two expressions, not just one. Here's a case:
(def mappings {:a 1 :b 2 :c 3})
What if we want to get rid of the mapping of :a
to 1
? We could do
this:
(def mappings ((#_:a #_1 :b 2 :c 3)))
But because #_
ignores the next expression, there is a better way. Two
#_
s will ignore the next 2 expressions:
(def mappings ((#_#_:a 1 :b 2 :c 3)))
Now there's just one thing to delete if you want to turn it back on.
Thanks to Ray McDermott and the rest of the panel at Apropos Clojure for this final tip.
Conference alert ๐จ
I booked my tickets to the 2019 Clojure/conj in Durham, North Carolina. If you're going, let me know! I haven't been to a Conj in a couple of years and I'm really excited.
Ask me about my book and I'll give you a discount code.
I am considering bringing a board game to play at the board game night.
Currently recording ๐ฅ
Property-Based Testing with test.check is now split into three courses, Beginning, Intermediate, and Advanced.
Last week I promised a flood but all I've got is a trickle. Coming back from vacation is hard :). However, they are now available to purchase for a low price for the launch sale. I will end the sale after the Conj. That gives you two weeks to buy them. They will never be this inexpensive again!
Book update ๐
I have been getting such great stories from readers of Grokking Simplicity. People tell me they are making their code more organized and testable. After all of the work I put into the book, it feels good that it's having such a great impact.
You can buy the book and use the coupon code TSSIMPLICITY for 50% off.
Thanks for reading.
Clojure Challenge ๐ค
Last week's challenge
Well, I got no submissions from last week.
This week's challenge
Write a program that outputs all possibilities to put a + or - or nothing between the numbers 1-9 (in order) such that the result is 100. For example:
1 + 2 + 34 - 5 + 67 - 8 + 9 = 100
The function should output a list of strings with these formulas.
Hint: this is a recursive problem. Use divide and conquer.
As usual, please reply to this email to send me your submissions. I'll collect them up and share them in the next issue. If you don't want me to share your submission, let me know.
Rock on!
Eric Normand