Author Archives: Lou Franco

Write While True Episode 31: The Order of Words

I’m going to use these three books again for today’s topic, which is the order of words in a sentence.

I love that these books tackle mundane topics, things that seem innate, but aren’t. I mean, we can order words into something grammatical without much thought. Even though a ten-sentence word has ten factorial possible orderings, we can easily find the handful that are legal English.

Transcript

Public Software Playground Projects

I have dozens projects on my drive that are playgrounds for me to try out things I am learning. Each of them is a simple example of a “type” of project (e.g. a React Native app, a React App, a clojure program, a SwiftUI app, etc). I don’t actively maintain them until I need to use them again.

Two of these playground projects are public: Habits and App-o-Mat.

Habits is my first iOS App. I made it in 2008, and it’s the codebase I have continuously worked on the longest. It always builds in the latest Xcode, and it has both Objective-C and pre-CoreData sqlite code. It also has modern Swift.

App-o-Mat is a content site for iOS and watchOS tutorials, which is made in Django with a simple HTML-heavy front-end. I made it in 2014, and it’s my second longest continuously worked on codebase. I regularly migrate it to the lastest Python and Django (it was originally Python 2 and Django 1.0).

Whenever I want to try out new iOS features, I can usually find a place in Habits to do that. When I want to try out a new CSS framework, App-o-Mat is simple enough to try it out and see if I’d like it, but not too simple.

I started converting App-o-Mat to Tailwind a couple of days ago. I have run into enough edge-cases that I am sure that I am giving Tailwind a good look. I have tried out other CSS frameworks in the past (even just trying to update to the lastest Bootstrap) and it hasn’t gone as well as this is going. Tailwind is different enough that you need to try it on something real, and App-o-Mat

Making them public has been an incentive to keep working on them, which means they are playgrounds that are always ready for more play.

Tailwind Seems Nuts Until You Try It

Tailwind makes a complete mess out of your HTML. When you first try to do anything, it seems completely wrong. It feels like just a fancy style attribute.

But maybe all we needed was fancy style attribute after all.

I just finished rewriting the HTML for App-o-Mat‘s home page. I still have a lot to do, but the benefits are obvious:

  1. There is no CSS file (well not one that I write or maintain)
  2. My HTML structure is a lot simpler
  3. My site is in Django, so I have lots of ways to generate HTML partials and components
  4. The default behavior is very responsive and I can easily override what I need to
  5. It is trivial to debug in the browser inspector (the style is in the tag)
  6. They have thought of complex use cases like the typography plugin that can style markdown-generated HTML that you don’t control

Tailwind is the kind of thing that is more obvious if you’ve worked on bigger projects. The arbitrary class names, the disorganization, not knowing which class is bringing in which behavior, the chance that you mess up some other page that is sharing the class—that’s all solved with Tailwind.

The drawback (insane class attributes) is easily solved with the way we normally generate HTML in real projects.

It’s only day two, but it does feel to me like this makes more sense than Material (which is what I have been using for UI in my React projects). It will depend on how good the controls in TailwindUI are and if I can find what I need elsewhere.

My First Few Hours with Tailwind (2023)

I am late to Tailwind, which is how I like it, but Matt Rickard’s post convinced me that Tailwind has “won”, and specifically that it is the heir-apparent to Bootstrap. I’ve been looking to get App-o-Mat off of Bootstrap for a while, so I’m in. Ultimately, I might want to move to Tailwind for all of my projects, but App-o-mat is the simplest, so I’ll start there.

App-o-Mat is a Django site with almost no client-side javascript and a fairly simple design using Bootstrap (not flexbox) for layout. It was made in 2014, and it’s very much of its era.

My first impression was despair and I almost almost gave up right at setup because it needed npm. This made me think that Tailwind was not going to be compatible with a simple, HTML-dominant site.

I googled a bit and found some Django plugins, but they didn’t seem simpler or widely used. I googled a bit harder and eventually found the Tailwind Standalone CLI. This is more like it. It’s easy to adopt and to see exactly what it does, so I still end up with a project and deployment I understand.

The next issue I had is that App-o-Mat does have some forms and navigation where I need some UI Components. So, I ended up at TailwindUI, which I guess I need to buy, because there is no way I want to implement any of these components. I think Tailwind is going to wind up in more of my projects, so this price isn’t that bad.

I started planning out the project and decided that this was also a good time to bring the project into VSCode (from PyCharm). I love PyCharm, but GitHub CoPilot is too important to give up, and I’m so behind in my PyCharm updates, that going to VSCode seems about as easy. All of my other python projects are in VSCode now anyway.

The Most Consequential Clojure I Ever Wrote

In my congratulations to Rich Hickey, I mentioned that clojure influenced my code, but that I never wrote any professionally. I did, however, apply to a job opening at FogCreek/Trello with clojure code. They gated the application process with a programming question.

I call this code the most consequential clojure code I ever wrote because it got me an interview at FogCreek, which ultimately ended up in me working at Trello for almost seven years, during which we were acquired by Atlassian.

Since the question has been publicly answered many times, and is no longer used, I’ll reproduce it here:

Find a string of characters that contains only letters from “acdegilmnoprstuw” such that the hash(the_string) is 910897038977002.

If hash is defined by the following pseudo-code:

hash (s) {
h = 7
letters = "acdegilmnoprstuw"
for(i = 0; i < s.length; i++) {
h = (h * 37 + letters.indexOf(s[i]))
}
return h
}

For example, if we were trying to find the string where hash(the_string) was 680131659347, the answer would be “leepadg”.

I chose to use clojure because I didn’t know how big the value of h was going to get and wanted access to clojure’s implementation of BigInteger, which is seamless. All integer math in clojure promotes up to whatever size integer it needs. Once I thought of using clojure, I realized that it would be seen as a fun choice by the developers reviewing the code since FogCreek had a reputation of hiring developers that were interested in weird programming languages (see wasabi).

If you don’t want any hints on how to solve this, stop here.

So, they are asking you to invert the hash() function. In general, hash functions should not be invertible, but this hash is made by using simple lossless integer arithmetic with * and +, which both have inverses (/ and -). Each step of the function is invertible, so the function itself is invertible.

I decided to start with just implementing their pseudocode in clojure.

(defn fchash [arg]
  (let [letters "acdegilmnoprstuw"]
      (loop [h 7 s arg]
          (if-let [c (first s)]
              (recur (+ (* h 37) (.indexOf letters  (int c))) (rest s))
              h))))

And to make sure this was correct, I evaluated (fchash "leepadg") to make sure I got 680131659347.

There are a few tricks to inverting the code.

First, you need to figure out when the loop is done. You don’t know how long the string is supposed to be, so you need to detect somehow that you are done. For this, note that the hash is originally seeded with the number 7, so we expect that we’ll eventually get back to this number in the inverted version.

Second, you need to figure out what number was added after the hash was multiplied by 7. To get that, you can use mod 37 because the number must be less than the length of the letters string (which is 16) and 16 is less than 37, so using mod gets you the number that was added to the hash after it was multiplied by 37.

That should be enough to attempt an answer (in whatever language). If you want to see what I submitted, look here: Clojure inverse hash.

The Ending Should Oppose the Beginning

In episode 44 of Scriptnotes (transcript), John August and Craig Mazin talked about how the ending of a movie should relate to the beginning. One thing Mazin said made this clear:

… if you’re writing and you don’t know how the movie ends, you’re writing the wrong beginning. Because to me, the whole point of the beginning is to be somehow poetically opposite the end. That’s the point. If you don’t know what you’re opposing here, I’m not really sure how you know what you’re supposed to be writing at all.

In my post about The James Bond Opening to a software demo, I recommended starting with something exciting about how another customer is getting value. This should be short and sweet and gets the prospect to lean forward.

But next, talk about the problems the prospect is having right now, which you learned about in discovery. Remind them of this as you start their story—the one you are about to tell, which will take them from their life now to a new life after they buy your software. By the end of the demo they should be convinced to take the next step.

If you want to learn how to tell stories like this, I recommend learning how screenwriters do it. Scriptnotes is a great place to do that. They know how to tell a story where a protagonist makes a decision that inevitably leads them to a changed life. This is like the story you want your prospect to feel they are in.

Write While True Episode 30: Finding Nouns and Verbs

Every book on writing tells you to avoid adverbs (and even adjectives). I find that hard to do in first drafts, but I do try to remove them in edits. You can tell that I haven’t done enough editing if you see that I “really like” something or that a new programming language is “pretty good”.

Season 3

Books

Sweep Editing

Transcript

Sweep Edit for Adverbs

I use Joanna Wiebe’s technique of editing in sweeps, which means that I edit written work in multiple 2-pass sweeps that each address one problem. In each first pass, I highlight the text that I should fix in this sweep, and then I do a second pass to fix them. This is in contrast to fixing different problems in a single read-through of the work.

For example, right after I finish a first draft of a blog post, I do a sweep edit to make the piece about one specific message to one kind of audience. I highlight anything that isn’t part of that message, and then I go through those parts and either remove them or make sure they are short enough to not distract the reader. While I am doing this, I am not fixing grammar or tone because I will do that later—each sweep is focussed.

After reading Writing Down the Bones, I finally have a better way to make my writing use fewer adverbs and adjectives. I have always tried to find and remove adverbs, but now I also find better nouns and verbs for the sentence I just edited. This lets me gorge on as many adverbs and adjectives as I want in the first draft, because I can trust myself to fix them later.

The extra adjectives and adverbs actually help me. They are a wordy description of the better noun and verb for that sentence. I can use Goldberg’s noun and verb game or a thesaurus to find them.

I’ll be elaborating on this in tomorrow’s episode of the Write While True podcast.

Writing Down the Bones is a Playable Book

After I wrote yesterday’s review of Writing Down the Bones by Natalie Goldberg, I went to my copies of The Golden Book on Writing [amazon affiliate link] and The Elements of Style [amazon affiliate link] to find out what they had to say about verbs.

As expected, they also recommend that you avoid adverbs and pick out more specific verbs. I’ve heard this advice many times and all it has resulted in is that I remove most “very”, “really” and “pretty” intensifiers before I publish. I don’t take the second step, which should have been to find better nouns and verbs. This leaves my sentences imprecise and boring. The advice failed me because it didn’t come with any instructions. They just dropped a few examples and figured you’d get the idea.

Natalie Goldberg uses one sentence to say that you should use better verbs and then spends the next few pages showing you exactly how to do that. She gives you an exercise that will train you to think up more precise verbs. More importantly, it’s kind of fun. Like a game.

It’s play.