Thomas Denney

Student and app developer

Writing

Surprisingly, for a computer science student, I evenly split my time between typing and writing by hand. I generally begin by writing out my notes and problem sheets by hand before later preparing a typeset version of them, depending on what is required. In this first of a two part series I discuss the pens, inks, paper, and notebooks that I use, and why I often choose to write by hand.

For most of the last decade I've exclusively used fountain pens, with occasional forays into ball points, roller balls, and fine liners. Fountain pens have the significant advantage that ink will flow out of them with very little pressure, whereas a ball point requires you to apply pressure directly to the page, which is significantly less comfortable. The section (the part of the pen you grip) is also far nicer to hold on most fountain pens, firstly because it is often far wider than that of a ball point, thus keeping reasonable separation between your fingers, but also because many pens will also be shaped for holding (see the pictures of Lamy pens below) comfortably.

Unusually for a fountain pen user, I rarely write in cursive and do not italicise my letters. The main reason for this is that I have to write a lot of mathematical notation, and I've found it helps to be consistent between text and equations. I do, however, enjoy calligraphy but don't do it for regular note taking.

Parker Sonnet, Lamy Safari, and Pilot Metropolitan

Parker Sonnet, Lamy Safari, and Pilot Metropolitan

At the moment I am currently switching between Parker, Lamy, and Pilot pens. Parker pens are widely available in the UK, and I've found them to write very smoothly. My Parker pens all have medium nibs, which forces me to write slightly larger to ensure proper separation between characters. More recently I've come to enjoy using Lamy pens, which are often inexpensive, with fine nibs. I particularly like my Lamy demonstrator pen, which has a clear case, allowing you to see the internal working of the pen.

Lamy Demonstrator pen

Lamy Demonstrator pen

In nearly all my pens I use converters, rather than ink cartridges, as this allows me to use a far broader variety of inks. Until very recently I exclusively used Parker Blue-Black, but I've come to find the colour a little too grey. Instead, I have started using J. Herbin 1670 inks, with Emerald of Chivor and Ocean Blue pictured below:

Emerald of Chivor with fine nibbed Lamy Safari, Ocean Blue with medium nibbed Parker Sonnet

Emerald of Chivor with fine nibbed Lamy Safari, Ocean Blue with medium nibbed Parker Sonnet

To say these inks are fantastic is an understatement. The ink flows perfectly in all my fountain pens, and both have a deep, rich colour. The emerald ink contains small flecks of gold, so the writing will sparkle in some lighting conditions. These inks are very expensive compared to most, but they are by far the best I've ever used.

From personal experience I must also recommend Amodex Ink Stain Remover, especially if you use thicker, oil based inks. Aside from a dip pen that I use infrequently for calligraphy most of my pens do not have a tendency to leak, but when they do this stuff is a life saver.

Whilst pens and ink are important, the quality of the paper I write on is equally important to me. When I was at school I tended to use Ryman Superior paper, which is thick enough to avoid bleeding with most inks. The paper is, however, quite coarse so I've therefore switched to using Rhodia pads instead. I started with a dot pad, which is great for diagrams and testing pens or inks, but I then began using the larger lined pads. I recommend Rhodia NÂș 19 in white with lined pages. The pages of this pad do not come hole punched, and have a margin that is slightly too wide for my liking (although they're good for taking notes) but the paper has a much smoother finish than the Ryman paper. I've found that when writing on the back of sheets in Rhodia pads (which fold at the top, with a perforated edge for each page) it is generally best to either only fold over the top few sheets onto the back of the pad, or tear it off immediately.

Moleskine and Leuchtturm notebooks

Moleskine and Leuchtturm notebooks

As well as paper pads, I also write a great deal in notebooks. I currently use Moleskine and Leuchtturm notebooks, and I far prefer the latter. My Moleskine notebooks are smaller, so I tend to use them for todo lists and for jotting ideas down, whereas I tend to take longer notes in the larger (A4) Leuchtturm notebook. The paper is also more translucent in Moleskine notebooks, meaning that you get slightly more bleeding. The Leuchtturm notebook also has page numbers and a table of contents, which make it ideal for university notes (although, sadly, they don't come cheap). As all these notebooks are narrow ruled I've preferred to write with a fine nib and also use a darker ink colour, as the pages are not pure white. Fine liners also work well in these notebooks, but with ball points you generally have to apply so much pressure that you'll mark the page below. Furthermore, I wouldn't recommend using Lamy roller balls or the Moleskine pen in these notebooks, as the former is much to thick and the latter smudges too easily.

Whilst much slower than typing, I enjoy writing by hand because it gives me a lot more creative freedom over the appearance of my writing, is more ergonomic than typing, and the slower pace tends to force me to think a great deal more about what I'm writing.

Overall, I am very happy with my current writing setup, and I look forward to evolving it in the future. In the second of this two part series I will discuss the software and hardware that I use for typing.

Oxford term dates

When I come home for vacations from Oxford I suddenly find myself using real dates again, rather than thinking in terms of "Tuesday of 5th week" or "Sunday of 3rd week". However, during term time there is the occasional need to map between 'Oxford dates' and real dates.

Wolfson College provide a calendar that you can subscribe to that provides each week of each term, which is invaluable when scheduling lectures and tutorials into my calendar. Sometimes, however, I just need to very quickly find out what date an 'Oxford date' falls on, or what 'Oxford date' a regular date falls on.

I have therefore created a very simple Python script that provides this functionality, allowing you to run ./oxtermdate.py 2017-02-14 or ./oxtermdate.py Tu5 to map between the two. Currently you have to set an environment variable for the start of term (which you can find here), but seen as this only changes three times a year I am currently not bothered about automating it.

Comparing the implementation of generics

Generics are a common feature of statically typed programming languages that allow programmers to abstract algorithms and data structures over types. Typically implementations of generics - at the compiler and runtime level - will "instantiate" different concrete instances of generics types by replacing their type parameters with other types. The point at which this instantiation occurs, and whether it occurs per type or not varies between C++, Java, and C#.

C++

C++ implements generic classes, methods, and functions through templates, which are compiled into separate copies for each concrete type used with the generic type. Consider a simple generic class Box:

template<typename T>
class Box {
public:
    Box(T value) { _value = value; }
private;
    T _value;
};

Later when a function declares an instance of Box it is required to supply the name of a concrete type for the type parameter T:

Box<int> intBox(42);
Box<std::string> stringBox("Hello, world!");

For each compilation unit - generally a single C++ source file - instances are created by replacing T with the appropriate type and then compiling the generated code. The generated code is then type checked, to ensure that all used methods, fields, and operators are accessible. For example, the STL function std::sort is generic across all types, but will only compile when used with a type that overloads the < operator. It is an unfortunate disadvantage that C++ has no way of dictating this in the type system, but this is coming in the future with concepts.

A big advantage of the C++ approach is that there is no runtime performance cost compared to handwritten code, but it does come at the hefty disadvantage of compile time and code size. As each compilation unit includes copies of all the generic instances it uses, it is necessary for a linker to eliminate the redundant copies. For example, if both a.cpp and b.cpp used Box<int>, then implementations of Box<int> would feature in a.o and b.o, but if the two were linked together into program then a spare copy could be removed. Programmers can avoid this by declaring explicit instantiations in a header file and then forcing all of them to be implemented in a single object file, but this becomes awkward as the code size grows.

Slightly unique to C++ is the option to provide alternative specializations of generic classes for types where it may be more efficient to do so. For example, the STL specializes std::vector<bool> to represent boolean values with a single bit.

Java

The initial release of Java in 1995 did not include generics. The Generic Java project, started in 1998, was integrated into the language in 2004. As a result of the relatively late inclusion of generics, the authors of Generic Java were conscious that it would be necessary to maintain compatibility for existing code that used non-generic interfaces for classes, such as common collections, that could now be implemented using generics.

Prior to the introduction of generics, collections APIs used Object, Java's root reference type, as their element type. The Generic Java project therefore chose to 'erase' the generic type parameters by replacing them with Object in order to compile the generic class, and introduce the appropriate casts in client code. The following generic code:

public class Box<T> {
    public T value;
    public Box(T value) {
        this.value = value;
    }
}
//Client code
Box<Integer> intBox = new Box<Integer>(42);
Integer intFromBox = intBox.value;

Is therefore compiled to:

public class Box {
    public Object value;
    public Box(Object value) {
        this.value = value;
    }
}
//Client code
Box intBox = new Box(new Integer(42));
Integer intFromBox = (Integer)intBox.value;

A consequence of type erasure is that it restricts the type parameters to reference types, and as such it is not possible to create an instance of Box<int>, for example. In order to get around this, Java provides boxed classes which contain a field for Java's eight primitive value types. In Oracle's HotSpot JVM, this comes with the disadvantage that a Java object contains a header of one or two words, and to access any field at least one pointer traversal is required. There is therefore the initial cost of allocating memory on the heap for boxed instance, the memory cost of the object's header, the cost of traversing at least one pointer to get the boxed value, and the cost of garbage collecting the instance. In many cases it is difficult to efficiently use generics with primitive types.

Project Valhalla a recent effort to "incubate advanced Java VM and language features", supports the introduction of value types and generic specialisation to the language in order to make these cases more efficient.

Furthermore, without reflection it is not possible to create new instances of the generic argument either, i.e. object creation via new T() is not possible.

.NET

Most C++ compilers compile to native code "ahead of time" (AOT), whereas Java byte-code is compiled "just in time" (JIT) by a virtual machine, but .NET software can be compiled using either method. Typically, however, execution is via the JIT-compiled Common Language Runtime. At runtime, generic types are instantiated as they are required, so generics can be used with value and reference types. A single instance is shared for all reference types - effectively using type erasure like Java - but separate instances are created for value types. Rather than completely erasing types at compile time, the metadata section of .NET "portable executables" encodes the generic parameters of a type or method, allowing these to be replaced, and the method can then be JIT compiled. After an instance has been compiled it will be reused, and the generated native code remains in memory whilst the application is executed.

For most types found in .NET applications (references), this approach will offer similar performance to Java, as appropriate casts between the base reference type and the expected reference type must be inserted. Meanwhile, the .NET approach offers a significant advantage for value types as a separate instantiation is natively compiled for each value type used by the program, which avoids the need for boxing or unboxing, hence offering better performance.

Despite using type erasure for reference types, .NET allows new T() in generic methods by automatically using reflection methods, provided that a given type has the default constructor available.

As well as providing a JIT-environment for .NET applications, Microsoft provides a tool that compiles .NET bytecode assemblies to native code. This improves performance of .NET applications by removing the need for JIT compilation, and also reduces memory requirements.

Unlike native C++, .NET executables typically consist of multiple assemblies that are dynamically linked at runtime (either by the JIT or OS services). Suppose an assembly A.dll exposes the generic type List<T>, which is instantiated as List<string> and List<int> in both B.dll and C.dll, and that D.exe links to both B.dll and C.dll.

In the JIT environment the bytecode for List<T> will only be included in A.dll, but the native environment presents a greater challenge. The first option would be to include native code for List<string> and List<int> in the natively compiled B.dll and C.dll, but this violates .NET's principal that equal types should be identical.

In order to counteract this problem, Kennedy and Syme introduce further rules for the "home" of a particular instantiation:

  • The assembly that defines a generic type includes the instantiation for all reference types, like Java. In the case described above A.dll would include List<ref>
  • If an assembly needs a value type instantiation, then include it in the assembly. B.dll and C.dll would therefore require their own implementations of List<int>, but they could both use the implementation of List<ref> in A.dll for List<string>, as string is a reference type in .NET
  • At link time do not link to a generic type if an equal instantiation has already been linked to. The implementation of List<int> in C.dll would therefore be ignored if B.dll had already been linked in D.exe, thus resolving the identity issue

Conclusion

Generics are a useful addition to many programming languages, and there are further efforts to add higher-order "kinds" (a generalisation of parametrized types) to functional programming languages such as Haskell. The compilation techniques described above are used by main other programming languages, although recent languages such as Go remain resistant to their addition, citing increased compilation time and executable size as drawbacks.

The native code generated by compilers for statically typed languages is unlikely to change due to the stability of computer architectures, OS calling conventions, and memory layouts. Recent research and development into generics instead focusses on adding restrictions to the types that can be used with generics to increase type safety and programmer productivity whilst reducing the complexity of the compiler.

Automating the Wikipedia game

In the Wikipedia game, you typically click the random article button and aim for another Wikipedia article by clicking on the fewest links possible. At a recent Oxford CompSoc event we wrote bots to automate this process.

Before the event I wrote up a few Python scripts to play the game by using the MediaWiki API. There is an API call to fetch a list of links for a given page, but it unfortunately lists them alphabetically rather than in the order they appear. I therefore used the general API for fetching the MediaWiki markup for the page and scraped the links instead. This meant I could use a simple strategy of clicking the first link to get to Philosophy, and then using a known route from there to our goal page. Effectively this just performed a depth first search on the graph of links.

Most people chose to use and adapt this strategy, often by prioritising certain frequently linked to articles and using known routes from those articles, although at least a couple of people experimented with backlinks.

Whilst my "philosophy" strategy tended to reach the goal article within around forty links, the best strategy used a breadth-first search (capped at the first five links of an article) with certain well known routes used to reach the goal at the end. This was still a largely uninformed search, but by "knowing" the category of a Wikipedia article you could almost certainly reduce the number of clicks that you need.

Everyone stuck to search strategies and the Wikipedia API, rather than using the brute force approach of downloading a dump of all Wikipedia's text, and running Dijkstra's on it locally.

Minor site update

Over the past few days I've been migrating from Squarespace to a self-hosted site. If I've done this correctly, you should only notice a few minor visual changes.

The server now runs on DigitalOcean, with a NodeJS backend written in TypeScript. I'd hoped to avoid writing any server side code, either by generating a static site with Jekyll or by using a CMS, but Squarespace has irregular URLs. For example, dates can be written with any number of digits. I didn't fancy learning whichever CMS happens to be cool today, so writing a little NodeJS wasn't onerous.

Writing in TypeScript and using Visual Studio Code made my life a lot easier. They work great together, especially with IntelliSense and debugging. I would recommend doing the following:

  • If you're using any NPM modules, make sure you have DefinitelyTyped definitions

  • If there isn't a DefinitelyTyped definition, make sure you import via let module = require('module') rather than import module = require('module') because otherwise TypeScript will throw an error

  • Use tsc --watch to auto-recompile files

If you notice any broken URLs, please contact me so that I can fix them.

Keep Calm 4 for Android

I've just shipped a major update to Keep Calm for Android.

  • Photo backgrounds
  • Change the foreground colour
  • Material Design

Aside from new features, I'm now also including ads again - photo backgrounds and text colours had previously been 'pro' features before I removed Keep Calm Pro from Google Play.

Play Time 2

Play Time 2, my music statistics app for iOS, has just received a major update. You can now view how you listen to your music over time, view interactive graphs for your listening habits of individual songs, albums, and artists, and view more statistics than ever before. Play Time 2 is available for $0.99 from the App Store today.

Play Time, Over Time

Play Time, Over Time

Play Time, Over Time

Each time you launch Play Time it records the total play count of every song in your music library. As these change you'll be able to see how the total play time of any song, album, or artist, or your whole library, change over time. The graph itself is interactive and you can view the total play time at any point in time.

New statistics

New statistics

New statistics

Previously you could only view a handful of statistics about your music library, however you can now view average play time, duration, play count, title length, and rating as well as word counts in song titles. Songs, albums, and artists also show fun facts related to their play time. For example, I've spent about the same amount of time listening to Daft Punk as the gestation period of a mouse.

Interactive charts

Year vs Play Time

Year vs Play Time

There are now interactive charts that allow you to view:

  • Rating vs play time (if you rate your music you'll probably find that yours looks very similar to everyone elses!)
  • Year vs play time
  • Genre vs play time

Other new features

  • Support for new iPhones and the iPad with settings that sync via iCloud
  • Share any chart or statistic by tapping on it
  • CSV data export (works with Numbers/Excel/Google Drive on your iOS device or on your computer) in case you want to do even more analysis
  • Gravitational ratings (you'll get it when you see it)
  • Searching
  • Song/album/artist rankings
  • Completely redesigned UI with a new icon
  • The app is so much faster, its not even funny

You can download Play Time from the App Store for $0.99.

Circle Draw 2

Today I've released Circle Draw 2 which refreshes the UI and adds support for newer iPhones.

More importantly, however, the critical cats that score the circles are now higher resolution.

You can download the free update to Circle Draw from the App Store today.

Apps that include an app extension and a framework must support arm64

Yesterday I was finally shipping an update to one of my apps, but each time I tried submitting to iTunes Connect I got back error -9000:

Invalid architecture: Apps that include an app extension and a framework must support arm64

Googling didn't reveal too much (the project was set up fine to build for both 32-bit and 64-bit), but the following seemed to fix the issue:

  • Going through project.pbxproj and manually replacing IPHONEOS_DEPLOYMENT_TARGET = 7.0; with IPHONEOS_DEPLOYMENT_TARGET = 8.0; (I had set 8.0 in the UI, no idea why the file hadn't updated)
  • Ensuring that the 'Build Active Architectures Only' was set to NO for release builds (again, I had set this in the UI, but checked it in the project.pbxproj file)
  • Deleting an old static library from the Frameworks group. This is the weird one, but I suspect it was what was causing the issue. The app had previously linked to a static library that had been 32-bit only, but I had long since deleted it. The app itself didn't link against it, but there was still a link showing up for it in the Xcode project (it showed in red though, it didn't actually exist)

The phrasing of the error isn't great; there ought to be an 'or' rather than an 'and' in there (my app only contains a framework, not an extension).

Word Finder 2

After two years of no updates I have now updated Word Finder with new features, significant performance enhancements, and support for new iPhones. Word Finder allows you win (cheat?!) many common word games with wild card search, anagram search, Boggle search, and Letterpress search.

  • A brand new query execution engine that ensures all queries now execute instantly (the old version could take several seconds)
  • Search history
  • Easy entry mode for Boggle and Letterpress grids and improved entry for anagrams
  • Sorting options
  • Save your favourite words
  • View definitions for thousands of words via Wiktionary or the built in Apple dictionary
  • Modernised user interface

You can download the latest version of Word Finder for free from the App Store.