Archive for the ‘Various Frustrations’ Category

Overdrive, DRM, and Adobe Digital Editions

The Denver library recently migrated its ebook system. Incidentally, it wiped all my holds in the process and I have no idea what stuff I was waiting to read. So if you recced anything over the past 6 months and it was popular, chances are that I need you to remind me to read it again.

Anyway, today my first hold came in on the new system. I downloaded the ascm file as usual, double clicked, and when Adobe Digital Editions opened, I got this on my screen:

Yikes. I immediately assumed it was time to update Adobe Digital Editions. So I did that. And I tried opening it up again and I got this:

While you can see the massive UI improvements Adobe has made to its signature Mac e-reader, I was still rather stuck.

So I googled for E_ACT_NOT_READY and “IO Error on Network Request” and tried all the things that didn’t work until I found something that did work.

What didn’t work:

  • Clearing out ~/Documents/Digital Editions
  • Creating a new ~/Documents/My Digital Editions
  • Quitting and restarting the apps
  • Rebooting

What did work was reauthorizing my computer. Dunno why. I deauthorized and then reauthorized — good thing I remembered my username and password because it has been a gadzillion years since I did this last — and boom it finally worked.

(If you want to remove authorization by hand, toddle over to ~/Library/Application Support/Adobe/Digital Editions and kill the activation.dat file.)

Anyway, Scott Sigler’s “Alive” is now on my system ready for reading. I have no idea why I put this title on hold and who recommended it to me. I hope it’s good. Here’s finger’s crossed that this is a good read.

Apple TV, Home Sharing, and Missing Movies

I rented Hunt for the Wilderpeople last week, while it was the $0.99 featured rental. I’ve heard good things about this Kiwi movie (I’m a bit of a kiwiholic) and couldn’t wait to watch it.


So today, with a draft of Swift Style pushed up to Pragmatic, I thought I’d set it up for a nice family watch tonight. I opened the Computers > Rentals section on Apple TV and saw this:


I wasted about 20 minutes googling things like “why doesn’t my rental show up on my Apple TV” and checking my iTunes accounts and home sharing setup, when I suddenly remembered this had happened to me before.

With that spark of inspiration lingering in my mind, I went to iTunes on my computer (where I had rented it) and sure enough, it was still up in the cloud. I clicked the download button and got it down to my computer:


About 1.41 Gigabytes later (and several pause/resumes when the download speed got slow — seriously, at one point the ETA jumped from over 40 minutes to under 3), I returned to Apple TV and hopped into my home-sharing library.



So if you’re looking for a lost movie, or you can’t find your rental on Apple TV, make sure that if you rented it on your home computer, that you’ve downloaded it from the cloud before attempting to play it from ATV.

Enter the Python: Peeking at a language

Last week, I wrote about how I set up Xcode to run Python. It’s been working great. Xcode may not be everyone’s cup of tea, but I love it. Syntax highlighting, familiar keybindings, symbol completion. I couldn’t be happier. A lot of people pushed me to use Pycharm community edition, but while I’ve installed it and tried it a few times, I keep going back to Xcode. Warts and all.

I haven’t logged many hours in Python but it’s been a fascinating language experience. Let me go all metaphor on you. Way back in the 90’s there was this show called “Sliders“, about a bunch of people moving between parallel worlds. Almost everything was the same from world to world — normal humans, trees, buildings, whatever — but there were always fundamental differences in the culture and the people that always reminded you that you weren’t home.

Python is the Sliders version of Swift, the one where Chris Lattner was never born. Everything is eerily familiar and nothing is quite right. Where are my value types? My generics? My type extensions. Let me throw out another metaphor — one that will probably resonate with even fewer people: Python is the language version of the Nethack Rogue Level, where you enter “what seems to be an older, more primitive world.” It’s all familiar. Nothing is exactly the same.

This morning, I attempted to extend a type. I’m working with Anki’s Cozmo robot SDK, which is written for Python 3.5.1 or later. I’m trying to reconfigure many of the basic calls into more appropriate chunks suitable for teaching kids some programming basics.

Instead of focusing on asynchronous callbacks and exceptions, I want to provide really simple blocks that extend the robot type API in a way that hides nearly all the implementation details. I’m trying to build, in a way, a Python version of Swift Playgrounds but with a real robot. (And it’s going well, but more about that in another post.)

What I found was that Python really doesn’t want to extend types. You can subclass. You can compose. But so far, I haven’t found a way to add an extension that services an existing type. When I asked around, the Python gurus on freenode recommended I stop worrying about polluting the global namespace and embrace freestanding functions as needed.

Oh, my delicate Swift sensibilities! Adding global functions and constants? Cluttering the global namespace? I find myself clinging to Swift conventions. I create enumerations and type my arguments:

class Direction(IntEnum):
    '''Permitted driving directions.'''
    forward = 1
    backward = -1

def drive(robot: cozmo.robot.Robot, 
    direction: Direction = Direction.forward): ...

The Cozmo SDK defines its constants like this:

LEFT = 1
TOP = 4

I don’t think I’m in Swift-land anymore.

A lot of the things I like most about Python appear to be fairly new, like that ability to type arguments. I’m assured by some Pythonistas that this is almost entirely syntactic sugar, and there appears to be no type-checking, inference, or casting applied to calls.

I thought I would really hate the indentation-based scoping but I don’t. It’s easy to use (start a scope with a colon, indent 4 spaces for that scope). It reads well. It’s clean. Non-braced scoping ended up being a complete non-issue for me, and I mildly admire its clean look.

I’m less excited by Python’s take on structured documentation. The standard is outlined in PEP-257. Unlike Apple’s Swift Documentation Markup, Python markup doesn’t seem to support specific in-line tool use in addition to document generation. I’m sensitive to how much better Swift creates a structured system for detailing parameters, error conditions, return types, and descriptions, and how it scales from types to functions and methods to individual instances and provides Xcode integration.

So much in Python is very similar to Swift but with a slight twist to it. Closures? Lambdas are in there. Mapping? That’s there too. Partial application? Seems to be. Most times that I reach for a tool in my existing proficiencies, I can usually find a Python equivalent such as list comprehension, which is basically mapping across sequences and collections.

I’m sorely missing my value types. One of the first things I did when trying to work through some tutorials was to try to create a skeleton dictionary rather than type out full dictionaries for each instance. I quickly learned Python uses reference types:

# the original dict was more complicated
studentDict = {"name" : "", "tests" : []} 

joe = studentDict # create joe
joe["name"] = "joe"
bob = studentDict # create bob
bob["name"] = "bob"

# reference type
print(joe) # {'tests': [], 'name': 'bob'}
print(bob) # {'tests': [], 'name': 'bob'}


In any case, I’m still really really new to the language given my full-court-press on finishing Swift Style. As much as I wish I were writing this code in Swift, I’m glad that I have the opportunity to explore Python and hope I get to spend some time with Scala in the near future. This project is offering me a lot of valuable insights about where Swift came from and increased appreciation for the work the core Swift team put in to give us the language we have now.

Running Python in Xcode: Step by Step

As I’m preparing for a project that will involve Python programming, I need to get up to speed with at least a basic level of Python mastery. However, I’m not a big fan of using the interactive Python REPL, or whatever it is actually called:


I decided to use Xcode instead, and I’m finding it a much better solution for my needs:


Here’s the steps I took to set up this project:

Step 1: Install Python 3.5

If you run python -V at the command line, macOS reports “Python 2.7.10”, or at least it does on my system. Bzzt. I want 3.5.2, which is the most recent non-beta release, and dates to June of this year.

I grabbed my installer from the downloads page:

Step 2: Locate python3

I use tcsh, so where python3 reports /usr/local/bin/python3. The location is surely the same for you, but I don’t know what the equivalent for where is in bash.

Step 3: Create an Xcode project

File > New > Project > Cross-platform > External Build System > Next.


Enter a name (e.g. Python), and enter the path from Step 2 into the “Build Tool” line. Click Next.


Navigate to whatever location you like, and click Create.

Step 4. Create a Python file

Choose File > New,  select macOS > Other > Empty. Click  Next.


You should already be in your project’s top level folder. If not, go there. Name your file, choosing whatever name you like. I went with Make sure the “add to target Python” box is checked. Click Create.


Step 5. Edit your Run Scheme

The Xcode default should have the Run scheme selected:


Click and hold on the Python target in the jump bar. Select Edit Scheme…


The Run scheme displays, with the Info tab selected.

Step 6. Choose the Executable

I warn you now that this step is going to be delicate, fragile, and stupid. That’s because Xcode, for whatever reason, will not let you use the symbolic link at /usr/local/bin/python3. I don’t know why.

In the Info tab. Select “Other” from the Executable pop-up list. A file selection dialog appears.



Return to the terminal. Type: open /usr/local/bin. Select python3 and control-click/right-click. Select Show Original. This will probably be named python3.5. It’s not a symbolic link but unfortunately Xcode continues to be fussy about allowing you to select it as your executable because of the period in its name. Sigh.

Drag python3.5 onto the file dialog and click Choose, if you’re allowed to. If so, great. If not, you need to work around Xcode: create a hard link and then drag the link onto the dialog.

% ln python3.5 python35

I know, I know. Ew. But it’s better than copying, or worse, renaming the file. And no, symbolic links don’t seem to work here. Better solution? Let me know.

Finally, uncheck “Debug executable”. You don’t want to debug the Python language itself.


Step 7. Add Launch Arguments

Now, click the Arguments tab. Click + under “Arguments Passed On Launch” and type $(SRCROOT)/ followed by the name of the Python file you created in Step 4.


Step 8. Test it out.

Click Close to dismiss the scheme editor. Enter a program (don’t forget all those colons and tabs) and run it:


It’s a very odd thing to be jumping into Python with a Swift background. Clearly Swift has inherited a lot of Python genes. It also feels sinful to use such lax typing without compiler oversight. That said, my first experiences in Python can wait for another day and another post. More to follow.

Cocoapods and Copyright claims

So what do I do about this? Or more particularly about this: “Copyright (c) 2016 tangzhentao <>”? I don’t mind people using sources from my repos, but I do mind them claiming copyright. I would appreciate advice and thoughts.

Update: On Jeremy Tregunna’s advice, I sent an email: “You are welcome to create Cocoapods using my repositories, but you are not welcome to claim copyright ownership, change the license (BSD attribution in this case), or otherwise misattribute my code. ” I asked tangzhentao to correct the matter immediately.

Update: Tangzhentao responds: “I just saw this problem today in Github and then I went to check my email. Thank everybody to piont out this mistake, especially Erica Sadun. Now I have corrected this mistake. But I don’t know if I really correct this mistake. If not, please remind me, thanks.” There are no changes to the authorship or copyrights, I have asked him/her to update within 24 hours or I will contact Github.

Swift Holy War: Comments are not an Anti-pattern

Got into a debate yesterday about this write-up by developer Andrew Warner. His “Beware the Siren Song of Comments” suggests that developers delude themselves because comments detract from code quality:

Comments decay. They aren’t compiled, and they’ll never get executed at runtime. If they become out of date or incorrect, no test is going to fail and no user is going to complain. Programmers work around them out of fear that “somebody might need this comment or it might provide some value in the future”, pushing them along far after they’re useful (if you can even argue that they were useful in the first place).

His recommendation?

[Y]ou don’t have any excuse to write comments. Give these methods a try, and I promise you’ll have a cleaner codebase that’s easier to maintain.

I don’t claim that comments should counterbalance bad design decisions like poor naming or flawed algorithms. I do believe they play an important role in good coding practices — whether or not your code is meant strictly for internal use or to be consumed as APIs.

As I discussed on this blog a few weeks ago, there’s a big difference between the you writing code and “future you”, your team, and anyone else reading code. Here’s what I have to say about commenting in Swift Style:

Comment, comment, comment and while you’re at it, write tests. Tests can save you the whole “What I was doing here?” because you can just look at what is broken and what you expected to work.” It’s better to write less code and make up that time by explaining the code you did write better.

Sure, it helps to leave in a “TODO:” where it counts (“the performance is really bad here”) but while you’re at it, try to leave a few ideas about what exactly is going wrong, and what hypotheses you have rolling around your soon-to-be-extinct neurons. Past you understood things. Future you is clueless.

It always costs less to fix things in the past because you’ve invested in uploading the full design into your brain. Re-upping that design and getting back up to speed involves huge penalties.

Comments can explain the non-obvious, the tricky, or the counter-intuitive to a reader: This is intentional. This thing affects that thing. This data is not validated at this stage. Responsibility for this process now passes to this delegate. Comments enable you to establish what your assumptions are at which points in code and they allow you to comment on design qualities.

Comments create a record of intent. They may mention approaches that were tried and why they were abandoned. They may discuss how design decisions came to be — what paths were explored and why some of those paths weren’t chosen in the end.

Comments allow you to colocate thoughts with the code they refer to. Commit messages are helpful but I don’t think a commit message is  the proper place to document workarounds or unexpected behavior. Plus version control history may not travel with source code, if the code is reused in another project.

Comments provide a bread crumb trail of design decisions that aren’t kept in working memory and cannot be intuited just from reading code or scanning tests. Unexpected complexity is one of the things you’ll want to comment about. In fact, commenting on the unexpected is important because the alternative is essentially a bug.

Structured comments add another layer of utility, supporting API consumption. Markup allows these special comments to automatically convert into highly formatted local documentation supporting another set of readers beyond code review, debugging, maintenance, and enhancement.

Comments don’t just paper over bad design and coding. They document a process of making code right, supporting future reading and modification. Good comments reduce the mental effort needed by readers each time they review your source, enabling them to focus more on specific tasks like “how to I add this feature” rather than “what the hell was going on here”. While good code can at times be “self documenting”, that doesn’t mean it always is (or even usually is) self documenting.

As stepping stones to “past you”, good comments document what you were thinking and why you did things the way you did. Your past design decisions should never be a mystery or a burden placed before future readers of your code no matter how brilliant or insightful you expect them to be.

CGAffineTransform constructors and transformers

Core Graphics transforms provide control over coordinate systems, drawing contexts, and paths by enabling you to apply rotation, scaling, and translations. As I’ve been writing about Swift Style, I hope I’m now better able to articulate why I hate the way they’ve been automatically named into Swift.

The current Swift constructors and transformers are:

  • init(rotationAngle: CGFloat)
  • init(scaleX: CGFloat, y: CGFloat)
  • init(translationX: CGFloat, y: CGFloat)
  • rotated(by: CGFloat)
  • scaledBy(x: CGFloat, y: CGFloat)
  • translatedBy(x: CGFloat, y: CGFloat)

Here are my issues:

Confusing naming. “Scale” can be a noun or verb. You can only figure out which one was intended by looking at the translation API. If you have to look at another API to figure out some meaning, the API was written wrong.

In this example, if the two arguments were swapped around and balanced (xScale, yScale), the API would make a lot more sense. I’m not arguing for those terms. I just want to make the point that you should avoid using ambiguous words. This is a classic example of that error.

Missing Types. Why scale and translate by identical meaningless “x” and “y” values? Or rotate by “rotationAngle”? There are better, more exact terms of art and a couple of missing types to support those terms.

Although Core Graphics added CGVector, it is still missing two key types: CGAngle (stores radians or degrees)  and CGScale (stores sx, sy scaling factor pairs).

If I were in charge, you’d be able to initialize a CGAngle using radians, degrees, and π count (for example, 360 degrees is 2π and 45 degrees is 0.25 π). And you’d be able to pull out properties for each of those items as well from a unified structure. A CGScale would provide a natural way to store scaling factors.

Redundancy. If you can come up with a more redundant term than rotationAngle, I’d like to hear it.  rotationAngle uses two nearly identical words to do the work of one: “radians”. It presumes only one confusing initialization style while ignoring other common use cases like “degrees” and “multiples of pi”.

Incorrect Type Use. Although it’s convenient to break out factors into component elements, you’re really translating by a vector or scaling by an (sx, sy) pair. You should be allowed to use these types (for example, scale: CGScale) as well as the broken down member calls (for example, sx:sy:).  This is most notable in the use of CGVector. Although the CGVector type was introduced long after Affine Transforms, transforms were never updated to take advantage of  a semantically richer approach.

Mix and Match Prepositions. Core Graphics includes rotated(by:), scaledBy(), translatedBy(). So where does that “by” belong? In a coherent API, each “by” should either be in the parentheses or outside.

I vote “out”. Doing so enables you to create call families like these, where the specifics of the labels preserve share abstractions and the by isn’t glommed onto the first argument label, throwing off the API’s balance.

public func translatedBy(tx: CGFloat, ty: CGFloat) -> CGAffineTransform
public func translatedBy(vector: CGVector) -> CGAffineTransform

Speaking of unbalanced arguments, scaleX is way longer than y, as is translationX vs y, yet both arguments have equal weight and priority in the calls. Unbalanced labels offer another good indicator of badly designed APIs.


Writing updates and asking “Is Github my new Dropbox?”

I’m testing the waters for the first time in using Github rather than Dropbox to coordinate a private project. I’ve used private repos before for material that wasn’t meant for public consumption or to stage material that would then later be released openly but this is the first time I’m testing it out for material that’s substantially not code.

I’ve been meaning to give this a go ever since Github changed its policy to allow unlimited private repositories. I used to be limited to just five in total and I guarded those slots carefully. Under the new policy, I have repos to burn. Today was the first time that I set one up to use in this way.

It feels odd using Github instead of Dropbox as I’m so used to my Github content being primarily open, and Dropbox requiring explicit permissions. Have you tried using Github this way? And how have your experiences been?

The reason I’m testing out Github is that I’m updating iOS Drawing for Swift. I have a week or so to burn while I’m waiting on editorial feedback and tech review on my Swift Style title from Pragmatic. It will take another 4-6 weeks for Addison Wesley to release iOS Drawing rights back to me but I figured I’d get a head start writing some test chapters and get some early feedback about the project while I had some downtime.

I’ve used Dropbox for years to provide material to beta readers and gather their feedback as well as to coordinate material on multiple machines. In testing out Github, I was inspired by Pragmatic’s workflow.

Pragmatic uses a delightfully retro SVN version controlled interactions between editors and authors. (I’ve had to create an SVN/git cheatsheet to remind myself how to SVN all the things.) Pearson/AW in contrast uses Basecamp to manage projects. Basecamp offers a lot of great team features including messaging, calendars, email updates, and so forth, and I’ve been quite happy with it.

Book projects tend to be hefty, especially those with lots of illustrations and sample code but Github has generous file policies. It imposes a 1GB repo limit, 50 MB file warnings, and 100MB file limits.  These are far beyond what I’d need.

I’ve recently changed my overall personal workflow, having been inspired by conversations with editors at O’Reilly. O’Reilly has been pioneering modern, flexible content using markup source. I took my lead from them. (I’m personally using CommonMark instead of AsciiDoc and pandoc instead of Atlas, but the ideas are similar.)

Pandoc has been a pure delight. Even if CommonMark offers less nuance and control than Microsoft Word (however ugly MS Word is, it has power and all the ugly but practical features you need for professional publishing), pandoc allows me to push from manuscript to book in seconds.

I don’t have to use Calibre to build epub, pdf, and mobi output. My code examples are readable and my tables of contents are perfect. I’ve written a bunch of command-line utilities that automate the process of building the ebooks, zipping up archives, and storing copies in a Dropbox beta folder. I still use Dropbox to provide early reader access.

I built Swift Style‘s first draft using this workflow, writing in MacDown, an open source macOS Markdown editor. I like MacDown’s side-by-side display but, to be honest, for material of any size, it has no way to keep the text and output in sync, especially once you introduce illustrations.

If I find some time, I’ll probably try to mess with the source to add this functionality because once you drop the ability to see your edits as you add them, the utility loses a lot of its charm but that’s a project for another day.

In the meantime, I’m just getting settled into Github for this project. A lot of my work steps are similar: I start by pulling and wrap up by pushing but now it’s to the repo, and not to Dropbox. Github offers more version control than Dropbox’s undelete functionality and I don’t have the same worries about filling up my quota.

I’m curious: Are you using Github for non-coding projects? And how has that worked out for you? Did the DNS incident a few days ago make you rethink? Or are you committed to this kind of collaborative tool? Let me know. Thanks!

Solving Mathieu’s Phone: The mystery of disappearing gigs

The other day, Mathieu’s 16 GB phone suddenly had no space. Even after rebooting, even after reformatting (and not restoring from backup), all his spare bytes were being sucked into a black hole.

He had no songs, few apps, a modest number of photos, and under a gigabyte of space available, making him unable to compile, load, and tests his apps.


Each time he deleted one of his apps, the space would mysteriously fill up within a few minutes, adding to the ever increasing “other” bar in iTunes:


This delete-then-lose-space behavior made me think that iCloud was trying to store files locally on his phone to reduce cloud access. I suggested that he disable iCloud and sync just the bare essentials like contacts, calendars, and notes. (Mathieu has a paid 300GB iCloud plan.) Sure enough once he logged out and rebooted, over 7GB of space was freed up and he was able to use his phone again.

I’m not super-familiar with iCloud so if anyone can further explain how this works, and how to set up the phone to limit it from glomming space, I’d sure appreciate being able to pass that along. Thanks!

Responding to bad errors with bug reporting

Soroush K writes,  Here’s one annoying thing about Swift 3. The line

let location = geofenceNotifier.locationDataStore
    .cached?.first(where: { $ = locationID })

should be using `==` instead of `=` but the error you get is `Cannot call value of non-function type ‘Location?’`. It should give me an error saying “Hey, `id` is a `let` so you can’t assign to it” or “You’re not returning a Boolean.” and not “we’re trying to call `Location?` as a function.

While I can see where the team was going with this error I agree that it probably reflects the wrong most common error case. When you encounter bad Swift errors, file a bug report at bugs. and explain why you think it’s a bad error and what you think should have been a better approach.