PurelyFunctional.tv Newsletter 341: Tip: tidy up your ns form
From OO to Clojure Workshop!
Watch my free workshop to help you learn Clojure faster and shift your paradigm to functional.
Issue 341 - August 26, 2019 · Archives · Subscribe
Clojure Tip 💡
ns declaration tidy
We've all done it at some point. We're really rolling on a new project and we're itching to import a new library. So we copy and paste from the example in the README and paste it right into our code.
After a few hours, the top of our file looks like this:
(ns my-project.core (:use some-library) (:use another-library) (:require [clojure.string :refer [upper-case lower-case]) (:require [clojure.java.io :as io] [foo.bar :refer [baz ;; cux ]]))) (use 'favorite-lib.core) (require 'lib4clj.core) (import 'java.util.Date)
It's a mess! It's hard to see what's been imported, and it will slow you down. (Also: there's a bug in there that would be way easier to spot with some tidying.)
But what's worse is the impression it makes on others. If you're looking for a job and you send someone this code, here is what is going through their mind: "Oh, no! This person has never worked on a serious project."
At least that's the strong impression it gives me. If you want to make a good impression, clean that up. Cleaning it up will exercise your code movement skills. You will be moving a lot of code once you get the job. It also shows respect for the person who will be reading the code.
Here's what the above code looks like when it's neat and tidy:
(ns my-project.core (:require [some-library :refer :all] [another-library :refer :all] [clojure.string :refer [upper-case lower-case]] [clojure.java.io :as io] [foo.bar :refer [baz]] [favorite-lib.core :refer :all] [lib4clj.core]) (:import java.util.Date))
It's much easier to read and gives a more organized impression. However,
I would go further. I converted
This is usually not ideal if you're doing it to a lot of namespaces. You
should choose a namespace alias and use it instead.
(ns my-project.core (:require [some-library :as sl] [another-library :as al] [clojure.string :as str] [clojure.java.io :as io] [foo.bar :refer [baz]] [favorite-lib.core :as fl] [lib4clj.core :as lib4clj]) (:import java.util.Date))
Woah! Clean as a whistle and easy on the eyes.
Here are some recommendations for squeaky-clean
- Put all dependencies into the
ns. No exceptions.
- Don't use
:use. In general, people recommend against it. If you need similar functionality, use
:refer :all. But see #3.
:refer :allunless you have a good reason. Laziness is not a good reason. A good reason is that it is a well-known library whose functions are named to help you know where they came from. An example is
clojure.testinside of a testing namespace.
- Give your namespaces short, descriptive aliases. Abbreviation is
good. Use well-known aliases for common libraries, like
:refertoo many names. A handful is okay.
- Use good whitespace. New lines are important. Alignment can help readability. Keep it indented correctly.
Are there any guidelines you follow? Hit reply and let me know.
Book status 📖
My book is out! You can buy the book now in early access. The first three chapters are available and you'll get updates as new chapters come out.
Grokking Simplicity teaches functional programming in a friendly way, to those who are not familiar with it or who were turned off by the overly academic resources.
You can get 50% off the normal prices with discount code MLNORMAND. It will work until August 31, so don't delay. I don't really control the sales and discounts, so I don't know when the next one will be.
Also, there's no "look inside" on my book, so I'll share some images of pages here. Click the picture to see a bigger version.
I regret describing The Bell Curve as a "racist, pseudoscientific screed". Last week I mentioned the book in the context of Apollo: The race to the moon.
The Bell Curve is indeed a controversial book. I was told about it in High School by a teacher who said it was racist. I never read it myself. I simply parroted what he taught me to you in this newsletter. You deserve better than repeated hearsay.
A couple of readers disagreed with my words. I looked into it and I realized my mistake. I know nothing about the book, and very little about the controversy around it. I'm not defending the book nor am I supporting it. But I should not have used such strong language about a topic I know nothing of. If the topic interests you, please form your own opinions.
I am grateful that you put your trust in me to have my newsletter in your inbox every week. I betrayed that trust by speaking out of turn. I apologize.
Conference alert 🚨
Clojure/conj CFP and Opportunity Grant applications are due soon. The conference is in November in Durham, NC.
Currently recording 🎥
I am now recording a course called Property-Based Testing with test.check. Property-based testing (PBT) is a powerful tool for generating tests instead of writing them. You'll love the way PBT makes you think about your system. And you can buy it now in Early Access. Of course, PF.tv members have had access since the beginning, along with all of the other courses.
New lessons this week include:
- [Testing pure functions]
(https://ericnormand.podia.com/advanced-clojure-bundle) --- Pure
functions are the easiest to test, so that's where we start. We test
three fairly mathematical functions (
We look for complete coverage of the behavior by trying to find an
incorrect implementation that could pass the tests. Then we test two
real-world functions I snagged from some real projects. These are a
little more involved since we need to create custom generators for
them. All the better to learn from!
2. Testing stateful
Once you bring in mutable state, the complexity of your system
skyrockets. Now you have to deal with actions performed in arbitrary
order. We look at two examples of stateful systems and how to test
them. Testing mutable state is where Property-Based Testing really
starts to shine. We essentially test every part of the interface in
hundreds of combinations.
I've made the first and fifth lessons free to watch. Go check them out.
Members already have access to the lessons. The Early Access Program is open. If you buy now, you will get the already published material and everything else that comes out at a serious discount. There are already 9 hours of video, and looking at my plan, this one might be 12 hours. But that's just an estimate. It could be more or less. The uncertainty about it is why there's such a discount for the Early Access Program.
Brain skill 😎
We can often learn better in long periods of focus. Learning means challenging your brain. That can be uncomfortable. Your brain will rebel and seek out distractions. Often the most uncomfortable part is right at the beginning. Being able to focus means sticking with it long enough to get over the initial hurdle.
Focus also helps you keep more stuff in your head at once. Our attention
is very limited. A distracting noise or idea could bump out the hour of work you've done to load a difficult concept into your head. Being able to focus means eliminating those distractions so you can work with the idea efficiently.
This guide from Scott Young has useful tips for increasing your ability to focus.
Clojure Challenge 🤔
Last week's challenge
The puzzle in Issue 340 was to write a simplifier for the symbolic differentiator we did the week before.
You can check out the submissions here.
This week's challenge
permutations of a sequence
The permutations of a sequence are all of the sequences with the same elements but in different orders. Here are some examples.
The permutations of
[1, 2] are
[1, 2] and
The permutations of
[1, 2, 3] are
[1, 2, 3],
[1, 3, 2],
[2, 1, 3],
[2, 3, 1],
[3, 1, 2], and
[3, 2, 1].
The number of permutations grows really fast with the size of the list.
Your challenge is to write a function that generates all permutations of a list. Your function should return a lazy sequence.
Note: there already is a great, fast implementation of this function in clojure.math.combinatorics
As usual, please send me your implementations. I'll share them all in next week's issue. If you send me one, but you don't want me to share it publicly, please let me know.