<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6421990566053383182</id><updated>2012-01-27T05:14:29.103-05:00</updated><category term='Teaching'/><category term='Computing'/><category term='Productivity'/><category term='Language'/><category term='Vision'/><category term='UX'/><category term='Poetry'/><category term='User Interfaces'/><category term='Philosophy'/><category term='Prog'/><category term='Calendars'/><category term='Design'/><category term='Concatenative'/><category term='Iterators'/><category term='Lisp'/><category term='Programming'/><category term='Web'/><category term='Politics'/><title type='text'>The Big Mud Puddle</title><subtitle type='html'>Jon Purdy writes blarticles on computing, language, and design.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>43</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7809135750320006974</id><published>2012-01-25T12:49:00.001-05:00</published><updated>2012-01-25T23:08:37.857-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><category scheme='http://www.blogger.com/atom/ns#' term='Computing'/><title type='text'>Yep, Programming Is Borked</title><content type='html'>I recently read “&lt;a href="http://jonbho.net/2012/01/24/i-want-to-fix-programming/"&gt;I want to fix programming&lt;/a&gt;”, which touches on one of the fundamental problems with programming as we know it. I agree with the author, but I think many of the commenters failed to understand the issue, so I’d like to present it in another way.&lt;br /&gt;&lt;br /&gt;I’ve been programming for a long time, mostly because I’m addicted to solving puzzles. I’m very much into programming languages, partly because as a programmer I’m surrounded by them, but also because language is an important part of what makes us human.&lt;br /&gt;&lt;br /&gt;So while programming is a craft I enjoy, and I love having the power to create awesome stuff practically &lt;i&gt;ex nihilo&lt;/i&gt;, I too am disappointed in what we have to work with. Here’s why.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Process-Oriented versus Result-Oriented&lt;/span&gt; &lt;span style="font-size: large;"&gt;Programming&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Concatenative, functional, object-oriented, logic—whatever paradigm you choose, they all have the same issue: they require that you describe the &lt;i&gt;how&lt;/i&gt; rather than the &lt;i&gt;what&lt;/i&gt;. In any language you can name, a program is a description of the process by which you compute what you want, when it could be just a description of what you want. Sure, some languages are more declarative than others, but &lt;b&gt;this is orthogonal to the issue of “declarative versus imperative”&lt;/b&gt;—a language that expresses a process declaratively is still &lt;i&gt;process-oriented&lt;/i&gt;, not &lt;i&gt;result-oriented&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;That’s the real issue. As programmers, &lt;b&gt;we solve problems using code&lt;/b&gt;. Even a fun problem like “a game like this should exist but doesn’t” is valid. So we should be able to express our code in terms of its intended result, not the process by which that result is attained.&lt;br /&gt;&lt;br /&gt;The author proposes a style of programming based on constraint satisfaction. From a set of constraints, it’s possible to derive an algorithm that meets them. Of course, we naturally worry about the properties of the algorithm the compiler will derive; is it Θ(&lt;var&gt;n&lt;/var&gt;!) when it could be Θ(&lt;var&gt;n&lt;/var&gt; log &lt;var&gt;n&lt;/var&gt;)? But while that is a reasonable worry, it is not—strictly speaking—relevant.&lt;br /&gt;&lt;br /&gt;See, there are many equivalent sets of constraints that define a particular algorithm, and by selecting intelligently from those, we &lt;i&gt;can&lt;/i&gt; be confident that the compiler will derive what we intend. &lt;b&gt;Our job should be to intelligently express requirements as formal constraints&lt;/b&gt; for the compiler to satisfy.&lt;br /&gt;&lt;br /&gt;I know that sounds boring, and I was initially skeptical that useful programs could be made this way. But think about it: &lt;b&gt;every non-trivial program already &lt;/b&gt;&lt;b&gt;is &lt;/b&gt;&lt;b&gt;implemented this way&lt;/b&gt;, just in a slow, error-prone, manual fashion. A programmer takes some requirements, formalises them, then painstakingly translates them into a suitable process. We can avoid one of those steps.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;A Realistic Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Say you’re writing a game. The first thing on your to-do list is to be able to move a character around the screen with the arrow keys. In just about any existing language, you have to construct a bunch of unrelated infrastructure to make this happen:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Transforming continuous physics into a discrete representation&lt;/li&gt;&lt;li&gt;Dealing with issues of frame rates, rendering, and collision&lt;/li&gt;&lt;li&gt;Managing the state and resources of living and dead objects&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;All of this crap is unrelated to just making something that works.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Often, much of this work has already been done for you by a library author, but the fact remains that &lt;i&gt;someone&lt;/i&gt; had to do the busywork. &lt;a href="http://www.haskell.org/haskellwiki/Functional_Reactive_Programming"&gt;Functional reactive programming&lt;/a&gt;, in contrast, gets this right. You can say precisely what you mean:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The character consists of:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Acceleration of ( &lt;var&gt;a&lt;sub&gt;x&lt;/sub&gt;&lt;/var&gt; , &lt;var&gt;a&lt;sub&gt;y&lt;/sub&gt;&lt;/var&gt; )&lt;/li&gt;&lt;li&gt;Velocity of ( &lt;var&gt;v&lt;sub&gt;x&lt;/sub&gt;&lt;/var&gt; , &lt;var&gt;v&lt;sub&gt;y&lt;/sub&gt;&lt;/var&gt; )&lt;/li&gt;&lt;li&gt;Position at ( &lt;var&gt;x&lt;/var&gt;, &lt;var&gt;y&lt;/var&gt; )&lt;/li&gt;&lt;li&gt;Sprite of size ( &lt;var&gt;w&lt;/var&gt;, &lt;var&gt;h&lt;/var&gt; )&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;When an arrow key is pressed, change the acceleration:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Left: ( ‒1, 0 )&lt;/li&gt;&lt;li&gt;Right: ( +1, 0 )&lt;/li&gt;&lt;li&gt;Up: ( 0, ‒1 )&lt;/li&gt;&lt;li&gt;Down: ( 0, +1 )&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Integrate over time: &lt;/li&gt;&lt;ul&gt;&lt;li&gt;Velocity from acceleration&lt;/li&gt;&lt;li&gt;Position from velocity&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The colour of a pixel at ( &lt;var&gt;p&lt;sub&gt;x&lt;/sub&gt;&lt;/var&gt; , &lt;var&gt;p&lt;sub&gt;y&lt;/sub&gt;&lt;/var&gt; ) is:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;If ( &lt;var&gt;p&lt;sub&gt;x&lt;/sub&gt;&lt;/var&gt; , &lt;var&gt;p&lt;sub&gt;y&lt;/sub&gt;&lt;/var&gt; ) is within the sprite ( &lt;var&gt;x&lt;/var&gt;, &lt;var&gt;y&lt;/var&gt;, &lt;var&gt;x&lt;/var&gt; + &lt;var&gt;w&lt;/var&gt;, &lt;var&gt;y&lt;/var&gt; + &lt;var&gt;h&lt;/var&gt; ):&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The colour of the pixel at ( &lt;var&gt;p&lt;sub&gt;x&lt;/sub&gt;&lt;/var&gt; ‒ &lt;var&gt;x&lt;/var&gt;, &lt;var&gt;p&lt;sub&gt;y&lt;/sub&gt;&lt;/var&gt; ‒ &lt;var&gt;y&lt;/var&gt; ) in the sprite&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Otherwise:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The background colour&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;This is a complete, fully declarative, fully &lt;i&gt;result-oriented&lt;/i&gt; description of the program. It contains &lt;i&gt;only&lt;/i&gt; those details that are relevant to the problem at hand, and every detail is expressed as a constraint that can be plugged directly into an FRP system—which is really a simple constraint solver—to derive the runtime behaviour. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;And Whither Hence?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Prolog serves as an example of constraint-based programming, and Haskell FRP libraries are nice, but these are basically just toys compared to what we can do.&lt;br /&gt;&lt;br /&gt;There is no reason we cannot make a better, more result-oriented language, or even just make existing process-oriented languages &lt;i&gt;look&lt;/i&gt; more result-oriented to get some momentum for the paradigm. Take a look at &lt;a href="http://chalicegames.com/swym/SwymWebIntro.html"&gt;Swym&lt;/a&gt; (“Say What You Mean”), where the &lt;code&gt;etc&lt;/code&gt; keyword lets you do things like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;List.byPairs: [[.1st, .2nd], [.3rd, .4th], etc];&lt;br /&gt;byPairs[1..10] == [[1,2],[3,4],[5,6],[7,8],[9,10]];&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Which even does something sane when you give it a different number of arguments:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;[1,2,3].byPairs == [[1,2]];&lt;br /&gt;[1,2].byPairs == [[1,2]];&lt;br /&gt;[1].byPairs == [];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This is really exciting stuff, but &lt;b&gt;it shouldn’t have to be&lt;/b&gt;, and we can do even better. The implementation of a few “magic” operators like &lt;code&gt;etc&lt;/code&gt; and &lt;code&gt;each&lt;/code&gt; could make even an imperative language look much more result-oriented.&lt;br /&gt;&lt;br /&gt;For a while, I was working on a language called Prog. It was to be an imperative language for generic programming, with dependent typing. Many of the magic was implemented with “radioactive types”, unstable types that could exist only during evaluation, which decayed into ordinary types thereafter. These were used, for instance, to implement various query operators on iterable structures:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;which (1..10) &amp;gt; 5 == (6, 7, 8, 9, 10);&lt;br /&gt;each (1..5) ** 2 == (1, 4, 9, 16, 25);&lt;br /&gt;each (1..3) * each (1..3) == ((1,2,3), (2,4,6), (3,6,9));&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;After reading that article and the comments, I’m inspired to work on Prog again, if I can find the time. Expect to see more blarticles about it. A project in the same vein that’s consuming a lot of my energy right now is a tool to help non-programmers make professional-quality interactive media. If you don’t know how to program, you have limited means of creating games and other media applications. All the authoring software that’s out there falls into two categories:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tragically underpowered&lt;/li&gt;&lt;li&gt;Needlessly complicated&lt;/li&gt;&lt;/ul&gt;So, using research into how people best solve problems, I’m making a tool that helps people solve the problem of having an idea and not being able to make it a reality. At the end of the day, that’s a frustration that a lot of programmers face. If as a programmer you feel inspired to contribute, please contact me at &lt;a href="mailto:evincarofautumn@gmail.com"&gt;evincarofautumn@gmail.com&lt;/a&gt;, and I’ll let you know how you can get involved.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7809135750320006974?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7809135750320006974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2012/01/yep-programming-is-borked.html#comment-form' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7809135750320006974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7809135750320006974'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2012/01/yep-programming-is-borked.html' title='Yep, Programming Is Borked'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4192873961684564456</id><published>2011-12-29T19:19:00.000-05:00</published><updated>2011-12-31T02:25:16.159-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Design'/><title type='text'>The Web Is Wrong</title><content type='html'>&lt;span style="font-size: large;"&gt;The Analogies Are Wrong&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Originally, web pages were static documents, and web browsers were static document viewers; there was text, some formatting, and images—if you could pay for the bandwidth to serve them. Hyperlinks were the really big thing, because they were the main point of user interaction—but what a powerful thing they were, and still are.&lt;br /&gt;&lt;br /&gt;Then along came CGI and Java, and the web was transformed: all of a sudden, a web browser became a way to serve interactive content to users. A web page was no longer just a document, but a portal to a living, breathing world. You yourself could make content that would appear on a page for others to see. That was wicked cool, and it’s still a huge part of what makes the web so compelling today.&lt;br /&gt;&lt;br /&gt;The more interactive the web has become, the more it has been used to connect people and their interests—and the less the “document” analogy has applied. At this point, the vast majority of pages that I use on a daily basis are not documents in any real sense: they are &lt;i&gt;applications&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Nobody&lt;/i&gt; refers to Twitter, Google+, Facebook, Stack Exchange, Blogger, or even forums and message boards as &lt;i&gt;documents&lt;/i&gt;. It’s laughable! Not only has the analogy been stretched so far that it’s absurd, but it &lt;i&gt;has been&lt;/i&gt; absurd since about fifteen years ago. But that’s not all.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Human-Readability Is Wrong&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Why  are we still using text-based document formats for all of our web interaction? HTML is fine for writing documents, but why do we actually &lt;i&gt;transmit&lt;/i&gt; it as text? Why do we make software that just writes HTML for us, serving pages to the browser whose source is nigh indecipherable to a human user? What is to be gained from using text-based documents for stylesheets and scripts? Human-readability? Not at all.&lt;br /&gt;&lt;br /&gt;Programmers may be surprised to note that the vast majority of users do not ever view the sources of a web page. They don’t know what makes things tick, they don’t care, and even if they did, they wouldn’t be able to decipher it all without experience, especially if the source had been minified.&lt;br /&gt;&lt;br /&gt;If you’re not yet convinced that this whole situation is outlandishly, hilariously wrong, let’s talk about &lt;a href="http://en.wikipedia.org/wiki/Minification_%28programming%29"&gt;minification&lt;/a&gt;. Minification is taking a text-based document—where the &lt;i&gt;sole reason&lt;/i&gt; for being text-based is human-readability—and compressing it to such an extent that it is no longer human-readable, but still text-based. Now for absolutely no reason whatsoever. Have I made anybody facepalm yet?&lt;br /&gt;&lt;br /&gt;Furthermore, a minified document still has to be parsed according to the rules of the unminified language. This means that minification relies on details of the parser, which for permissive HTML and subtle JavaScript could be fragile and dangerous. In addition, the browser must perform all of the parsing and internal compilation it would for unminified source, causing a totally unnecessary performance hit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;The Obvious Solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At the very least, we should stop serving HTML, CSS, and JavaScript to users. Let’s instead serve things in concise, binary format—&lt;i&gt;compiled&lt;/i&gt; documents and stylesheets, and, by far the most important…&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Compiled JavaScript that runs in a standard stack-based VM&lt;/b&gt;, which, let me stress, could easily be targeted by other languages. Because as if the situation weren’t mad enough, nowadays we write &lt;a href="https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS"&gt; languages that compile to JavaScript&lt;/a&gt;, just so that they can run in a web browser.&lt;br /&gt;&lt;br /&gt;By using binary formats, browsers will be exchanging less &lt;i&gt;data&lt;/i&gt; with servers in order to convey the same &lt;i&gt;information&lt;/i&gt;, improving performance. Web page performance is an important consideration: if your page takes too long to load, no one will bother waiting for it to load, and you’ll lose traffic.&lt;br /&gt;&lt;br /&gt;Serving binary data is just as reliable as serving textual data. The direct source of a page won’t be human-readable, but so what? The source of the desktop applications you use isn’t typically human-readable unless the source is open &lt;i&gt;and&lt;/i&gt; you seek it out. What’s wrong with using the same principle for Web pages? And the compiled version will contain the same data, so you will always be able to see decompiled HTML or CSS if you want it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;The Non-Obvious Solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But there is, in my opinion, an even better solution than that. In order to make a standard-issue web application, you must deal with &lt;i&gt;a minimum of four&lt;/i&gt; languages: HTML, CSS, JavaScript, and a server-side language such as Perl, or Haskell, or whatever you like, really, as long as you can install a toolchain on your server.&lt;br /&gt;&lt;br /&gt;But even if you don’t write one or more of these directly, you must still contend with them, and that becomes problematic when the abstractions leak. This is too complicated. Beginners need consistency, and the majority of developers are always going to be beginners, so we have no choice but to help them.&lt;br /&gt;&lt;br /&gt;The multitude of languages is good, in a way: each language ostensibly serves a single purpose. HTML is for structure and content; CSS, for presentation; JavaScript, frontend interaction; and the server-side language, backend interaction. And the modularity that this brings is, in a way, a good thing. However, you can attain modularity in many sane ways, without defining complete domain-specific languages.&lt;br /&gt;&lt;br /&gt;Moreover, you can do it without necessitating that code in one language be composed and transmitted by another language as text, which is awkward and unsafe. Injection attacks are ubiquitous for a reason.&lt;br /&gt;&lt;br /&gt;So what if, instead of serving content in three languages (plus images and videos and what have you), we were to use &lt;i&gt;just one language&lt;/i&gt; for presentation, styling, and interaction alike? A page would be served as a compiled bundle, and the browser would &lt;i&gt;just run it&lt;/i&gt; in a protected VM. Content that doesn’t need to be loaded asynchronously could just be embedded in the bundle.&lt;br /&gt;&lt;br /&gt;You could then take it a step further: web applications could be treated as sources of interactive, structured information. They could be be queried in structured fashion, vastly simplifying content scrapers; or composed with one another and with desktop applications, using something analogous to pipes. We could create powerful distributed applications, or share data across our networks however we like.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Final Remarks&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is, I believe, an important problem, and one I’m actively trying to solve. If enough people demonstrate interest, maybe we can make this a reality, and give the web the overhaul it needs. Because, at the moment, the web is just plain wrong.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4192873961684564456?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4192873961684564456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/web-is-wrong.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4192873961684564456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4192873961684564456'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/web-is-wrong.html' title='The Web Is Wrong'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7739638374217292032</id><published>2011-12-14T22:54:00.000-05:00</published><updated>2011-12-16T23:22:21.406-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Computing'/><title type='text'>There Are Only Types</title><content type='html'>I never liked object-oriented programming. I started programming half a lifetime ago, and I found object-oriented languages early on, because of their popularity. For the most part I was uncomfortable with them, but it took some time to learn enough about programming to really understand why.&lt;br /&gt;&lt;br /&gt;So I became proficient in Java and C++ and what have you, and I acknowledge that these languages can be useful for some things. If a language has some library that lets you get your task done quicklier or at lower cost, then it’s probably safe to choose it over another language that might be better, in the usual sense of “good” = “expressive”. Quality isn’t the whole story when it comes to quality.&lt;br /&gt;&lt;br /&gt;It wasn’t the many fanatical followers of what seemed more like a radical philosophy than an actual technology that ultimately turned me away from OOP. I realised at some point that the primary reason I disliked that world was the fact that I find it really difficult to decompose the world in terms of objects. Not because I found object-oriented programming difficult; just that I found it unnatural.&lt;br /&gt;&lt;br /&gt;I’ll clarify. An object is an entity that responds to messages and has some internal information. But not all things conceptually talk to one another, nor have state; so I thought this was backward; why think about entities that &lt;i&gt;manifest&lt;/i&gt; qualities, when you can just think about qualities themselves? Why would you declare the contracts (interfaces) between entities before you know if those contracts are true? And most importantly, why would you use two different languages to compute the values and types in one program?&lt;br /&gt;&lt;br /&gt;This is how I—inadvertently—came to independently reinvent the concept of dependent type systems. Values depend on types, which can be verified and manipulated and so forth; but types, too, depend on values, and this reverse relationship is treated in exactly the same way. For a trivial example, in a dependent type system, you can encode the type “list of size N with elements of type T”, or “sorted list” or “balanced tree”. A dependent type system in an imperative language would obviate the need for a lot of explicit imperative implementations of contracts on data structures.&lt;br /&gt;&lt;br /&gt;But I went a step further than that. Conceptually, types tend to be computed as a &lt;i&gt;side-effect&lt;/i&gt; of computation on values. That is, almost any language you can name is interested in computing values, and only verifies types as something of an afterthought—assuming, of course, it verifies types at all. This is true even of languages with very rich type systems such as Haskell.&lt;br /&gt;&lt;br /&gt;But what if, I thought, you were to turn that on its head? I became intrigued with this problem around +37 (2007), I think, and set about designing a language in which, essentially, &lt;i&gt;all terms denote types&lt;/i&gt; and values are computed as a side-effect of reasoning about those types.&lt;br /&gt;&lt;br /&gt;For example, the term “3” is not just the value 3, but a reference to the set of &lt;i&gt;all&lt;/i&gt; underlying values&lt;i&gt; &lt;/i&gt;that are equal to 3. By “underlying value”, I mean machine representation: every possible size and signedness of integer or floating-point number. But, since types were computed non-strictly, the singleton type of 3 could be represented with a regular old machine integer, which would be converted only as needed.&lt;br /&gt;&lt;br /&gt;There are several advantages to dealing with singleton types rather than ordinary values. The first is that value equivalence becomes explicitly type- and context-sensitive, rather than implicitly so; type equivalence behaves similarly if you generalise to singleton kinds. And though it may not be immediately obvious, type checking within a type system based on singleton types &lt;i&gt;is&lt;/i&gt; statically decidable, because singleton types are basically just equivalence classes, and subtypes form proper subsets of those classes. That means, essentially, that we can prove some kinds of extensional equality.&lt;br /&gt;&lt;br /&gt;So singleton types have a few perks, and they coexist nicely with a dependent type system. Unfortunately, dependent types are not statically decidable, because you cannot, in general, prove that two functions are extensionally equal, which is what statically deciding dependent types would require.&lt;br /&gt;&lt;br /&gt;But that’s actually not such a bad thing. In a system with singleton types, the types themselves contain enough information to provide more reasonable diagnostics in the event of a type error. And of course the compiler would not attempt to decide all types statically, but only those which are known to be decidable; the rest would be decided dynamically. Taking this view, static typing can be seen as a constant-folding optimisation, and likewise constant-folding can be seen as a form of static typing, for in this system types and values are one and the same.&lt;br /&gt;&lt;br /&gt;I never did finish the language that would implement these ideas, but I fully intend to. And at the very least, exploring this field gave me some insight and informed my ability to write programs in existing languages. But to this day I have to shake my head at the languages I still use every day, from C++ to Haskell.&lt;br /&gt;&lt;br /&gt;Because they don’t know that there are only types.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7739638374217292032?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7739638374217292032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/there-are-only-types.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7739638374217292032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7739638374217292032'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/there-are-only-types.html' title='There Are Only Types'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7345737974919245322</id><published>2011-12-13T15:26:00.003-05:00</published><updated>2011-12-16T23:22:42.727-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Concatenative'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Concatenative Rant</title><content type='html'>What follows is a rant disguised as a question, which I was going to post on Programmers.SE, but I ultimately thought better. Enjoy. &lt;br /&gt;&lt;br /&gt;Most of our favourite programming languages get lumped into the categories of “imperative” or “functional”. While those paradigms don’t exactly present a &lt;i&gt;complete&lt;/i&gt; picture of what languages are out there—or even how the languages that are out there actually work—they serve to characterise the majority of what we work with on a daily basis. And all is well with the world.&lt;br /&gt;&lt;br /&gt;Except perhaps not. Conceptually speaking, in an imperative language, I order the computer to do what I want; in a functional language, I describe what I want the computer to do. However, in a functional language, I have to contend with more than functions, and the fundamental unit of computation is &lt;i&gt;not&lt;/i&gt; the function, but rather &lt;i&gt;function application&lt;/i&gt; (specifically, beta reduction).&lt;br /&gt;&lt;br /&gt;I can still write useful programs in both kinds of languages, but I find it odd that functional languages get the reputation for purity when I can’t even write most expressions in point-free form.&lt;br /&gt;&lt;br /&gt;Enter &lt;a href="http://en.wikipedia.org/wiki/Concatenative_programming_language"&gt;concatenative languages&lt;/a&gt;. When your programming language is stack-based, you can think of it imperatively: all terms denote imperative operations on stacks. But you can also think about it declaratively: all terms denote functions, the juxtaposition of terms denotes function composition, and a program is just a single large function, written entirely point-free. It’s turtles all the way down.&lt;br /&gt;&lt;br /&gt;That, to me, seems really elegant. It’s the Holy Grail of paradigms: one which is easy to compile, efficient on existing machines, and yet also amenable to straightforward formal analysis. &lt;a href="http://www.cat-language.com/"&gt;Cat&lt;/a&gt;, for instance, is statically typed, with a simple type inference algorithm based on Hindley-Milner.&lt;br /&gt;&lt;br /&gt;And don’t get me started on the opportunities for metaprogramming. In some concatenative languages, I can straightforwardly implement comments, strings, or even numbers as syntactic extensions &lt;i&gt;in the language itself&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;So what gives? Why aren’t these languages everywhere? Is it simply that &lt;b&gt;exceptional languages can’t be popular because most programmers can’t be exceptional?&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7345737974919245322?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7345737974919245322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/concatenative-rant.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7345737974919245322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7345737974919245322'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/concatenative-rant.html' title='Concatenative Rant'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-1745161690870187560</id><published>2011-12-06T11:26:00.001-05:00</published><updated>2011-12-06T14:43:40.194-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Calendars'/><title type='text'>Redefining the Epoch</title><content type='html'>&lt;span style="font-size: large;"&gt;The Internet Calendar&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;In the Gregorian calendar, it is the year 2011 of the Common Era—or Anno Domini if you’re more of a traditionalist. In the Hebrew calendar, it’s 5772 Anno Mundi. In the Chinese calendar, it’s 4708 or 4648—depending on which of the two epochs you prefer. In the Islamic calendar, it’s 1433 Anno Hegirae. And, just for kicks, in the &lt;a href="http://en.wikipedia.org/wiki/Discordian_calendar"&gt;Discordian calendar&lt;/a&gt; it’s 3177 YOLD.&lt;br /&gt;&lt;br /&gt;The epochs of all of these calendars have one thing in common: they refer to important historical events in the cultures that spawned them. But in an era of global communication, they are, for all intents and purposes, &lt;i&gt;completely arbitrary&lt;/i&gt;. We can do better.&lt;br /&gt;&lt;br /&gt;It’s fairly silly that the vast majority of us still cleave to the Gregorian epoch as though it were culturally neutral—because it is assuredly not. Now, there’s nothing &lt;i&gt;wrong&lt;/i&gt; with a Christian epoch for a calendar, as least insofar as there’s nothing inherently wrong with &lt;i&gt;any&lt;/i&gt; particular epoch. But certain dates are certainly more culturally relevant than others, and ours is not an exclusively Christian culture.&lt;br /&gt;&lt;br /&gt;What, then, is the day that started our era?&lt;br /&gt;&lt;br /&gt;My vote is for the day when the Internet—as we would come to know it—came into existence. That day, &lt;b&gt;the 29th of October, 1969&lt;/b&gt;, defines a cultural turning point that has since changed the world in unfathomably many and deep ways.&lt;br /&gt;&lt;br /&gt;The first year following the epoch is +0; the year preceding, −0. The best way to understand this is by thinking of a date as a fractional number of years since the epoch: January 1, 1970 (the epoch for Unix) is +0.1749. Lisp was created in −10.  Keep in mind that I don’t want to change &lt;i&gt;anything&lt;/i&gt; else about our calendar: not our system of months, nor the days of the week, nor the way we calculate leap years. Those all work just fine.&lt;br /&gt;&lt;br /&gt;So, without further ado:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;This is the year +42, and today is the day that I redefined the epoch.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Discuss.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-1745161690870187560?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/1745161690870187560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/redefining-epoch-internet-calendar.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1745161690870187560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1745161690870187560'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/12/redefining-epoch-internet-calendar.html' title='Redefining the Epoch'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5980861686672137604</id><published>2011-11-12T14:19:00.001-05:00</published><updated>2011-11-12T14:40:58.911-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Languages versus Implementations</title><content type='html'>In the world of programming languages, there is a clear distinction between the language itself, and the implementation of the language. There is only one abstract Python, but there are many concrete implementations of Python. Only one Haskell, but several implementations thereof.&lt;br /&gt;&lt;br /&gt;However, this is a false dichotomy. Each implementation is &lt;i&gt;necessarily&lt;/i&gt; different from the others, mainly because implementing an identical specification in identical fashion is boring and doesn’t solve any problems.&lt;br /&gt;&lt;br /&gt;Outside of those implementations we make as a learning process, we programmers typically create new implementations of existing languages in search of better performance or better user experience. I don’t expect anyone to agree with me that changing the performance characteristics of a language is the same as a change to the language, but that is what I believe.&lt;br /&gt;&lt;br /&gt;More importantly, the implementors of a language will often try to make their implementation stand out as more productive, more useful to the programmer, by adding &lt;i&gt;extensions&lt;/i&gt;. Whether or not these extensions are intended for widespread adoption by other implementations, and whether you call them extensions or pragmas or whatever else, the effect is the same. A program that is accepted by one implementation is either &lt;i&gt;not accepted&lt;/i&gt; by another, or it &lt;i&gt;runs differently&lt;/i&gt; under the different implementations.&lt;br /&gt;&lt;br /&gt;The moment this happens, the two implementations are implementing different languages—with a lot of overlap, certainly, but nevertheless distinct. This divergence happens inadvertently as well: because of bugs, one implementation will likely fail or produce incorrect output for a program that another implementation handles just fine, and vice versa. These are still, by the same reasoning, implementing different languages.&lt;br /&gt;&lt;br /&gt;So next time you go to accuse someone of conflating the theoretical and the practical, consider that they may simply be ignoring theory for the sake of practicality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5980861686672137604?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5980861686672137604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/11/languages-versus-implementations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5980861686672137604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5980861686672137604'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/11/languages-versus-implementations.html' title='Languages versus Implementations'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-1101617096485743787</id><published>2011-11-03T18:45:00.000-04:00</published><updated>2011-11-03T18:47:55.143-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Productivity'/><title type='text'>What’s My Best Time of Day?</title><content type='html'>Since I find myself quite suddenly in my last year of college, I now realise that I have access to something unique and oddly exciting: statistics about my college career. I decided to take a look at my grade data for the past few years, and see if I couldn’t discern a few things:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;How much did my inability to get up early affect my grades?&lt;/li&gt;&lt;li&gt;What are the hours at which I am most capable of productive work?&lt;/li&gt;&lt;li&gt;How much does what I’m learning affect my grades?&lt;/li&gt;&lt;li&gt;In what seasons am I most productive?&lt;/li&gt;&lt;li&gt;What is the best amount of work per week for me?&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;The results were really interesting. First, I grouped classes by &lt;b&gt;the time the class started&lt;/b&gt;, and calculated the average weighted GPA (0.0–4.0) for each group. The chart below shows that I am neither a morning nor an evening person—midday and midafternoon are when I do my best work, but right after lunch, I’m apparently just as useless as in the morning.&lt;br /&gt;&lt;br /&gt;&lt;script src="//ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js" type="text/javascript"&gt; {"dataSourceUrl":"//docs.google.com/spreadsheet/tq?key=0AnAvUQIehWVedEJTZDRlTC15RURBenU5Q0ZIbjU4cWc&amp;transpose=0&amp;headers=1&amp;range=A1%3AB10&amp;gid=0&amp;pub=1","options":{"series":{"0":{"color":"#cc0000"}},"reverseCategories":false,"curveType":"","titleX":"Hour","backgroundColor":"#ffffff","pointSize":"7","width":600,"lineWidth":2,"logScale":false,"hasLabelsColumn":true,"hAxis":{"maxAlternations":1},"vAxes":[{"title":"GPA","minValue":2,"viewWindowMode":"explicit","viewWindow":{"min":2,"max":4},"maxValue":4},{"viewWindowMode":"pretty","viewWindow":{}}],"title":"GPA by Starting Hour of Class","height":266,"interpolateNulls":false,"legend":"none","reverseAxis":false},"state":{},"chartType":"LineChart","chartName":"Chart 1"} &lt;/script&gt;&lt;br /&gt;Next, I grouped classes by my subjective impression of &lt;b&gt;how much I learned&lt;/b&gt;. This was less interesting: like most people, I do best when I’m learning something, but also fine when the work is easy.&lt;br /&gt;&lt;br /&gt;&lt;script src="//ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js" type="text/javascript"&gt; {"dataSourceUrl":"//docs.google.com/spreadsheet/tq?key=0AnAvUQIehWVedEJTZDRlTC15RURBenU5Q0ZIbjU4cWc&amp;transpose=0&amp;headers=1&amp;range=C1%3AD4&amp;gid=0&amp;pub=1","options":{"vAxes":[{"title":"GPA","minValue":2,"viewWindowMode":"explicit","viewWindow":{"min":2,"max":4},"maxValue":4},{"viewWindowMode":"pretty","viewWindow":{}}],"series":{"0":{"color":"#cc0000"}},"reverseCategories":false,"title":"GPA by Amount Learned","titleX":"Amount Learned","backgroundColor":"#FFFFFF","legend":"none","logScale":false,"reverseAxis":false,"hAxis":{"maxAlternations":1},"hasLabelsColumn":true,"isStacked":false,"width":600,"height":266},"state":{},"chartType":"ColumnChart","chartName":"Chart 2"} &lt;/script&gt;&lt;br /&gt;Then I discovered something quite counter to my expectations. When I grouped my grades by &lt;b&gt;season of the year&lt;/b&gt;, I had thought winter would be my worst quarter, because of the stress and lack of sunlight. It turns out that my grades tell a different story:&lt;br /&gt;&lt;br /&gt;&lt;script src="//ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js" type="text/javascript"&gt; {"dataSourceUrl":"//docs.google.com/spreadsheet/tq?key=0AnAvUQIehWVedEJTZDRlTC15RURBenU5Q0ZIbjU4cWc&amp;transpose=0&amp;headers=1&amp;range=E1%3AF4&amp;gid=0&amp;pub=1","options":{"vAxes":[{"title":"GPA","minValue":2,"viewWindowMode":"explicit","viewWindow":{"min":2,"max":4},"maxValue":4},{"viewWindowMode":"pretty","viewWindow":{}}],"series":{"0":{"color":"#cc0000"}},"reverseCategories":false,"title":"GPA by Quarter","titleX":"Quarter","backgroundColor":"#FFFFFF","legend":"none","logScale":false,"hasLabelsColumn":true,"hAxis":{"maxAlternations":1},"reverseAxis":false,"isStacked":false,"width":600,"height":266},"state":{},"chartType":"ColumnChart","chartName":"Chart 3"} &lt;/script&gt;&lt;br /&gt;I don’t know why this is, but my hunch was that &lt;b&gt;I work better under stress&lt;/b&gt;. Autumn and spring are my favourite seasons, when I feel happiest. To test this hypothesis from a different angle, I grouped quarters by &lt;b&gt;number of hours per week&lt;/b&gt; of class time.&lt;br /&gt;&lt;br /&gt;&lt;script src="//ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js" type="text/javascript"&gt; {"dataSourceUrl":"//docs.google.com/spreadsheet/tq?key=0AnAvUQIehWVedEJTZDRlTC15RURBenU5Q0ZIbjU4cWc&amp;transpose=0&amp;headers=1&amp;range=G1%3AH9&amp;gid=0&amp;pub=1","options":{"series":{"0":{"color":"#cc0000"}},"reverseCategories":false,"titleX":"Hours","backgroundColor":"#FFFFFF","pointSize":"7","logScale":false,"hAxis":{"maxAlternations":1},"hasLabelsColumn":true,"vAxes":[{"title":"GPA","minValue":2,"viewWindowMode":"explicit","viewWindow":{"min":2,"max":4},"maxValue":4},{"viewWindowMode":"pretty","viewWindow":{}}],"title":"GPA by Hours per Week of Class","legend":"none","reverseAxis":false,"isStacked":false,"width":600,"height":266},"state":{},"chartType":"AreaChart","chartName":"GPA by Hours"} &lt;/script&gt;&lt;br /&gt;Apparently, when given a sane amount of work, I do fine. Past a certain point I can’t keep up, but then, beyond that threshold of stress, my performance improves significantly. Really weird stuff.&lt;br /&gt;&lt;br /&gt;I hope to be able to apply this information to &lt;b&gt;make my life easier&lt;/b&gt; and perhaps &lt;b&gt;get more things done&lt;/b&gt;. If you can obtain hard data about your work habits, you can derive a surprising amount of useful information about how you can improve them. That in turn will make it easier for you to be productive. Try it—you’ll like it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-1101617096485743787?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/1101617096485743787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/11/what-is-my-best-time-of-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1101617096485743787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1101617096485743787'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/11/what-is-my-best-time-of-day.html' title='What’s My Best Time of Day?'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-870003870077091714</id><published>2011-10-19T17:45:00.003-04:00</published><updated>2011-11-04T13:12:08.119-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='UX'/><title type='text'>Programming Languages Suck at UX</title><content type='html'>I wish I could say that programming languages are notorious for their terrible usability—unfortunately, very few people seem to have noticed, and those that &lt;i&gt;have&lt;/i&gt; noticed don’t seem to be particularly upset about it. Frankly, that pisses me off, so I’m going to rant about it, and hopefully give the problem some of the notoriety it deserves. I’d like to point out that this is by no means an exhaustive list of the (many, many) problems with programming languages!&lt;br /&gt;&lt;br /&gt;(If you don’t have the time or desire to read all of the ranting, at least skim the boldfaced points. There’s some good stuff in there.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;The Humanity!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When it comes to any kind of functional design, user experience is not just some tangential concern: it is of &lt;i&gt;the utmost importance&lt;/i&gt;.&lt;span style="font-size: small;"&gt; &lt;/span&gt;The moment you make a design choice that doesn’t benefit the user, you’re doing it &lt;i&gt;wrong&lt;/i&gt;, and your design will be &lt;i&gt;bad&lt;/i&gt;. I’ll get more articulate in a minute, but first I want to admonish all language designers. You are wrong and bad.&lt;br /&gt;&lt;br /&gt;We’re all guilty of it. No one can design something useful that will satisfy &lt;i&gt;everybody’s&lt;/i&gt; expectations. But we can avoid making language design choices that benefit the computer without benefiting the programmer—such choices are nonsensical and absurd.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;&lt;span style="font-size: small;"&gt;If you’re not designing for humans, why are you designing at all? &lt;/span&gt;&lt;/b&gt;♦&lt;br /&gt;&lt;br /&gt;That doesn’t mean we shouldn’t explore new computational paradigms, new ways of reasoning about and optimising programs. What it means is that we should do so in the spirit of making programming easier and more enjoyable, so that developers can focus on the problems that they want to solve, rather than the linguistic obstacles that get in their way.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Non-linguistic Languages&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I find it baffling that most designers of &lt;i&gt;programming languages&lt;/i&gt; give no concern to the &lt;i&gt;language&lt;/i&gt; aspect. We are linguistic creatures by nature, and we have strong intuitions about how language is supposed to work.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Larry_Wall"&gt;Larry Wall&lt;/a&gt; is a notable (partial) exception to the norm, appropriate considering he studied linguistics back in the day. Perl is what you might call a semi-naturalistic programming language. This has nothing to do with “natural-language programming”, which is largely bunk: natural language itself is not suitable for programming computers any more than Nahuatl is suitable for talking to a Welshman.&lt;br /&gt;&lt;br /&gt;A naturalistic language, then, is one that exhibits &lt;i&gt;usability&lt;/i&gt; characteristics of natural languages. I’ll wager that everyone’s first languages are either spoken or signed, followed shortly by the written forms (if any) of those languages. A second language can be much easier to learn if it is more similar to your native tongue, and I think this holds for programming languages as well.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;We learn new things in terms of what we already know.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;One of my favourite things about Perl (well, &lt;a href="http://en.wikipedia.org/wiki/Perl_6#Sigil_invariance"&gt;not Perl 6&lt;/a&gt;) is the fact that it has &lt;a href="http://en.wikipedia.org/wiki/Noun_class"&gt;noun classes&lt;/a&gt;, inflected with &lt;a href="http://en.wikipedia.org/wiki/Sigil_%28computer_programming%29"&gt;sigils&lt;/a&gt; (basically typed dereferencing operators). &lt;code&gt;$x&lt;/code&gt; (“the scalar x”) is a completely different thing from &lt;code&gt;@x&lt;/code&gt; (“the array x”), which too is a completely different thing from &lt;code&gt;%x&lt;/code&gt; (“the &lt;a href="http://en.wikipedia.org/wiki/Hash_table"&gt;hash&lt;/a&gt; x”). Agreement in type is analogous to grammatical agreement in number or gender, which is very common in human language.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;Different things should look different; related things, related.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;Another thing Perl mimics in natural language is implicit reference. &lt;code&gt;$_&lt;/code&gt; is like the pronoun “it”, a default thing, the current subject of discussion, which in many situations can be assumed. Programming languages use explicit reference almost exclusively. In order to perform a series of operations on a value, the programmer must &lt;i&gt;explicitly name&lt;/i&gt; that value for &lt;i&gt;every operation&lt;/i&gt;. Oddly enough, this is even the case in the highly English-like &lt;a href="http://inform7.com/"&gt;Inform&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In one of the object-oriented languages of which everyone seems to be so fond, this could be as simple as keeping track of the current object “under discussion” and allowing it to be assumed where an object would otherwise be expected.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;Languages should let us elide repetition. &lt;/b&gt;♦&lt;br /&gt;&lt;br /&gt;One thing I like about concatenative languages such as Forth and Factor is that there is essentially no named state—you can create variables as a convenience, but at the heart of it, everything is just dataflow.&lt;br /&gt;&lt;br /&gt;Computer languages are (characteristically) so wholly unlike and inferior to natural language that it’s almost comical to call them languages at all. You express ideas every day in your native tongue that have no analogue in any programming language in existence. In most languages, you can apply productive rules to derive new terms, whereas basically all programming languages are purely &lt;a href="http://en.wikipedia.org/wiki/Isolating_language"&gt;isolating&lt;/a&gt; with positional syntax.&lt;br /&gt;&lt;br /&gt;Naturalistic programming languages will never be pretty. They are not minimal, or elegant, or simple, but despite all that, they are intuitive and useful. More importantly, they meet users’ expectations about how language is supposed to work.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;Humans have expectations. Do not judge them; only exploit them.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;All of the “ugly” features of natural languages evolved for specific reasons, and the designs that evolution has wrought can be borrowed to create better designs for our artificial languages.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Erroneous Errors&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Real-world languages have loads of redundancy, which greatly improves error recovery; a programming language with judicious syntactic redundancy can issue warnings instead of errors for imperfect but understandable input, improving the user’s experience.&lt;br /&gt;&lt;br /&gt;If a compiler &lt;i&gt;can&lt;/i&gt; deliver detailed diagnostic messages, then it &lt;i&gt;must&lt;/i&gt; do so; if there is not enough information to provide a meaningful diagnostic, then it shouldn’t provide any more information than is relevant to the programmer.&lt;br /&gt;&lt;br /&gt;If I write &lt;code&gt;int f(X x)&lt;/code&gt;, where &lt;code&gt;X&lt;/code&gt; is an undeclared type, the compiler should &lt;i&gt;not&lt;/i&gt; do what GCC does, which is to write the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;error: expected ‘)’ before ‘x’&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This tells me &lt;i&gt;nothing&lt;/i&gt; about what is actually wrong, but in an effort to be specific, it gives me &lt;i&gt;misleading&lt;/i&gt; specific information. If I were to insert &lt;code&gt;)&lt;/code&gt; before &lt;code&gt;x&lt;/code&gt;, I would then get:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;error: expected declaration specifiers before ‘x’&lt;/pre&gt;&lt;br /&gt;Followed by further, largely nonsensical errors that depend on what follows the declaration of &lt;code&gt;f()&lt;/code&gt;. It should say either something both specific and helpful, such as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;error: use of undeclared type ‘X’ in parameter list of function ‘f’&lt;/pre&gt;&lt;br /&gt;Or, if that is not possible, then at least something not so specific that it becomes incorrect:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;error: the parameter list of function ‘f’ is invalid&lt;/pre&gt;&lt;br /&gt;♦ &lt;b&gt;Errors should be useful, or vague enough not to be misleading.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;This is not just an implementation issue. Languages are often structured in such a way that it is very difficult to provide meaningful error messages, because constructs are too context-dependent or informationally sparse to obtain a meaningful message from an appropriately narrow and targeted view of the source.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Terrible Typography&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most programmers don’t seem to care about legibility. If they did, they would probably be angry that we still use fixed-width fonts for programming. Our programming languages aren’t designed in such a way that they look any good in proportional-width fonts, and monospaced fonts are needed to carry out tabular formatting in editors that don’t support &lt;a href="http://nickgravgaard.com/elastictabstops/"&gt;the sanest known way to handle tabulation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Sigh. At least most of us agree that it’s a good idea to keep code width low. It is a bit sad, though, that we call the rule of thumb the “80-column rule”.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;I yearn for the day when we measure code width in ems.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;Monospaced fonts arose in the first place due to technical limitations: first, because typewriters could only move a fixed distance per character typed, and second, because it was easier to address characters on a graphical display as a regular grid of fixed-size sprites. Fixed-width fonts are a typographical oddity that survived through tradition and little else. &lt;br /&gt;&lt;br /&gt;Programming notation is the way it is primarily because of the fallacy that programming is mathematics. In reality, writing software is also very much like, well, writing.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;Programming &lt;/b&gt;&lt;b&gt;notation should evoke mathematics and prose alike.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;In prose, for example, punctuation merely &lt;i&gt;explicates&lt;/i&gt; the structure and organisation of the text, and gives hints as to cadence and prosody. In programming languages, as in mathematics, punctuation abbreviates common operations—but it is also abused to stand in for structures that, in mathematical notation, would ordinarily be indicated with richer formatting.&lt;br /&gt;&lt;br /&gt;The formatting problem is a side-effect of the fact that we still live in the Stone Age when it comes to our notational character set. No offense to ASCII, but it was already showing its age in the late 80s when Unicode showed up.&lt;br /&gt;&lt;br /&gt;But thanks to the peculiar tenacity of fixed-width typefaces, most programming languages can still be comfortably written &lt;i&gt;on a 50-year-old typewriter&lt;/i&gt;. How’s that for backward compatibility?&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Impossible Input Methods&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;On account of the limited circa-1960 palette of characters we use in our languages&lt;/span&gt;, we’re constantly making notational compromises, approximating glyphs with digraphs and trigraphs. Should “&lt;code&gt;&amp;lt;=&lt;/code&gt;” really mean “≤” when it actually looks like “⇐”?&lt;br /&gt;&lt;br /&gt;When I tutored computer science, I saw students write &lt;code&gt;=&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;gt;=&lt;/code&gt; many a time, because they expected the &lt;i&gt;conceptual&lt;/i&gt; reverse of &lt;code&gt;&amp;lt;=&lt;/code&gt; to be the &lt;i&gt;visual&lt;/i&gt; reverse of it, as with ≤ and ≥. Similarly, the students frequently confused the left and right sides of assignment—i.e., they would write &lt;code&gt;y = x&lt;/code&gt; when they meant &lt;code&gt;x = y&lt;/code&gt;—because with “&lt;code&gt;=&lt;/code&gt;” there is no visual indication of the direction of assignment, nor of the fact that mutating assignment is &lt;i&gt;not&lt;/i&gt; the same as mathematical equality.&lt;br /&gt;&lt;br /&gt;Why don’t we use hyphens for hyphenation, minus signs for subtraction, and dashes for ranges, instead of the hyphen-minus for all three? Why do we use straight quotes (&lt;code&gt;""&lt;/code&gt;) when curved quotes (&lt;code&gt;“”&lt;/code&gt;) can be nested (or contain straight quotes) without escaping? There’s a wealth of time-tested typographical convention in both mathematics and prose that programming language designers simply &lt;i&gt;discard&lt;/i&gt; without a second thought. &lt;i&gt;Without a first thought.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;Throw away &lt;/b&gt;&lt;b&gt;traditions&lt;/b&gt;&lt;b&gt;that don’t &lt;/b&gt;&lt;b&gt;work&lt;/b&gt;&lt;b&gt;; respect those that do&lt;/b&gt;&lt;b&gt;.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;These compromises &lt;i&gt;would&lt;/i&gt; be totally unnecessary thanks to Unicode, but our editors and input methods lag so far behind that it’s still infeasible to comfortably enter many non-ASCII characters without dedicated editor support.&lt;br /&gt;&lt;br /&gt;And no such support exists, because a language that uses “&lt;code&gt;-&amp;gt;&lt;/code&gt;”, which can be written in any editor, is more marketable than one that uses “→” and relies (however little!) on outside tools. On Linux I can use a compose key, which is only a mild inconvenience, but on Windows I’m stuck with Alt codes or Character Map.&lt;br /&gt;&lt;br /&gt;We value terseness in a language because it increases the information density of the code, so we can work with more meaning at once, both per screen and per brain. Punctuation symbols are generally the most concise way to express a concept, and &lt;i&gt;some&lt;/i&gt; symbolic notation in a language is absolutely good, insofar as it reduces cognitive load and eye movement. But the legibility of a punctuation-heavy language suffers just as greatly as that of one without any punctuation at all.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;The Fear&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Perhaps the biggest problem with programming language design is that, because it is so bad, people are &lt;i&gt;afraid&lt;/i&gt; to use tools that can help them. They are &lt;i&gt;afraid&lt;/i&gt; of the whitespace sensitivity of Python, because they &lt;i&gt;assume&lt;/i&gt; it will violate their expectations, and therefore cause them a hassle. In reality, whitespace sensitivity in Python and Haskell are totally innocuous, and actually quite helpful—because they are designed with some thought behind them.&lt;br /&gt;&lt;br /&gt;♦ &lt;b&gt;When you only know the bad, you quietly assume all things are bad.&lt;/b&gt; ♦&lt;br /&gt;&lt;br /&gt;It’s no wonder people stick so tenaciously to a single language or language family. Their expectations were violated time and again when they were learning how to program, so they assume that learning a new language is always like that—and sadly, it often is. They don’t want their expectations to be violated again, so they stick to what they know. Even if it’s bad, at least it’s familiar.&lt;br /&gt;&lt;br /&gt;We need to get rid of that kind of thinking—not just so that language design can move forward, but so that we can quit worrying about languages and &lt;i&gt;get shit done&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-870003870077091714?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/870003870077091714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/programming-languages-have-bad-user.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/870003870077091714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/870003870077091714'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/programming-languages-have-bad-user.html' title='Programming Languages Suck at UX'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-8676692883824945939</id><published>2011-10-15T17:54:00.004-04:00</published><updated>2011-10-15T17:54:37.108-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>Tabs vs. Spaces? I’ll Do You One Better</title><content type='html'>Now, I don’t ordinarily like to get involved in holy wars, because arguing about programming serves largely to waste time that could be spent &lt;i&gt;actually&lt;/i&gt; programming. But I’m making an exception in this case in order to make, shall we say, a modest proposal.&lt;br /&gt;&lt;br /&gt;While doing research for an article, I rediscovered &lt;a href="http://nickgravgaard.com/elastictabstops/"&gt; elastic tabstops&lt;/a&gt;, which are a fairly sane way of managing indentation and tabulation, especially if you like to use proportional-width fonts for programming. Unfortunately, it’s not as widely implemented as it ought to be, and the reference implementation (a gedit plugin) leaves something to be desired in terms of efficiency.&lt;br /&gt;&lt;br /&gt;The search for an Emacs implementation (which, sadly, proved fruitless) led me to all kinds of juicy “discussions” concerning the merits of tabs versus spaces. There are many arguments for both, but summarising and responding to them are beyond the scope of this article.&lt;br /&gt;&lt;br /&gt;The peculiar thing to me was that people kept stressing the &lt;i&gt;semantic&lt;/i&gt; nature of the tab character versus the space character. In typewriter terms, spaces are for moving the cursor a fixed width, while tabs are for moving until the next tabstop.&lt;br /&gt;&lt;br /&gt;On a typewriter and in word-processing programs, you can easily change the global positions of the tab stops, but formatting code is a subtler problem, and I think, as long as we’re sticking to tabs versus spaces, elastic tabstops &lt;i&gt;are&lt;/i&gt; the best solution.&lt;br /&gt;&lt;br /&gt;But who says we &lt;i&gt;must&lt;/i&gt; stick to just tabs and spaces? There are plenty of other ASCII control characters that just sit around doing nothing these days; why don’t we repurpose them? As long as we’re thinking semantically, the ASCII control characters offer some interesting possibilities in the way of code formatting and semantic markup:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;HT (Horizontal Tabulation)&lt;/b&gt; would be used &lt;i&gt;only&lt;/i&gt; for formatting of tabular data, in the same manner as elastic tabstops—but &lt;i&gt;never&lt;/i&gt; for indentation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;VT (Vertical Tabulation)&lt;/b&gt; would serve to terminate rows in tabular data, allowing table cells to vary in height, e.g., by containing linefeeds.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;SI (Shift In) and SO (Shift Out)&lt;/b&gt; could be repurposed to mark increases and decreases, respectively, in indentation. This has the benefit of not &lt;i&gt;requiring&lt;/i&gt; indentation characters to be repeated at the start of every line, but the redundancy of doing so would improve degradation for tools that rely heavily on indentation, such as Python.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;BS (Backspace)&lt;/b&gt; would appear at the beginning of a line to “dedent” code such as a line or case label in C, which is subordinate to its parent, yet not equal to its siblings.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;FF (Form Feed)&lt;/b&gt; could separate logical sections of code, and thus be used like the “region” markers available in many IDEs. You still see some old source files with this convention from time to time.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;US, RS, and GS (Unit, Record, and Group Separators)&lt;/b&gt; could provide further logical division of code, or  semantically mark up data types and their related operations.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;And that’s just in the C0 range. Consider the possibilities with some control codes from the C1 set:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;BPH (Break Permitted Here)&lt;/b&gt; would indicate where lines should be wrapped before other text-wrapping methods are applied. This would eliminate the need to manually insert linefeeds to break long lines.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;NBH (No Break Here)&lt;/b&gt; like its cousin above, would provide an otherwise absent means of indicating that no line break is to be inserted at the current position.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;SSA and ESA (Start and End of Selected Area)&lt;/b&gt; could be used by editors to save the current selection, preserving editor state in a central location in the file.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTS and VTS (Horizontal and Vertical Tabulation Set)&lt;/b&gt; would cause a tabstop to be set at the current position, overriding the automatic behavior of the elastic tabstops.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTJ (Horizontal Tabulation with Justification)&lt;/b&gt; would produce a right-aligned rather than left-aligned field in a table.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;PLD and PLU (Partial Line Down and Up)&lt;/b&gt; could automatically produce rich formatting for subscripts and superscripts.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Imagine just throwing a few simple control characters in your files, and being able to interact with beautifully typeset, richly formatted code, with all styling defined by local CSS so you never have to see code formatted in a way you don’t like.&lt;br /&gt;&lt;br /&gt;Control characters have the advantage of being immune to interpretation by a lot of tools. Existing editors and compilers would need only minimal changes to accept code with semantic markup. An appropriately designed editor could even convert code on the fly for backward compatibility with unmodified compilers.&lt;br /&gt;&lt;br /&gt;I hope you get that I’m not &lt;i&gt;really&lt;/i&gt; serious about this—an earnest proposal for something as broad as “inline language-agnostic semantic code markup” would need to take a &lt;i&gt;lot&lt;/i&gt; more into consideration than some old telecom codes.&lt;br /&gt;&lt;br /&gt;I think many would agree that the &lt;i&gt;idea&lt;/i&gt; has some merit, but few would agree on any &lt;i&gt;particular&lt;/i&gt; implementation of it. Then again, who knows? Literate programming has its adherents, and that’s not so very different in spirit.&lt;br /&gt;&lt;br /&gt;(Oh, and for the love of all that is holy, don’t anybody get the idea that comments containing HTML or LaTeX or whatever would be a good solution. Just try it and see how far you get.)&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-8676692883824945939?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/8676692883824945939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/tabs-vs-spaces-ill-do-you-one-better.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/8676692883824945939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/8676692883824945939'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/tabs-vs-spaces-ill-do-you-one-better.html' title='Tabs vs. Spaces? I’ll Do You One Better'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5109467882252567492</id><published>2011-10-08T14:23:00.004-04:00</published><updated>2011-10-08T14:38:23.536-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Productivity'/><title type='text'>Please Write More Crappy Productivity Articles</title><content type='html'>Every article about productivity is either crappy or excellent. If it’s excellent, I read it all the way through in order to absorb every detail about how I can get more things done—in doing so, I get nothing done. If, however, the article sucks, then I quit reading it immediately and go work on something I care about.&lt;br /&gt;&lt;br /&gt;For me, then, good articles about productivity are usually counter to my productivity, and crappy articles are helpful. I’m so disgusted with them that I can’t help but want to work on something to counteract the time I lost by starting to read them.&lt;br /&gt;&lt;br /&gt;Therefore, bloggers, please write more crappy productivity articles, so I can get shit done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5109467882252567492?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5109467882252567492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/please-write-more-crappy-productivity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5109467882252567492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5109467882252567492'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/please-write-more-crappy-productivity.html' title='Please Write More Crappy Productivity Articles'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-638611985992268417</id><published>2011-10-08T13:28:00.001-04:00</published><updated>2011-10-08T15:14:18.874-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>Regexes Parse XML Just Fine, Actually</title><content type='html'>Despite what you may believe, or may have heard from a particular famous Lovecraftian &lt;a href="http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454"&gt;answer&lt;/a&gt; on Stack Overflow, you can actually use regular expressions to parse arbitrary XML. Of course, they’re not regular expressions in the strict mathematical sense, but rather in the sense with which most of us are familiar—Perl regexen.&lt;br /&gt;&lt;br /&gt;This relies on a seemingly little-known but tremendously handy feature of Perl regular expressions: &lt;code&gt;(?N)&lt;/code&gt; will recursively match an instance at the current position of whatever is in capture group &lt;code&gt;N&lt;/code&gt;. This lets you recursively match delimiters, limited to a depth of 50 unless you build yourself a special Perl.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;only&lt;/i&gt; bit you can’t do in the regular expression engine itself is assert that the names of two matching tags are equal, because you can’t match backreferences in recursive submatches. This isn’t a problem if you assume your input is well-formed. I’m talking about parsing &lt;i&gt;XML&lt;/i&gt;, not checking whether some input actually &lt;i&gt;is&lt;/i&gt; XML. &lt;a href="http://evincarofautumn.blogspot.com/2011/10/correctness-is-boolean.html"&gt;Correctness is a Boolean&lt;/a&gt;, after all: invalid XML is not XML.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I wrote a quick Perl script to demonstrate this using a number of test strings, both those well formed and those less than perfect. This was in part because I feel like doing “impossible” things lately, and in part because I wanted to brush up on my Perl. The point of it is not to be a good solution, but rather the opposite: there is a certain joy in getting something to work in &lt;i&gt;completely the wrong way&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Anyway, the body of it goes like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;my $element = qr{ ( $STag ( $CharData? (?: $Reference | $CDSect | $PI&lt;br /&gt;    | $Comment | (?1) )* $CharData? ) $ETag ) }sx;&lt;br /&gt;                 # ^&lt;br /&gt;                 # The morsel that matches $element recursively.&lt;br /&gt;&lt;br /&gt;my @stack = '&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Title&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Lies.&amp;lt;/h1&amp;gt;'&lt;br /&gt;    . '&amp;lt;p&amp;gt;&amp;lt;i&amp;gt;You&amp;lt;/em&amp;gt;, my friend, have been told them.&amp;lt;/p&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;';&lt;br /&gt;&lt;br /&gt;$" = "\n\n";&lt;br /&gt;while (@stack) {&lt;br /&gt;    my $string = shift @stack // '';&lt;br /&gt;    my @groups = $string =~ m/$element/g;&lt;br /&gt;    print "@groups\n\n" if @groups;&lt;br /&gt;    unshift @stack, map {&lt;br /&gt;        s/^&amp;lt;($Name)(?:$S*$Attribute)*$S?&amp;gt;//; my $a = $1;&lt;br /&gt;        s/&amp;lt;\/($Name)$S*&amp;gt;$//;                 my $b = $1;&lt;br /&gt;        $a eq $b ? $_ : undef&lt;br /&gt;    } @groups;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This recursively enumerates all tags and their contents in some rough semblance of hierarchical order:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;&amp;lt;html&amp;gt;…&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;head&amp;gt;…&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;…&amp;lt;/body&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;head&amp;gt;…&amp;lt;/head&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;title&amp;gt;…&amp;lt;/title&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;body&amp;gt;…&amp;lt;/body&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;h1&amp;gt;…&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;…&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;h1&amp;gt;…&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;Lies.&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;p&amp;gt;…&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;i&amp;gt;…&amp;lt;/em&amp;gt;, my friend, have been told them.&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;i&amp;gt;…&amp;lt;/em&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;You&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;title&amp;gt;…&amp;lt;/title&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;Title&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;Here for your enjoyment is the script in its entirety, which ought to match all matched tags that are valid according to the XML specification, including weird tag names, comments, &lt;code&gt;&amp;lt;![CDATA[...]]&amp;gt;&lt;/code&gt;, and all that other fun stuff.&lt;br /&gt;&lt;br /&gt;I’m admittedly unsure of whether the rules involving lookahead and lookbehind actually match the spec, but it was what came to mind. The rules in question are &lt;code&gt;$CData&lt;/code&gt;, &lt;code&gt;$CharData&lt;/code&gt;, &lt;code&gt;$PITarget&lt;/code&gt;, &lt;code&gt;$PI&lt;/code&gt;, and &lt;code&gt;$Comment&lt;/code&gt; (but they seem to work okay from what little testing I’ve done).&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;&lt;br /&gt;use warnings;&lt;br /&gt;use strict;&lt;br /&gt;&lt;br /&gt;my $S = qr{ \x20 | \x09 | \x0D | \x0A }x;&lt;br /&gt;&lt;br /&gt;my $NameStartChar = qr{ : | [A-Z] | _ | [a-z] | [\xC0-\xD6] | [\xD8-\xF6]&lt;br /&gt;    | [\xF8-\x{2FF}] | [\x{370}-\x{37D}] | [\x{37F}-\x{1FFF}]&lt;br /&gt;    | [\x{200C}-\x{200D}] | [\x{2070}-\x{218F}] | [\x{2C00}-\x{2FEF}]&lt;br /&gt;    | [\x{3001}-\x{D7FF}] | [\x{F900}-\x{FDCF}] | [\x{FDF0}-\x{FFFD}]&lt;br /&gt;    | [\x{10000}-\x{EFFFF}] }x;&lt;br /&gt;&lt;br /&gt;my $NameChar = qr{ $NameStartChar | - | \. | [0-9] | \xB7&lt;br /&gt;    | [\x{0300}-\x{036F}] | [\x{203F}-\x{2040}] }x;&lt;br /&gt;&lt;br /&gt;my $Char = qr{ \x09 | \x0A | \x0D | [\x20-\x{D7FF}] | [\x{E000}-\x{FFFD}]&lt;br /&gt;    | [\x{10000}-\x{10FFFF}] }x;&lt;br /&gt;&lt;br /&gt;my $Name = qr{ $NameStartChar $NameChar* }x;&lt;br /&gt;&lt;br /&gt;my $EntityRef = qr{ &amp;amp; $Name ; }x;&lt;br /&gt;&lt;br /&gt;my $CharRef = qr{ % $Name ; }x;&lt;br /&gt;&lt;br /&gt;my $Reference = qr{ $EntityRef | $CharRef }x;&lt;br /&gt;&lt;br /&gt;my $AttValue = qr{ " (?: [^&amp;lt;&amp;amp;"] | $Reference )* " }x;&lt;br /&gt;&lt;br /&gt;my $Attribute = qr{ $Name $S? = $S? $AttValue }x;&lt;br /&gt;&lt;br /&gt;my $STag = qr{ &amp;lt; $Name (?: $S* $Attribute )* $S? &amp;gt; }x;&lt;br /&gt;&lt;br /&gt;my $ETag = qr{ &amp;lt;/ $Name $S? &amp;gt; }x;&lt;br /&gt;&lt;br /&gt;my $CDStart = qr{ &amp;lt;!\[CDATA\[ }x;&lt;br /&gt;&lt;br /&gt;my $CDEnd = qr{ \]\]&amp;gt; }x;&lt;br /&gt;&lt;br /&gt;my $CData = qr{ (?&amp;lt;! $CDEnd ) $Char* (?! $CDEnd ) }x;&lt;br /&gt;&lt;br /&gt;my $CharData = qr{ (?&amp;lt;! $CDEnd ) [^&amp;lt;&amp;amp;]* (?! $CDEnd ) }x;&lt;br /&gt;&lt;br /&gt;my $CDSect = qr{ $CDStart $CData $CDEnd }x;&lt;br /&gt;&lt;br /&gt;my $PITarget = qr{ (?! [Xx][Mm][Ll] ) $Name }x;&lt;br /&gt;&lt;br /&gt;my $PI = qr{ &amp;lt;\? $PITarget (?: $S (?: (?&amp;lt;! \?&amp;gt; ) $Char* (?! \?&amp;gt; )))? \?&amp;gt; }x;&lt;br /&gt;&lt;br /&gt;my $Comment = qr{ &amp;lt;!-- (?: (?: (?! - ) $Char ) | (?: - (?! - ) $Char ) )*&lt;br /&gt;    --&amp;gt; }x;&lt;br /&gt;&lt;br /&gt;my $element = qr{ ( $STag ( $CharData? (?: $Reference | $CDSect | $PI&lt;br /&gt;    | $Comment | (?1) )* $CharData? ) $ETag ) }sx;&lt;br /&gt;&lt;br /&gt;my @stack = '&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Title&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Lies.&amp;lt;/h1&amp;gt;'&lt;br /&gt;    . '&amp;lt;p&amp;gt;&amp;lt;i&amp;gt;You&amp;lt;/em&amp;gt;, my friend, have been told them.&amp;lt;/p&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;';&lt;br /&gt;&lt;br /&gt;$" = "\n\n";&lt;br /&gt;while (@stack) {&lt;br /&gt;    my $string = shift @stack // '';&lt;br /&gt;    my @groups = $string =~ m/$element/g;&lt;br /&gt;    print "@groups\n\n" if @groups;&lt;br /&gt;    unshift @stack, map {&lt;br /&gt;        s/^&amp;lt;($Name)(?:$S*$Attribute)*$S?&amp;gt;//; my $a = $1;&lt;br /&gt;        s/&amp;lt;\/($Name)$S*&amp;gt;$//;                 my $b = $1;&lt;br /&gt;        $a eq $b ? $_ : undef&lt;br /&gt;    } @groups;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I would call this a good (okay, slow and overspecified, but still kinda neat) &lt;i&gt;practical&lt;/i&gt; solution to a problem that’s &lt;i&gt;theoretically&lt;/i&gt; unsolvable. That, incidentally, will be the theme of many of my upcoming posts, so stay tuned if you’re into it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-638611985992268417?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/638611985992268417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/regexes-parse-xml-just-fine-actually.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/638611985992268417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/638611985992268417'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/regexes-parse-xml-just-fine-actually.html' title='Regexes Parse XML Just Fine, Actually'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7652436552780816128</id><published>2011-10-06T15:03:00.004-04:00</published><updated>2011-10-08T14:37:39.839-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Steve Jobs Was a Jerk</title><content type='html'>And that was what made him great. He was fierce, uncompromising, and brilliant, and his devotion to elegance earned him a massive following that he truly deserved. But unlike many fierce, uncompromising, brilliant jerks, he was willing to learn—and that’s what made him nigh unstoppable.&lt;br /&gt;&lt;br /&gt;People talked bad about him all the time. I’ve badmouthed him enough, and I’ll continue to do so. His death won’t make me change my opinions. But even though I think he was kind of a jerk, I also can’t speak more highly of him, and I didn’t even know the guy. Jobs consistently did what most of us can’t bring ourselves to do: whatever needed to be done.&lt;br /&gt;&lt;br /&gt;Either we’re not motivated enough, or too afraid of failure, or too concerned with hurting people, to do what needs to be done in our own lives. It is okay to want to be successful, provided of course that you’re not actually evil. And just to be clear, I don’t think the man was evil. He loved his wife and his companies and the wicked cool life he created with the support of those around him.&lt;br /&gt;&lt;br /&gt;As I see it, the closest thing to luck that we can get is to keep an open mind—to learn to see opportunities, even if they’re not what we’re looking for, and to treat obstacles as things to be overcome or creatively worked around, not insurmountable walls. My friends know that I’m an unusually lucky person, and I attribute it entirely to this mindset, one which I’d wager Jobs must have shared in order to get where he did.&lt;br /&gt;&lt;br /&gt;Our time on this planet is finite. Let’s all serve the memory of Mr. Jobs by taking a leaf out of his book, and doing what we ought to do—no matter what anyone else thinks.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7652436552780816128?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7652436552780816128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/steve-jobs-was-jerk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7652436552780816128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7652436552780816128'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/steve-jobs-was-jerk.html' title='Steve Jobs Was a Jerk'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-3223860178033576909</id><published>2011-10-06T05:31:00.001-04:00</published><updated>2011-10-08T14:37:18.027-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Teaching'/><title type='text'>Correctness is a Boolean</title><content type='html'>The most misleading thing about the way programming is taught is how programs are graded. Students are used to receiving a score that represents the &lt;i&gt;sum&lt;/i&gt; of the correct parts of an assignment. You can think of it start as starting with a zero and earning points up to a maximum of 100, or as starting with 100 and losing points from there. As for me, I prefer to simply avoid thinking about it.&lt;br /&gt;&lt;br /&gt;But when it comes to software, this kind of grading makes &lt;i&gt;almost no sense whatsoever&lt;/i&gt;. Especially in the imperative languages that are generally taught to beginning students of programming, the effect of a statement depends crucially on the effects of the statements preceding it, and not just lexically, but &lt;i&gt;temporally&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;An error in a single line of a program is not necessarily local to that line, but more likely has effects that propagate forward in time or outward in an expression to cause further errors. By grading programs subjectively according to how many of the statements seem appropriately designed and sequenced, teachers influence students to treat programs as though their &lt;i&gt;objective&lt;/i&gt; correctness is dependent on the mere sum of the subjective correctness of &lt;i&gt;&lt;/i&gt;their parts.&lt;br /&gt;&lt;br /&gt;Beginning programmers often have difficulty thinking above the level of individual statements in order to develop a high-level understanding of program structure and meaning. Professors don’t need to further their confusion by giving them a skewed representation of what makes a program right.&lt;br /&gt;&lt;br /&gt;A program ought to be like a proof: a single flaw, and it’s not correct. “Correct” means that it does everything it ought to, and nothing it oughtn’t. That says nothing about the amount of work required to make an incorrect program correct, because that’s entirely subjective; it could be a difference as small as a single character, or as great as the entire program. The changes needed are not necessarily local to individual statements, nor even comprehensible at the statement level.&lt;br /&gt;&lt;br /&gt;That’s why, if I ever end up teaching programming, I’ll grade my assignments on the basis of correctness and subjective style &lt;i&gt;separately&lt;/i&gt;, and draw a clear distinction between the two. If your program is correct, you’re guaranteed a passing grade. All the points beyond that you gotta earn by writing elegantly. It’s only fair.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-3223860178033576909?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/3223860178033576909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/correctness-is-boolean.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3223860178033576909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3223860178033576909'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/10/correctness-is-boolean.html' title='Correctness is a Boolean'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7225549941720949370</id><published>2011-09-28T11:20:00.000-04:00</published><updated>2011-09-28T11:22:44.596-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>How to Be Productive</title><content type='html'>&lt;span style="font-size: large;"&gt;Blindingly Obvious Truths&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;This is how to be productive. Most of these things are absurdly, staggeringly obvious. That’s &lt;a href="http://evincarofautumn.blogspot.com/2011/09/tricky-programming-concepts-arent.html"&gt;kinda my style&lt;/a&gt;. Anyway, since not very many of us are the kind that &lt;a href="http://blog.eladgil.com/2011/09/hire-for-ability-to-get-shit-done.html"&gt;get shit done&lt;/a&gt;, we apparently need to be reminded every once in a while. Pin this to your wall—pin it to all of your walls—and look at it to give yourself a mental kick in the ass when you know you should be working.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Get out of bed.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If, like me, you have &lt;a href="http://en.wikipedia.org/wiki/Delayed_sleep_phase_syndrome"&gt;delayed sleep phase syndrome&lt;/a&gt;, then &lt;a href="http://www.humbledmba.com/become-a-morning-person-how-to-end-insomnia-f"&gt;fix it&lt;/a&gt;. If it’s hard to get up when the sun comes up, then your sleep schedule is probably not healthy, and it &lt;i&gt;is&lt;/i&gt; negatively affecting your productivity. We are a diurnal species. Deal with it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Be healthy.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It ought to go without saying that you need good diet and exercise habits to be healthy. What you may not realise is that &lt;i&gt;health is happiness&lt;/i&gt;, and for many of us, &lt;i&gt;happiness is productivity&lt;/i&gt;. (I can’t say &lt;i&gt;all&lt;/i&gt;, because surely there are some dark tormented programmers out there whose work is fueled by the darkness and torment in their dark tormented souls of tormentful darkfulness. Or something.)&lt;br /&gt;&lt;br /&gt;For instance, when my blood sugar is low, I hate the world—then I eat a sandwich and everything’s fine. If you feel like hell all the time, your body is &lt;i&gt;probably&lt;/i&gt; trying to tell you something. Sleep right, eat well, exercise occasionally, spend time with friends, find a mate, and mate with them often.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Work on one thing.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Multitasking is doing many things at once—badly. Innumerable studies have shown that multitaskers are just fooling themselves into believing they’re improving their productivity. You &lt;i&gt;can&lt;/i&gt; be a true “jack of all trades” &lt;i&gt;if&lt;/i&gt; you work on one thing at a time. Don’t distract yourself from what you’re working on with thoughts of what you’re not working on. It’s an endless cycle of self-subversion that can only be broken with focus.&lt;br /&gt;&lt;br /&gt;If I want to write a blarticle, I &lt;i&gt;just do it&lt;/i&gt;. If I need to do homework, I just—well, okay, first I complain a lot, but then I just do it. I didn’t post a &lt;a href="http://youtube.com/whyevernotso"&gt;vlog&lt;/a&gt; entry for months, and then I said “no, this will not do” and made something. It was shitty. It doesn’t matter. I did it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Work till you’re done.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Have a project that needs finishing? Don’t waste your valuable time making small changes. Get your hands dirty and implement that feature you want. No one else is going to do it, and you have the time. It probably won’t even be as hard as you think. If it seems guaranteed to be difficult, you might be fixating on a difficult solution when there is a much simpler one. Reflect.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;When you’re done, stop.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You must take time to relax and play. If you work hard, you earn the right to relax hard. You will feel the profound satisfaction that comes from creating something through your own focused efforts, and your sleep will be easy and deep.&lt;br /&gt;&lt;br /&gt;Now go, and do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7225549941720949370?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7225549941720949370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-to-be-productive.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7225549941720949370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7225549941720949370'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-to-be-productive.html' title='How to Be Productive'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-3437648761274983660</id><published>2011-09-27T17:59:00.001-04:00</published><updated>2011-09-27T18:35:31.917-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Simulation is Abstraction is Power</title><content type='html'>A more abstract programming language is more powerful. This is one of precious few things that most software developers agree on. C is more powerful than assembly, C++ is more powerful than C, and Lisp is more powerful than most developers realise—or will ever take advantage of. And that’s fine.&lt;br /&gt;&lt;br /&gt;But whence cometh abstraction? Sure, you can say that all abstractions are generalisations of some category of operations or structures, but that’s shallow and basically useless. There’s more to it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Abstraction comes from simulation.&lt;/b&gt; Computers run simulations of idealised computation; more abstract languages are better at simulating the ideal. Low-level languages deal with real hardware, while high-level languages simulate ideal hardware. A few examples:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;References&lt;/b&gt; simulate unstructured memory.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Garbage collection&lt;/b&gt; simulates unbounded memory.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Dynamic typing&lt;/b&gt; simulates lack of typing.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Threads&lt;/b&gt; simulate parallel execution.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Tail recursion&lt;/b&gt; simulates unbounded recursion. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;(Depending on how far you want to go with the analogy, recursion simulates a whole bunch of things, including self-reference, fractal structure, and induction.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Simulation is about removing dependency.&lt;/b&gt; A program &lt;i&gt;can&lt;/i&gt; depend on manual memory management, but it &lt;i&gt;cannot&lt;/i&gt;, by definition, depend on garbage collection. With memory management fully abstracted away, memory management ought to be a &lt;i&gt;nonexistent&lt;/i&gt; concept from the perspective of the language.&lt;br /&gt;&lt;br /&gt;Your program probably pretends it has infinite memory anyway. Provided your program doesn’t crash, the system &lt;i&gt;does&lt;/i&gt; have unbounded memory as far as you know. &lt;i&gt;Most&lt;/i&gt; programs that are working properly don’t run out of memory unless they’re deliberately designed to, for lack of a better phrase, fuck shit up.&lt;br /&gt;&lt;br /&gt;Similarly, as we all know, threads may &lt;i&gt;actually&lt;/i&gt; run on separate cores, and thus truly in parallel—that’s sorta the point. But the thing about a language that offers powerful abstractions for parallelism is that &lt;i&gt;you don’t need to care&lt;/i&gt;. It’s taken care of. As far as you need to know, the system can perform an infinite number of computations at once.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Abstractions are (imperfect) simulations of limitlessness.&lt;/b&gt; As a language designer, you can (and&amp;nbsp;should) offer pragmatic limitations and safeguards for the benefit of the fallible developer. But to make a more &lt;i&gt;powerful&lt;/i&gt; language, you must &lt;i&gt;remove &lt;/i&gt;limitations. When you do so, you discover the nature of the underlying simulation—and simulation is abstraction is power. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-3437648761274983660?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/3437648761274983660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/simulation-is-abstraction-is-power.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3437648761274983660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3437648761274983660'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/simulation-is-abstraction-is-power.html' title='Simulation is Abstraction is Power'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-1311279001011304868</id><published>2011-09-22T12:25:00.001-04:00</published><updated>2011-09-23T20:35:42.967-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Tricky Programming Concepts Aren’t</title><content type='html'>&lt;span style="font-size: large;"&gt;What Teachers do Wrong&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Teachers use subversive language. They say things like “this is a bit tricky” before introducing a concept. It’s &lt;i&gt;intended&lt;/i&gt; to remind you to pay attention, but mostly it turns students off—it says “this is hard; I don’t expect you to understand it”.&lt;br /&gt;&lt;br /&gt;Frankly, that’s bullshit, and it has appeared—and caused problems—in &lt;i&gt;nearly every class I’ve ever taken&lt;/i&gt;. It’s especially visible in mathematics and the sciences, but foreign language, social studies, literature, and even drafting are not immune.&lt;br /&gt;&lt;br /&gt;The fine arts, notably, &lt;i&gt;do&lt;/i&gt; avoid it: it’s not &lt;i&gt;conceptually&lt;/i&gt; difficult to improve your process and observational skills—and no art teacher I’ve ever encountered pretends it will be anything other than hard work and dedication. (Paul Graham got this one right: &lt;a href="http://www.paulgraham.com/hp.html"&gt;hacking and painting&lt;/a&gt; are &lt;i&gt;very&lt;/i&gt; similar.)&lt;br /&gt;&lt;br /&gt;I may have an irresponsibly intertwingled worldview, but it seems to me that &lt;i&gt;most things are not conceptually difficult&lt;/i&gt;. At all. Even the most high-level concept, explained correctly, can be absorbed and applied by any person of average intelligence. The important thing is the explanation.&lt;br /&gt;&lt;br /&gt;Learning should not be about overcoming difficult ideas: it should be about realising how simple those ideas actually are.&lt;br /&gt;&lt;br /&gt;I think the main reason that fine art instruction is effective is that, when a student says “I can’t draw/paint/compose/&amp;amp;c.”, the teacher’s natural response is to say “you can—you must; just practice”.&lt;br /&gt;&lt;br /&gt;And they do, and they get better. Most people are not going to become master painters or composers, of course, for the same reason that most people won’t become masters of anything. But perhaps more of the people who are capable of mastery would strive for it if we used encouraging, practical teaching methods like we know we ought to.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;What Programming is About&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Programming is fundamentally about doing three things with a problem:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Discovery&lt;/b&gt;&lt;br /&gt;First, know what problem you need to solve. Finding interesting problems is half the fun of research. If you don’t mind solving uninteresting problems, you probably aren’t a very interesting programmer, or even very interested in programming.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Understanding&lt;/b&gt;&lt;br /&gt;Once you know the problem, you need to understand it deeply. You need to understand its subproblems, and their subproblems, all the way down to the units that make up your &lt;i&gt;problem domain&lt;/i&gt;. (This is recursion.)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Expression&lt;/b&gt;&lt;br /&gt;When you understand the problem, you can express it. This is &lt;i&gt;not&lt;/i&gt; just writing the code you designed earlier, as some “software engineering” evangelists will have you believe. Expression itself contains discovery and understanding, which leads to further expression. (This is tail-recursion. It’s also why the “waterfall” method is flawed.)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This is &lt;i&gt;exactly&lt;/i&gt; like the process of &lt;a href="http://evincarofautumn.blogspot.com/2011/07/oxymoronic-computer-science-software.html"&gt;essay writing&lt;/a&gt;: you discover your thesis, engage in research to understand your topic, then begin the process of expressing yourself in a logically connected essay. While figuring out your expression, you discover and understand further details and incorporate them into further expression.&lt;br /&gt;&lt;br /&gt;An essay is ideally just a proof of a thesis; similarly, a program is ideally a solution to an intellectual problem. Both have practical effects in the real world, and at the heart of it, they really are the same thing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;“Tricky” &lt;/span&gt;&lt;span style="font-size: large;"&gt;Programming &lt;/span&gt;&lt;span style="font-size: large;"&gt;Concepts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Two things are consistently taught in such a way that beginning programmers fail to properly understand them. Things that are so stunningly simple and pervasive that it’s baffling that &lt;i&gt;anyone&lt;/i&gt; could fail to understand them.&lt;br /&gt;&lt;br /&gt;I’m talking of course about pointers and recursion.&lt;i&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;What baffles me is how people seem to be so inclined to analogy when the vast majority of programming concepts are &lt;i&gt;stupendously&lt;/i&gt; literal.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A pointer points. A reference refers.&lt;/b&gt; These are the same thing.&lt;br /&gt;&lt;br /&gt;(Don’t the C++ folks in the audience give me any crap about C++ references. They’re not magic, they’re non-nullable immutable pointers—just another reference type.)&lt;br /&gt;&lt;br /&gt;The address of a thing is not the thing itself, but it is good enough (and often, in fact, better). I can steal anything in your house, break your windows, burn it down, and all I need to know is where your house is. I can use the words “burn your house down”, and even though I have not actually burnt your house down, you know exactly what I’m referring to.&lt;br /&gt;&lt;br /&gt;Reference is a &lt;i&gt;fucking pillar&lt;/i&gt; of language. I say “fucking” because it’s fucking important. We use finite-sized symbols to refer to concrete objects and abstract concepts alike, and it takes no more cognitive effort to say the word “apple” than it does to say the word “universe”. (Referring to something is a constant-time operation.)&lt;br /&gt;&lt;br /&gt;Most people have no trouble understanding the concept of reference, of course—but then they fail to see why it’s important, least of all in programming. But again, you don’t even need analogies here—the explanations are comically, tautologically simple:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A linked list is a list of things that are linked.&lt;/li&gt;&lt;li&gt;A tree is a hierarchy of things that are linked.&lt;/li&gt;&lt;li&gt;A queue is a queue of things.&lt;/li&gt;&lt;li&gt;A stack is a stack of things.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If someone doesn’t understand these things, they’re probably trying too hard. To implement a linked list, just open your eyes and &lt;i&gt;think&lt;/i&gt; about what the term &lt;i&gt;means&lt;/i&gt;: it is a list, and at each place there must be a thing, and the address of the next thing if there is one.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;That’s all.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Recursion is even more important to programming, even less understood by beginners, and yet  even more visible in daily life. If you remember one thing, remember this:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;References are for referencing, and recursion is for self-referencing.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;A mind-squishingly huge number of natural things have &lt;a href="http://en.wikipedia.org/wiki/Fractal"&gt;fractal&lt;/a&gt; structure, from clouds to mountains to plants to coastlines to trees. A branch of a tree looks just like a whole tree, only smaller. Because of this, doing stuff to part of a tree is basically like doing stuff to a whole tree.&lt;br /&gt;&lt;br /&gt;You can thus write instructions for doing stuff to entire trees very concisely: to snuggle a whole tree, first snuggle the base of the tree, then snuggle each branch as though it were a whole tree.&lt;br /&gt;&lt;br /&gt;This works in less silly examples as well: to sort people by height, pick one, move all the shorter people to his left, and all the taller people to his right, then sort each side. Bam. You’ve just invented &lt;a href="http://en.wikipedia.org/wiki/Quicksort"&gt;quicksort&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Don’t Be Fooled&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I think Joel Spolsky got it &lt;i&gt;severely, totally, irresponsibly wrong&lt;/i&gt; in his article &lt;a href="http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html"&gt;The Perils of JavaSchools&lt;/a&gt;, wherein he basically claims that understanding pointers and recursion is an aptitude, not a skill.&lt;br /&gt;&lt;br /&gt;Not only is it the same kind of subversive language that teachers mistakenly use, it betrays a &lt;i&gt;deeply mistaken&lt;/i&gt; belief that the concepts of pointers and recursion are somehow inherently difficult.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;They are not.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you think all I’m saying is “programming is not as hard as people make it out to be”, then you’ve missed the point. Programming &lt;i&gt;is&lt;/i&gt; hard, like writing and design, because it is intimately related to both. It’s just that the basics of programming are no harder than the basics of any other kind of design.&lt;br /&gt;&lt;br /&gt;Pointers and recursion are among the most basic things in the world. The real world, the one in which we live—and that’s &lt;i&gt;why&lt;/i&gt; they show up in computing in the first place.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;♦ ♦ ♦&lt;/div&gt;&lt;br /&gt;My sincerest thanks to all of the kind folks at &lt;a href="http://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt; (and now &lt;a href="http://www.reddit.com/r/programming"&gt;/r/programming&lt;/a&gt;!) for reading, upvoting, commenting, and +1ing. Your many praises and criticisms are deeply appreciated, for giving me the motivation and humility to write even better content in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-1311279001011304868?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/1311279001011304868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/tricky-programming-concepts-arent.html#comment-form' title='52 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1311279001011304868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1311279001011304868'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/tricky-programming-concepts-arent.html' title='Tricky Programming Concepts Aren’t'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>52</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-51264817836589173</id><published>2011-09-17T00:36:00.001-04:00</published><updated>2011-09-17T03:35:28.284-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><title type='text'>What’s Wrong with Lisp</title><content type='html'>Lisp is a brilliant language. You can do things in it that are impossible in other languages, and that’s wicked cool. But though I think there is an upper limit to language expressiveness, I don’t believe Lisp represents that limit. Here’s why.&lt;br /&gt;&lt;br /&gt;A quote I see from time to time—and for some reason have been seeing a lot lately—comes from the author of perhaps my favourite book, Le Petit Prince, the marvelous Antoine de Saint-Exupéry:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;“A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.”&lt;/blockquote&gt;&lt;br /&gt;In short, minimalism = perfection, and Lisp (well, Scheme anyway) favours it: uniform syntax, a few special forms, and then it’s turtles all the way up.&lt;br /&gt;&lt;br /&gt;But even though I’d be the first to say that there’s a lot to take away from a thorough study of Lisp, there’s also a lot that could be taken away from Lisp itself, and for that reason I can only recommend it as an intermediate step in a programmer’s journey to linguistic nirvana.&lt;br /&gt;&lt;br /&gt;See, this may come as a shock, but &lt;b&gt;Lisp is not the most powerful language&lt;/b&gt;. Just as there are countless things that are ugly in most languages but mundane (if not beautiful) in Lisp, so too are there things that are ugly in Lisp and beautiful in other languages. They’re easy to see when you go looking for them.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It all boils down to the ability to concisely represent patterns.&lt;/b&gt; When a programmer in language X sees repetitive code, he refactors it using the tools available in X. To the programmer of some better language Y, even the most beautiful solution in X is imperfect, because he sees it as a workaround for the fact that X does not have what Y does. A Band-Aid solution, if you will.&lt;br /&gt;&lt;br /&gt;Lisp macros are seen as the final word in abstraction and beauty. See repetitive code, make a macro, repeat. But aren’t macros the same kind of Band-Aid solution that exists in every language? Lisp just has nicer Band-Aids. (Ones with spaceships and unicorns on them.) And make no mistake, there is a language with nicer Band-Aids than Lisp.&lt;br /&gt;&lt;br /&gt;To paraphrase Paul Graham: when you look down the spectrum of programming language power, you know you’re looking down; but when you look up, all you see are weird languages. Lisp programmers look down on all other languages—but what languages look weird to them?&lt;br /&gt;&lt;br /&gt;I advise Lisp programmers to get off their pedestal and look through the weird, the esoteric, and the insane, to reach the power of what lies beyond. Question your assumptions. Why the oh-so-important parentheses? Simple: nesting! So why do you need nesting? To create scope. Why do you need scope? Variables, of course. So why do you need variables? To store values, obviously. What is the purpose of a value? To model state. Why do you need state? You don’t.&lt;br /&gt;&lt;br /&gt;If you model everything in terms of data flow, for example, you no longer need state or any of the other things that come with it. You can write your program solely in terms of function composition. You don’t even need scoping (lambda abstraction) or application at all. You don’t need an absurd Haskellian type system to keep things functionally pure, either.&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The point is that lambda calculus is only the beginning.&lt;/b&gt; It is (for lack of a better term) the assembly language of functional programming. A language that directly models the operations of a Turing Machine is plainly rather boring, but what baffles me is that nobody seems to notice that &lt;i&gt;the same is true of one that models lambda calculus&lt;/i&gt;. Lisp dresses it up, but only very little. We can do much better.&lt;br /&gt;&lt;br /&gt;Let us take more away, to reveal what more is yet to be.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-51264817836589173?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/51264817836589173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/whats-wrong-with-lisp.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/51264817836589173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/51264817836589173'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/whats-wrong-with-lisp.html' title='What’s Wrong with Lisp'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-6655918582729614621</id><published>2011-09-15T18:10:00.000-04:00</published><updated>2011-09-17T01:14:21.018-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>How to Pronounce Hexadecimal Numbers</title><content type='html'>In 1999, the IEC introduced  &lt;a href="http://en.wikipedia.org/wiki/Kibibyte"&gt;kibibyte&lt;/a&gt; and friends, because they were pissed off that kilobyte means 1000 bytes, but programmers wanted it to mean 1024 bytes and were insistently using it that way, correctness be damned. Unfortunately, nobody really gave a damn, and even though some things (Ubuntu for instance) show data sizes in KiB, nobody actually &lt;i&gt;says&lt;/i&gt; “kibibyte”.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://programmers.stackexchange.com/q/107479/2107"&gt;Someone asked&lt;/a&gt; recently on the Programmers Stack Exchange how hexadecimal numbers ought to be pronounced. In a valiant effort to pull an IEC and come up with a useful thing that nobody will use, here’s my system of pronunciation for hex numbers. The system is based on English (specifically American English) because it’s the lingua franca of programming. Enjoy.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Hexadecimal Number&lt;/th&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Decimal Equivalent&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0001&lt;/code&gt;&lt;/td&gt;&lt;td&gt;One&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;0&lt;/sup&gt; = 1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;⋮&lt;/code&gt;&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 000a&lt;/code&gt;&lt;/td&gt;&lt;td&gt;A (ay) = ten&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 000b&lt;/code&gt;&lt;/td&gt;&lt;td&gt;B (bee) = eleven&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 000c&lt;/code&gt;&lt;/td&gt;&lt;td&gt;C (cee) = twelve&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;⋮&lt;/code&gt;&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0010&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Tex&lt;/td&gt;&lt;td&gt;1 × 16&lt;sup&gt;1&lt;/sup&gt; = 16&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0020&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Twentex† = two tex&lt;/td&gt;&lt;td&gt;2 × 16&lt;sup&gt;1&lt;/sup&gt; = 32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0030&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Thirtex† = three tex&lt;/td&gt;&lt;td&gt;3 × 16&lt;sup&gt;1&lt;/sup&gt; = 48&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0040&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Fortex† = four tex&lt;/td&gt;&lt;td&gt;4 × 16&lt;sup&gt;1&lt;/sup&gt; = 64&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0050&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Fiftex† = five tex&lt;/td&gt;&lt;td&gt;5 × 16&lt;sup&gt;1&lt;/sup&gt; = 80&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0060&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Sixtex = six tex&lt;/td&gt;&lt;td&gt;6 × 16&lt;sup&gt;1&lt;/sup&gt; = 96&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0070&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Seventex = seven tex&lt;/td&gt;&lt;td&gt;7 × 16&lt;sup&gt;1&lt;/sup&gt; = 112&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0080&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Eightex = eight tex&lt;/td&gt;&lt;td&gt;8 × 16&lt;sup&gt;1&lt;/sup&gt; = 128&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0090&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Ninetex = nine tex&lt;/td&gt;&lt;td&gt;9 × 16&lt;sup&gt;1&lt;/sup&gt; = 144&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 00a0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Tentex = ten tex&lt;/td&gt;&lt;td&gt;10 × 16&lt;sup&gt;1&lt;/sup&gt; = 160&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 00b0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Eleventex = eleven tex&lt;/td&gt;&lt;td&gt;11 × 16&lt;sup&gt;1&lt;/sup&gt; = 176&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;⋮&lt;/code&gt;&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 0100&lt;/code&gt;&lt;/td&gt;&lt;td&gt;One hundrex&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;2&lt;/sup&gt; = 256&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0000 1000&lt;/code&gt;&lt;/td&gt;&lt;td&gt;One thousax&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;3&lt;/sup&gt; = 4096&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0001 0000&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Tex thousax = one thoutex‡&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;4&lt;/sup&gt; = 65536&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0010 0000&lt;/code&gt;&lt;/td&gt;&lt;td&gt;One hundrex thousax = tex thoutex&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;5&lt;/sup&gt; = 1048576&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x0100 0000&lt;/code&gt;&lt;/td&gt;&lt;td&gt;One milliox = one hundrex thoutex&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;6&lt;/sup&gt; = 16777216&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;0x1000 0000&lt;/code&gt;&lt;/td&gt;&lt;td&gt;One billiox†† = one thousax thoutex&lt;/td&gt;&lt;td&gt;16&lt;sup&gt;9&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;⋮&lt;/code&gt;&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;td&gt;⋮&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;† By analogy with “thirty”, “forty”, &amp;amp;c.&lt;br /&gt;&lt;br /&gt;†† This system is based on the &lt;a href="http://en.wikipedia.org/wiki/Long_and_short_scales"&gt;short scale&lt;/a&gt;—one billiox equals one thousax milliox, and one trilliox is one thousax billiox.&lt;br /&gt;&lt;br /&gt;‡ I introduced the term “thoutex”, equal to &lt;code&gt;0x10000&lt;/code&gt;, because it’s more obvious that &lt;code&gt;0x0001 0000&lt;/code&gt; is “one thoutex” rather than “tex thousax”: four-digit grouping makes more sense in hex, but three-digit grouping is the default in English, so I had to come up with something, and the hypothetical “thouten” sounded good in my mind to adapt.&lt;br /&gt;&lt;br /&gt;Fractions are formed as in English, by adding -th: one texth, one hundrexth, one thousaxth, one thoutexth, &amp;amp;c.&lt;br /&gt;&lt;br /&gt;Example: &lt;code&gt;0xa400f20.cd&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;Ten hundrex fourtex thousax, fifteen hundrex twentex and twelvetex thirteen hundrexths&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Ay hundrex fourtex thousax, eff hundrex twentex and ceetex dee hundrexths&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Ay milliox, four hundrex thousax, eff hundrex twentex and ceetex dee hundrexths&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Happy pronouncing! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-6655918582729614621?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/6655918582729614621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-to-pronounce-hexadecimal-numbers.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/6655918582729614621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/6655918582729614621'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-to-pronounce-hexadecimal-numbers.html' title='How to Pronounce Hexadecimal Numbers'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-3485987893106937000</id><published>2011-09-14T11:35:00.000-04:00</published><updated>2011-09-17T01:14:58.753-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Thoughts on Metaprogramming in Very</title><content type='html'>I'm currently implementing the metaprogramming system in my pet language, Very. The language is inspired by Forth and Lisp, both of which are known for their strong metaprogramming capabilities. Here's how metaprogramming works in Very.&lt;br /&gt;&lt;br /&gt;Very is a stack-based, concatenative language: words (the concatenative analogue of functions) manipulate a stack of values to perform computation. Very macros are words that run at compile-time: while words usually manipulate values, macros usually manipulate code. The interpreter reads and parses the source, then repeatedly expands all macro invocations until none remain, before evaluating the result.&lt;br /&gt;&lt;br /&gt;Very also has an analogue of Lisp's reader macros: in Lisp, you can specify a callback function that is executed by the source reader when it encounters some predefined character or group of characters. Unfortunately, reader macros must explicitly operate on a stream object, whereas proper macros operate solely on S-expressions.&lt;br /&gt;&lt;br /&gt;A Lisp reader macro can function like an ordinary macro by calling &lt;code&gt;read&lt;/code&gt; on the stream it receives, to retrieve S-expressions rather than characters, but this interface is awkward, and offers no facility for performing manipulations at the raw token level.&lt;br /&gt;&lt;br /&gt;In Very, you can declare that a particular sequence of characters forms a &lt;i&gt;token&lt;/i&gt;, which is then treated by the reader as an indivisible unit. Very reader macros are simply &lt;i&gt;ordinary macros&lt;/i&gt;, whose name may have been declared as a token. Macros have the ability to manipulate the incoming queue of source at whatever level they choose—there are words for reading (and unreading) terms, raw tokens, and characters. A character is just a number; a string, a list of numbers; and a term, a number or list of terms. It's that simple.&lt;br /&gt;&lt;br /&gt;So Very offers better abstractions than Lisp for source manipulation madness: you could implement any language entirely in Very macros, and have it run under the Very interpreter, and doing so would be a lot less painful than in Lisp. The Very web framework will make extensive use of macros to allow arbitrary HTML and CSS to function as ordinary values, and such goodies as automatic validation will come practically for free.&lt;br /&gt;&lt;br /&gt;One thing I've been worried about as a result of all this metaprogramming insanity is how to support syntax highlighting of Very code. Languages such as Very that cannot be parsed without being evaluated aren't exactly amenable to tool support, because writing complete tools requires writing a nearly-complete implementation of the language.&lt;br /&gt;&lt;br /&gt;I've decided to offer a compile-time facility for semantic annotation, which at the heart of it would tag regions of source with labels. An editor could run Very code through a preprocessing phase to obtain an annotated and escaped version of the source, which would contain enough information to correctly highlight the code.&lt;br /&gt;&lt;br /&gt;Semantic annotations could also be used as compiler hints for static typing, parallelisation, and other optimisations. If possible, I'd like to implement annotations as macros—conversely, it may be possible to implement macros by tagging regular words with a &lt;code&gt;compile-time-word&lt;/code&gt; annotation. Will update will my progress on that insanity when I come to it.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-3485987893106937000?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/3485987893106937000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/thoughts-on-metaprogramming-in-very.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3485987893106937000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3485987893106937000'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/thoughts-on-metaprogramming-in-very.html' title='Thoughts on Metaprogramming in Very'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7406288963970774797</id><published>2011-09-13T20:07:00.003-04:00</published><updated>2011-09-17T01:17:46.570-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='User Interfaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Design'/><title type='text'>This “Trello” Business</title><content type='html'>So &lt;a href="http://www.fogcreek.com/"&gt;Fog Creek Software&lt;/a&gt; has launched a new thingamajig called &lt;a href="http://trello.com/"&gt;Trello&lt;/a&gt;. Here are my initial thoughts.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Everything needs a purpose in order to survive.&lt;/b&gt; (Even if that purpose is to have no purpose. How Zen.) It should be easy to say, concisely, what your story is about, what your software does, and what your product is for. Why did you make it and why do I care?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So what's Trello about? &lt;/b&gt;Projects, basically. That's concise enough that it holds my attention, and doesn't immediately shout “useless gimmick” or “totally misguided”. You get a pretty interface (boards) to what is essentially groups (lists) of lists (cards). I usually have an immediate negative reaction to coinage of proprietary slang, and now is no different: I don't know &lt;i&gt;why&lt;/i&gt; I'm organising lists of “cards” on a “board”. The physical analogy just isn't doing it for me.&lt;br /&gt;&lt;br /&gt;Anyway, by default, you get three top-level groups, presumably for tasks: future (to-do), present (doing), and past (done). It's an intuitive model that people will like, but, well, it's not unique.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;And no goal is worth pursuing unless it's unique.&lt;/b&gt; Your product will be successful if people want it, and people usually want things that either &lt;i&gt;haven't been done before&lt;/i&gt;, or &lt;i&gt;haven't been done right&lt;/i&gt;. Project management solutions have been done. Scads of times, in myriad different ways. So the tacit assumption that Trello makes is that its model for project and team organisation is &lt;i&gt;superior&lt;/i&gt; to those of its competitors. (Yes, free services have competitors.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So how is it different?&lt;/b&gt; Trello makes it very easy to collect bundles of junk related to a task, and sort them chronologically. You can add comments, checklists, and files, as well as attach coloured “labels” to tasks. I would say this is where it really shines, but it just doesn't excite me.&lt;br /&gt;&lt;br /&gt;(For one thing, the interface is still a tad buggy: when adding items to a checklist in Firefox 6.02, the most recent item replaces the previous item, so only one item displays until the card is closed and reopened. Also, I ran into some synchronisation issues when it came to creating, closing, and reopening boards, as well as archiving—because there's no such thing as “delete” in the Trello world—and unarchiving cards. This mainly consisted of duplicate items and things that were supposed to be gone having some trouble taking the hint.  Most things seemed to work fine, however, and I expect the wrinkles will get ironed out soon.) &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The real problem is that I don't need it.&lt;/b&gt; I can make my own to-do list in whatever format I please. (Emacs org-mode is excellent for this, but any document will do.) I can put that to-do list in a Dropbox folder with whatever other files I'm working on, and share it with whomever I please. I can set up any old task tracker and wiki on my server and get essentially all of the features that I'd use in Trello. And if I didn't have a server, I would use one of the many available freemium services.&lt;br /&gt;&lt;br /&gt;To my mind, the only clear advantage to Trello is that it centralises, simplifies, and prettifies these things for, well, non-technical users. And yet I somehow doubt that many of them will need digital project-management software...&lt;br /&gt;&lt;br /&gt;In short, I think it's a beautiful thing that will perish for lack of an audience. But I definitely hope to be proven wrong.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7406288963970774797?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7406288963970774797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/this-trello-business.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7406288963970774797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7406288963970774797'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/this-trello-business.html' title='This “Trello” Business'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-6441390851138807035</id><published>2011-09-07T21:49:00.003-04:00</published><updated>2011-09-17T01:14:53.278-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>My Current Language Project</title><content type='html'>I was thinking about redoing my website in anticipation of a game I may or may not be making.  None of the languages or frameworks out there at the moment really speak to me, though. I've been reading about &lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt; lately, and I think it's a superb language. I thought about using it, but there were some things I wanted to add, and some things about its philosophy that I didn't agree with. So I decided to make yet another language for web development.&lt;br /&gt;&lt;br /&gt;The code-name of the project is Very, because for some reason I've been fond of naming my projects adverbs lately. It's a dynamically typed, concatenative, lazy language with homoiconic syntax, closely related to Forth and Lisp.&lt;br /&gt;&lt;br /&gt;Very has very few builtins: the core special forms include only a few stack combinators (&lt;code&gt;dup&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;, &lt;code&gt;swap&lt;/code&gt;, &lt;code&gt;quote&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;compose&lt;/code&gt;) and some operations for introducing definitions. Fewer stack combinators are of course possible, but these represent a good balance of minimalism and efficiency. It's the definition special forms that are particularly interesting.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;def&lt;/code&gt; special form is nothing special: it creates a word by binding a name to a quotation that is applied when the word is invoked. This gives you general recursive functions. The &lt;code&gt;extern&lt;/code&gt; special form gives you the ability to invoke functions through the C FFI, which is how many secondary builtins are defined.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;token&lt;/code&gt; special form is more subtle. By default, only parentheses, quoted strings, and whitespace-delimited identifiers (which include numbers) are recognised by the tokeniser. &lt;code&gt;token&lt;/code&gt; modifies the lexer to treat a particular sequence of characters as a single token regardless of any adjacent nonwhitespace characters. This allows a program to introduce new special tokens as it is being read.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;macro&lt;/code&gt; special form is where things get really interesting. Macros are words that operate on a stack of terms that have been read since the point of invocation of the macro, allowing them to perform arbitrary operations on the source. Macros have access to the full power of the language, and may do anything that ordinary words can.&lt;br /&gt;&lt;br /&gt;In addition, macros have the ability to manipulate the queue of terms that &lt;i&gt;have yet to be read&lt;/i&gt;, meaning they are not restricted to the usual postfix syntax. Macros can invoke other words, including macros, directly at compile-time or indirectly through macro expansion.&lt;br /&gt;&lt;br /&gt;The macro system will be used to provide high-level, user-friendly syntactic forms that correspond directly to efficient underlying operations, so those used to a more traditional infix imperative syntax will have no trouble, but those interested in working closer to the philosophy of the language are still encouraged to do so.&lt;br /&gt;&lt;br /&gt;At the moment, I've got most of the basics in place, and am currently working on macros. I'm sure there will be plenty of examples to show off as I get more done. Until then.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-6441390851138807035?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/6441390851138807035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/my-current-language-project.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/6441390851138807035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/6441390851138807035'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/my-current-language-project.html' title='My Current Language Project'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4677468116369936099</id><published>2011-09-06T20:47:00.002-04:00</published><updated>2011-09-17T01:15:20.288-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Iterators'/><title type='text'>Iterators as a Model of Lazy Computation</title><content type='html'>As I often do, I'm working on a pet language project, which I'll describe in future posts. One of the key concerns for this language is laziness: computation should be deferred as long as possible. For various reasons I'm writing the implementation in C++, so I was looking for a convenient means of expressing lazy computation in an imperative language.&lt;br /&gt;&lt;br /&gt;I'm very fond of the work of Alexander Stepanov, who is largely responsible for the popularity of generic programming, one of the driving principles of the C++ standard library. He advocated type-agnostic algorithms expressed in terms of iterators (and iterator ranges) as a means of generically implementing families of operations on any data structure that can be traversed linearly.&lt;br /&gt;&lt;br /&gt;It occurred to me that iterators are, for eager imperative languages, an excellent model of lazy computation. An iterator models a lazy function over a list, which can accept or return any number of values it pleases at a time. Composition of these functions is modelled as iterator adaption: composable iterators are those that are constructable from an iterator range of compatible type.&lt;br /&gt;&lt;br /&gt;Fundamentally, an iterator is an object that can be dereferenced and advanced&lt;code&gt;&lt;/code&gt;. However, in order to be used properly by generic functions in the standard library, C++ iterators must fulfill a number of other requirements. These details are not immediately relevant to the implementation of algorithms, and readability of algorithms expressed as iterators consequently may suffer in C++.&lt;br /&gt;&lt;br /&gt;For imperative programmers, it may require some unusual thinking in order to properly decompose algorithms in terms of iterator adaption. At present, the implementation of my language project is decomposed into the following steps, each of which is modelled by an iterator type that is then aliased for convenience.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Convert the input stream to a raw bytes.&lt;/li&gt;&lt;li&gt; Buffer the bytes to allow backtracking.&lt;/li&gt;&lt;li&gt;Interpret the bytes as UTF-8 and produce UTF-32 code points.&lt;/li&gt;&lt;li&gt;Partition those code points into tokens.&lt;/li&gt;&lt;li&gt;Parse those tokens into terms.&lt;/li&gt;&lt;li&gt;Establish an execution context in which to evaluate those terms.&lt;/li&gt;&lt;li&gt;Run the interpreter.&lt;/li&gt;&lt;/ul&gt;All of these operations are composed and executed by just one line of code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;run(interpreter(terms(tokens(utf32(buffered(characters(stream)))))));&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Only &lt;code&gt;run()&lt;/code&gt; is an imperative operation: it's a function that sends the result of &lt;code&gt;std::copy()&lt;/code&gt;ing the iterator range to a no-op output iterator called &lt;code&gt;ignore_iterator&lt;/code&gt;. Every other identifier here is an aliased name of an iterator type. In order to evaluate an expression, the minimum number of terms needed to constitute a valid expression is read, and consequently also the minimum number of tokens and characters. Waste not.&lt;br /&gt;&lt;br /&gt;The good thing about iterators here is that they strongly encourage you to fully encapsulate all of the state that you use, at least as much as an ordinary function. Iterators must conform to very strict requirements in order to be used with the usual algorithms and adapters, and those that break those expectations will simply not work properly. (Unfortunately in C++ that usually means spectacular crashes.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The type aliases involved in the above sample are also relatively simple:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;typedef std::istreambuf_iterator  &amp;lt;char&amp;gt;       characters;&lt;br /&gt;typedef buffer_iterator           &amp;lt;characters&amp;gt; buffered;&lt;br /&gt;typedef utf8::unchecked::iterator &amp;lt;buffered&amp;gt;   utf32;&lt;br /&gt;typedef lex_iterator              &amp;lt;utf32&amp;gt;      tokens;&lt;br /&gt;typedef term_iterator             &amp;lt;tokens&amp;gt;     terms;&lt;br /&gt;typedef context_iterator          &amp;lt;terms&amp;gt;      interpreter;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You'll note the use of the standard C++ &lt;code&gt;std::istreambuf_iterator&lt;/code&gt; as well as &lt;code&gt;utf8::unchecked::iterator&lt;/code&gt; from the excellent iterator-centric &lt;a href="http://utfcpp.sourceforge.net/"&gt;UTF8-CPP&lt;/a&gt; library. The &lt;a href="http://www.boost.org/doc/libs/1_47_0/libs/iterator/doc/index.html"&gt;Boost.Iterator&lt;/a&gt; library contains a number of general-purpose iterators and adapters, which may be useful depending on your particular application.&lt;br /&gt;&lt;br /&gt;Note that each operation must refer to the type of the previous operation: this is another reason I'm not terribly fond of C++ for this. Type inference doesn't apply to constructors, so in order to have the compiler infer the type of the composed iterator, you would have to replace the type aliases with template functions that forward to the constructors of the appropriate types. Ugh. C++ requires entirely way too much machinery to accomplish what ought to be simple operations.&lt;br /&gt;&lt;br /&gt;It's equally possible to model interactive applications in this manner. Loops could be represented as cyclical iterators adapting linear sequences to circular ones, and loops with exit conditions could be represented helically. I haven't proved it, but it seems apparent that iterators can model any general recursive algorithm, because at their heart they're just lazy functions plus some state. It also occurs to me that you could use this technique to very easily and efficiently compile a lazy functional language into an imperative one.&lt;br /&gt;&lt;br /&gt;Anyway, I hope this gives my nonexistent readers some interesting ideas. If anyone knows of an imperative language that would be good for this sort of thing, do let me know. I grow tired of C++.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4677468116369936099?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4677468116369936099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/iterators-as-model-of-lazy-computation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4677468116369936099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4677468116369936099'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/iterators-as-model-of-lazy-computation.html' title='Iterators as a Model of Lazy Computation'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4719502583730695105</id><published>2011-09-06T13:11:00.000-04:00</published><updated>2011-09-06T13:11:09.180-04:00</updated><title type='text'>How College Has Been Worth It for Me</title><content type='html'>I've just started my fourth year at &lt;a href="http://www.rit.edu/"&gt;RIT&lt;/a&gt;, which is to be my last as an undergrad. I feel this puts me in a good position to reminisce, so here are some thoughts on my experiences in college.&lt;br /&gt;&lt;br /&gt;First, college has not really been worth it to me academically. I've been programming for a very long time for someone my age, because I like it a lot. I always assumed that when I got to college there would be vast depths of further knowledge to explore in that field. It turned out that there weren't—at least not &lt;i&gt;vast&lt;/i&gt; ones. Pretty much everything I've learned about programming lately I've learned in the same way I always have: on my own, because not very many people know or care about the kinds of things I'm interested in.&lt;br /&gt;&lt;br /&gt;That's not to say that I haven't gained something by being here, but my knowledge has increased in breadth, not in depth. By far the best classes for me have been Creative Writing and the many Chinese language classes I've taken for my minor. I could have studied these things at any liberal arts college and probably learned just as much, but the fact is that I like these professors quite a lot and now I'm biased.&lt;br /&gt;&lt;br /&gt;So how have I benefited from my post-secondary adventures? Socially. I made friends, broke up with a girlfriend who wasn't good for me, started &lt;a href="http://www.youtube.com/whyevernotso"&gt;vlogging&lt;/a&gt;, got a boyfriend, broke up with said boyfriend, and am now in an open relationship with a girl that I like quite a lot and wouldn't mind being involved with for quite a long time. I'm a lot more comfortable in public than I've ever been before.&lt;br /&gt;&lt;br /&gt;So if you're wondering whether college is good for you academically as a self-taught individual: it probably isn't, unless (as I have) you study something completely different than what you've taught yourself already.&lt;br /&gt;&lt;br /&gt;But you can't neglect the importance of spending time getting to know people who share your interests, people you'll probably get along with, people you never imagined you &lt;i&gt;would&lt;/i&gt; get along with. You'll end up with mates, roommates, flatmates, classmates, and sex mates.&lt;br /&gt;&lt;br /&gt;And the thing about humans is that we tend to mate for life.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4719502583730695105?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4719502583730695105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-college-has-been-worth-it-for-me.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4719502583730695105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4719502583730695105'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-college-has-been-worth-it-for-me.html' title='How College Has Been Worth It for Me'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5706723151310865471</id><published>2011-09-06T10:58:00.002-04:00</published><updated>2011-09-17T01:15:40.415-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>How to Live on Your Language</title><content type='html'>&lt;div class="post-text"&gt;So &lt;b&gt;let's say you want to make a living&lt;/b&gt; off writing the next popular language. Assume "making a living" means the equivalent of reasonable pay at a full-time job (any job—not necessarily a technical one). If you really love what you do, you'll probably accept a little bit less to do it, so let's say &lt;b&gt;$12.50 an hour&lt;/b&gt;, or &lt;b&gt;$2000/month&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;While working a stable job, you release your first version and set up a facility for donations. You then engage in continuous development and marketing, to a degree proportional to the number of users of your language. Let's estimate conservatively that &lt;b&gt;1% of your users will donate&lt;/b&gt;, and each of them will donate an average of &lt;b&gt;$1/year&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;That means that in order to get your &lt;b&gt;$2000/month salary&lt;/b&gt;, you need to have &lt;b&gt;2000 donating users&lt;/b&gt; for each of the &lt;b&gt;12 months&lt;/b&gt; in the year. That's &lt;b&gt;2.4 million users&lt;/b&gt; total. Let's now assume that it takes &lt;b&gt;10&amp;nbsp;years&lt;/b&gt; for a language to become this popular: you must therefore acquire an average of &lt;b&gt;240&amp;nbsp;000 users per year&lt;/b&gt;, or &lt;b&gt;20&amp;nbsp;000 users per month&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;If you're working the equivalent of full time (&lt;b&gt;160 hours/month&lt;/b&gt;), your promotion strategy and implementation quality must be sufficient to gain an average of &lt;b&gt;125 users &lt;i&gt;per hour&lt;/i&gt;&lt;/b&gt;. And that's repeat users, of course: if &lt;b&gt;20%&lt;/b&gt; of the people who try your language become repeat users, you actually need a conversion rate of &lt;b&gt;625 people/hour&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Even if &lt;i&gt;every one&lt;/i&gt; of the people you convince directly convinces &lt;i&gt;four more people&lt;/i&gt; to try your language—and for the sake of simplicity, assuming that they don't go on to try to convince others—then you're still back down to the &lt;b&gt;125&amp;nbsp;users/hour&lt;/b&gt; figure.&lt;br /&gt;&lt;br /&gt;Now, this may seem totally unreasonable, but believe it or not it can &lt;i&gt;still&lt;/i&gt; work: say your marketing strategy produces roughly linear growth over the 10-year period during which your language is gaining ground, and then plateaus. That means at the beginning you'll be converting an average of &lt;b&gt;0&amp;nbsp;users/hour&lt;/b&gt;, and 10 years later you'll be gaining &lt;b&gt;250&amp;nbsp;users&lt;/b&gt;. (Again, &lt;i&gt;hourly&lt;/i&gt;. Perspective, here.)&lt;br /&gt;&lt;br /&gt;That's an average increase of &lt;b&gt;25 users per hour per year&lt;/b&gt;: at the end of each year, you're converting &lt;b&gt;25 more people per hour&lt;/b&gt;—or &lt;b&gt;4000 more people per month&lt;/b&gt;—than you were at the start of the year.&lt;br /&gt;&lt;br /&gt;So let's revisit that &lt;b&gt;2.4 million users&lt;/b&gt; ballpark: is it feasible to gain that many users in &lt;b&gt;10&amp;nbsp;years&lt;/b&gt;? If we accept the (inherently flawed, but usable nonetheless) statistics offered by &lt;a href="http://langpop.com/" rel="nofollow"&gt;Langpop&lt;/a&gt; as accurate, we get the following information about the &lt;b&gt;top 7 languages&lt;/b&gt; currently trending through Yahoo search. If one result is accepted as representative of one user (I know, bear with me), these numbers indicate the rounded approximate average number of users gained per year since the language first appeared.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;C++: 500k&lt;/li&gt;&lt;li&gt;C: 400k&lt;/li&gt;&lt;li&gt;Java: 700k&lt;/li&gt;&lt;li&gt;PHP: 400k&lt;/li&gt;&lt;li&gt;Perl: 150k&lt;/li&gt;&lt;li&gt;C#: 300k&lt;/li&gt;&lt;li&gt;Python: 150k&lt;/li&gt;&lt;/ol&gt;This puts things back in the realm of possibility: if you make a language that's as popular as, say, Python, then in &lt;b&gt;20 years&lt;/b&gt; you will have enough users to make development and support (and&amp;nbsp;marketing!) of that language into your full-time job.&lt;br /&gt;&lt;br /&gt;Make one &lt;b&gt;as popular as C#&lt;/b&gt;, and &lt;b&gt;you can do it in 10&lt;/b&gt;. Cool!&lt;br /&gt;&lt;br /&gt;…Except of course that putting it that way trivialises the &lt;i&gt;vastly&lt;/i&gt; unlikely and difficult undertaking that is making a language so popular. But hey, if you've got a good idea, and you can manage to get to the top entirely on your own, without the contributions of any other developers who would take a cut of your donation money, then you're a genius, and you deserve it.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;The original version of this article was posted on &lt;a href="http://programmers.stackexchange.com/questions/83380/whats-the-business-in-developing-a-programming-language/83407#83407"&gt;Programmers.SE&lt;/a&gt; and is duplicated here so I remember where I put it.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5706723151310865471?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5706723151310865471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-to-live-on-your-language.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5706723151310865471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5706723151310865471'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/how-to-live-on-your-language.html' title='How to Live on Your Language'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-1859950198813200679</id><published>2011-09-05T14:12:00.000-04:00</published><updated>2011-09-17T01:15:56.958-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Turing Completeness is not Practical Completeness</title><content type='html'>&lt;br /&gt;As a discussion comparing the relative merits of different programming languages grows longer, the probability of an appeal to Turing completeness as a measure of linguistic equivalence approaches 1. It's practically &lt;a href="http://en.wikipedia.org/wiki/Godwin%27s_law"&gt;Godwin's law&lt;/a&gt; of programming languages.&lt;br /&gt;&lt;br /&gt;Appealing as it is, the notion that whatever is possible in one language is possible in all is &lt;i&gt;simply untrue&lt;/i&gt;. Turing completeness refers merely to the ability to implement any &lt;a href="http://en.wikipedia.org/wiki/Computable_function"&gt;computable function&lt;/a&gt;. There are plenty of &lt;a href="http://en.wikipedia.org/wiki/Esoteric_programming_language"&gt;esoteric languages&lt;/a&gt; that have no or very limited I/O, and plenty of non-esoteric languages that have little to no ability to interface with libraries and other languages.&lt;br /&gt;&lt;br /&gt;The fact that languages &lt;i&gt;do&lt;/i&gt; differ in their strengths and weaknesses is precisely the main reason we use different languages at all. Different tools are best suited to different situations. The next time someone commits this fallacy, point them to the concept of the &lt;a href="http://en.wikipedia.org/wiki/Turing_tarpit"&gt;Turing tarpit&lt;/a&gt;, and if further investigation doesn't prove to them that theoretical equivalence is not the same as practical equivalence, invite them to implement a simple algorithm such as &lt;a href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check"&gt;CRC32&lt;/a&gt; in &lt;a href="http://www.esolangs.org/wiki/Brainfuck"&gt;Brainfuck&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-1859950198813200679?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/1859950198813200679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/turing-completeness-is-not-practical.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1859950198813200679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1859950198813200679'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/09/turing-completeness-is-not-practical.html' title='Turing Completeness is not Practical Completeness'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-3393374225605231975</id><published>2011-07-29T15:58:00.000-04:00</published><updated>2011-09-17T01:16:09.845-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>Oxymoronic: Computer Science &amp; Software Engineering</title><content type='html'>I think I'll kill two birds with this stone. At RIT, there are two main computing majors: Computer Science and Software Engineering. Both of these are misnomers.&lt;br /&gt;&lt;br /&gt;See, Computer Science is concerned primarily with programming as it relates to computing theory. Programming, while certainly related to the design of (reasonably) precise things, is by no means scientific. Science is systematic, rigorous, testable, and predictable. Computer hardware and software alike operate under the illusion of determinism and reliability for the sake of pragmatism alone.&lt;br /&gt;&lt;br /&gt;Further, computing theory is only related to computing insofar as programmers actually implement the mathematical ideas of the theorists. Research is valueless without eventual application.&lt;br /&gt;&lt;br /&gt;Software Engineering, on the other hand, is concerned with programming in the context of project management. It asks what the &lt;i&gt;process&lt;/i&gt; is (or ought to be) for creating software in teams of people according to business requirements. Software engineers also operate under an illusion of determinism and reliability, but their misplaced faith is not in computers—instead their money is on programmers. The fool and his money have parted.&lt;br /&gt;&lt;br /&gt;So computers are fallible, and programmers are fallible, and it's a wonder any of us ever gets anything done at all. The best programmers know the secret of how things are really done in the software world: communication.&lt;br /&gt;&lt;br /&gt;I don't mean meetings, or agile (or worse, Agile), or documentation, or any of dozens of other borderline buzzwords that a manager might throw around. No, I mean the plain and simple fact that &lt;b&gt;programming is writing&lt;/b&gt;, and programmers have the unique task among authors of writing in such a way that &lt;i&gt;both&lt;/i&gt; computers &lt;i&gt;and&lt;/i&gt; humans can readily parse and evaluate their work.&lt;br /&gt;&lt;br /&gt;Of course, any fool can write for one or the other. If I write an informal description of an algorithm on paper, it's perfectly human-readable; if I write a formal implementation of an algorithm in heavily optimised machine code, then it's perfectly computer-readable.&lt;br /&gt;&lt;br /&gt;And this is why I hate the word &lt;i&gt;code&lt;/i&gt;. If you call it “coding” for a computer, then the quality of your writing from a human perspective is probably &lt;i&gt;utter trash&lt;/i&gt;. Don't get me wrong, of course: for a first draft, utter trash is perfectly acceptable provided it can still convey the intended meaning.&lt;br /&gt;&lt;br /&gt;But for a final draft, a certain amount of editing is necessary. Programmers differs from writing in another key aspect: though neither a program nor a work of prose is ever truly complete (&lt;i&gt;final draft&lt;/i&gt; is an oxymoron as well), you must release both sometime; the difference is that a program, like a work of nonfiction, can be updated in editions to maintain freshness and currency.&lt;br /&gt;&lt;br /&gt;Programming is like creating a diamond from scratch. When you code, you make the stone. You may then polish what's there and cut what shouldn't be, but both the &lt;i&gt;colour&lt;/i&gt; and the &lt;i&gt;clarity&lt;/i&gt; of that stone are immutable. No amount of refactoring will fix an idea that was poorly styled or unclear from the outset.&lt;br /&gt;&lt;br /&gt;In conclusion, I might add that I insist that programming is &lt;i&gt;not&lt;/i&gt; art. I believe this simply because I'm not good at art, but I am good at programming. I'm also good at design and craft, and that's what I believe programming is.&lt;br /&gt;&lt;br /&gt;Programming is writing for one audience who seemingly doesn't understand you but is also endlessly critical, and simultaneously for another who seemingly understands you but is also painfully literal. It is writing manuals and dictionaries and phrasebooks to help these two disparate audiences communicate. It's logical, illogical, philological, analogical, anthropological, and frequently epistemological.&lt;br /&gt;&lt;br /&gt;I fucking love it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-3393374225605231975?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/3393374225605231975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/oxymoronic-computer-science-software.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3393374225605231975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/3393374225605231975'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/oxymoronic-computer-science-software.html' title='Oxymoronic: Computer Science &amp; Software Engineering'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4185307052961495486</id><published>2011-07-29T01:02:00.000-04:00</published><updated>2011-09-17T01:16:28.152-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Politics'/><title type='text'>Oxymoronic: Pharmaceutical Company</title><content type='html'>There is a magical place where geniuses in white coats carry out research and produce remedies in the everlasting fight against human ailment. Most of them do what they do because they want to help people. The rest of them are businessmen (and women). Businessfolk are in the business of turning the work of the workers into the business of the businessfolk. By “the business of the businessfolk”, I naturally mean “the money of the businessfolk and the investors, and to a certain extent the workers as well, and to a much smaller extent some philanthropy and humanitarian aid to keep up appearances”.&lt;br /&gt;&lt;br /&gt;So therein is the oxymoron: while you started your pharmaceutical company with good intentions, trying to reduce human suffering, now you don't want to reduce it at all, because when human suffering decreases, you'll see an equal decline in the sales of your remedies. That represents an equal decline in the funding available for your workers to carry out your research, which represents a loss of research, which allows ailments to propagate unfettered and suffering to &lt;i&gt;increase&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Ordinarily I don't believe in doing things for the sake of doing things, but as a pragmatist, my objective morality compels me to pursue the path of least human suffering, as well as the path of least absurd complexity, which in this case means making a slightly unusual suggestion:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pharmaceutical companies should not be companies. They should be government services.&lt;/b&gt; And before you say that our government is too far in debt to be creating more services, why don't we cut everything that &lt;i&gt;isn't&lt;/i&gt; a public service and just see if the simplest concept isn't really the best?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4185307052961495486?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4185307052961495486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/oxymoronic-pharmaceutical-company.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4185307052961495486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4185307052961495486'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/oxymoronic-pharmaceutical-company.html' title='Oxymoronic: Pharmaceutical Company'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-2625555754498834899</id><published>2011-07-29T00:42:00.000-04:00</published><updated>2011-09-17T01:16:38.537-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>On Brilliance</title><content type='html'>You are brilliant, but you don't know that the following things are true: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Your work is meaningless until proven meaningful; don't complain, work.&lt;/li&gt;&lt;li&gt;You do not have to be an insufferable asshole; you probably will anyway.&lt;/li&gt;&lt;li&gt;You are not better because you are smarter; you are worse for believing you are.&lt;/li&gt;&lt;li&gt;The world is not a meritocracy; your sense of entitlement is undeserved.&lt;/li&gt;&lt;li&gt;Intelligence is not a skill; you have to be able to &lt;i&gt;do&lt;/i&gt; something.&lt;/li&gt;&lt;li&gt;The truth is not self-evident; you &lt;i&gt;do&lt;/i&gt; have to explain.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.uie.com/brainsparks/2011/07/08/beans-and-noses/"&gt;You can't stop people from sticking beans up their nose&lt;/a&gt;; it won't stop you from trying.&lt;/li&gt;&lt;li&gt;You are a fool; wisdom comes only from knowing the depth of your own folly.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-2625555754498834899?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/2625555754498834899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/on-brilliance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/2625555754498834899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/2625555754498834899'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/on-brilliance.html' title='On Brilliance'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-2116803733948254356</id><published>2011-07-06T16:38:00.001-04:00</published><updated>2011-09-17T01:16:50.058-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Why Closures?</title><content type='html'>In a language with reasonably rich partial function application, it seems to me that there's very little need for implicit closures. In pseudocode:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;greeter = λname.&lt;br /&gt;    message = 'Hello, ' + name + '!'&lt;br /&gt;    return λε. print(message)&lt;br /&gt;&lt;br /&gt;greeter("world")()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Could easily be rewritten explicitly as something along the lines of:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;greeter = λname.&lt;br /&gt;    message = 'Hello, ' + name + '!'&lt;br /&gt;    return λm. print(m) fix message&lt;br /&gt;&lt;br /&gt;greeter("world")()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Where `fix` is an operator accepting a lambda and some parameters and returning a new lambda with the given parameters fixed, that is, &lt;code&gt;λx. f(x) fix y&lt;/code&gt; is identical to &lt;code&gt;λε. f(y)&lt;/code&gt;. With the appropriate consideration given to reference semantics, this would have exactly the same effect; indeed, C++0x lambdas can be written with explicit closures exclusively:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;return [&amp;amp;message]() -&amp;gt; void { std::cout &amp;lt;&amp;lt; message; }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Supporting implicit capture not only complicates implementation; as with exceptions and globals, implicit capture reduces locality and makes analysis more difficult. Limiting functions to explicit capture requires support for lambdas with multiple parameters, because you cannot write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sub = λx. λy. (x - y)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Instead you must write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sub = λx, y. (x - y)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Which lends itself to partial application quite nicely:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;neg = sub(0)&lt;br /&gt;ident = sub(?, 0)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;It would seem, then, that the primary reason for supporting implicit capture is historical, namely the roots of functional programming in the lambda calculus. And really, since implicit capture is the basis of scope, the fact that a functional language can easily survive without it calls into question whether the concept of scope is necessary or good. Functional programming is all about making state explicit, after all. Why not hold a function accountable not only for values it uses, but also for operations? I intend to play with this idea in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-2116803733948254356?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/2116803733948254356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/in-language-with-reasonably-rich.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/2116803733948254356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/2116803733948254356'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2011/07/in-language-with-reasonably-rich.html' title='Why Closures?'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5351627622667940774</id><published>2010-10-24T19:27:00.000-04:00</published><updated>2011-09-17T01:16:58.999-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>Error Message Pun</title><content type='html'>This came up in conversation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;void monopoly() {&lt;br /&gt;    goto jail;&lt;br /&gt;    int go = 0;&lt;br /&gt;jail:&lt;br /&gt;    return;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main() { monopoly(); }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In GCC, it produces the error:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;monopoly.cpp: In function `void monopoly()':&lt;br /&gt;monopoly.cpp:4: error: jump to label `jail'&lt;br /&gt;monopoly.cpp:2: error:   from here&lt;br /&gt;monopoly.cpp:3: error:   crosses initialization of `int go'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Haw haw haw I'm done. A more substantial post is coming soon. Hope you had a good weekend.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5351627622667940774?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5351627622667940774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/10/error-message-pun.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5351627622667940774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5351627622667940774'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/10/error-message-pun.html' title='Error Message Pun'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-7988262911457898557</id><published>2010-10-20T13:17:00.001-04:00</published><updated>2010-10-20T18:23:16.964-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><title type='text'>BarCamp Rochester</title><content type='html'>So somebody on campus decided a couple of weeks ago that it'd be a good idea to organise a &lt;a href="http://en.wikipedia.org/wiki/BarCamp"&gt;BarCamp&lt;/a&gt; here in Rochester this coming weekend. I thoroughly approve of the BarCamp philosophy, and saw this as a great excuse to yammer about Prog for a while to a group of people who might be interested &lt;em&gt;and&lt;/em&gt; understand anything I say. Heady stuff.&lt;br /&gt;&lt;br /&gt;Anyway, I've been putting together a presentation on the current state of programming languages, their future, and Prog's particular approach to bridging the gap. Prog is thoroughly under-documented and constantly undergoing minor revisions as I work on it, but now that I'm forcing myself to speak about it cohesively, I've been forced to cohere many of my thoughts. In order to help myself get these ideas down, and in order to ensure that they're recorded in full in case my public speaking skills fail me, here's basically what I'll be talking about on Saturday.&lt;br /&gt;&lt;br /&gt;There's not a lot of disagreement in the major points of where programming languages are headed:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Functional Programming&lt;/strong&gt; (or something like it)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Concurrency&lt;/strong&gt; that doesn't make your head cave in&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Static Typing&lt;/strong&gt; to structure development&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Type Inference&lt;/strong&gt; to eliminate potential boilerplate from static typing&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Generic Programming&lt;/strong&gt; for modularity and clarity&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Functional programming is associated with declarative rather than imperative style, the importance of data flow over control flow, immutability of data rather than mutable state, referential transparency of functions, and, as a result of all of these, strong support for concurrency. Unfortunately, FP has consistently been seen as something of an academic, ivory-tower pursuit, despite its obvious utility and even ubiquity. In most functional languages, it's no more awkward to manage state and exceptions than in most imperative languages; the difference is how &lt;em&gt;relevant&lt;/em&gt; state is to program flow and correctness. Consequently, FP is seen as having a high barrier to entry because it feels very alien to CS students who, these days, are all spoon-fed Java. Peh.&lt;br /&gt;&lt;br /&gt;Prog draws a few important concepts from functional programming:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;All types are immutable by default&lt;/li&gt;&lt;li&gt;Pure, constant functions can be evaluated statically&lt;/li&gt;&lt;li&gt;&lt;em&gt;Operations&lt;/em&gt; and &lt;em&gt;algorithms&lt;/em&gt; are more important than &lt;em&gt;objects&lt;/em&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Now, about concurrency. It's become obvious to everybody and their aunt that concurrent programming is where it's at, or at least, where it will be. Processors have increasingly many cores, and distributed, high-volume systems are commonplace even now. There are a few approaches to concurrent programming, and the one most likely to fail is of course the object-oriented one. I don't mean to be too harsh on OO (at least, not right now), but there's wide agreement that explicit threading and locking in a system designed around mutable objects is difficult. And programmers will eventually give up technologies and philosophies that get in the way of their ability to &lt;em&gt;get stuff done&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;The alternatives, though, are promising. The &lt;a href="http://en.wikipedia.org/wiki/Actor_model"&gt;Actor model&lt;/a&gt; is a sound mathematical model of concurrent computation that allows, among other things, formal proofs of program correctness (or, more accurately, the absence of program incorrectness) in concurrent systems. Implicit parallelisation is commonplace in languages without mutable state such as &lt;a href="http://www.haskell.org/haskellwiki/Introduction"&gt;Haskell&lt;/a&gt;, and even explicit threading is becoming more lightweight and manageable in languages such as &lt;a href="http://golang.org/"&gt;Go&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The main problem with concurrency, I think, has been that it's easy to understand but hard to implement, and difficult to verify when trying to account for edge cases, especially in systems based on state. And for ages people have been complaining that immutability makes concurrency easy &lt;em&gt;but&lt;/em&gt; mutability is nice and natural for a vast number of applications. What we're seeing, then, is a disparity between &lt;em&gt;the needs of programmers&lt;/em&gt; and &lt;em&gt;the hardware they're working with&lt;/em&gt;. And hardware insists on going in a difficult direction.&lt;br /&gt;&lt;br /&gt;So how does Prog handle concurrency? Well, as in Haskell, unrelated and pure operations can be implicitly parallelised, and the &lt;em&gt;type system&lt;/em&gt; provides the required &lt;em&gt;granularity:&lt;/em&gt; spawning too many small threads is inefficient in terms of thread-creation overhead, but spawning too few large threads is inefficient in terms of lost parallelisation opportunities. Explicit threading in Prog is still cheap because it's simply a hook into the type system to &lt;em&gt;encourage&lt;/em&gt; (but not require) automatic parallelisation.&lt;br /&gt;&lt;br /&gt;Further, Prog has intrinsic support for software transactional memory (STM) using so-called &lt;em&gt;atomic regions&lt;/em&gt;, which, again, imbue a scope with type information that causes all operations, and the group of operations as a whole, to become atomic (which, for mutable objects, means implicit locking).&lt;br /&gt;&lt;br /&gt;In Prog, values have the inherent capability of receiving and acting upon messages; this is simply inversion of control between a function and its arguments. So while in some sense Prog is like Ruby, where &amp;ldquo;everything is an object&amp;rdquo;, it is also like lambda calculus, where &amp;ldquo;everything is a function&amp;rdquo;. In Prog there is little to distinguish values from functions, just as there is little to distinguish values from types or even metatypes.&lt;br /&gt;&lt;br /&gt;So communication between threads is handled using this messaging facility, and a call from one thread to a function in another behaves identically to a thread-local call. Immutable data are shared implicitly, while mutable data are shared explicitly but locked implicitly.&lt;br /&gt;&lt;br /&gt;Now, about static typing. A static type system significantly simplifies the processes of static correctness analysis, improves maintainability by localising changes and making errors detectable at compile-time, and creates some measure of assurance of consistent program behaviour. When safety constraints are known and enforcible at compile-time via the type system, the theoretical correctness and consistency of a program becomes much more trustworthy. In addition, purely static typing implies a certain degree of runtime performance improvement over purely dynamic typing.&lt;br /&gt;&lt;br /&gt;Prog's type system is static and strictly enforced. A single variant type provides a consistent interface for both dynamic typing and generic programming. As previously stated, all types are immutable unless explicitly qualified as mutable. Types and values are indistinguisable, and static assertions based on type inference are the basis of correctness in generic programming. An expression can be imbued with a context type, which may improve the performance of or otherwise affect its evaluation. As a result of context-selection, unlike in many other languages, Prog functions can be overloaded on return type alone.&lt;br /&gt;&lt;br /&gt;Type inference is an absolute necessity in a statically typed system. For one thing, it reduces boilerplate (e.g., C++0x lets you type &lt;code&gt;auto&lt;/code&gt; when you don't feel like typing &lt;code&gt;std::list&amp;lt;std::map&amp;lt;std::string, int&amp;gt;&amp;gt;::const_iterator&lt;/code&gt;), but it's also essential in generic programming to be able to perform known operations on values of unknown type. Type inference is closely related to overloading: a good example of this is to be found in C++, where function template parameters can be inferred from function arguments. Ideally, type inference does away with needless casting, making necessary casts stand out as hazardous or incorrect. It improves syntactical clarity, and naturally becomes generic programming.&lt;br /&gt;&lt;br /&gt;Prog's type inference capabilities are numerous. First, objects are implicitly declared upon their first use, and imbued with the type of their initialiser. Overloading occurs both statically and dynamically, entirely depending on the types that are actually used. Any necessary casts are carried out using explicit, loud, scary, easy-to-find casting operators, and otherwise the syntax is completely freed from any mention of typing where it's not needed. And the type system comes to our aid once more, and ensures that immutability guarantees static evaluation: if an expression is constant, it's statically evaluable; if the type of an expression is constant, it's statically inferable.&lt;br /&gt;&lt;br /&gt;Now, here comes the good stuff. I could ramble about generic programming all day. The most common exposure to generic programming that people have in the OO world is templates (or &amp;ldquo;generics&amp;rdquo; if you're from &lt;em&gt;that&lt;/em&gt; camp). But if you haven't read the work of Alexander Stepanov, you simply must. Generic programming is not just about generic types, but also about generic algorithms and the abstract properties of data structures, most importantly their complexity requirements and guarantees.&lt;br /&gt;&lt;br /&gt;Generic programming at its best relies heavily on the iterator model, but Prog generalises this to include ranges as well, which are, at their heart, syntactic sugar for iterators. Prog provides the external constraints that make generic programming possible via the type system. Generic algorithms in Prog can simply accept variant instances and rely on the type system to handle static versus dynamic evaluation, mutability guarantees, and so on. Explicit static assertions verify preconditions and postconditions and protect invariants. Algorithms are thus exposed as cleanly as possible, complexity guarantees are in some cases statically verifiable, and the Prog type system makes all of this super-easy.&lt;br /&gt;&lt;br /&gt;As an example, here's a naive C++ implementation of &lt;code&gt;max&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;template&amp;lt;class T&gt;&lt;br /&gt;const T&amp;amp; max(const T&amp;amp; a, const T&amp;amp; b) {&lt;br /&gt;  return b &amp;lt; a ? a : b;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;template&amp;lt;class T&gt;&lt;br /&gt;T&amp;amp; max(T&amp;amp; a, T&amp;amp; b) {&lt;br /&gt;  return b &amp;lt; a ? a : b;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This returns the maximum of two values, and is overloaded to accept either constant or non-constant values, such that it can be used as either an rvalue or an lvalue. The Prog equivalent does not require such explicit differentiation, though for strict equivalence with the above it does require a static check that the two values are of the same type:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;def max(a : any&amp;amp;, b : any&amp;amp;) : any&amp;amp; {&lt;br /&gt;  assert @a == @b;&lt;br /&gt;  b &amp;lt; a ? a : b&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here's another short example of how software transactional memory is expected to work:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;def transfer(a : mutable Account&amp;, b : mutable Account&amp;,&lt;br /&gt;    x : int) : bool {&lt;br /&gt;&lt;br /&gt;    atomic {&lt;br /&gt;        a.withdraw(x);&lt;br /&gt;        b.deposit(x);&lt;br /&gt;    } except prog::atomic_abort {&lt;br /&gt;        return false;&lt;br /&gt;    };&lt;br /&gt;    return true;&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And at this point the talk will degenerate in to Q-and-A, but this is a blog, so I guess I'm done rambling. It's not as though I have a massive amount of readership anyhow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-7988262911457898557?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/7988262911457898557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/10/barcamp-rochester.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7988262911457898557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/7988262911457898557'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/10/barcamp-rochester.html' title='BarCamp Rochester'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5095645346129780239</id><published>2010-10-03T21:11:00.001-04:00</published><updated>2010-10-20T18:23:45.985-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><title type='text'>A Walk in the Woods</title><content type='html'>When I need to get some really good thinking done, I've learned that there's nothing better for me than to relax and avoid thinking at all for a while. My brain is so glad for the brief holiday that it returns to work with renewed vigour, and accomplishes things as though it was working diligently the whole time I wasn't communicating with it.&lt;br /&gt;&lt;br /&gt;There are few places where I can really get into this state—the shower is one that I have in common with many others, but a shower can reasonably be only so long for a number of reasons. Another good place is graveyards: the dead tend to be pretty accommodating hosts when it comes to quiet thinkers.&lt;br /&gt;&lt;br /&gt;But I think the best place for me is the woods. Going for a long walk in the woods, trying in vain to confound my irritatingly accurate sense of direction, and getting some exercise are all great things, but they're even better when I get to go for a walk with the deer.&lt;br /&gt;&lt;br /&gt;Yes, you read that right. The area around RIT is swarming with deer. On a recent late-night walk, I saw no fewer than a dozen by the side of the road, and that's no exaggeration. So it came as little surprise to me this evening when I ran into a couple of does in the forest.&lt;br /&gt;&lt;br /&gt;Now, RIT deer are fairly docile. You'll never get them to eat out of your hand, but they won't spook if you're reasonably nice to them. Usually announcing your presence in a soothing voice and talking to them occasionally is enough to dispel their fears and let you get as close as five feet from them. One was still young and the other fully grown, and the fawn was noticeably more skittish than the adult, so kept her distance more.&lt;br /&gt;&lt;br /&gt;I was able to walk with them for quite some time before they decided it'd be a good idea to cross a stream, and, clad in sneakers as I was, I wasn't prepared to slog through ankle-deep mud and knee-deep water. So I made my way through the dry part of the swamp to a hillock where I read Dracula and watched the sunset.&lt;br /&gt;&lt;br /&gt;Why am I telling you all of this? What does this have to do with programming or linguistics? Not much, really, but it is kinda nice, and people like stuff like that. And anyway, it got me thinking about the universality of expression, which is something we humans seem to not just take for granted, but often entirely ignore. An animal can understand your intent and your emotions even if it can't grasp the meaning behind what you're saying. Hell, a human can, too; we're not immune. Tone of voice and body language are enormously important, and yet we seem to always get lost in the intricacies of verbalisation.&lt;br /&gt;&lt;br /&gt;We should probably just relax and eat some acorns.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5095645346129780239?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5095645346129780239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/10/walk-in-woods.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5095645346129780239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5095645346129780239'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/10/walk-in-woods.html' title='A Walk in the Woods'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5437329993519636338</id><published>2010-09-30T15:42:00.007-04:00</published><updated>2011-09-17T01:17:29.049-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='User Interfaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Design'/><title type='text'>Threateningly User Interface Toolkits</title><content type='html'>The topic of cross-platform GUI toolkits has been beaten so far past death that it must be in some deep level of undeath by now. Programmers want to be able to develop cross-platform software that's consistently pretty no matter what the environment, and they want to be able to do it regardless of language. In theory, this is a great idea, and a number of &lt;i&gt;theoretically&lt;/i&gt; great user interface libraries have been created with this goal in mind. In practice, however, GUI libraries lack consistent idioms, have arcane internals, require significant runtime support, and have an API that is specific to one language or else limited to an arcane C FFI that reflects neither the idioms of the host language nor even of the toolkit itself.&lt;br /&gt;&lt;br /&gt;Clearly, this is not ideal. So what solutions are there? I think perhaps it's more interesting to look at the failings of existing solutions, in order to arrive at some common failure set that can be singly addressed.&lt;br /&gt;&lt;br /&gt;I'll start with Java. It's not my favourite language, by any means; I don't find the object-oriented paradigm particularly valuable or useful, and many other features of Java's design make it appear to me to be a "money language", a misguided attempt on the part of Sun to turn language design into profit. (Or if it's not misguided, then it's surely evil.) Java's decision to have a UI toolkit bundled with the standard library is simultaneously very wise and very foolish. On the one hand, you can start writing a graphical program in Java using only the tools that you have on a fresh install of the JDK, and the runtime requirements are fulfilled by the JRE. On the other hand, using any other interface toolkit, whose idioms might be better suited to a particular application, is horrifically unnatural and usually requires foreign language bindings or a Java wrapper. Admittedly, this is primarily a symptom of a VM architecture, whose own pros and cons are outside the scope of this post.&lt;br /&gt;&lt;br /&gt;So Java's approach to UI toolkits is restrictive but idiomatic. Okay.&lt;br /&gt;&lt;br /&gt;Now how about C? Well, you can use the native user interface functions on Windows (which I can't imagine anyone actually putting themselves through anymore, though apparently it is still done), or use another library with C bindings such as GTK+. The benefit to the latter is that libraries that expose only a C API tend not to be over-designed: presenting a clean API usually means maintaining clean internals, and this is a Good Thing. Unfortunately, the procedural medium for user-interface design is somewhat restrictive and unnatural. This is a problem primarily when the API does not naturally provide for a data-driven interface, forcing the programmer to either jump through hoops to add data bindings to the UI, or else duplicate all of their state between logic and presentation.&lt;br /&gt;&lt;br /&gt;So C-API toolkits are flexible but archaic. Alright.&lt;br /&gt;&lt;br /&gt;Arguably, some UI projects originally conceived as wrappers for C-style toolkits have been developed so intelligently as to present a flexible &lt;i&gt;and&lt;/i&gt; idiomatic interface with minimal hassle. In this regard, I think &lt;a href="http://www.gtkmm.org/en/"&gt;gtkmm&lt;/a&gt; is the ideal choice for C++, despite some minor GTK+ runtime support issues on Windows.&lt;br /&gt;&lt;br /&gt;But even gtkmm is not ideal. All of these toolkits have one thing in common that makes them painful to use in many sorts of applications where the UI cannot directly correspond with the underlying model: they are all &lt;i&gt;frameworks&lt;/i&gt; and not &lt;i&gt;libraries&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;The crucial difference between framework and library is control: a framework imposes its structure on an application that uses it, while a library lives only to serve and stay as much as possible out of the way.&lt;br /&gt;&lt;br /&gt;So my thinking is that an ideal user interface toolkit would have the following characteristics:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It would be a library, staying lightweight and unobtrusive.&lt;/li&gt;&lt;li&gt;It would be flexible, allowing new components to be created easily.&lt;/li&gt;&lt;li&gt;It would be natural and neutral, using UI design idioms that span language boundaries.&lt;/li&gt;&lt;li&gt;It would be fully data-driven: UI components would contain no data of their own.&lt;/li&gt;&lt;li&gt;It would require minimal runtime support.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In view of these goals, I think the best model is OpenGL. An unnatural choice, you might say, but I think the concept is perfect: a procedural interface to an open standard of primitives from which any user interface can be created.&lt;br /&gt;&lt;br /&gt;I know I said procedural interfaces are bad for UI, but only if you're trying to force high-level concepts such as buttons and scroll views into a set of procedure calls. We need to &lt;i&gt;really&lt;/i&gt; get back to basics, here: margins, padding, anchoring, layout, and rendering.&lt;br /&gt;&lt;br /&gt;Runtime support would come in the form of an extremely lightweight cross-platform core (similar to &lt;a href="http://www.libsdl.org/"&gt;SDL&lt;/a&gt;) that would provide the minimal bindings for getting a native window up and running and drawing some damn components. Absolutely everything else would come from the application side, so libraries, theme engines, etc. could be trivially written atop the core specification.&lt;br /&gt;&lt;br /&gt;Now, speculation of this sort is all well and good, but it is indeed just speculation, and people will get tired of me if I ramble about possible futures rather than practical realities. Therefore, I'm going to prove that what I detail is not only &lt;i&gt;possible&lt;/i&gt;, but also &lt;i&gt;necessary&lt;/i&gt; and &lt;i&gt;relevant&lt;/i&gt;. I'm going to make this thing.&lt;br /&gt;&lt;br /&gt;Just see if I don't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5437329993519636338?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5437329993519636338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/09/threateningly-user-interface-toolkits.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5437329993519636338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5437329993519636338'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/09/threateningly-user-interface-toolkits.html' title='Threateningly User Interface Toolkits'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4593200990568164532</id><published>2010-09-25T10:35:00.003-04:00</published><updated>2010-09-30T16:15:57.682-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Poetry'/><title type='text'>Haunting</title><content type='html'>One day I found a tale of old&lt;br /&gt;whose name I'd known but failed to seek,&lt;br /&gt;and reading it consumed my night&lt;br /&gt;till I retired, satisfied,&lt;br /&gt;but fell into such fevered dreams&lt;br /&gt;as ne'er had I experienced&lt;br /&gt;that when I woke did not depart&lt;br /&gt;and haunted me throughout the day.&lt;br /&gt;&lt;br /&gt;I went about my daily life,&lt;br /&gt;in hopes my madness soon would end,&lt;br /&gt;but fell into anxiety&lt;br /&gt;with paranoia calling me.&lt;br /&gt;I would not go; I could not stay.&lt;br /&gt;I grappled with the rationale&lt;br /&gt;that this was all a side-effect&lt;br /&gt;of what I had consumed last night.&lt;br /&gt;&lt;br /&gt;Eventually it did depart.&lt;br /&gt;My thoughts regained their normal state.&lt;br /&gt;But I cannot quite shake the thought&lt;br /&gt;that something changed inside me then.&lt;br /&gt;Beware the thoughts of writers who&lt;br /&gt;would prick you with their wicked pens.&lt;br /&gt;Beware the words of others, friend;&lt;br /&gt;it will make all the difference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4593200990568164532?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4593200990568164532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/09/haunting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4593200990568164532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4593200990568164532'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/09/haunting.html' title='Haunting'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5813443799701812510</id><published>2010-09-10T19:38:00.002-04:00</published><updated>2010-09-30T16:17:32.114-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Language Hate</title><content type='html'>Users of &lt;a href="http://www.stackoverflow.com/"&gt;StackOverflow&lt;/a&gt; will no doubt have seen a certain very popular community-wiki question: &lt;a href="http://stackoverflow.com/questions/282329/what-are-five-things-you-hate-about-your-favorite-language"&gt;What are five things you hate about your favorite language?&lt;/a&gt; It comes from &lt;a href="http://use.perl.org/~brian_d_foy/journal/32556"&gt;Brian D. Foy's journal&lt;/a&gt; on the same subject, wherein he suggests that those who cannot find five things to hate about a given programming language (such as design flaws, warts, or general annoyances) "don't know the language well enough to either advocate it or pull in the big dollars using it".&lt;br /&gt;&lt;br /&gt;In large part, this is true. Conversely, I think there's a lot of unfounded language hate out there, and people who make claims about the purportedly inferior quality of a language typically &lt;em&gt;also&lt;/em&gt; don't know said language well enough to make such claims. The reality is that there are simply a lot of people out there who are either simply misinformed, or worse, making arbitrary assumptions about languages that they neither know nor understand, and this is principally because they're afraid.&lt;br /&gt;&lt;br /&gt;When you don't know a technology, it looks opaque at best, and hideous at worst. If a programmer doesn't experience an instant passionate attraction to a language (and, believe me, this is about as rare as it gets), the natural reaction is often to go exactly the opposite route and hate on it for no reason. This is the source of innumerable blog entries and forum posts excruciatingly detailing the author's visceral negative reaction, which typically goes something like this:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Installed new language.&lt;/li&gt;&lt;li&gt;Ran "hello world".&lt;/li&gt;&lt;li&gt;Left alone for a while.&lt;/li&gt;&lt;li&gt;Decided to attempt mid-size project in language.&lt;/li&gt;&lt;li&gt;Became frustrated when new language didn't work like old language.&lt;/li&gt;&lt;li&gt;Gave up.&lt;/li&gt;&lt;li&gt;Ranted about the failings of new language.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;All of this is kind of a prelude to the important issue here: what I think. (After all, this is my blog.) Now, I can't say that language choice is wholly &lt;em&gt;immaterial&lt;/em&gt;, as every language has its own strengths and weaknesses that should be appreciated even when the language itself is not suited to one's own needs. Take &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;, for instance. I have never used Erlang, nor do I plan to do so in the near future. However, I can certainly appreciate the beauty of the syntax, the tightness and purity of the type system, and, of course, the breathtakingly simple concurrency support. Finding things to praise about a language that you know very little about is the first step toward actually getting yourself to sit down and &lt;em&gt;learn&lt;/em&gt; it the way it was meant to be learned: standing on its own, with its own idioms, subtleties, strengths, &lt;em&gt;and&lt;/em&gt; weaknesses.&lt;br /&gt;&lt;br /&gt;But that brings me back around. Anyone who knows me knows I use C++ more than anything else, and there is only one reason for this: it doesn't get in my way. If I can come up with a program, chances are I'll be able to implement it efficiently, robustly, and, using appropriate idioms and libraries, quickly. Further, I don't pay a hidden cost for features that I don't use, which to me is another very important aspect of a language.&lt;br /&gt;&lt;br /&gt;But what do I hate about C++? Ha! That I could limit it to only five things! In essence, everything I hate about C++, or any language that I use, is any "feature" or peculiarity that gets in the way of &lt;a href="http://www.hhhh.org/wiml/virtues.html"&gt;The Virtues of a Programmer&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Laziness&lt;/strong&gt;: C++ makes me type. I may be a blazing fast typist. I may even have changed my keyboard layout to avoid as much as possible having to hit the Shift key while programming. But if there's anything about C++ that I dislike, it's the boilerplate. I'll be honest, I'm lazy. I like my editor to generate boilerplate code for me, but I also like it to generate it exactly as though I had typed it, which quite often is not possible. Thus C++ irritates my laziness.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Impatience&lt;/strong&gt;: C++ makes me jump through hoops to express certain common ideas that are not natural to the language, and this is only slightly ameliorated by use of the (rather well designed) STL. I am impatient, and I want my program do be done as soon as possible so I can start using it and showing it off. Thus C++ irritates my impatience.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Hubris&lt;/strong&gt;: C++ makes it difficult to maintain standards of code quality. While this is a natural trade-off against the raw expressive power of the language, C++ is definitely biased toward pragmatism in lieu of elegance and purity. I have seen the horrors of bad C++ code, from the run-of-the-mill C written in C++ to the sort of stuff with a comment above it saying just &lt;code&gt;I'm sorry&lt;/code&gt;. But I digress.&lt;br /&gt;&lt;br /&gt;If I haven't made these bad qualities seem bad enough, you're probably right. But they're the things that bother me on a day-to-day basis, and putting them up against the well-known Virtues is a good way of illustrating the reason behind the hate, without going into too much language-specific detail. In the context of these virtues, it becomes quite easy to analyse certain qualities about your preferred language that you like or dislike.&lt;br /&gt;&lt;br /&gt;I would be remiss if I didn't go on to admit something that many who meet me are surprised to discover: I dislike Python. I've hardly used Python, and I already very much dislike it. It's simply a tool that I don't want to be involved with unless it's an absolute necessity.&lt;br /&gt;&lt;br /&gt;Why? That's easy. The fundamental philosophy of Python is "there should be one, and preferably only one, obvious way to do it", designed as the antithesis of Perl's &lt;a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it"&gt;TMTOWTDI&lt;/a&gt;. This is in direct conflict with my views as a programmer, a linguist, and a human being. Bold words, eh?&lt;br /&gt;&lt;br /&gt;Don't get me wrong. This philosophy is quite well integrated into the design of Python, and on the whole I have to praise it for its simplicity and relative consistency despite its massive growth over the years. But &lt;em&gt;I simply can't abide prescriptivism&lt;/em&gt;. TMTOWTDI expresses an analysis of the real situation of programming and linguistics. There really &lt;em&gt;is&lt;/em&gt; more than one way to write any given program, in the same way that there is more than one way to say a phrase. There are idioms, subtleties, and nuances. There is &lt;em&gt;craftsmanship&lt;/em&gt;. Is it any surprise that Larry Wall was a student of linguistics, while Guido Van Rossum studied mathematics and computer science?&lt;br /&gt;&lt;br /&gt;It all comes down to pragmatism versus elegance, and for me, despite my obsession with precise, beautiful code, writing an ugly program that works is better than writing a beautiful program that does nothing.&lt;br /&gt;&lt;br /&gt;The only other reason I have for disliking Python is a very small nitpick: its syntax. No, I don't mean whitespace; I'm fine with that bit. It's just that human languages have loads of redundancy and compressibility and texture, which combined make it easy to read and comprehend running text at high speed. Python's syntax is deliberately minimalistic, and consequently there's very little for the eye to hold on to, so the reading rate is (for me) drastically lowered. It's the same reason I have trouble reading Lisp and even its kid brother Scheme, pretty little thing though the latter is.&lt;br /&gt;&lt;br /&gt;This is the very same reason that I can never get myself to really learn Spanish or Italian, though I can already understand quite a bit from my knowledge of French and Latin. A phonetic orthography decreases the amount of redundancy in a word, reducing the ability to compensate for errors, and consequently reducing the reading rate. Like I said, only a minor problem.&lt;br /&gt;&lt;br /&gt;Anyway, I strongly encourage you to look at your own preferred language and ask yourself what you hate about it, or take a language you think you hate, and ask yourself what there is to like. Especially if you're designing a programming language, this can provide some startling insight into what tools you, as a programmer, need to be developing and using.&lt;br /&gt;&lt;br /&gt;I think that's about it for today. Good night, and good luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5813443799701812510?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5813443799701812510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/09/language-hate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5813443799701812510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5813443799701812510'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/09/language-hate.html' title='Language Hate'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-9133473482247427245</id><published>2010-08-26T09:33:00.002-04:00</published><updated>2010-09-30T16:17:24.751-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><title type='text'>Macript</title><content type='html'>As I write, I'm reinstalling Linux because an upgrade fried my ability to boot. After backing up my home directory onto my Windows partition, I decided I needed something to do while downloading installation files. So I was going through some of the little one-off projects that I've done over the past few months, and decided to write about this one.&lt;br /&gt;&lt;br /&gt;I call it Macript, a portmanteau of "macro" and "script". It's a short Perl program that reads a source file, scans it for anything that looks like a macro invocation, tests for whether a script by that name exists in the directory where Macript was invoked, and, if it does, expands the invocation to the standard output result of running that script with whatever arguments happen to be given via the macro.&lt;br /&gt;&lt;br /&gt;That's pretty much it. And let me say, as a preprocessing step, it's much too useful. I would say that it's entirely changed my build process, but that would be a lie, because I'm pretty stuck in tradition. However, I suspect that a lot of people stand to benefit from a tool like this.&lt;br /&gt;&lt;br /&gt;Say you want to perform some text-based program translation for which the ordinary C preprocessor is insufficient, or for which you simply don't want to resort to hairy macros or x-macros. Want to produce forward declarations for all of the functions in a source file? Easy. Want to perform conditional compilation based on the results of a configuration script? Piece of cake. Want to generate compile-time warnings about uses of functions that are marked &lt;code&gt;// DEPRECATED&lt;/code&gt; in the source? Trivial.&lt;br /&gt;&lt;br /&gt;All kinds of code generation and static analysis tasks become a breeze by adding this one simple preprocessing step to your build. I strongly encourage you to try it out, and I suspect you'll be pleased with the results. The best part is that it's not an enormous investment. Even software that relies heavily on Macript can almost certainly be rewritten to avoid it, but it just happens to automate a few things that can make life a whole heck (or at least a fourth of a heck) of a lot easier.&lt;br /&gt;&lt;br /&gt;I promise you'll be able to find it on Sourceforge very soon. Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-9133473482247427245?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/9133473482247427245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/08/macript.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/9133473482247427245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/9133473482247427245'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/08/macript.html' title='Macript'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4944080289519820336</id><published>2010-08-25T17:04:00.001-04:00</published><updated>2011-09-17T01:17:15.153-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><title type='text'>Prog, Constify, and Pointer Single Loop</title><content type='html'>Hello again.&lt;br /&gt;&lt;br /&gt;This summer holiday, in the absence of a job, I've spent a lot of time working on Prog, and recently I actually finished a compiler of sorts. It produces an intermediate format suitable for text-based translation (via the C preprocessor, for instance) into any target language that supports, whether directly or indirectly, a high-level translation from Prog. I'm working on the C++ target, and it's currently possible to compile trivial programs such as Hello World and FizzBuzz, among others.&lt;br /&gt;&lt;br /&gt;So I didn't make my January release last year, but I will make it long before next year, and I'm happy about that. After all, I'm nineteen years old, and the longer I wait to release a language, the less impressed people will be by my age! I'm kidding, of course. I really just want the damn thing to be done so I can use it and enjoy it, and so that others can do the same.&lt;br /&gt;&lt;br /&gt;On to the longer, more peculiar part of the title. I've been browsing Stack Overflow a lot lately—in fact, perhaps more than I should—and a topic came up recently that I thought was interesting enough to write about here.&lt;br /&gt;&lt;br /&gt;The question concerned the possibility of a "&lt;code&gt;constify&lt;/code&gt;" operation in C++, that would, for the remainder of the duration of the current scope, cause a variable to be treated as though it had been declared &lt;code&gt;const&lt;/code&gt;. The original poster wanted to be able to write something like the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;std::vector&amp;lt;int&amp;gt; v;&lt;br /&gt;v.push_back(1);&lt;br /&gt;v.push_back(2);&lt;br /&gt;v.push_back(3);&lt;br /&gt;constify v;&lt;br /&gt;v.push_back(4); // This is now a compile-time error.&lt;/pre&gt;&lt;br /&gt;Now, the real use of such an operation doesn't really show in &lt;code&gt;std::vector&lt;/code&gt;, especially since C++0x introduces an &lt;code&gt;initializer_list&lt;/code&gt; constructor that makes it trivial to initialise a &lt;code&gt;const std::vector&lt;/code&gt;. But to be able to initialise a &lt;code&gt;const&lt;/code&gt; object by calling mutating methods on that object? I was intrigued.&lt;br /&gt;&lt;br /&gt;Obviously the syntax would have to change somewhat. The simplest route was obviously to declare a local &lt;code&gt;const&lt;/code&gt; reference bound to the original variable. My original &lt;code&gt;constify&lt;/code&gt; macro looked like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#define constify(type, id) \&lt;br /&gt;type const&amp;amp; id##_const(id), &amp;amp; id(id##_const)&lt;/pre&gt;&lt;br /&gt;The first declaration creates a &lt;code&gt;const&lt;/code&gt; reference &lt;code&gt;var_const&lt;/code&gt; bound to the constified variable &lt;code&gt;var&lt;/code&gt;. It then binds another reference named &lt;code&gt;var&lt;/code&gt; to &lt;code&gt;var_const&lt;/code&gt;. It has to be done this way because &lt;code&gt;type const&amp;amp; id(id);&lt;/code&gt; is erroneous, due to the fact that both mentions of &lt;code&gt;id&lt;/code&gt; refer to the local variable, not the existing one.&lt;br /&gt;&lt;br /&gt;To use this version of the macro, it had to be wrapped in its own scope, such as a loop body or bare block:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;std::vector&amp;lt;int&amp;gt; v;&lt;br /&gt;// ...&lt;br /&gt;{&lt;br /&gt;    constify(std::vector&amp;lt;int&amp;gt;, v)&lt;br /&gt;    // ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Using the macro outside a local scope resulted in a duplicate definition of the constified variable. I didn't like the requirement of wrapping the macro in its own scope, so I sought a more elegant solution. Nobody likes trying to mash a block into a macro invocation, so I decided to try turning the macro into something more like an inbuilt C++ construct, that could be used like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;constify (var) {&lt;br /&gt;    // var is const for the duration of this scope.&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The first problem was easily solved: how to have the compiler deduce the type of the constified variable. C++0x introduces the &lt;code&gt;decltype&lt;/code&gt; keyword, which allowed me to rewrite &lt;code&gt;constify&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#define constify(id) \&lt;br /&gt;decltype(id) const&amp;amp; id##_const(id), &amp;amp; id(id##_const);&lt;/pre&gt;&lt;br /&gt;So far so good. (NB: In non-C++0x compilers, there is often a &lt;code&gt;typeof&lt;/code&gt; extension with a very similar effect.) But how to allow for the clean syntax? The answer was in what I'll call, for lack of a better term and only because I've never seen it before, the Pointer Single Loop idiom.&lt;br /&gt;&lt;br /&gt;Basically, the &lt;code&gt;constify&lt;/code&gt; macro had to introduce a &lt;code&gt;for&lt;/code&gt; loop, which would provide the scope for the local variables &lt;code&gt;var_const&lt;/code&gt; and &lt;code&gt;var&lt;/code&gt;, while also executing only once. There is no way to introduce a loop control variable of a type unrelated to that of the constified variable, and no way to produce a local scope surrounding the expansion of the macro without also requiring that the loop body be mashed as a parameter into the invocation of &lt;code&gt;constify&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Meet the Pointer Single Loop idiom. It relies on the fact that, for any variable &lt;code&gt;t&lt;/code&gt; of type &lt;code&gt;T&lt;/code&gt;, this loop executes only once:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;for (T* p = &amp;amp;t; p; p = 0) {}&lt;/pre&gt;&lt;br /&gt;Further, since it's possible to construct a pointer to any type, and since we already have the name of the variable to be constified, it's trivial to construct the final implementation of &lt;code&gt;constify&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#define constify(id) \&lt;br /&gt;for (decltype(id) const&amp;amp; id##_const(id), \&lt;br /&gt;    &amp;amp; id(id##_const), * constify_index = &amp;amp;id; \&lt;br /&gt;    constify_index; constify_index = 0)&lt;/pre&gt;&lt;br /&gt;Like the earlier implementations of &lt;code&gt;constify&lt;/code&gt;, this accepts an &lt;code&gt;id&lt;/code&gt; and binds it to a local, immutable &lt;code&gt;id&lt;/code&gt; via &lt;code&gt;id_const&lt;/code&gt;. The difference is that it uses a Pointer Single Loop to execute the next statement once in the context of the new local variables. It requires only that the variable &lt;code&gt;constify_index&lt;/code&gt; be reserved for the purpose of the loop idiom, and works exactly as expected:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;std::vector&amp;lt;int&amp;gt; v;&lt;br /&gt;&lt;br /&gt;v.push_back(1);&lt;br /&gt;v.push_back(2);&lt;br /&gt;v.push_back(3);&lt;br /&gt;&lt;br /&gt;constify (v) {&lt;br /&gt;&lt;br /&gt;    v.push_back(4); // This is a compile-time error.&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This also works if &lt;code&gt;v&lt;/code&gt; happens to be declared &lt;code&gt;const&lt;/code&gt; already. In all, it was very easy to write, and I imagine that judicious use of C++0x features alongside an idiom of this sort could result in very sensible, readable extensions to C++, which provide real value to the language while retaining compatibility across standards and compilers. I can totally see Boost going for something like this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4944080289519820336?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4944080289519820336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/08/prog-constify-and-pointer-single-loop.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4944080289519820336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4944080289519820336'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/08/prog-constify-and-pointer-single-loop.html' title='Prog, Constify, and Pointer Single Loop'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-8522170110682134256</id><published>2010-05-13T12:08:00.001-04:00</published><updated>2010-09-30T16:16:52.090-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Vision'/><title type='text'>Vision Update</title><content type='html'>It's been a long, mad journey, but I made it all the way to Vision 1.2. This version has a bunch of fixes and additions that really flesh the language out in terms of usability and security. There's even a build for Mac OS X now, and I'm going to put together a Debian package, too. You should hop on the Vision train by visiting &lt;a href="http://sourceforge.net/projects/vision-language/"&gt;the Sourceforge project page&lt;/a&gt;, and &lt;a href="http://vision-language.sourceforge.net/cgi-bin/Home"&gt;the project home page&lt;/a&gt;, too!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-8522170110682134256?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/8522170110682134256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/05/vision-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/8522170110682134256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/8522170110682134256'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/05/vision-update.html' title='Vision Update'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-1374963748056008650</id><published>2010-03-18T07:48:00.007-04:00</published><updated>2010-09-30T16:17:10.935-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><category scheme='http://www.blogger.com/atom/ns#' term='Vision'/><title type='text'>Language Updates</title><content type='html'>Well, I paused working on my game to get back to working on Prog, then paused Prog again to whip up &lt;a href="http://sourceforge.net/projects/vision-language"&gt;Vision&lt;/a&gt;, a tiny little thing for making templates for dynamic Web content—or any XML content, really. I set up both &lt;a href="http://prog.sourceforge.net/cgi-bin/MainPage"&gt;the Prog site&lt;/a&gt; and &lt;a href="http://vision-language.sourceforge.net/cgi-bin/Home"&gt;the Vision site&lt;/a&gt; using Vision, and it appears to be both handy and scalable. Here's a quick example.&lt;br /&gt;&lt;br /&gt;Each page on the Vision site (okay, at the moment, &lt;i&gt;the&lt;/i&gt; page on the Vision site) consists of two files: the Vision script that generates the output, and the content file giving the body text. The Vision file is very simple:&lt;br /&gt;&lt;br /&gt;&lt;pre style="overflow:auto"&gt;&lt;code&gt;#!/home/groups/v/vi/vision-language/vision&lt;br /&gt;@include Page;&lt;br /&gt;Page {&lt;br /&gt;    "Vision Web Templating Language";&lt;br /&gt;    ../htdocs/MainPage&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This gives the path to the Vision interpreter, includes a page template in a file called Page, and then invokes the template of the same name with some text and the contents of a file. That's it. The Page template is very simple, too, and looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="overflow:auto"&gt;&lt;code&gt;@define Page (TITLE; BODY) {&lt;br /&gt;    html {&lt;br /&gt;        head {&lt;br /&gt;            title { "Vision &amp;amp;gt; "; TITLE }&lt;br /&gt;            link (rel "stylesheet"; type "text/css"; href "/style.css");&lt;br /&gt;        }&lt;br /&gt;        body {&lt;br /&gt;            div main {&lt;br /&gt;                div (class "cell") { h1 { TITLE } }&lt;br /&gt;                div (class "cell") { BODY }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, the template produces an HTML document with whatever title and body content were specified. Everything else on the site is controlled by the CSS document &lt;tt&gt;style.css&lt;/tt&gt;. New pages can be created quite easily by authoring a new content file and duplicating the Vision script with a reference to the new file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-1374963748056008650?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/1374963748056008650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/03/language-updates.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1374963748056008650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1374963748056008650'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/03/language-updates.html' title='Language Updates'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-5803878843755029959</id><published>2010-02-05T08:57:00.000-05:00</published><updated>2010-02-05T08:57:40.967-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><title type='text'>Prog (Non-)Release</title><content type='html'>Yup, I started working on something else and Prog got temporarily shelved. I'm back on it at the moment, though, and it's coming along rather nicely again. I feel bad for missing my January release window, but it's not going to stop me from working hard on it and getting it out there. There's a mailing list now on &lt;a href="http://groups.google.com/group/prog-language/"&gt;Google Groups&lt;/a&gt; and I've decided to launch the code base on &lt;a href="http://code.google.com/p/prog-language/"&gt;Google Code&lt;/a&gt; rather than &lt;a href="http://sourceforge.net/projects/prog"&gt;Sourceforge&lt;/a&gt; because the latter recently got rid of their wikis, which &lt;a href="http://code.google.com/p/prog-language/w/list"&gt;Google has&lt;/a&gt;. This blog will now contain only news entries and updates rather than general information; that will be pushed straight to the wiki.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-5803878843755029959?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/5803878843755029959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2010/02/prog-non-release.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5803878843755029959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/5803878843755029959'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2010/02/prog-non-release.html' title='Prog (Non-)Release'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-1419799149005834381</id><published>2009-11-30T16:49:00.008-05:00</published><updated>2009-12-02T09:55:00.632-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><title type='text'>Prog Type System</title><content type='html'>&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;Prog is designed in such a way that it can be either interpreted or compiled. As such, many of its fundamental types are mapped directly onto underlying machine types; though the overhead of the interpreter makes the speed advantage of certain types moot, a compiled Prog program does not suffer from this overhead and can take full advantage of the type system. The following types are essential to the functionality of Prog: &lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;/div&gt;&lt;ul style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;void&lt;/span&gt;&lt;br /&gt;The type of an expression that returns no value, e.g., &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;@X&amp;nbsp;==&amp;nbsp;void&lt;/span&gt; iff &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;X&amp;nbsp;==&amp;nbsp;null&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;any&lt;/span&gt;&lt;br /&gt;The type of an expression that returns a value of any type. This is a flag type that allows type-independent functions and heterogeneous containers in interpreted Prog. Generally, the use of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;any&lt;/span&gt; is not allowable in compiled Prog, for two reasons: first, it implies that all types are polymorphic, and second, it allows types to remain unresolved until runtime, both of which are disallowed by the restrictions on compiled Prog.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;type&lt;/span&gt;&lt;br /&gt;The type of an expression that returns a type, e.g., &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;@@X == type&lt;/span&gt; is always &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;true&lt;/span&gt;. This is internally either an enumerated type (i.e., an integer) or a map (for dynamic object-oriented programming). &lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;ul style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ref::T&lt;/span&gt;&lt;br /&gt;A reference to a value of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt;. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt; is unspecified or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;any&lt;/span&gt;, the reference is untyped (like a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;void&lt;/span&gt; pointer in C/C++, but slightly less dangerous because of interpreted Prog's use of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;RTTI&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;code&lt;/span&gt;&lt;br /&gt;A reference to code, created by wrapping code in curly braces (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{}&lt;/span&gt;) to defer its evaluation until it is explicitly invoked with the application operator (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;()&lt;/span&gt;). Functions can be composed with the composition operator (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;*&lt;/span&gt;), e.g., &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;f(g(x))&lt;/span&gt; is equivalent to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;(f&amp;nbsp;*&amp;nbsp;g)(x)&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;const&lt;/span&gt; operator, when applied to a type, returns the constant (immutable) equivalent of that type. Applied to an expression, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;const&lt;/span&gt; returns an immutable copy of or reference to its argument. There is a matching &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mutable&lt;/span&gt; operator, which returns the non-constant equivalent of a type or expression, but its use is intended for debugging purposes only, and as such it is disabled by the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;strict&lt;/span&gt; pragma.&lt;br /&gt;&lt;br /&gt;Prog integral types are templated; the template parameter indicates the number of desired bits. The type returned is guaranteed to have no fewer than the number of bits requested; if no suitable type is available, an exception is raised. For example, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int::8&lt;/span&gt; might return an 8-bit integer and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int::9&lt;/span&gt; a 16-bit integer, but &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int::128&lt;/span&gt; might raise an exception. In compiled Prog, the template parameter must be a constant expression, because the type must be instantiable at compile time. Prog defines the following integral types:&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int::N&lt;/span&gt;&lt;br /&gt;An integer of at least &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; bits. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; is unspecified, the native word size of the system is used. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; is &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0&lt;/span&gt; or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1&lt;/span&gt;, the lowest possible size is used.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char::N&lt;/span&gt;&lt;br /&gt;A character of at least &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; bits. Equivalent to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int::N&lt;/span&gt;, except treated as a character by I/O and locale functions. Additionally, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char::any&lt;/span&gt; may be used to store a character in a variable-width encoding; unlike most uses of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;any&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char::any&lt;/span&gt; and containers thereof are guaranteed to work even in compiled Prog.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bool&lt;/span&gt;&lt;br /&gt;A Boolean of at least 1 bit. Equivalent to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int::1&lt;/span&gt; or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int&lt;/span&gt; (whichever is faster), but restricted to the values &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;false&lt;/span&gt;&amp;nbsp;(&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0&lt;/span&gt;) and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;true&lt;/span&gt;&amp;nbsp;(&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1&lt;/span&gt;).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;For &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char&lt;/span&gt;, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;signed&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unsigned&lt;/span&gt; operators return the signed and unsigned equivalents, respectively, of the integral type in question. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char&lt;/span&gt; are both signed by default, while &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bool&lt;/span&gt; is internally unsigned.&lt;br /&gt;&lt;br /&gt;Floating-point types, too, are templated to accept minimum required widths, but because hardware floating-point implementations may vary, accepting the default template parameter is a good idea. Prog defines three floating-point types:&lt;br /&gt;&lt;br /&gt;&lt;ul style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;real::N&lt;/span&gt;&lt;br /&gt;A non-imaginary floating-point number of at least &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; bits. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; is unspecified, the native double-precision float is used. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; is &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0&lt;/span&gt; or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1&lt;/span&gt;, a single-precision float is used.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;imag::N&lt;/span&gt;&lt;br /&gt;An imaginary floating-point number of at least &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; bits. Equivalent to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;real::N&lt;/span&gt;, except treated as though multiplied by the imaginary unit.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;complex::N&lt;/span&gt;&lt;br /&gt;A complex number, the result of mixed operations on &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;real&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;imag&lt;/span&gt; values. Casting a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;complex&lt;/span&gt; to a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;real&lt;/span&gt; or an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;imag&lt;/span&gt; returns the real or imaginary part of the number, respectively, e.g., &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;real(C)&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;imag(C)&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;A number of additional, non-trivial types are provided by the runtime. They are defined in and automatically imported from the internal library &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;prog&lt;/span&gt;, and are treated as built-in types by the interpreter and standard library types by the compiler. These types include:&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;string::(N, T)&lt;/span&gt;&lt;br /&gt;A string (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;S&lt;/span&gt;) of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; characters of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt;. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt; is unspecified, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char&lt;/span&gt; is used. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; is unspecified, the string is variable-length. Strings are created with the quoting operators (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;""&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;''&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$q()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$r()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$s()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$w()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$x()&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;range::T&lt;/span&gt;&lt;br /&gt;A homogeneous range (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;R&lt;/span&gt;) between values of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt;, which are mutually comparable with the less-than (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;&lt;/span&gt;) operator. If T is unspecified or any, the range is heterogeneous, and valid as long as all types involved are mutually comparable. Ranges are created with unary relational operators (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;=&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;=&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;==&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;!=&lt;/span&gt;) and manipulated with bitwise operators (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;amp;&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;|&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;^&lt;/span&gt;), and are useful in a wide variety of situations, from looping to container slicing to pattern matching.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;list::(N, T)&lt;/span&gt;&lt;br /&gt;A homogeneous list (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;L&lt;/span&gt;) of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; values of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt;. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;N&lt;/span&gt; is unspecified, the list is variable-length; if &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T&lt;/span&gt; is unspecified or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;any&lt;/span&gt;, the list is heterogeneous. Implemented internally as a double-ended queue, all elements are contiguous in memory, so indexed element access occurs in constant time. Lists can be sliced with range subscripts and iterated by element.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;map::(K, V)&lt;/span&gt;&lt;br /&gt;A map (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;M&lt;/span&gt;) from key objects of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;K&lt;/span&gt; to value objects of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;V&lt;/span&gt;. The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;keys&lt;/span&gt; operator returns a list of the map's keys, and the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;values&lt;/span&gt; operator returns a corresponding list of the map's values. If &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;V&lt;/span&gt; is unspecified or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;any&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;@(values&amp;nbsp;M)&amp;nbsp;==&amp;nbsp;list::any&lt;/span&gt;. If neither &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;K&lt;/span&gt; nor &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;V&lt;/span&gt; is specified, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;@(keys&amp;nbsp;M)&amp;nbsp;==&amp;nbsp;list::any&lt;/span&gt; as well.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;object&lt;/span&gt;&lt;br /&gt;An object, for object-oriented programming. The type of an object is deduced from its structure, and object types can be composed to produce derived or related types. The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;public&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;protected&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;private&lt;/span&gt; operators are used to bestow &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;object&lt;/span&gt; members with qualifications on their visibility and accessibility, and the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;const&lt;/span&gt; operator can be used to create constant members.&lt;br /&gt;&lt;br /&gt;Operations on an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;object&lt;/span&gt; implicitly perform dispatching. Many of Prog's operators can be overloaded for use on an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;object&lt;/span&gt; simply by defining a method with the appropriate name, which is the same as the operator, and must therefore be a backquoted or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$i()&lt;/span&gt;-quoted identifier.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I'll elaborate on object-oriented programming in Prog at a later date. A number of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;object&lt;/span&gt; types are provided by the standard library, including but not limited to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;handle&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;file&lt;/span&gt; by &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;io&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;socket&lt;/span&gt; by &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;net&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;thread&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;concept&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;contract&lt;/span&gt; by their associated libraries.&lt;br /&gt;&lt;br /&gt;The one remaining type warrants significantly more discussion than the others, in part due to its complexity, but principally due to its ubiquity in idiomatic Prog. The type is called &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt;. Only iterable containers and ranges can be cast to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; type. All operations on an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; are performed on each element of the container it references, &lt;i&gt;including&lt;/i&gt; subscript access. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,monospace; margin-left: 1em;"&gt;&lt;pre&gt;L = (1, 2, 3);          # L == (1, 2, 3)&lt;br /&gt;++each(L);              # L == (2, 3, 4)&lt;br /&gt;L = ((1, 2), (3, 4))    # L == ((1, 2), (3, 4))&lt;br /&gt;each(L)[0] *= 2;        # L == ((2, 2), (6, 4))&lt;br /&gt;each(L)[1] = 0;         # L == ((2, 0), (6, 0))&lt;br /&gt;++each(L[0]);           # L == ((3, 1), (6, 0))&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note that the result of an operation on an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; is also an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt;. Internally, the object keeps a closure with which each operation on the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; is composed in succession. When an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; is evaluated, i.e., used in an operation that it does not override, it performs the closure on each element of its sequence and returns the (perhaps modified) sequence.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,monospace; margin-left: 1em;"&gt;&lt;pre&gt;L = (1, 2, 3);          # L == (1, 2, 3)&lt;br /&gt;++each(L);              # L == (2, 3, 4)&lt;br /&gt;L = ((1, 2), (3, 4))    # L == ((1, 2), (3, 4))&lt;br /&gt;each(L)[0] *= 2;        # L == ((2, 2), (6, 4))&lt;br /&gt;each(L)[1] = 0;         # L == ((2, 0), (6, 0))&lt;br /&gt;++each(L[0]);           # L == ((3, 1), (6, 0))&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;An operation on more than one &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; is performed in parallel, i.e., the closure applies to two values and the iterators are incremented simultaneously. The type can thus be used to assign ranges between iterable containers:&lt;br /&gt;&lt;div style="font-family: Times,&amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,monospace; margin-left: 1em;"&gt;&lt;pre&gt;L1 = (1, 2, 3);&lt;br /&gt;L2 = (10, 20, 30); &lt;br /&gt;each(L1) += each(L2);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note that an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; cannot be passed as a parameter to a function; a function that includes &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; in its signature will never be called, because  &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; overrides the function-application operator, like many other operators, to operate on each element of the underlying sequence rather than the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; itself. The type cannot be used as a context, either, so saying &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;func() : each&lt;/span&gt; is the same as casting the (iterable) result of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;func()&lt;/span&gt; to a value of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Note also that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; overrides even the conditional operators &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;if&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unless&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;elsif&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;elsun&lt;/span&gt; to act like looping operators, evaluating the condition for each value. The following function returns the number of occurrences of a value in a sequence.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,monospace; margin-left: 1em;"&gt;&lt;pre&gt;count[(iterator, iterator, any) =&amp;gt; unsigned int] = {&lt;br /&gt;&lt;br /&gt;    (first, last, value) = [];&lt;br /&gt;    c : unsigned int = 0;&lt;br /&gt;&lt;br /&gt;    ++c if each(first ... last) == value;&lt;br /&gt;    return c;&lt;br /&gt;&lt;br /&gt;};&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The entire iteration over an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; is considered a single operation, regardless of the particular threading implementation. This means that iteration cannot be interrupted, and thus the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; cannot be invalidated, even if its iterator would be invalidated (if, for instance, the sequence were modified or deleted). The sequence &lt;i&gt;can&lt;/i&gt;, however, be modified by another thread after the each is created but before iteration begins, that is, while the closure is being composed.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;each&lt;/span&gt; type is very powerful and very safe, and its use is strongly encouraged.&lt;br /&gt;&lt;br /&gt;So there you are. The whole of the basic type system spelled out in (perhaps minorly excruciating) detail. I feel like I should have some sort of clever and witty conclusion to put here, but I don't. Oh, well.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-1419799149005834381?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/1419799149005834381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2009/11/prog-type-system.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1419799149005834381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/1419799149005834381'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2009/11/prog-type-system.html' title='Prog Type System'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-4729560531117385309</id><published>2009-11-29T19:53:00.004-05:00</published><updated>2011-09-17T01:18:13.007-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Prog'/><title type='text'>The History of Prog</title><content type='html'>&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;Prog is my current programming language project, due for release in January of 2010. I'm of the opinion that it takes a hefty dose of passion for language design—and a mile-long list of abandoned ideas and failed projects—to learn enough about the subject to make something halfway decent. To explain the design of Prog, then, in future posts, some of my personal history might shed some light on why I've made the design choices I have.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;The first full specification for a programming language that I ever wrote was of a language called jCode, which I named (rather arrogantly, in retrospect) after myself. I had just begun to come into my own in the way of object-oriented programming techniques, even if I didn't know it at the time, since I was still using good old Microsoft QuickBASIC 4.5, one of the first languages I learned, and arguably the one I've abused the most. The driving idea of jCode was that a program should be highly modular, each of its sections infinitely reusable. A source file contained declarations of &lt;i&gt;units&lt;/i&gt;, which functioned half like libraries and half like objects, each of which had eight sections: a public &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;INTERFACE&lt;/span&gt;, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;IMPLEMENTATION&lt;/span&gt; of that interface, data &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;IMPORTS&lt;/span&gt; from external units, data &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;EXPORTS&lt;/span&gt; to importing units, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DATA&lt;/span&gt; declarations and initialisation, additional &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CODE&lt;/span&gt; for use by the implementation, and two other sections whose specifics are lost to the mists of time (read: I can't remember for the life of me and I lost the original specification).&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;Unfortunately for this language and for myself, jCode as it was conceived was never completed. At the time I conceptualised it, I did not have the programming skills to deduce how to implement it. The farthest I got was the crude beginning of an interpreter, which was able to locate units and their sections within a source file, obtain the list of raw commands from each section, and begin to try to evaluate them. In time, as I moved on to other languages (notably C, then C++), I naturally developed different ideas about programming, and my dedication to jCode was lost.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;At this point I became highly interested in esoteric programming language design. On many afternoons, I would consult a friend for a random topic and the next day I would have a working interpreter for an esoteric language based on the suggested concept. I still have many of these interpreters, though, sadly, I have lost many more. Most of them were implemented (rather shoddily, I'll admit) in Perl or BASIC, since these languages afforded handy text-processing capabilities and plain old familiarity, respectively.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;Along came my next idea, Sylph. Though not Prog's earliest ancestor, it is certainly the earliest one that bears instantly recognisable similarity to Prog. Sylph was a recognisably C++-like language, but it was also heavily influenced by Pascal, my primary development language at the time. This is ironic, since though Sylph was intentionally very different from its predecessors, what drew me to Pascal in the first place was its similarity to my own jCode. The Sylph interpreter made it slightly farther than the jCode interpreter had: source files were tokenised (albeit not always correctly) instead of being analysed line-by-line, and the crashy, hackish beginnings of code to turn these tokens into a parse tree was there in the implementation that I still have somewhere.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;Though the idea behind Sylph was noble, it lacked uniqueness. It was to be a strictly typed, dynamic language, and lightweight (hence the name) in the sense that it was small, but versatile, and would require little to nothing in the way of a standard library. I intended to define a meaning for every possible type and number of argument to every one of the many operators, with the ability to create user-defined operators as well. It was a hell of a thing to implement.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;Eventually, I tired of working on Sylph because it had ceased to inspire me. I began programming frequently in assembly language, and I was fascinated by the amount of control the programmer had—albeit, of course, at the expense of safety—when data types were not strictly enforced, as they are in C++, and would have been in Sylph. My next idea earned its name from my new approach to typing: Lax.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;Lax was based on the idea of a &lt;i&gt;construct&lt;/i&gt;, which could contain any kind of data, including code, and store it as a raw sequence of bytes in memory, giving the programmer maximum control over data representation, yet still in a high-level language. A standard library would have provided built-in code constructs that could be used for common tasks. The basis of Lax was created, and it was sound, but the standard library never grew beyond a single module for I/O. This project, too, was scrapped, because, having been designed rather poorly from the beginning, it became too difficult to maintain.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;The immediate ancestor of Prog was called Sol. Prog inherited many features from Sol, but of the two, Sol is more like Perl and Prog is more like Python. The principal difference between Sol and its ancestors is that there are no &lt;i&gt;statements&lt;/i&gt;, only &lt;i&gt;operators&lt;/i&gt;. The whole of a Prog or Sol program is one long expression that, like any other expression, performs some side effects and returns a value. The refinement of Sol that makes Prog distinct is the addition of a strict typing system, since that came back into favour with me, and the banishment of magical identifiers. Apart from these, and until quite recently, the idea that would become Prog saw very few changes for two long years while I pursued other interests.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;So why did I pick up the idea that was Sol, give it a new name, and begin redesigning it? For the same reason that I always did: I can't help it. The hope is that maybe this time I have enough experience to actually complete and release a useful general-purpose language.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif;"&gt;January's just around the corner, but, as long as things go the way they've been going, so is Prog.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-4729560531117385309?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/4729560531117385309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2009/11/history-of-prog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4729560531117385309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/4729560531117385309'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2009/11/history-of-prog.html' title='The History of Prog'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6421990566053383182.post-8304397862339718534</id><published>2009-11-25T00:09:00.005-05:00</published><updated>2011-09-17T01:18:30.721-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='Language'/><category scheme='http://www.blogger.com/atom/ns#' term='Design'/><title type='text'>Prog Blog</title><content type='html'>&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;Well, here it is. The opening post. Like the first page of a book, it might not be the most memorable—or even the best—part of the content, but it is responsible for one very important thing: the first impression. This post should define the subject of this blog, in enough detail to be truly definitive, but with enough slack to allow change. Typically, authors will go on here about their interests, their hobbies, and what they're likely to present to their readers, but I think this is naive and restrictive; why contrive some specific and artificial goal for a blog? It tends to fall apart after a while, and authors lose readers because of it.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;br /&gt;But—and there's almost always a 'but'—since I don't have any readership to lose, I might as well at least &lt;i&gt;warn&lt;/i&gt; whoever happens to read this thing of the nature of the content they might find herein. So here goes.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;First, I am a linguist. I like to learn, study, analyse, concoct, and otherwise manipulate language. I speak English natively and French fluently, and I have survival knowledge in a wide variety of other languages. At present, the focus of my studies is Chinese.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;Second, I am a programmer. Programming is something I do, do often, and do fairly well. At present I'm working on a programming language called Prog and an organiser called Org. I like short, descriptive names for software, and I like software that obeys the Principle of Least Surprise without fail.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;Third, I am an artist. Art and design are things that I do, do slightly less often, and, at least in my opinion, do rather less well.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;Like anyone, I have more to me than three things. Eventually that might become apparent. In any case, now that I've bored everyone (all one or so of you) to tears with talk of myself, I can get on to the most important part of the first post:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: left;"&gt;The end.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Times New Roman&amp;quot;,serif; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6421990566053383182-8304397862339718534?l=evincarofautumn.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evincarofautumn.blogspot.com/feeds/8304397862339718534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://evincarofautumn.blogspot.com/2009/11/prog-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/8304397862339718534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6421990566053383182/posts/default/8304397862339718534'/><link rel='alternate' type='text/html' href='http://evincarofautumn.blogspot.com/2009/11/prog-blog.html' title='Prog Blog'/><author><name>Jon Purdy</name><uri>https://profiles.google.com/115420443999474491901</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
