I realized I haven’t talked yet about my workspace setup, including the choice of computer(s) and operating system(s) which I prefer. A topic like that is a perfect opportunity to provide fuel for countless flamewars raging through the Internet forums, so it seems like a no-brainer if you want to round up some passionate readers ;)
So, what’s the best these days? Is it Windows or Linux? Or maybe OS X? Should you get a Mac or a(n other kind of) PC? Make it a desktop or just a laptop? Or perhaps subscribe to the post-PC doctrine and grab a tablet?…
Well, I don’t know. I won’t really advise anything here. Myself, I take more… holistic approach. I just use all of these things :)
As I see it, desktop PC is the place where stuff gets done. Be it “work” or play, you cannot easily forfeit the conveniences of big monitor(s), full keyboard layout, snappy mouse that fits your palm, and a comfortable chair.
Thing is, those two activities require two completely different operating systems. When it comes to games, Windows is still reigning supreme, with only some small glimpses of what might shake up this status quo. Sadly, I have little hope much will change here in the foreseeable future.
On the other hand, it’s pretty much given that the best system for most kinds of development work is some flavor of Linux, preferably sporting such powerful a package manager as
apt-get. There are no (good) alternatives for certain vendor lock-ins (*cough* iOS) but if you are not forced to comply with them, anything else is almost certainly an inferior choice.
How to reconcile those requirements? There is dual booting, of course, but the need of frequent resets would get old very quickly. So instead of that, and after conducting a bit of a research, I opted for virtualization, choosing a simple solution of running Linux as guest OS through VirtualBox.
This turned out to be super easy to set up; the only “trick” was to flip a switch in BIOS in order to enable CPU virtualization features, required to run a 64-bit system as guest. With these on, performance is a non-issue: it feels like running directly on the hardware, for all intents and purposes – including running Android emulator inside the VM :)
Now, if only all that goodness could be made available on the go… Although some may pretend it is, most (sane) people cater to their mobility needs by getting a laptop. This is immediately a compromise because of the form factor alone, but even more so because of inevitably inferior hardware specs one could cram into it.
So no, I didn’t try to replicate the VM-based setup described above :) While possible, it seemed way more sensible to try and kill two birds with one stone by getting a computer that:
As you’ve likely guessed, that description accurately fits a MacBook. Of its virtues and woes I have already written elsewhere, so let’s just say it fulfills its purpose pretty well.
And even when it doesn’t, there is always Chrome Remote Desktop to bridge the gap :)
Those cute little text formats are all the rage now, especially Markdown and reStructuredText. You can write them pretty easily, without lots of markup boilerplate that HTML entails, so they increasingly rule the READMEs of various open source projects. Both GitHub and Bitbucket support them perfectly well for this purpose.
They are obviously not WYSIWYG, though, so you may want to check the formatting first, before showing your prose to the rest of the world. There are some standard HTML generators for each of those text formats, but it would be more convenient to have one tool to rule them all…
And so there is Pandoc. That nifty utility is capable of converting from many input text formats into a vast variety of output formats, including HTML and PDF. It can be installed very easily on most systems:
and downloadable installers are available for OS X and Windows.
pandoc is a well behaved command line program, so it can accept both files and standard input, enabling it to be used in shell pipelines. Unfortunately, browser executables are not so cooperative – they generally want files, not just streams of data. We can circumvent that with the use of
/tmp directory and a little bit of shell scripting:
This should work
chrome, and likely with any other browser.
Next step? Maybe deploy a file system watcher, hook it up with some browser instrumentation, and make the page reload whenever a change in the source is detected. Non-trivial, but definitely doable :)
is an example of hashbang. It’s a very neat Unix concept: when placed at the beginning of a script, the line starting with
# (hash) and
! (bang) indicates an interpreter that should be chosen when running the script as an executable. Often used for shells (
#!/bin/zsh…), it also works for many regular programming languages, like Ruby, Python or Perl. Some of them may not even use
# as comment character but still allow for hashbangs, simply by ignoring such a first line. Funnily enough, this is just enough to fully “support” them, as the choice of interpreter is done at the system level.
Sadly, though, the only portable way to write a hashbang is to follow it with absolute path to an executable, which makes it problematic for pretty much anything other than /bin/*sh.
Take Python as an example. On many Linuxes it will be under /usr/bin/python, but that’s hardly a standard. What about /usr/local/bin/python? ~/bin/python?… Heck, one Python I use is under /usr/local/Cellar/python/2.7.3/bin – that’s installed by Homebrew on OS X, a perfectly valid Unix! And I haven’t even mentioned virtualenv…
This madness is typically solved by a standard tool called env, located under /usr/bin on anything at least somewhat *nixy:
env looks up the correct executable for its argument, relying on the
PATH environmental variable (hence its name). Thanks to env, we can solve all of the problems signaled above, and any similar woes for many other languages. That’s because by the very definition, running Python file with the above hashbang is equivalent to passing it directly to the interpreter:
Now, what if you wanted to also include some flags in interpreter invocation? For
python, for example, you can add
-O to turn on some basic optimizations. The seemingly obvious solution is to include them in hashbang:
Although this may very well work, it puts us again into “not really portable” land. Thankfully, there is a very ingenious (but, sadly, quite Python-specific) trick that lets us add arguments and be confident that our program will run pretty much anywhere.
Here’s how it looks like:
Understandably, it may not be immediately obvious how does it work. Let’s dismantle the pieces one by one, so we can see how do they all fit together – down not just to every quotation sign, but also to every space.
The overall direction where Python 3 is going might be a bit worrying, but it’s undeniable that the 3.0 line has some really nice features and quality-of-life improvements. What’s not to love about Unicode string literals enabled by default? Or the
filter all being generators? Neato!
There are also few lesser known points. One is the new
nonlocal keyword. It shares the syntax with the
global keyword, which would make it instantaneously fishy just by this connotation. However,
nonlocal looks genuinely useful: it allows to modify variables captured inside function’s closure:
What about Python 2.x, though – are we out of luck? Well, not completely. There are a few ways to emulate
nonlocal through other pythonic capabilities, sometimes even to better effect than the
nonlocal keyword would yield.
Speaking of yielding… As you have probably noticed right away, the example above is quite overblown and just plain silly. You don’t need to play functional just to count some values – you would use a loop instead:
Really, the previous version is just a mindless application of the classic Visitor pattern, which is another reason why you shouldn’t do that: pattern overuse is bad. This saying, Visitor obviously has its place: it’s irreplaceable when traversing more complicated structures in more bureaucratic languages. A simple list of numbers in Python is the direct opposite of both of these characteristics.
Complex data structures exist in any language, however. How would we run some Python code for every node in a tree, or maybe graph? Unrolling the DFS or BFS or whatever traversal algorithm we use certainly doesn’t sound like an elegant and reusable approach.
But even then, there is still no need for functions and closures. We can easily get away with the simple
for loop, if we just find a suitable iterable to loop over:
bst_nodes function above is not black magic by any stretch. It’s just a simple example of generator function, taking advantage of the powerful
This works because both
bst_nodes functions are executed “simultaneously”. That has the same practical effect as calling the visitor function to process a node, only the “function” is concealed as the body of
Language geeks (and Lisp fans) would say that we’ve exchanged a closure for continuation. There is probably a monad here somewhere, too.
Generators can of course solve a lot of problems that we may want to address with
nonlocal, but it’s true you cannot write them all off just by clever use of
yield statement. For the those rare occasions – when you really, positively, truly need a mutable closure – there are still some options on the board.
The crucial observation is that while the closure in Python 2.x is indeed immutable – you cannot add new variables to it – the objects inside need not be. If you are normally able to change their state, you can do so through captured variables as well. After all, you are still just “reading” those variables; they do not change, even if the objects they point to do.
Hence the solution (or workaround, more accurately) is simple. You need to wrap your value inside a mutable object, and access it – both outside and inside the inner function – through that object only. There are few choices of suitable objects to use here, with
dictionaries being the simplest, built-in options:
If you become fond of this technique, you may want to be more explicit and roll out your own wrapper. It might be something like a
Var class with
set methods, or just a
Finally, there is a variant of the above approach that involves a class rather than function. It is strangely similar to “functor” objects from the old C++, back when it didn’t support proper lambdas and closures. Here it is:
Its main advantage (besides making it a bit clearer what’s going on) is the potential for extracting the class outside of the function – and thus reusing it. In the above example, you would just need to add the
__init__(self, key) method to make the class independent from the enclosing function.
Ironically, though, that would also defeat the whole point: you don’t need a mutable closure if you don’t need a closure at all. Problem solved? ;-)