My friend Amy Bowser-Rollins kindly invited me on her Legal Tech Mastery show. This is extra special because I get to be episode one:
Author: Josiah Ulfers
Copying antifeatures: multiline strings
Multiline strings are a Good Thing but they usually end up implemented just a little bit wrong.
Delimiters
First, they require special delimiters. Most grammars could easily allow ordinary strings to break across lines, and many languages could even add this in a backward-compatible way. A string that includes line breaks is no harder to parse than a single-line string:
foo = " Hello world "
To the great annoyance of programmers everywhere, languages generally require special delimiters for multiline strings:
foo = """ Hello world """
Thus, when we find ourselves typing a string literal and the line gets uncomfortably long, the language makes us go back to the beginning and change delimiters. Vice versa when shortening strings.
Indentation
Most multiline strings end up being indented. Ruby gets multiline string quote style right, but fails on indentation:
def do_stuff() foo = " hello world " return foo end puts do_stuff() # "\n hello\n world\n "
What are those leading spaces doing? I can’t think of a time when I’ve ever wanted a string literal to maintain its source indentation at runtime.
Almost always, multiline strings fall into two categories:
Indentation is irrelevant | Needs trim and dedent |
---|---|
sql = " select * from foo where bar and baz " |
help = " usage: frob [-nicate] frob the widget -n turn on the n " |
So there are many use cases where trimming and dedenting is warranted, but almost none where it hurts.
CoffeeScript almost got both aspects right, but it makes a distinction between “multiline strings”, that use ordinary quotes and “block strings,” which use triple-quotes. Ordinary strings collapse line breaks to single spaces, triple-quoted strings trim and dedent correctly.
Next time: the perils of such subtle distinction in quote style.
Painless Android releases revisited
Previously, I described a Gradle script that handily generates release version codes for Android apps. The generated version codes take the form [date][number]
.
I finished that article with a litany of Gradle bugs. Today: fresh Google bugs!
In May, Google added automatic crash reporting to the Google Play developer console. Before auto-reporting, users had to explicitly send reports when apps crashed. So far so good, but if you’re testing on a physical device, you might notice something alarming: reports of bugs you already fixed, or crashes you only saw in development.
Apparently, Google forgot to filter out reports from debug-mode applications. Perhaps Google would claim this is a feature, but it means that you can’t tell which crashes are actually happening in the wild.
Google says crash reporting is “opt-in.” This is meant ironically, since the option to turn it off doesn’t actually exist on, for example, the Samsung S8. (There is a different option, “report diagnostic information.” As far I can tell, it’s a placebo.)
To work around this, we need to make crash reports from the debug version look somehow different from the production version. Crash reports include the version code, so remember that suffix? We can use that. Instead of using one number per release, use two: one for the release, one for the next development version:
// Version code updates when released to a date-based format. Even-numbered version codes are // release builds, odd-numbered version codes are debug builds. MAX five releases per day. def releaseVersionCode = null def writeVersionCode(versionCode) { def releaser = project.plugins[net.researchgate.release.ReleasePlugin] def propsFile = releaser.findPropertiesFile() def props = new Properties() propsFile.withInputStream { props.load(it) } props.versionCode = versionCode.toString() propsFile.withOutputStream { props.store(it, null) } } task nextDebugVersionCode { doLast { // Even though this runs after the release build, project.versionCode is still the version // code *before* release. The Release plugin runs the release build in a separate Gradle // invocation, so the release package picks up version changes in gradle.properties. When // control returns here though, it's the original Gradle invocation, and has *not* reloaded // gradle.properties. writeVersionCode(releaseVersionCode + 1) }} updateVersion.dependsOn nextDebugVersionCode task setReleaseVersionCode { doLast { def current = project.versionCode.toInteger() releaseVersionCode = new Date().format('YYMMdd0', TimeZone.getTimeZone('UTC')).toInteger() if (releaseVersionCode <= current) { // Should only happen when there is more than one release in a day releaseVersionCode = current + 1 } writeVersionCode(releaseVersionCode) }} unSnapshotVersion.dependsOn setReleaseVersionCode
So, now the first release of the day gets suffix zero, the debug version that follows gets suffix one, and so on. I’m writing this on July 26, so if I cut two releases today, my version codes will be:
- 1707260, production
- 1707261, debug
- 1707262, production
- 1707263, debug
It’s subtle, but at least now we can tell which crashes actually happened to people using your app: they are even numbers.
Or are they?
It appears that Google stores the crash data on the phone and reports it only once per day. The version code it reports is the version running on the phone when it sends the report, not when the crash actually happened.
If the app updates in the interim, we can still get crash reports for bugs already fixed and they will seem to come from a version that includes the fix.
I don’t know of any workaround.
Keyboard Savior Xtreme released
Tired of websites trapping your shortcut keys for their own ends? Me too. Usually, the problem is that they take over the Firefox slash-to-search shortcut. But what can we do about it?
First, we could tolerate it and just use ctrl+f instead. On some slash-abusing sites, like Bitbucket, this isn’t a terrible option: they rarely include long pages that require quick jumps. In api documentation, however, it’s nightmarish.
Second, we could try to stamp out the evil by filing bugs and fighting for justice. There is some hope for this: Github, for example, used to abuse the slash key and no longer does. In general, however, it devolves into Whac-A-Mole. Django rightly rejected slash abuse in in 2008, only to have it sneak into the Django docs in 2015. [As if to prove my point, Github reinstated slash abuse not long after I wrote this.]
Finally, we could just fix it. This Greasemonkey script lets you list known abusers and prevent them from seeing slash keystrokes. After some time, however, I realized that my Greasemonkey approach did not go far enough: it only prevents abuse of one keystroke and only on selected sites.
In fact, there are only a handful of sensible reasons for any website to capture a keystroke, ever. Why not just stop them all?
So, I welcome Keyboard Savior Xtreme. Take back all your keystrokes.
Comefrom0x10 released
After a long hiatus while I built Text Collector, last week I finally returned to my paradigm shifting language, Comefrom0x10. It now has a home page on Read the Docs that features a tutorial, standard library documentation and more.
Except for a couple minor bugs, its implementation was actually functionally complete eight months ago. I hesitated to release it, however, because of rather embarrassing performance problems.
Now, it wouldn’t be fair to say that Cf0x10 is just slow. It’s catastrophically slow. The brainfuck.cf0x10 program takes 10 seconds to run helloworld.b on the laptop I’m using to write this, and gets dramatically worse as the program gets longer.
What went wrong?
It’s not a fundamental problem with the comefrom paradigm, but a consequence of the twisted way the language took on a life of its own during implementation. I started with the idea that I was building a rather ordinary stack-based interpreter, but Cf0x10 would have none of it. As it evolved, the original idea became a disfigured mutant: I can demonstrate with tests that it works, but it’s too convoluted to allow necessary optimizations.
Oh well, as they say, first make it right, then make it fast release it.
How Unicode can save math: part 2
It’s widely known that decimal – or “numbers” to most of us – is an inferior system. Decimal doesn’t work well for computers, which prefer base two and it doesn’t work well for humans either, at least not when compared to dozenal.
Dozenal is also called “duodecimal,” or “base 10” (when writing in dozenal) and it is a much more natural system for humans than decimal. The usual example of why is a clock. Look how neat it is with the number 10 right at the top:

Dozenal has a big problem though, as we can see from the clock. What number does 10 represent, when you see it out of context? You just don’t know.
For decades, we’ve solved this problem in computer programming with funny prefixes. To a programmer, dozenal and decimal might be “base 0xA” and “base 0xC”. Likewise, in a dozenal world, we might write “hexadecimal” as “base 0z14” or something. If we need to start writing all our numbers with warts to indicate the base, however, dozenal seems doomed.
But wait, there’s hope. Unicode already contains the digits for “dek” and “el.” (That’s ten and eleven, if you’re not a cool dozenal kid.) If your browser doesn’t have a suitable font, refer to the clock above. If it does, they look like this:
↊ ↋
Now all we need is nine more Unicode symbols for the rest of the digits. Zero is special: for zero, there need be only one.