Tuesday, May 29, 2012

A month with a mac

I recently took the plunge, and started using a Macbook Air. My setup at work had been a capable linux desktop, an underpowered Windows box, and an adequate dual-boot windows/linux laptop. The linux desktop remains my primary at-work development environment, and the only thing I'd like to change about it is to upgrade its monitor to something that supports very high resolutions.

The Macbook offers a potential compromise between portability, capability, corporate interoperability, and development suitability. Well first off the bat, two things are not even compromised: portability and corporate interoperability are just 100% fine. In fact, my office experience has actually been better on the mac, as it has a more recent Office edition and higher screen resolution. Big thumbs up. Capability is, roughly, the same as the last laptop. Fine, but nothing particularly outstanding. The user interface is clean and responsive at all times, but I can still grind the thing to a halt if I try to do too much with it. However, that's really no different to the underpowered Windows box or laptop I used to have.

So the final, and all-important issue: development suitability. It's "okay". That's actually pretty amazing, considering that I work as a professional software engineer developing Python applications for a linux environment. There are lots of little issues, and a few big ones. But it basically works.

First of all, let's take a step back and talk about writing code on the machine. Xcode, the IDE that comes standard, is something I couldn't understand and get comfortable with, maybe because I'm neither writing OSX apps nor web apps. That's right, I'm writing old-school client/server GUI apps, in Python, for linux. Fortunately, my favourite editor, Sublime Text, is available. I've done a lot of learning how to use the mac, but for the task of writing code I just slipped into the beautiful environment of Sublime Text like putting on an old pair of slippers in winter. It's just great.

The screen resolution, for me, noticeably reduces eyestrain. It's easier to read the text when there is more resolution in each character. I'm not a micro-font-size weenie either, although I do like it small enough to see a decent chunk of code at a glance. It's the default font, looks like a size ten fixed-width. But size ten, at high resolution, is finished-off well. The backlit keyboard is nice, and they keyboard feel is also great. A decent amount of space between the keys is tactile and keeps the typo rate down. It's easy to feel when you've drifted off the center of the key and might have smooshed the wrong letter. It's great for "authoring" on.

The setup of software for me takes a little while. First up, you'll want macports installed. Or brew. Or fink. I don't really know how to figure out which is better, but I just think of them like apt or yum. They install things for you. But not everything works, and there is a decent amount of stuff installed in my system now which I downloaded and compiled manually, which will now probably drift over time. Without a whole community of developers keeping the whole system moving forward, I'll have to do it myself, and I'll probably only notice when things break. Sometimes things don't work. For example, I installed wxPython form a binary, but it doesn't run. I don't know why. I couldn't get pyCairo to install either, and apparently a lot of people have trouble with this. On a mac, you are officially off the beaten path, and you can expect to run into some trouble from time to time.

On the plus side, the terminal does provide me with a familiar environment. It does what I want. I can run most of what I want. I got a real kick out of running ipython notebook, setting up numpy and scipy, and sending my CPUs off to processing land for 5 minutes cranking through some scientific data processing.

The whole system definitely "comes together" in a way neither linux nor Windows does. Distributors could learn a lot from working on a mac about how to build a system that people can just "be" on. Be, on a mac. The dock is awesome, the fact the UI is basically always responsive is awesome. It's hard to describe how nice it is having the whole system integrate well. It's like when you're in the office, and the airconditioner turns off, and you suddenly hear the silence and realise how noisy it was. Having a systems parts integrate well is exactly like that.

Ultimately, I think the Mac is a beautiful machine and a beautiful OS. It is okay as a development platform for linux/open source applications, without having to bother with dual-boot or working in a VM. For testing, obviously, you will need to prove the system on the end-users environment. But that is always true. It's also clearly possible to use this in a business setting. If you're a small startup, using a Mac will let you interface with the business world and the developer world at the same time, mostly. But you will also have to do some extra work to master your environment, and get over some hurdles yourself.

File paths and nested dictionaries

Really, I just want to boost the pagerank of this page: http://code.activestate.com/recipes/475156-using-reduce-to-access-deeply-nested-dictionaries/

I had an issue where I had a list, say [1,3,4,6,7, "result"], which I wanted to smoosh into a nested dictionary and get back easily. I found my own way to store said items (built up programmatically in the course of other logic), but I wanted an easy way to get them.

I will now reproduce the solution from the above page in full, for your convenience:

# In your hand you have a dict instance representing the database 'object'
dbo={'m':{'d':{'v':{'version':1}}}}

# You know this thing corresponds to a table whose rows follow some convention
# indicating 'depth', say '__' hapens to be the seperator.

# You wan't to access a particular element, but you know it only by its column
# name 'm__d__v__version'

name='m__d__v__version'

version = reduce(dict.get, name.split('__'), dbo)

assert version == 1

foo = reduce(dict.get, 'm__d__v__foo'.split('__'), dbo)

assert foo == None