Monday, October 20, 2008

Types: Values versus Locations

Minor thought I had this morning: I was doing some prep work for the conference I'm speaking at next week, and I noticed I was being perhaps overly pedantic about the terminology of types in a way that only matters for imperative languages.

I habitually make explicit the distinction between values and locations of a particular type. I might say, the storing of values of multiple types in a location of a single type is an instance of polymorphism. In describing a class, I might say, this is "an iterator over a stream of values of type T", instead of just saying "an iterator over a stream of T" (no, not a teapot!).

The distinction is important in languages that have mutable state. Locations can have their address taken, they are subject to polymorphism, and the location itself has an identity independent of its value. Values, on the other hand, cannot have their address taken - at most, the value is or contains an address. Values always have a fixed type, but locations may contain values of different types if the type of the location is polymorphic. Locations may be lvalues or rvalues, but values are always rvalues (unless you dereference, index or field-access them). Especially important is the fact that implementations of closures in imperative languages like C#, Delphi, Ruby, etc. have almost always opted to capture locations, not values.

However, consider a pure language, like Haskell. If the language doesn't have mutable state, there's no such thing as a location (at the conceptual level). If you have an iterator in such a language (perhaps modeled using a tail-call continuation design), it's redundant to say "iterator over a stream of values of T" - it's always OK to say "iterator over a stream of T" instead. And the closures might capture values or locations, as performance demands, since the semantics don't change.

Painfully Amateur Philosophy addendum: locations are a pretty physical concept - you know the data is in there in memory somewhere - but values are more of a platonic concept, existing in some pure universe, and we can only refer to them by metaphor and convention by using specific bit patterns interpreted in precise ways. I specifically use the word metaphor in the conceptual metaphor sense: in no way are the electron levels inside the machine representing the ASCII characters of "cat" anything like the furry mammal. Rather, the bit pattern is like a pointer only the human mind can dereference, once it has been transformed into what humans have agreed to be a semantically equivalent representation on screen (which is just a different part of memory) or on paper (which is just bits streamed out over the wire).

Perhaps most people find this obvious and boring, but what interests me is the way the representational power of the bits is entirely unmagical, yet it permits meaning to be stored inside the machine. I say meaning, by which I mean that we humans, the only judges of what is meaningful, find to be meaningful, but no more: I do not think meaning is something inherent in objects, just in judges. What if brains had no more magic in their neurons than the circuits in the machine? (It seems entirely plausible to me, and to many programmers I imagine. And this would constrain those judges to be mere boolean functions over matter patterns.)

In such a scenario, qualia would be beyond our power to deconstruct using physical means, since the brain/machine could be evaluated "on paper", and such an evaluated brain would report the same qualia as you or I, and we would have no way to argue otherwise in a one on one dialogue (this is how I think of the Turing test - as a philosophical concept, not an actual benchmark, which I think is silly and pointless). Under this assumption, there isn't any argument that could prove that the machine isn't conscious which doesn't itself rely on arbitrarily chosen boolean functions which explicitly return false for non-mysterious matter patterns (e.g. capable of "understanding"). Closely related is the problem of other minds, about which I'm on Turing's side - if we can't tell the difference, then there isn't any.

Perhaps consciousness and the experience of qualia is just what matter feels like when it's part of a causal chain? (The technical term, I understand from my Googling, is "type physicalism", though epiphenominalism is related.)

Philosophy over. I need to get back to work :)

Saturday, October 18, 2008

WASD's little known alternative, QWAS

I was reading a review of a new Microsoft gaming keyboard today and I noticed that it has extra highlighting for the traditional WASD keyboard layout most commonly used by first-person shooters (FPSs).

This interests me because I don't use WASD; I use a variant that I have almost never seen anyone else describe, namely, QWAS, with W for forward, Q/S for strafe left/right, and A for reverse.

It was a long time in gestation. I started out playing Doom with just the keyboard, like most other people at the time, but then I read - I forget where and can't find the reference - about using the mouse for looking and the keyboard, specifically the Z and X keys, for strafing, with Space, Ctrl and mouse buttons used in some combination for Use, Fire, Forward, Run, etc. I didn't find this combination especially easy to use, though, so it wasn't long before I stumbled onto the QWAS hold I use today. I do, however, find it puzzling that so few other people use it.

The reason I don't use WASD is because I think the layout is awkward for the wrist when the keyboard is centrally positioned, ready for touch-typing:

Moreover, since, like most men, my ring finger is much longer than my index finger, WASD means my ring finger on the A key is in an uncomfortable cramp-prone position:

When this is compared with the QWAS layout, the advantage in comfort and ergonomics - for my hand shape and keyboard positioning, at least - is clear:

The Search for Differentiation and Build vs Buy/Adopt/Coopt

There's been some chatter in the development blogosphere recently about that old chestnut, the build vs buy decision; but in these days of open source development, there are more alternatives to build: adoption and cooption (private forking / customized modules etc.).

Jeff Atwood wrote an article about not being ashamed to write your own software (i.e. build) when the functionality in question is core to your business. Much of the reaction to Jeff's fairly strongly stated article has been pulling in the opposite direction. I'd like to argue back in Jeff's direction, though.

The basic trouble I have is that the vast majority of open source is crap. Once you tread outside the critical path of high-user-base server-side software, like (to take three examples completely at random) Linux, Hibernate and MySQL, you very quickly get stuck in the mire; even then, much of the "good" open-source software is only good in parts.

For example, if you're looking for a mature, well-designed and stable interface for writing drivers for Linux - exactly what is needed to make supplying binary drivers viable for hardware vendors - tough luck, buddy. Economically speaking, incentives in open source are almost always not aligned with consumers' interests, but rather with the companies which hire the developers: and those guys are usually consultant / service shops, i.e. aligned with corporate customers, not consumers. Firefox is an exception because of Google advertising revenue, which is correlated with consumer adoption, thus their incentives are aligned.

Rails has a solid concept and has a reasonably good API, but its execution is, IMHO, not great. I have little patience for server-side technologies that aren't thread-safe, as request/response cycles are trivially parallel; though, from an historical viewpoint I can understand it, as relatively few scripting languages implement threading. All the same, though, the kind of coding that would make a server-side library thread-unsafe, I wouldn't tolerate even if the platform was single-threaded: it implies poorly-factored mutable global state. I wouldn't touch PHP with a barge pole - I have zero technical respect for the language.

To compete, you need differentiation: you need to do something, for some subset of the market, in a way that is head and shoulders better than every other choice. Open source (or, indeed, buying) can only give you what everyone else has; you need to add in the magic yourself that makes you stand out. Private forks of open-source software are one way of doing that, but is vulnerable to all the usual problems that forking has (staying current, merging bugfixes, divergent evolution, etc.). Creating your differentiating software yourself means your codebase will be smaller and more perfectly adapted to your problem domain, and thus easier to maintain and keep up to date than a private fork of an ongoing public open-source project.

The only real question is which software in your organization is, in the language of strategic management, going to help give you a sustainable competitive advantage. Open source software and third-party libraries can never give you that (unless you own the founding team & brand), because they are equally available to your competitors. Choosing the balance of build vs buy means trading off risk and cost versus lack of differentiation. You have to measure and compare the resources available to you and the risk of non-completion of differentiated software, taking into account opportunity cost, with the lack of differentiation that would come from the buy / ad/coopt decision.

Where the balance lies thus depends on both sides: how much [human+monetary] capital you have, versus the competitive landscape on the other. Whether a third-party library exists or not, in and of itself, is not a sufficient reason to always use it. Making users happy isn't sufficient; you must make them happier than the competition, and that's not going to happen if you don't do something the competition isn't already doing. The only thing that holds you back is risk & capital versus the reward in differentiation.