Haycorn

How Knuth Brushes His Teeth

A premature optimization?

Q: Do you have any other insights 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 efficient 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 surprisingly scriptable, including OS X applications. (Especially Apple’s applications). This is the good news. The bad news is that said scripts are difficult to write and debug, and they don’t play very well with Unix-style shell scripts. (Manipulating Unix-style filenames is especially painful.)

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

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

The AppleScript code is complicated and involves far more workarounds than it really should but, hey, it does work.

Tips

Some tips and tricks in no particular 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 languages as return (string) foo
  • Built-in properties can contain spaces: track number of current track is equivalent to something like currentTrack['trackNumber'] in JavaScript
  • AppleScript tries to be English-like (never a good idea): assignment is via set foo to bar (not set foo = bar) and you see things like count of every media item of container src
Debugging

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 messages are pretty awful; for a slightly (slightly!) better development 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 AppleScript to and from a text editor into Script Editor.)

Shell scripting

There’s a few different ways you can run AppleScript from the command line. First of all, you can use the standard #! 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, especially for anything that involves 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

# AppleScript code
/usr/bin/osascript - "$@" << END

on run argv
  # ...
end run

END
Applications API

Use Script Editor’s “File | Open Dictionary…” to figure out what different applications let you do via AppleScript. Apple applications often expose a reasonably large API; for others you might get something minimal, or even nothing at all.

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

Working with filenames

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 information on handling filenames, see:

Tabs and Makefile

From: Michael Stillwell <...@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 complained that the requirement that each command line begin with a tab was suboptimal, and that some alternative approach should be used. As the story goes, the author was receptive to this criticism, but explained 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 surprisingly resistant to search), when I discovered that make’s author works at Google, and so it might be possible to get a definitive answer by emailing 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 whitespace now?

From: Stuart Feldman <...@google.com>
Date: Mon, 20 Apr 2015 at 15:51
Subject: Re: make versus tabs
To: Michael Stillwell <...@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, rewritten the next weekend …)

So I gave up on being smart and just used a fixed pattern (^) to indicate rules.

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

So event hough 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 software engineering lectures.

Side note: I was awarded the ACM Software Systems Award for Make a decade ago. In my one minute talk on stage, I began “I would like to apologize”. The audience then split in two - half started laughing, the other half looked at the laughers. A perfect bipartite graph of programmers and non-programmers.

Old Code & Large Numbers

Found an old passive aggressive (or maybe just aggressive) letter of mine that was published in an Australian science magazine for teens called Double Helix.

Horrible photo. It includes code, in BASIC. Numbered lines. There is a “clear screen” command though I seem to have avoided GOTO.

Not really related, but while looking through Wikipedia for more information on this problem (it’s an an example of a Tag System), I came across some fascinating examples of conjectures that have extremely large (numeric) counter-examples. (i.e. conjectures resistant to computer-derived counter-examples, and common sense.)

They are:

Scott Aaronson has an intriguing blog post on the biggest number you can write down in 15 seconds using standard 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() structures often recall async “callback hell”, there’s no consistency to APIs that return promises, and there’s no design patterns to introduce some order. (If working with push notifications, for example, you’re likely to end up with at least three Promise-returning constructions: a static property (.ready), a getter (.getSubscription()) and a verb (.subscribe()).)

One approach to improving this situation is to lean on ES6’s yield or ES7’s await and use Babel or Traceur to transpile 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 resolves to

Since you never really need the promise and the value the promise resolves to at the same time, give them the same name–they represent the same thing anyway, and giving them completely separate names makes no sense. (Annotating the types Hungarian-notation style might help, but it turns out that prepending or appending p or promise to variable names looks silly.)

That is, if your promise is foo, then the name of the argument should also be foo:

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

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

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

Eliminate Promise chaining with functions, objects–any which way you can

Promise hell usually isn’t quite as bad as callback hell, but it can certainly be hell-ish. For example, some Promise-based APIs you may be able to encapsulate common operations on a

Separate Promise code from non-Promise code

A lot of code mixes together logic and the boilerplate that goes with the Promise syntax. Try to avoid mixing the two by moving all the boilerplate somewhere else. (Encapsulating it inside an object might a viable choice.)

It’s possible 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 language as first class values. (That is, if you could use Promises wherever you would otherwise use values.) Is it possible to actually write code like this, by moving move the Promise-manipulation code somewhere else? If this is possible, is it otherwise a good idea?

printf-style debugging of Promises

Here’s a simple function for console.log-style debugging of Promises:

function 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 multiple “listeners” to a Promise

Archive