Haycorn

How Knuth Brushes His Teeth

A pre­ma­ture optimization?

Q: Do you have any other in­sights to offer into how you use maths in your work?

A: For instance, when I brush my teeth I’ve got eight areas to cover, namely Left and right, upper and lower, inside and outside. It’s most ef­fi­cient to follow a “Hamiltonian path” or “Gray code”:

  • left upper outside
  • right upper outside
  • right upper inside
  • left upper inside
  • left lower inside
  • right lower inside
  • right lower outside
  • left lower outside

(source)

AppleScript Tips for Shell Scripting

OS X is sur­pris­ingly scriptable, in­clud­ing OS X applications. (Especially Apple’s applications). This is the good news. The bad news is that said scripts are dif­fi­cult to write and debug, and they don’t play very well with Unix-style shell scripts. (Manipulating Unix-style file­names is es­pe­cially painful.)

Here’s an example of what can be done: select works like open except that it opens a Finder window with the ar­gu­ments selected:

$ select *.gif
select *.gif output
select *.gif output

The Ap­ple­Script code is com­pli­cated and in­volves far more workarounds than it really should but, hey, it does work.

Tips

Some tips and tricks in no par­tic­u­lar order.

Basics
  • Use & for string concatenation: return "Hello, " & name
  • Use as [type] to coerce to a string (you’ll need this for sane debugging): return foo as string would be written in C-like lan­guages as return (string) foo
  • Built-in prop­er­ties can contain spaces: track number of current track is equiv­a­lent to some­thing like currentTrack['trackNumber'] in JavaScript
  • Ap­ple­Script tries to be English-like (never a good idea): as­sign­ment is via set foo to bar (not set foo = bar) and you see things like count of every media item of con­tainer src
De­bug­ging

log to dump output for debugging, though note that some types are coerced into strings for output–compare the output of log obj and log class of obj if not sure.

Script Editor

osascript’s error mes­sages are pretty awful; for a slightly (slightly!) better de­vel­op­ment experience, use the Script Editor application. This gets you syntax highlighting, and slightly better log messages.

For best results click on the “page” icon in the bottom of the window to reveal the “messages” tab:

Script Editor screenshot
Script Editor screenshot

(Unfortunately Script Editor can’t open files that start with a shebang (see below)–you’ll need to copy and paste Ap­ple­Script to and from a text editor into Script Editor.)

Shell script­ing

There’s a few dif­fer­ent ways you can run Ap­ple­Script from the command line. First of all, you can use the stan­dard #! shebang with osascript as the interpreter:

$ cat hello.sh
#!/usr/bin/osascript

return "Hello, World"
$ chmod +x hello.sh
$ ./hello.sh
Hello, World

To read arguments, use the run method:

$ cat hello.sh
#!/usr/bin/osascript

on run argv
 return "Hello, " & item 1 of argv
end run
$ ./hello.sh Clem
Hello, Clem

You might often find that you often want to do some pre-processing via bash, es­pe­cially for any­thing that in­volves filenames. This can be achieved (as in the select example) via a bash “heredoc”:

#!/bin/bash

# bash code
if [ $# == 0 ]; then
 echo "usage: $(basename $0) args"
 exit
fi

# Ap­ple­Script code
/usr/bin/osascript - "$@" << END

on run argv
 # ...
end run

END
Ap­pli­ca­tions API

Use Script Editor’s “File | Open Dictionary…” to figure out what dif­fer­ent ap­pli­ca­tions let you do via AppleScript. Apple ap­pli­ca­tions often expose a rea­son­ably large API; for others you might get some­thing minimal, or even nothing at all.

Spotify, for example, only lets you play/pause/next/prev. You can also get some in­for­ma­tion about the currently-playing track. One the other hand Apple Photos has a fairly rich API. (Example script.)

Working with file­names

Need the current working directory?

set pwd to do shell script "pwd"

Create file object from Unix-style path (with “/”):

(POSIX file unixpath)

Get Unix-style path from a file object:

(POSIX path file)

For more in­for­ma­tion on han­dling filenames, see:

Tabs and Makefile

The com­put­ing world is lit­tered with un­for­tu­nate mis­takes that managed to make the leap from small-scale in­con­ve­nience to a source of grief to mil­lions or billions–at which point so many people and systems have been become ac­cus­tomed to the error that fixing it is impossible.

One no­to­ri­ous example is the spelling of HTTP header referer, which escaped the Netscape Cor­po­ra­tion em­bed­ded in the bowels of their web browser without anyone notic­ing the error. From there it spread to every other web browser (they needed to be compatible), and finally RFC1945, the Hy­per­text Trans­fer Pro­to­col stan­dard itself. (At least, I’m pretty sure how things happened, but Wikipedia is inconclusive. Does anyone know?)

Another is the fateful de­ci­sion of the author of make to have the space char­ac­ter and the (visually identical) tab char­ac­ter do very dif­fer­ent things. Very early on, the story goes, the author re­al­ized that this was a mistake, but by that point dozens of people were relying on it—backward-compatibility needed to be preserved—and so the tabs had to stay.

Un­for­tu­nately I couldn’t find a good source for this story online, so I emailed the author, Stuart Feldman, and asked him if it was true.

From: Michael Still­well <...@google.com>
Date: Mon, 20 Apr 2015 at 15:33
Subject: make versus tabs
To: Stuart Feldman <...@google.com>

Once upon a time I heard a story that soon after make was
released, one of its first users com­plained that the re­quire­ment
that each command line begin with a tab was suboptimal, and that
some al­ter­na­tive ap­proach should be used. As the story goes, the
author was re­cep­tive to this criticism, but ex­plained that sadly
it was now too late to change the way things worked, because too
many people were used to current behavior. The punchline, of
course, was that at this point make had perhaps dozens of users.

I was Googling a bit to try and figure out whether my memory was
correct (it's sur­pris­ingly re­sis­tant to search), when I
dis­cov­ered that make's author works at Google, and so it might be
pos­si­ble to get a de­fin­i­tive answer by email­ing you directly.

So, to satisfy my curiosity, perhaps you could tell me: is the
story true? Are there any other details you can recall and share?
And how do you feel about tabs versus spaces versus white­space
now?
From: Stuart Feldman <...@google.com>
Date: Mon, 20 Apr 2015 at 15:51
Subject: Re: make versus tabs
To: Michael Still­well <...@google.com>

Story is only partly true.

I used tabs because I was trying to use Lex (still in first
version) and had trouble with some other patterns.

(Make was written over a weekend, rewrit­ten the next weekend ...)

So I gave up on being smart and just used a fixed pattern (^\t)
to in­di­cate rules.

Within a few weeks of writing Make, I already had a dozen friends
who were using it.

So even though I knew that "tab in column 1" was a bad idea, I
didn't want to disrupt my user base.

So instead I wrought havoc on tens of millions.

I have used that example in soft­ware en­gi­neer­ing lectures.

Side note: I was awarded the ACM Soft­ware Systems Award for Make
a decade ago. In my one minute talk on stage, I began "I would
like to apologize". The au­di­ence then split in two - half started
laughing, the other half looked at the laughers.

A perfect bi­par­tite graph of pro­gram­mers and non-programmers.

Old Code & Large Numbers

Found an old passive ag­gres­sive (or maybe just aggressive) letter of mine that was pub­lished in an Aus­tralian science mag­a­zine for teens called Double Helix.

Hor­ri­ble photo. It in­cludes code, in BASIC. Num­bered lines. There is a “clear screen” command though I seem to have avoided GOTO.

Not really related, but while looking through Wikipedia for more in­for­ma­tion on this problem (it’s an an example of a Tag System), I came across some fascinating ex­am­ples of con­jec­tures that have ex­tremely large (numeric) counter-examples. (i.e. con­jec­tures re­sis­tant to computer-derived counter-examples, and common sense.)

They are:

Scott Aaron­son has an in­trigu­ing blog post on the biggest number you can write down in 15 seconds using stan­dard math notation.

See also Graham’s number.

Promise Patterns

Promises are still pretty new, and whilst their place in the Javascript world is by this point pretty secure (most of the newer JS APIs are Promise based), the ways in which they’re used are still evolving: the clunky syntax and nested .then() struc­tures often recall async “callback hell”, there’s no con­sis­tency to APIs that return promises, and there’s no design pat­terns to in­tro­duce some order. (If working with push notifications, for example, you’re likely to end up with at least three Promise-returning constructions: a static prop­erty (.ready), a getter (.getSubscription()) and a verb (.subscribe()).)

One ap­proach to im­prov­ing this sit­u­a­tion is to lean on ES6’s yield or ES7’s await and use Babel or Traceur to tran­spile future Javascript into the Javascript of today, but there’s a few things you can do without leaving browser-compatible Javascript.

Use the same name for the promise and the name of the value the promise re­solves to

Since you never really need the promise and the value the promise re­solves to at the same time, give them the same name–they rep­re­sent the same thing anyway, and giving them com­pletely sep­a­rate names makes no sense. (Annotating the types Hungarian-notation style might help, but it turns out that prepend­ing or ap­pend­ing p or promise to vari­able names looks silly.)

That is, if your promise is foo, then the name of the ar­gu­ment should also be foo:

foo.then(function (foo) {
 // ...
});

Similarly, a func­tion like fetch() does not return a fetchPromise; it returns a response:

var re­sponse = fetch(...);
response.then(function (response) {
 // ...
});

Eliminate Promise chain­ing with functions, objects–any which way you can

Promise hell usually isn’t quite as bad as call­back hell, but it can cer­tainly be hell-ish. For example, some Promise-based APIs you may be able to en­cap­su­late common op­er­a­tions on a

Separate Promise code from non-Promise code

A lot of code mixes to­gether logic and the boil­er­plate that goes with the Promise syntax. Try to avoid mixing the two by moving all the boil­er­plate some­where else. (Encapsulating it inside an object might a viable choice.)

It’s pos­si­ble that it will help to convert simple values into Promises:

Try to write the code you’d write if Promises were built in to the language

When working with Promises, try to imagine what the code would look like if Promises were built in to the lan­guage as first class values. (That is, if you could use Promises wher­ever you would oth­er­wise use values.) Is it pos­si­ble to ac­tu­ally write code like this, by moving move the Promise-manipulation code some­where else? If this is possible, is it oth­er­wise a good idea?

printf-style de­bug­ging of Promises

Here’s a simple func­tion for console.log-style de­bug­ging of Promises:

func­tion DEBUG(s, p) {
 p.then(console.log.bind(console, s, "RESOLVED"), console.warn.bind(console, s, "REJECTED"));
 return p;
}

Use it like this:

var user = foo.getUser(); // returns a Promise
DEBUG("user = ", user);
user.then(...)

Remember that .then() lambdas can return promises

Resolving a list of promises to arguments

Remember that you can attache mul­ti­ple “listeners” to a Promise

Archive