PurelyFunctional.tv Newsletter 377: Three states of key-value pairs
Issue 377 - May 11, 2020 · Archives · Subscribe
Clojure Tip 💡
Three states of key-value pairs
Sometimes I'm using a map and I want to both get the value for a key and check if the key exists in the map at the same time. In most cases, it would look something like this:
(if-some [v (get mp k)]
(println "It's in there:" v) ;; v is never nil
(println "It's not in there."))
That works most of the time. But sometimes, you might have and expect
the value to be nil
. It happens. In that case, you would confuse two
separate cases, when it's in there but it's nil
and when it's not in
there at all.
In that case, I usually break out into a full on contains?
check:
(if (contains? mp k)
(let [v (get mp k)]
(println "It's in there:" v)) ;; sometimes v is nil
(println "It's not in there."))
That works. It separates out the three cases. Normally you wouldn't
care, but notice that it's really got to do the map lookup twice. It's
also got a let
nested in the if
. I didn't know this for the longest
time, but there's actually a function in core that can do this in one
step. Check this out.
(if-some [[_ v] (find mp k)]
(println "It's in there:" v) ;; sometimes v is nil
(println "It's not in there."))
The function that allows this is
find
. It looks up a key
in a map, returns the map entry (key-value pair), or nil
if the key is
not found.
This function highlights that there are actually three cases. Sometimes
we bundle the nil
cases together (as in the first code example).
Sometimes we bundle nil
values in with non-nil values (as in the
second and third code examples). Or we could treat all three cases
specially. The thing is we have the choice---albeit it's implicit and
not always clear from the code.
Quarantine update 😷
I know a lot of people are going through tougher times than I am. If you, for any reason, can't afford my courses, and you think the courses will he lp you, please hit reply and I will set you up. It's a small gesture I can make, but it might help.
I don't want to shame you or anybody that we should be using this time to work on our skills. The number one priority is your health and safety. I know I haven't been able to work very much, let alone learn some new skill. But if learning Clojure is important to you, and you can't afford it, just hit reply and I'll set you up. Keeping busy can keep us sane.
Stay healthy. Wash your hands. Stay at home. Wear a mask. Take care of loved ones.
Clojure Challenge 🤔
Last week's challenge
The challenge in Issue 376 was to find the distances to the nearest vowels in a string. You can see the submissions here.
You can leave comments on these submissions in the gist itself. Please leave comments! There are lots of great discussions in there. You can also hit the Subscribe button to keep abreast of the comments. We're all here to learn.
This week's challenge
Sudoku Validator
Write a function that validates a finished sudoku board. It should take
a vector of vectors. The inner vectors represent rows from the sudoku
board. The rows should contain nine integers. If the board is
well-played, the function should return true
, otherwise, false
.
(sudoku-valid? [[ 1 5 2 4 8 9 3 7 6 ]
[ 7 3 9 2 5 6 8 4 1 ]
[ 4 6 8 3 7 1 2 9 5 ]
[ 3 8 7 1 2 4 6 5 9 ]
[ 5 9 1 7 6 3 4 2 8 ]
[ 2 4 6 8 9 5 7 1 3 ]
[ 9 1 4 6 3 7 5 8 2 ]
[ 6 2 5 9 4 8 1 3 7 ]
[ 8 7 3 5 1 2 9 6 4 ]]) ;=> true
(sudoku-valid? [[ 1 1 2 4 8 9 3 7 6 ]
[ 7 3 9 2 5 6 8 4 1 ]
[ 4 6 8 3 7 1 2 9 5 ]
[ 3 8 7 1 2 4 6 5 9 ]
[ 5 9 1 7 6 3 4 2 8 ]
[ 2 4 6 8 9 5 7 1 3 ]
[ 9 1 4 6 3 7 5 8 2 ]
[ 6 2 5 9 4 8 1 3 7 ]
[ 8 7 3 5 1 2 9 6 4 ]]) ;=> false
Notes:
- A sudoku puzzle is successfully solved if all rows contain the numbers 1-9, all columns contain 1-9, and the nine 3x3 boxes contain 1-9. See the Wikipedia page for more information.
Thanks to this site for the challenge idea where it is considered Expert level in JavaScript.
You can also find these same instructions here. I might update them to correct errors and clarify the descriptions. That's also where submissions will be posted. And there's a great discussion!
As usual, please reply to this email and let me know what you tried. 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