<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.jacius.info</title>
	<atom:link href="http://blog.jacius.info/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jacius.info</link>
	<description></description>
	<lastBuildDate>Wed, 12 Sep 2012 12:44:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>A Personal Lisp Crisis</title>
		<link>http://blog.jacius.info/2012/05/29/a-personal-lisp-crisis/</link>
		<comments>http://blog.jacius.info/2012/05/29/a-personal-lisp-crisis/#comments</comments>
		<pubDate>Wed, 30 May 2012 00:20:41 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Lisp]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=969</guid>
		<description><![CDATA[There is a half-jocular saying among atheists, that the surest way for a Christian to lose their faith is to read the Bible, cover to cover. The idea is that if you really scrutinize it, and don&#8217;t gloss over the strange, antiquated, or inconsistent parts, it stops seeming so profound and special. I don&#8217;t know [...]]]></description>
			<content:encoded><![CDATA[<p>There is a half-jocular saying among atheists, that the surest way for a Christian to lose their faith is to read the Bible, cover to cover. The idea is that if you really scrutinize it, and don&#8217;t gloss over the strange, antiquated, or inconsistent parts, it stops seeming so profound and special. I don&#8217;t know if that&#8217;s really true of Christianity, but I have recently had a similar experience that shook my belief that Common Lisp was a profound and special Lisp dialect.</p>
<p><span id="more-969"></span>Over the past 7 months or so, in addition to learning and using Common Lisp, I have been giving thought to the social issues affecting Common Lisp and its community. Over the past two months, I have been working on two projects, described below, to try to address the issues that most affect newcomers.</p>
<p>To gain perspective on the causes and social context surrounding these issues, I have been studying Common Lisp&#8217;s history, reading (among other things) the historical accounts of Richard Gabriel, Guy Steele, Kent Pitman, and others. (I can recommend, for example, <a href="http://dreamsongs.com/Files/Hopl2.pdf">The Evolution of Lisp</a>, <a href="http://dreamsongs.com/Files/PatternOfLanguageEvolution.pdf">A Pattern of Language Evolution</a>, <a href="http://dreamsongs.com/Files/clcrit.pdf">A Critique of Common Lisp</a>, <a href="http://www.nhplace.com/kent/Papers/cl-untold-story.html">Common Lisp: The Untold Story</a>, and of course <a href="http://dreamsongs.com/WIB.html">Lisp: Good News, Bad News, How to Win Big</a>.) I have also been reading <a href="http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/html/cltl/clm/node1.html">Common Lisp the Language, 2nd Edition</a> and the <a href="http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm">Common Lisp HyperSpec</a>, scrutinizing every inch of the language itself.</p>
<p>My research has given me a broader and more informed perspective than I had before. Before, I could see that the social climate surrounding CL was slowing its adoption rate and holding back progress, but I assumed its roots were healthy and strong. But now, it seems that CL is subsisting mainly on a fleeting aura of mystique, while other languages are surpassing it both technically and socially. That situation is untenable. Unless something changes, I don&#8217;t see how CL can have much of a future, except as an amusing curio for fans of antique computer technology.</p>
<p>If that was the only thing I had realized, it would have just strengthened my resolve to address the issues head-on. But, I also realized than CL is not the culmination of Lisp&#8217;s evolution, it is merely one box in a vast flowchart. It is a long-lived and popular dialect, and its creation was a significant milestone in Lisp history, but aside from historical interest CL is not an especially remarkable Lisp. It is a middle-of-the-road dialect, just as you would expect from something designed to be a compromise among numerous competing dialects.</p>
<p>CL is a fairly solid practical language, but it could have been much better. Inter-dialect politics, and the need to appease established interest groups, prevented the language from reaching its potential when it was created. Similar attitudes have prevented the core language from being cleaned up in the past 20 years, and likely will continue to do so indefinitely. There has been some activity building improved languages on top of CL, but there are better languages (particularly Scheme) to be foundations for that.</p>
<p>These realizations prompted a crisis for me. A month ago, I was ready and willing to dedicate myself to building a place for CL among a new generation of programmers. But now I&#8217;m not so sure. On the one hand, I have invested a lot of time into CL already, and it&#8217;s not a <em>bad</em> language, just not very exciting or inspiring. I could learn to live with it, and even smooth out most of its warts. On the other hand, there are certain attitudes that I find extremely demotivating and frustrating, and those attitudes seem to be more prevalent in the CL community than in many other languages&#8217; communities.</p>
<p>To put it simply, the CL language and community both fall far below their potentials. It might be possible to shift the culture in a more positive direction, but that would require a sustained effort by many people, and would probably involve frequent stressful confrontrations with the &#8220;worst offenders&#8221; in the community. There are decades of inertia and ingrained attitudes that would not be easily changed.</p>
<p>The reward for all that effort would merely be preserving a lackluster language, a &#8220;fixer-upper&#8221; that would require further effort to turn it into something really worth using. And even if the core language were changed, CL would lose its mystique and become &#8220;just another Lisp&#8221;, unable to use longevity or historical significance as a crutch. It would have to compete with other languages solely on its actual merits, which nowadays are not as strong as CL proponents like to believe.</p>
<p>I enjoy a good challenge, but this seems more like a fool&#8217;s errand. There are other languages with healthier communities, more momentum, cleaner cores, and features on par with CL. So I have to ask myself, why bother with CL?</p>
<p>I would love to discover some factor I have overlooked, some redeeming quality that would make CL worth fighting for. But the harder I look, the less likely that seems.</p>
<h3 id="next-generation">The Next Generation of Common Lispers?</h3>
<p>There are numerous issues affecting CL, but one that I thought I might be able to make an impact on was its low adoption rate. CL has a smaller user base than many other languages, as well as a smaller influx of new users, and (I suspect) a lower retention rate among those new users. This issue has many underlying causes, most of them social. There are a few technical issues, but they would be easily solved if the social issues did not prevent it.</p>
<p>(Some CL proponents insist that a low adoption rate is not a problem. The usual argument is that it is better to have a small number of highly skilled and intelligent users than a large number of mediocre users. But that is a false dichotomy, a cop-out to avoid actually addressing the problem. And even if it were logically valid, it is based on the assumption that CL is attracting and retaining users based on skill and intelligence. I would argue that the social climate surrounding CL merely favors people with certain <em>personality traits</em>, regardless of skill or intelligence.)</p>
<p>Many people in the CL community have long had an attitude of, &#8220;We do not need to make an effort to attract the next generation of programmers, or to make things easier for them. CL is so amazing that the best programmers will naturally seek it out and devote themselves to learning and using it.&#8221; That attitude may have been justified at some point in the past, but it is certainly not anymore.</p>
<p>These days, there are numerous languages whose technical merits are on par with CL, and many of them have more positive social climates, more forward-looking attitudes, and more effective ways of welcoming, supporting, and educating new users. CL is barely competitive from a technical standpoint, and significantly outclassed from a social standpoint.</p>
<p>Aside from a few unusual features, the only significant attraction CL seems to have left is the exaggerated mystique created by the writings of Paul Graham and other vocal Lisp advocates. Even that won&#8217;t draw new programmers to CL for much longer, especially with languages like Clojure and Racket offering the &#8220;Lisp Experience&#8221; with more useful and relevant built-in features, better community management, and more momentum.</p>
<h3 id="handling-newbies">&#8220;Handling Newbies Effectively&#8221;</h3>
<p>The first project I planned to release was a paper highlighting and analyzing the various social issues affecting CL newbies, and offering practical advice for addressing those issues. These issues include not only the apathy (and occasionally outright hostility) that many oldbies show toward newbies, but also the inadequate social framework the community has in place for welcoming, orienting, supporting, and educating newbies.</p>
<p>For example, CL has no central location where newbies can find reliable information, documentation, or other learning resources. Instead, information is scattered across the web, with no way for newbies to know if it is up to date and reliable. (I&#8217;m sure many CL proponents are now itching to &#8220;correct my ignorance&#8221; and explain that CL is just a language standard with many different implementations, which is why there is no central website. Well, guess what? Newbies don&#8217;t know or care about that. They want reliable and helpful information, not excuses for why the community is so disorganized.)</p>
<p>There are also not many good places for CL newbies to get support from other Lispers. The only well-established venue I know of that caters to newbies is <a href="http://lispforum.com">LispForum.com</a>, and it does not seem to get much promotion or attention from the broader community. So instead of newbies finding someplace where they are <em>welcome</em>, they usually end up someplace where they are <em>barely tolerated</em>, such as the #lisp IRC channel or comp.lang.lisp newsgroup. Those are probably the two least hospitable places for newbies, yet they are the two most popular and widely promoted venues, so many newbies end up there anyway (much to the vexation of some oldbies). Granted, #lisp and comp.lang.lisp can be great if you need answers to specific technical questions, but they are really lousy if you need orientation, advice, encouragement, or other forms of &#8220;hand holding&#8221;.</p>
<p>I have also observed many negative social attitudes which, while certainly not universal among CL programmers (and not unique to the CL community), are prevalent enough that they affect the entire community, and make the social climate less hospitable to newbies. A few of the most common and most harmful attitudes are defensiveness, nitpicking, zealotry, arrogance, lack of empathy, and social dominance based on a narrow set of values. Social dominance is an especially significant factor, because it means that the &#8220;alphas&#8221; in the community cannot be censured for bad behavior, unless those behaviors are truly egregious. (For example, if an alpha were to provide a newbie with &#8220;sample code&#8221; that would in fact delete all files on the newbie&#8217;s computer, the worst reprimand the alpha can expect is a few people saying, &#8220;Tsk tsk, you know you shouldn&#8217;t do that&#8221;. But just as many people would consider it an amusing prank, albeit cliché. They might even congratulate the alpha on teaching the newbie a lesson, thereby negating any reprimand the alpha received.)</p>
<p>The paper I&#8217;ve been working on goes into much greater detail, and gives more examples of challenges newbies face. But, I have started to doubt that publishing it would help the CL community at all. Many of the most serious social issues that affect the CL community are older than CL itself. Many people over the years have pointed them out, yet the same issues remain. So what good would it do to point them out again? The people whose attitudes and behaviors are most harmful, are the least likely to listen. The people who <em>would</em> listen, have probably heard it before. Why bother?</p>
<p>Yet, it&#8217;s obvious that the situation cannot possibly improve if no one speaks out. Sweeping things under the rug doesn&#8217;t make them go away. As uncomfortable as it may be, the only hope for addressing the issues is to start discussing them openly. Indeed, perhaps the most important social issue affecting the CL community is widespread complacency and apathy, which prevent the other issues from being addressed.</p>
<p>I will probably publish my paper eventually, because the same issues affect many tech-oriented communities to some degree. The CL community may be too far gone, but my paper might do some good elsewhere.</p>
<h3 id="cluel">CLUEL</h3>
<p>The other project I have been working on is CLUEL, the Common Lisp Usability Enhancement Layer. Whereas my paper would highlight the social issues and challenges newbies face while learning Common Lisp, CLUEL would directly tackle the problems that make the language itself unnecessarily difficult to learn and use.</p>
<p>About two months ago, I described some of the <a href="http://blog.jacius.info/2012/04/04/a-rubyists-impressions-of-common-lisp/#historical-baggage">historical baggage</a> that makes CL harder to learn, and adds to the mental burden on all CL programmers without adding any real value to the language. Since that time, I have spent over 100 hours poring over the CL language (not including the time spent researching CL&#8217;s history, writing about social issues, or planning CLUEL&#8217;s project infrastructure). I have personally looked up the documentation for every one of the 987 symbols in CL. I certainly can&#8217;t remember every detail, but I can truthfully say that I have some knowledge of the purpose of every single function, macro, special operator, global variable, and constant in standard CL.</p>
<p>In the same way that researching Lisp history has given me a better understanding of CL&#8217;s origins, scrutinizing the language itself has given me a better understanding of how inconsistent and crufty it is. Depending on how forgiving you feel, there are between a few dozen and a few hundred examples of features whose names are inconsistent, obscure, misleading, or otherwise poorly chosen. There are numerous features that are redundant, obsolete, or rarely needed, yet they are given the same prominence as the most essential parts of the language, because everything is lumped together in a single package.</p>
<p>Frankly, CL is just not a well designed language. That fact is not a reflection of the people involved, who as individuals were quite intelligent and capable. It merely reflects the process used to design the language. Considering that CL was debated in committee for 10 years, with numerous competing interest groups each tugging in a different direction, I&#8217;m impressed that it didn&#8217;t turn out even worse than it did. (I&#8217;m even more impressed that the whole standardization process didn&#8217;t fall apart entirely. Although I sometimes wonder if that might have been preferable in the long run.) However, there is a big difference between a language being &#8220;not bad, given the circumstances&#8221; and it being &#8220;well designed&#8221;.</p>
<p>The most obvious solution to the problem of it not being well designed, would be to revise the language standard to make it better. But that would be a futile and misguided effort. Even if you could get enough people in the CL community to agree that revising the standard was worthwhile, there would be just as much debating, bickering, and nitpicking as there was during the original standardization process. A committee is just not a good mechanism for designing a coherent language (or much of anything else, for that matter).</p>
<p>A better approach, more practical and more likely to yield real improvements, would be to create a new package (or multiple packages) that can be used as a test bed for experimenting with the language. It&#8217;s easy to start, you don&#8217;t have to create widespread consensus, and it doesn&#8217;t disrupt anyone who doesn&#8217;t want to use your package. This approach has been recommended by quite a few knowledgeable people, including <a href="http://s3.amazonaws.com/weekly-repl/weekly-repl_ep-1.mp3">Peter Seibel at ILC 2010</a> (near the end of his talk). This also harkens back to the tradition of prototyping new dialects on top of existing dialects (although I do not consider CLUEL to be a new dialect).</p>
<p>That approach is exactly what I had planned for CLUEL. The process I used for creating the proof of concept was something like this, although with lots of jumping back and forth between steps:</p>
<ol>
<li>
Partition all standard CL symbols into packages based on a theme or concept. At last count, I had tentatively settled on 22 packages: <code>core</code>, <code>general</code>, <code>types</code>, <code>cons</code>, <code>sequence</code>, <code>array</code>, <code>string</code>, <code>stream</code>, <code>file</code>, <code>read</code>, <code>write</code>, <code>symbol</code>, <code>package</code>, <code>clos</code>, <code>structure</code>, <code>hash-table</code>, <code>math</code>, <code>bitwise</code>, <code>condition</code>, <code>debug</code>, <code>host</code>, and <code>time</code>. Some symbols belong to more than one package.
</li>
<li>
For each package, partition the symbols into layers based on how useful they are:</p>
<ul>
<li>Symbols that are &#8220;often useful&#8221; stay in the main packages, which are available by default when using CLUEL.</li>
<li>Symbols that are &#8220;sometimes useful&#8221; are moved to the extra packages, which can be included when needed.</li>
<li>Symbols that are &#8220;rarely useful&#8221; are omitted from CLUEL entirely, but could still be accessed via the standard CL package if desired.</li>
</ul>
</li>
<li>
<p>For each symbol in CLUEL, decide whether its name is sufficiently meaningful, memorable, and consistent with the rest of the language. If it is not, give it a new, better name. (I developed a way to easily create aliases for existing functions, macros, special operators, global variables, and constants.)</p>
<p>This involved a lot of jumping back and forth, because renaming one symbol might affect the consistency of other symbols. Or, I might discover some pattern or naming convention that affects symbols I had already processed, so I would have to go back and rename them.</p>
<p>This step also involved a <em>lot</em> of consulting the documentation to make sure I understood exactly what an operator did. That led to a few surprises. For example, I didn&#8217;t realize that <code>ldiff</code> and <code>tailp</code> are <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_ldiffc.htm">so closely related</a>. Indeed, their names suggest that they are entirely unrelated, which is a sign that they are poor names (or at least, <code>ldiff</code> is). Those functions were likely invented independently, and they make sense individually, but when you put them together their names (and argument orders) are inconsistent.</p>
</li>
<li>
<p>Define a handful of new functions and macros to improve consistency, &#8220;fill in the gaps&#8221;, or improve usability in other ways. For example, there is no non-destructive sort function in standard CL, so I added a simple one. It may seem counterintuitive, but adding a new function in cases like this can <em>reduce</em> the cognitive load for users, because it makes the rules and patterns more consistent, with fewer exceptions to learn and remember.</p>
<p>Another way to improve consistency and reduce cognitive load is to consolidate many similar functions into one generic function. For the proof of concept, I experimented with this for accessing containers (consolidating <code>nth</code>, <code>elt</code>, <code>aref</code>, <code>svref</code>, <code>char</code>, <code>schar</code>, and <code>gethash</code>) and counting their contents (consolidating <code>length</code>, <code>array-total-size</code>, and <code>hash-table-count</code>).</p>
</li>
</ol>
<p>If that process seems to involve many subjective judgement calls, that&#8217;s because it did. But this was merely the proof of concept, to demonstrate that this sort of endeavor is feasible. In the long run, the initial design of CLUEL is irrelevant, because it was intended to be changed soon, with the involvement of more people. The more important aspects of CLUEL, its cultural values, emerged as I was planning the project and working on the proof of concept:</p>
<ul>
<li>
A focus on the needs of <strong>programmers of many different experience levels</strong>. That means, among other things, going out of our way to get feedback from newbies. Contrast that with Common Lisp, which was designed mainly to satisfy the needs of the kinds of people on the committee: expert Lisp hackers with code bases written in earlier Lisp dialects, and the implementators of those dialects (who were also expert Lisp hackers). A well-designed programming language (or nearly any other kind of tool) can be suitable for newbies and experts alike. It is not necessary to &#8220;dumb it down&#8221; to make it approachable for newbies.
</li>
<li>
An emphasis on <strong>user-centered design</strong>. Many of the same principles and techniques that are used to design doorknobs, toasters, electronic gadgets, and software user interfaces are just as applicable to designing programming languages. Some established usability testing techniques would be difficult to run, because of the time investment involved in learning a programming language, but other testing methods are applicable, and new testing methods can be invented to suit the new domain.
</li>
<li>
An emphasis on <strong>iterative design and change</strong>. Good user-centered design requires the ability to field-test a design, gather feedback, and incorporate that feedback as changes into the next round of design. With most programming languages, the cost of changing the language (once it is out &#8220;in the wild&#8221;) are very high, so design iterations are usually measured in years or decades, if they occur at all. I planned CLUEL to support multiple API editions, so that each new API edition could potentially be quite different from past editions, without breaking any software that depended on past editions. (Once an API edition is released, it would never be changed in a way that breaks compatibility, only to fix bugs or improve performance.) And, I extended <code>defpackage</code> to make it very easy to define new editions based on older ones, so the costs to iterate are very low.
</li>
<li>
A <strong>culture of collaboration, support, and respect</strong>. Beyond addressing purely technical issues, CLUEL would be a chance to lead by example in addressing social issues. Besides being a good thing on general principle, having a positive community atmosphere would also be a practical necessity for CLUEL. It is impossible to perform user-centered design in an atmosphere of self-centeredness, defensiveness, or resistance to change. You must be willing to look beyond your own needs and preferences, accept feedback and criticism of your design, and change whatever needs to be changed. This naturally means you must embrace diversity, respect other people&#8217;s viewpoints, and earnestly consider even ideas that you don&#8217;t yourself like. And, because newbies are included in the target demographic for CLUEL, you must give attention and effort to supporting them, mentoring them, and soliciting their feedback.
</li>
</ul>
<p>It&#8217;s important to point out that CLUEL was not designed to be a new dialect, or to ever exist separate from standard CL. Like it says in the name, CLUEL was a &#8220;usability enhancement layer&#8221;, a more usable and well-designed language interface for writing Common Lisp software. CLUEL would not add any new semantics or functionality to CL, just present (a subset of) the existing functionality in a better way.</p>
<p>A key feature of CLUEL was that code written in CLUEL would be fully compatible with code written in standard CL. So, for example, an application written in CLUEL could use libraries written in standard CL, and vice versa. (Unfortunately, that makes it impractical to address certain fundamental issues, such as the messy semantics of <code>nil</code>.)</p>
<p>I really poured myself into CLUEL. I estimate that over the past 2 months, I&#8217;ve spent over 100 hours studying the CL language and considering how to make it more usable, another 100 hours researching Lisp history and other dialects to see what has been tried before, 60 hours planning project organization and policies, and 20 hours developing infrastructure for packages, aliases, etc.</p>
<p>Indeed, the code for the first iteration of CLUEL, the proof of concept, is about 80% done, and the project planning is about 60% done. But I don&#8217;t plan on finishing it, or even releasing the in-progress code. It hurts to throw something away after spending so much time and effort on it, but at this point that seems to be the best course of action.</p>
<p>Why? Because CL doesn&#8217;t seem worth it anymore. I certainly don&#8217;t want to potentially spend a few years maintaining CLUEL and building up its community, shackling myself to a language I don&#8217;t really care about. Worse, I suspect that even handing off CLUEL for someone else to run it would be a mistake, because it might prolong CL&#8217;s decline, and delay a better Lisp dialect with a healthier community from rising to prominence.</p>
<p>I&#8217;m not sure what dialect that might be, but the two main contenders, Scheme and Clojure, are both promising. They both have cleaner core languages, more momentum, and (from my initial impressions, at least) healthier communities than CL. I don&#8217;t know yet how prevalent the negative attitudes I&#8217;ve observed in the CL community are in the Scheme and Clojure communities, but at least they do not seem to be so inhospitable to newbies, which is a good sign.</p>
<p>(I have heard some CL proponents insist that Scheme and Clojure are not really Lisp dialects, or at least are not as Lispy as CL. I&#8217;ve even given that impression myself on at least one occasion. But that is just ideology, with no grounding in reality. There have been many different Lisp dialects over the past 60 years, on many different architectures, with many different features and syntaxes. There is no rational basis for claiming that CL is a more &#8220;true&#8221;, &#8220;pure&#8221;, or &#8220;faithful&#8221; Lisp dialect than Scheme or Clojure.)</p>
<p>I don&#8217;t currently have any plans to create something like CLUEL for Scheme or Clojure, for the simple reason that they don&#8217;t seem to need it. Both languages are much more well-designed, consistent, and usable than CL is. But they are certainly flexible enough to implement a similar &#8220;usability enhancement layer&#8221;, should I happen to discover that implementing one would be beneficial.</p>
<h3>What Now?</h3>
<p>Despite my concerns about Common Lisp, I haven&#8217;t completely ruled it out as a language choice for Ambienome or future projects. I&#8217;m keeping my mind open to the possibility that CL has some redeeming characteristic or feature that makes it worth using, maybe even worth fighting to preserve.</p>
<p>Lately, I have been investigating other languages, including <a href="http://clojure.org">Clojure</a>, <a href="http://racket-lang.org/">Racket</a> (a R6 Scheme implemention), and <a href="http://call-cc.org/">Chicken</a> (a R5 Scheme implementation). Clojure is quite interesting, and there are a lot of cool things being created with it, but I&#8217;m concerned the emphasis on functional programming and immutable data structures might make an already ambitious game project even more challenging. Racket is very polished and featureful, with great documentation, but it is licensed under the LGPL. Ambienome would be a commercial game, and although the LGPL <em>probably</em> wouldn&#8217;t be a problem, there are certain ambiguities that make me hesitate to use it. Chicken is not as polished or featureful as Racket, but the community is quite friendly and welcoming, and its close integration with C might make it easier to use various game libraries or interface with the OS.</p>
<p>I am also considering non-Lisp languages, like <a href="http://coffeescript.org/">CoffeeScript</a> with <a href="http://threejs.org">Three.js</a> (to make a browser game), or even going back to Ruby (perhaps <a href="http://jruby.org/">JRuby</a> with <a href="http://lwjgl.org/">LWJGL</a>). If possible, though, I&#8217;d like to keep using some Lisp dialect, because I have found Lisp to be conceptually powerful and enlightening.</p>
<p>Maybe, just maybe, I will start to miss something from Common Lisp, something that cannot be easily recreated in those other languages. But even if I don&#8217;t end up using CL, I don&#8217;t regret learning it. The experience has been very educational.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/05/29/a-personal-lisp-crisis/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
<enclosure url="http://s3.amazonaws.com/weekly-repl/weekly-repl_ep-1.mp3" length="35788188" type="audio/mpeg" />
		</item>
		<item>
		<title>Ambienome Brain Dump</title>
		<link>http://blog.jacius.info/2012/04/17/ambienome-brain-dump/</link>
		<comments>http://blog.jacius.info/2012/04/17/ambienome-brain-dump/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 18:42:08 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=949</guid>
		<description><![CDATA[Lately, I&#8217;ve been focusing so much on Common Lisp itself, that I have barely spent any time on Ambienome, the whole reason I&#8217;ve been learning it. It has been so long that I can barely remember what I was working on. (Physics engine integration, I think?) That&#8217;s no good, so I wanted to take some [...]]]></description>
			<content:encoded><![CDATA[<p>Lately, I&#8217;ve been focusing so much on Common Lisp itself, that I have barely spent any time on Ambienome, the whole reason I&#8217;ve been learning it. It has been so long that I can barely remember what I was working on. (Physics engine integration, I think?)</p>
<p>That&#8217;s no good, so I wanted to take some time to set my thoughts and ideas for Ambienome onto paper (so to speak). This will help me slide back into that mode of thinking, hone my ideas by putting them into words, leave a journal of how the game evolves, and maybe spark some interest in anyone reading this.</p>
<p>Caveat: you should not interpret any part of this as a promise or firm description of how the actual game will be. I&#8217;m just unloading my thoughts and ideas as they exist now. Everything is still subject to change, etc. <span id="more-949"></span></p>
<h2>Creation vs Play</h2>
<p>One thing I have not yet decided is how much focus will be on <em>creating</em> content, and how much focus will be on <em>playing</em> (or consuming) content. In other words, is Ambienome a game with a built-in creature creator, or a creative tool for designing interactive motion graphics and audio? Does the player create things to play with, or is the act of creation itself the gameplay? Where do I strike the balance?</p>
<p>I think it should lean more towards being a game that you can create custom content for. A typical user might spend two thirds of their time playing with user-created content, and one third creating new content. Naturally, individual users will have different interests and focuses, but I really want creating content to be accessible, highly interactive, and engaging. <a href="https://www.youtube.com/watch?v=ZRr3lgckIAM">Spore</a>,<a href="https://www.youtube.com/watch?v=qss4uy6C_g0">Minecraft</a>, and <a href="https://www.youtube.com/watch?v=_vHdU9ctp7M">Little Big Planet</a> are all excellent examples of this.</p>
<p>As I&#8217;m envisioning it now, users would create scenes, which would have various creatures as well as level geometry (walls, etc.) and maybe some non-creature objects/items. The game would come with a variety of pre-built creatures, and the user could also build their own from scratch or by modifying an existing creature. Creatures could be saved and re-used between scenes, exported or imported as files, and easily shared online. Likewise, scenes could be exported, imported, and shared online.</p>
<p>Ambienome would likely come with a few dozen pre-made scenes that gradually introduce new creatures and gameplay mechanics, as puzzle games often do. Some of the scenes would have specific puzzles or goals to solve, while others would be &#8220;free play&#8221; mode like <a href="https://www.youtube.com/watch?v=onmrp_FuoDE">Electroplankton</a>, where the only goal is to have fun playing with the creatures.</p>
<h2>Gameplay Mechanics</h2>
<p>There are many possible gameplay mechanics, ways in which you can interact with the scene, and creatures can interact with each other. Here are some that have been floating around in my head:</p>
<ul>
<li>Light/darkness (bioluminescence, light sensitivity)</li>
<li>Heat/cold (energy transfer)</li>
<li>Attraction/repulsion (magnetism)</li>
<li>Falling/floating (gravity, buoyancy)</li>
<li>Water/air currents (lines, splines, vortices)</li>
<li>Bubbles (for air supply, or carrying objects)</li>
<li>Sound pitch/harmony</li>
<li>Playing a melody (correct notes in correct order)</li>
<li>Physical contact (collision, bouncing, overlapping)</li>
<li>Eating food or other creatures</li>
<li>Life cycles (birth, growth, death)</li>
<li>Controlling creature directly with keyboard, mouse, or joystick</li>
<li>Creatures follow mouse pointer</li>
<li>Clicking and dragging to move creatures and objects</li>
</ul>
<p>These mechanics can be combined in interesting ways to create fun puzzles and free play scenes. For example, there might be a puzzle scene where you guide a creature to find some fruit and bring it back to the creature&#8217;s hungry offspring. But of course, there are obstacles in the way! First you have to bump into some singing sea cucumbers that each play a different note and glow a different color. When you play the correct melody, a hot magma stone appears. You carry the stone to a dormant hydrothermal vent, thereby heating up the vent. When the vent is hot, it produces a rising current which carries you up to reach some fruit hanging on a vine on the ceiling. You carry the fruit back to the hungry offspring, thus completing the scene. (This is all 100% scientifically accurate, of course. I saw it on the Discovery Channel. Honest!)</p>
<p>The game mechanics can also be used for free play scenes. One scene might have some jellies whose long tendrils ring like wind chimes when they move. When you move the mouse cursor, it creates a brief current, stirring the tendrils and making relaxing sounds. Perhaps there are schools of tiny fish hiding among some kelp, but they are attracted by the sound of the jellies&#8217; tendrils, so they emerge and start swimming around, leaving colorful trails as they move. There&#8217;s no goal to accomplish or puzzle to solve, you can just relax and enjoy the sights and sounds for as long as you wish.</p>
<p>Naturally, all the creatures and game mechanics used in the scenes that came with the game would also be available for users to create their own scenes. And, players would be able to use those scenes and creatures as starting points for their own creations. Maybe you want to add some hydrothermal vents from that puzzle scene to create warm water currents that stir the jellies&#8217; tendrils in the free play scene. Just press a button to switch to &#8220;create&#8221; mode, drag some vents into the scene, and voilà.</p>
<p>Ideally, creatures and scenes uploaded by other users would also be available for creating derivative works. But, that starts to get into some complex issues. How much control do users have over the license? Do all uploaded creations have to be under a certain license (perhaps some form of Creative Commons)? What about creations they don&#8217;t upload to a central service, just export as files? Can they choose &#8220;no derivatives&#8221;? Would the game try to enforce the license, for example by not allowing other users to modify scenes marked as &#8220;no derivatives&#8221;? These are some of the issues I&#8217;ll probably have to think about eventually. But, thankfully, not today.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/04/17/ambienome-brain-dump/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Rubyist&#8217;s Impressions of Common Lisp</title>
		<link>http://blog.jacius.info/2012/04/04/a-rubyists-impressions-of-common-lisp/</link>
		<comments>http://blog.jacius.info/2012/04/04/a-rubyists-impressions-of-common-lisp/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 22:26:34 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Lisp]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=872</guid>
		<description><![CDATA[It has been nearly 6 months since I dove into Common Lisp. I have been studying and/or using Common Lisp almost every day, working on Ambienome and related code. So, I wanted to take some time to document my observations, feelings, and impressions of Common Lisp at this time. Be advised that this is a [...]]]></description>
			<content:encoded><![CDATA[<p>It has been nearly 6 months since I dove into Common Lisp. I have been studying and/or using Common Lisp almost every day, working on <a href="http://blog.jacius.info/category/projects/ambienome/">Ambienome</a> and related code. So, I wanted to take some time to document my observations, feelings, and impressions of Common Lisp at this time. Be advised that this is a fairly long post, even though I have trimmed out a lot of details and examples to keep it from growing even longer. (Apparently I have a <em>lot</em> of impressions!)</p>
<p>I have approached CL from nearly 8 years of programming in Ruby. I mention this because my experience with Ruby has certainly colored my impressions of CL, and many of my observations are about how CL compares to Ruby. <span id="more-872"></span></p>
<h2 id="different-yet-similar">Different Yet Similar</h2>
<p>Overall, I&#8217;d rate Ruby and CL as being about equal, on my personal, subjective scale of programming language goodness. They differ in many ways, both good and bad, but it feels to me like the differences balance out. So, the two languages are <em>different</em>, but neither one is clearly <em>superior</em>.</p>
<p>On a conceptual level, the two languages are actually fairly similar. They are certainly more similar to each other than either one is to a language like C, for example. They both have an interactive prompt, automatic memory management and garbage collection, first-class functions, anonymous functions and closures, arrays and hash tables, mutable strings, arbitrarily large integers, namespaces (modules in Ruby, packages in CL), and class-based <abbrev title="Object Oriented Programming">OOP</abbrev> systems that don&#8217;t force you into an OOP style. There are probably many other smaller similarities that I could think of if I took the time. (A dedicated Lisper would point out that many of these concepts originated in some Lisp dialect or another.)</p>
<p>Naturally, the details of many of these things are different. For example, CL&#8217;s packages work very differently than Ruby&#8217;s modules, despite fulfilling the same basic purpose. But in general, the concepts in each language are similar enough that knowing one language will make it significantly easier to learn the other.</p>
<h2 id="strengths">Strengths (In Brief)</h2>
<p>There are several aspects of Ruby that I feel are especially strong relative to Common Lisp. Stated briefly, they are:</p>
<ul>
<li>Community (active, supportive, sharing)</li>
<li>Approachability (easy for someone new to get started)</li>
<li>Convenience (many useful constructs and patterns are built in)</li>
<li>Consistency of the object model (e.g. everything has a class)</li>
<li>Wide variety of available libraries (both standard and installable)</li>
</ul>
<p>Of course, Common Lisp has several areas where I feel it has the advantage:</p>
<ul>
<li>Flexibility (macros and read macros)</li>
<li>Generic functions system</li>
<li>Conditions and restarts</li>
<li><abbrev title="Integrated Development Environments">IDEs</abbrev>, built-in documentation</li>
<li>Optimization hints</li>
</ul>
<p>I describe these in more detail near the end of this post.</p>
<h2 id="weaknesses">Weaknesses</h2>
<p>I&#8217;d like to be able to make a list of the areas each language is weak, but I&#8217;m too close to Ruby because of my years of use, yet also distant from it because I haven&#8217;t used it actively for perhaps a year. Both of those situations affect my perspective and make it hard to see Ruby&#8217;s real flaws.</p>
<p>Of course, Ruby has some weird bits of syntax (like <code>{|args| ... }</code> code blocks) and other quirks, but no more so than most languages, including CL. Ruby&#8217;s performance is traditionally a bit weak, but that varies across implementations, and is improving in leaps and bounds. The community is generally pretty great, although I find the &#8220;<a href="http://www.businessweek.com/articles/2012-03-01/the-rise-of-the-brogrammer">brogrammer</a>&#8221; trend in some parts of the community to be distasteful and regressive.</p>
<p>My relationship to Common Lisp is a different situation. My eyes are still fresh and I&#8217;m actively using it, so I can see and describe Common Lisp&#8217;s shortcomings pretty clearly. But, I want to emphasize that just because I can still see the flaws in Common Lisp, that doesn&#8217;t mean there are no flaws in Ruby. I&#8217;m sure someone else could point out just as many problems in Ruby as I can in Common Lisp.</p>
<p>So, with that caveat, I&#8217;ll describe what I consider to be Common Lisp&#8217;s problem areas.</p>
<h3 id="batteries">Minor Problem: Batteries Not Included</h3>
<p>Ruby, Python, and other &#8220;batteries included&#8221; languages come with all kinds of nifty features (e.g. networking, regular expressions, XML/JSON/etc. support) right out of the box. A programmer coming to CL from one of those languages might expect CL to be the same way, but it&#8217;s not. Why?</p>
<p>The main reason is that CL has a formal ANSI standard, designed in the 1980s and early 1990s as a way to consolidate several different Lisp dialects. It took 10 years, countless man hours, and hundreds of thousands of dollars in direct expenses to finish the standard. Every detail was weighed and debated to make sure it was acceptable to the many people and groups with a vested interest in the process, such as the vendors who sold implementations of the old dialects.</p>
<p>So basically, only features that were acceptable to everybody were put in the standard. Things that they disagreed about, or that would put too much burden on the implementors, or that didn&#8217;t even exist back then, are not in the standard. Adding a new feature to the standard now would probably take many more years of debate and nitpicking, and would only succeed if practically everybody agreed that it was such a great feature that it is worth the effort. In other words, it would take a miracle and a half.</p>
<p>That is a very different scenario than you have with Ruby/Python/etc., where someone can submit a new feature to the most popular implementation, a core dev likes the features and commits it, and it&#8217;s released in the next version.</p>
<p>So, why is this not a huge deal in Common Lisp?</p>
<p>Well, most features can be written as libraries that you can install when you need them. CL is so flexible that even major changes to the language syntax can be installed as libraries! And with the advent of <a href="http://www.quicklisp.org/">Quicklisp</a>, installing libraries in CL is just as easy as installing gems in Ruby, or eggs in Python.</p>
<p>As for the features that can&#8217;t be written as libraries, individual CL implementations can provide them as extensions. For example, the implementation I use comes with a bunch of goodies that aren&#8217;t in the ANSI standard, such as threading, networking, code coverage and profiling tools, and a foreign function interface (FFI) for wrapping C libraries (such as OpenGL, as I&#8217;m using for Ambienome). If a feature is popular and many implementations provide it, someone will usually create a wrapper library that smooths out the differences between implementations, so that programmers can use the feature without being tied to one particular implementation.</p>
<p>(That&#8217;s an idealized scenario, of course. It doesn&#8217;t always work out so smoothly. Some implementations don&#8217;t add new features very often, if ever. Sometimes an implementation adds a feature in a way that isn&#8217;t compatible with other implementations, making it difficult or impossible to create a portable wrapper library. In such cases, if a programmer really needs the feature, they might target a specific implementation, rather than trying to keep their code portable. If they really need their code to be portable too, they can write code that acts differently for each implementation.)</p>
<p>That process of adding a feature to an implementation, letting other implementations copy it, and writing a wrapper library on top, is far from perfect. But, it&#8217;s faster, less onerous, and more flexible than trying to update the ANSI standard, and the results are usually satisfactory.</p>
<p>So, once you realize the implications of Common Lisp being formally standardized, and find out that there&#8217;s an easy way to install libraries, it&#8217;s not such a big deal that Common Lisp does not come with &#8220;batteries included&#8221;. </p>
<p>But, it&#8217;s still a minor problem that affects new Lispers coming from other languages. It might be possible to alleviate the problem through expectations management. If new Lispers understood from the start that many features are not part of the standard, but nevertheless are readily available as libraries, they wouldn&#8217;t be so surprised and disappointed.</p>
<p>I&#8217;m not sure who would be most effective at this sort of expectations management, though. Implementations? Book authors? Teachers? Bloggers? Wiki editors? IRC and newsgroup participants? I suspect all of the above are already doing it to some degree, yet many newcomers are still surprised. This is one area where having an &#8220;official website&#8221; for Common Lisp might make things easier.</p>
<h3 id="historical-baggage">Moderate Problem: Historical Baggage</h3>
<p>Common Lisp has a lot of historical baggage: things that are done a certain way just because that&#8217;s how they were done in the past, even if they don&#8217;t make much sense nowadays. Perhaps that&#8217;s only natural for a programming language with such a long history. CL itself is nearly 20 years old (or 30, if you count from the first edition of <a href="http://en.wikipedia.org/wiki/Common_Lisp_the_Language"><i class="title">Common Lisp the Language</i></a>), and it inherited baggage from several older Lisp dialects, going all the way back to the original Lisp over 60 years ago.</p>
<p>That&#8217;s not to say that other languages don&#8217;t have some historical baggage of their own. For example, Ruby and many other languages inherit the bizarre old syntax of putting a 0 (zero) in front of a number to interpret it as octal form. (E.g. <code>10</code> means ten, yet <code>010</code> means eight. Surprise!) CL seems to have an especially large amount of baggage, though, and many Common Lispers seem to cling to that baggage rather tightly.</p>
<p>Historical baggage manifests itself in CL in many ways. One way is as individual quirks, like the setq operator. Setq was, I hear, originally invented as shorthand, so you could write <code>(setq x 3)</code> instead of <code>(set (quote x) 3)</code>. But that was before the read macros were available; these days you can type <code>(set 'x 3)</code>, which also means <code>(set (quote x) 3)</code> and is not any more characters than using setq. (Although, setq works a bit differently in CL than in earlier Lisps, so <code>(setq x 3)</code> isn&#8217;t quite the same as either <code>(set (quote x) 3)</code> or <code>(set 'x 3)</code> anymore.) Furthermore, CL has the set<strong>f</strong> operator, which can do everything setq can do and more, so there&#8217;s not really any reason to retain setq. It&#8217;s just historical baggage, kept around because that&#8217;s what they used in the old days. (Setq is still quite widely used today, usually with the rationale that it expresses the programmer&#8217;s intentions more clearly because it can do fewer things than setf.)</p>
<p>Historical baggage also manifests as old idioms that affect many parts of the language. Take for example the idiom of adding &#8220;p&#8221; to the names of predicate functions, functions that check something and return true or false (actually t or nil, another bit of historical baggage). For example, <code>(evenp x)</code> returns true if the value of x is an even number. It could have been <code>(even? x)</code>, which I would argue is significantly clearer. But, Lispers used &#8220;p&#8221; in the old days, so (most, but not all) predicate functions in the CL standard use &#8220;p&#8221;, and therefore most Common Lispers still use &#8220;p&#8221; when they write their own predicate functions today.</p>
<p>Historical baggage also manifests itself as strange inconsistencies and curiosities in the underlying architecture. For example, Common Lisp has <em>types</em>, which it inherited from older Lisp dialects. It also has <em>classes</em>, which were added fairly late in the ANSI standardization process. Types and classes are very similar in many ways, but just different enough that they can&#8217;t be unified without breaking tons of old code. As a result, CL has both systems existing simultaneously, where each class has a corresponding type, but not all types have a corresponding class. Some features use types (like function and variable type declarations), while other features use classes (like generic function dispatching). I suppose the standards committee made the right choice given the circumstances back then, to avoid breaking all that old code. But, it is nevertheless historical baggage that all Common Lispers still carry nearly 20 years later.</p>
<p>Finally, historical baggage manifests itself as concepts and features that were useful many decades ago, but are pretty much obsolete today (and in some cases were already obsolete when the standard was written). For example, every symbol in Common Lisp has &#8220;properties&#8221;, a list of data that the symbol carries around in its guts. But nowadays, it would often be just as efficient to store that data in hash tables with the symbol as the key, and doing so would entirely avoid the possibility of two unrelated pieces of code coincidentally using the same property names. But, Lisp has had symbol properties since the very beginning, so Common Lisp has symbol properties too, along with the half-dozen functions used to manipulate them. (Symbol properties don&#8217;t seem to be used much anymore.)</p>
<p>These kinds of historical baggage aren&#8217;t a <em>serious</em> problem, because for the most part you can ignore the obsolete features, and either cover up or learn to live with the weird idioms and inconsistencies. But it is a moderate problem, because this historical baggage adds to the mental burden of every Common Lisp programmer in the world. (There are many, many other examples of historical baggage that I have omitted for the sake of brevity.)</p>
<p>It&#8217;s especially burdensome for new Lispers. Year after year, new Lispers have to go through a kind of rite of passage, learning the obscure idioms of years gone by, separating the useful features from the cruft, and trying to remember function names that seem arbitrary and inconsistent. Many of them give up and leave for other languages because of needless obstacles (this being just one of many they face). Some of them could have contributed a lot to the community over time, if only &#8220;the wall&#8221; hadn&#8217;t been built so high.</p>
<h3 id="community-atmosphere">Serious Problem: The Community Atmosphere</h3>
<p>That brings me to the most serious problem Common Lisp has: the community&#8217;s atmosphere, its prevailing moods and attitudes. This is such an important topic that it deserves its own post, but I&#8217;ll summarize the problem here.</p>
<p>I&#8217;ll admit that I started learning CL with the knowledge that many people (usually people who tried to join the community but were repelled) consider the community to be antagonistic, especially towards newcomers. So, I may be exhibiting some confirmation bias: seeing what I expected to see, and tending to ignore evidence to the contrary. But with issues like this, the widespread <em>perception</em> of a problem can be just as damaging as the reality of the problem itself.</p>
<p>I suspect that most people who use Common Lisp, as with any language, are probably decent folk who just want to write nifty code without a lot of fuss or drama. But these people are not very visible or active in community discussion venues (e.g. the comp.lang.lisp newsgroup or #lisp IRC channel). They&#8217;re off somewhere else, writing their nifty code in peace.</p>
<p>Alas, many of the people who <em>are</em> highly visible and active can best be characterized as &#8220;toxic&#8221;. These are people who, because of the nature of their personalities and attitudes, have a consistently negative emotional effect on the people they interact with. Without necessarily intending to do so, they have created a constant miasma of disrespect, nitpicking, defensiveness, discouragement, and intolerance. This toxic atmosphere permeates the entire culture, gradually driving less toxic people into seclusion or to other languages, or souring their moods such that they become toxic as well. This leaves an even higher concentration of toxicity, affecting even more people, on and on.</p>
<p>Is it possible to reverse this trend? I don&#8217;t know. It may be too late. If it can be reversed, I suspect the way to do it is for the quiet, decent folk to put on emotional hazmat suits and start being more active in the community. Participate in discussions, help new Lispers, and discourage toxic behavior by privately and tactfully informing people about the effect they have. Reducing the toxicity of the community atmosphere would be a major culture shift, but with a sustained effort it might be possible to create a more healthy and positive atmosphere.</p>
<p>I can&#8217;t help but compare this to the Ruby community&#8217;s notion of <abbrev>MINSWAN</abbrev> (Matz Is Nice So We Are Nice), and wish there were more positive role models in the CL community to set a good example. Most of the people who are revered in the CL community are quite intelligent and knowledgeable about CL and computer science, but are also very toxic. The motto for this community would be something along the lines of <abbrev>NaWTSWAT</abbrev>: <a href="http://en.wikipedia.org/wiki/Erik_Naggum">Naggum</a> Was Toxic So We Are Toxic. The community discussion venues have become an echo chamber, perpetuating and reinforcing the notion that it is okay to be derogatory and inflammatory, as long as you are intelligent or know a lot about CL. The people who disagree with this attitude tend to give up in disgust and either leave or stop talking, so you won&#8217;t hear many dissenting opinions about that from the people who remain.</p>
<p>This may seem like a gloomy assessment, but the situation is not all bad. There are some awesome people making cool things with Common Lisp, and many people who will try to help as best they can when you have a problem. It&#8217;s just a shame that the predominant attitude is so negative.</p>
<h2 id="not-all-bad">It&#8217;s Not All Bad!</h2>
<p>I have spent many more words so far describing the weaknesses and problems of Common Lisp, than describing its strengths and interesting features. But despite its quirks and baggage and toxic people, Common Lisp is an incredibly flexible and powerful tool for creating software. Ruby may offer a more polished baseline experience, but you can&#8217;t take it as far as you can take CL.</p>
<p>The ANSI Common Lisp standard may stand still, but Common Lisp does not. It is constantly growing and evolving on top of the stable (albeit lumpy and uneven) foundation provided by the standard. For example, <a href="http://common-lisp.net/project/asdf/">ASDF</a> (which is a bit like Rake or Make) was created in 2001, and revolutionized the way CL libraries are defined and loaded. ASDF laid the groundwork for <a href="http://www.quicklisp.org/">Quicklisp</a> (CL&#8217;s analog to RubyGems), created in 2010, to revolutionize the way CL libraries are downloaded and installed. That in turn lays the groundwork for further development and progress.</p>
<h3 id="flexibility">Flexibility (Macros and Read Macros)</h3>
<p>One reason CL can keep evolving without needing to change the standard, is the flexibility provided by features like macros and read macros. In addition to the usual small utility macros, I&#8217;ve created macros for Ambienome to implement a <a href="http://blog.jacius.info/2012/01/05/mini-project-proto-slots/">limited form of prototypal inheritance</a>, and extensible object properties. They are somewhat longer than the average macro, but fairly mundane; they merely expand into a few formulaic functions with the details filled in. There are much more complex and interesting things you can do with macros, like the famous (or infamous) <code>loop</code> macro, which implements a specialized mini-language within CL, dedicated to making it easy to write fairly sophisticated code loops. Even the Common Lisp Object System (CLOS), which provides CL&#8217;s class-based OOP system, is largely implemented via some very complex macros. CLOS and loop are both defined in the standard, but they probably could have been implemented as separate libraries. (I&#8217;m guessing that having those things standardized enables implementations to optimize their performance. Or maybe they were just considered fundamental to the language.)</p>
<p>Read macros take flexibility and extensibility even further. They let you write code in CL that reprograms the way CL parses the text of your source code, potentially altering the language in radical ways. One fairly common and not-so-radical use for read macros is adding syntax sugar. For example, the CL standard doesn&#8217;t have a literal syntax for reading or printing hash tables, but thanks to read macros you can <a href="http://frank.kank.net/essays/hash.html">add Ruby&#8217;s hash table syntax to CL</a> in 40 lines of code (or less if you don&#8217;t need the hashrockets and commas). Similarly, you can <a href="http://letoverlambda.com/index.cl/guest/chap4.html#sec_4">add literal syntax for regular expressions</a>, even though regular expressions are provided by libraries like <a href="http://weitz.de/cl-ppcre/">CL-PPCRE</a> instead of being defined in the standard. I don&#8217;t know of any other language where you can think of some syntax that would make the language more expressive or powerful, then add it with just a couple of afternoon hacking sessions.</p>
<h3 id="generic-functions">Generic Functions</h3>
<p>Next to CL&#8217;s flexibility from macros and read macros, the thing I find most interesting in CL is the generic functions system. Classes in CL don&#8217;t (usually) have methods in the same sense that classes in Ruby do. Instead, CL has generic functions, and each method implements the behavior as it relates to instances of a certain class (or combination of classes). It&#8217;s quite different from Ruby or any other object-oriented language I&#8217;ve used, but very flexible and powerful. I&#8217;d like to write more about the CLOS object model and how it compares to Ruby&#8217;s, but this post is already rather long.</p>
<h3 id="conditions">Conditions and Restarts</h3>
<p>Another interesting feature of CL is its condition system. Conditions are analogous to Ruby&#8217;s exceptions, but much more flexible and powerful. (That seems to be a recurring theme.) Besides raising errors and warnings, you can use conditions to send any kind of signal up the call chain, with the lower-level code possibly providing some &#8220;restarts&#8221;, ways to proceed. Depending on how you set up the restarts, your higher-level code might interrupt the lower-level code like in Ruby, or ignore the signal and resume the lower-level code where it left off, or modify something and <em>then</em> resume, or pretty much anything else you can imagine. I haven&#8217;t had much opportunity to use conditions in a substantial way yet, but I&#8217;m sure they will prove useful as my code matures.</p>
<h3 id="ide">Integrated Development Environments</h3>
<p>CL also has some nice IDEs. I use Emacs with <a href="http://common-lisp.net/project/slime/"><abbrev title="Superior Lisp Interaction Mode for Emacs">SLIME</abbrev></a>, which is a big step up from my Ruby workflow.  It offers the usual IDE amenities like tab-completion, parameter hints, jumping to function definitions, and looking up documentation (which is stored in each function/macro/etc., not derived from scanning comments like RDoc and YARD do). It also lets you inspect and modify the guts of most objects, which is pretty handy for debugging. And apparently even SLIME pales in comparison to the fancy IDEs provided by some commercial CL implementations.</p>
<h3 id="optimization">Optimization Hints</h3>
<p>Finally, CL has a system for declaring optimization hints to tweak the way the implementation compiles or interprets your code. (These are hints, so the implementation decides what to actually do. Some implementations might just ignore your hints.) Besides optimizing for computational speed, you can optimize for space (compiled code size, and runtime memory use), safety (run-time error checks), compilation speed, and/or ease of debugging. You can also optionally declare the argument and/or return types for functions, which can help the implementation generate even more efficient code. And finally, you can declare that a function can be compiled inline into other code that calls it, which can reduce or eliminate the overhead from function dispatch (this works well for short utility functions). I have read that with the right optimization hints, some implementations can compile number-crunching functions into code that is nearly as performant as C code. I&#8217;m pretty relaxed about performance (I used Ruby for over 7 years, after all!), but it&#8217;s nice to have extra tools available for dealing with bottlenecks.</p>
<h2 id="conclusion">Final Thoughts</h2>
<p>So, those are my impressions of Common Lisp after 6 months of focused study and use. There are a lot of good things about CL, but also some really bad. It&#8217;s a pretty amazing language, but has some warts and flaws. The community is mostly decent people, but anyone who tries to participate in discussion ends up choking in the toxic atmosphere. The warts and flaws can be covered up or worked around pretty easily, but creating a more healthy community atmosphere seems nearly impossible. But I hope it can happen somehow, because it&#8217;s a shame to see the language being held back like this.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/04/04/a-rubyists-impressions-of-common-lisp/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Physics Engine and Object Selection</title>
		<link>http://blog.jacius.info/2012/02/27/physics-engine-and-object-selection/</link>
		<comments>http://blog.jacius.info/2012/02/27/physics-engine-and-object-selection/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 00:15:38 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>
		<category><![CDATA[Lisp]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=859</guid>
		<description><![CDATA[This is the second part of my post about what I&#8217;ve been working on lately. In the first part, I talked about data structures and serialization. In this post, I talk about the physics engine and object selection via mouse picking. For Ambienome&#8217;s physics engine, I&#8217;m using SquirL, a Common Lisp port of the popular [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second part of my post about what I&#8217;ve been working on lately. In the first part, I talked about <a href="http://blog.jacius.info/2012/02/24/data-structures-and-serialization/">data structures and serialization</a>. In this post, I talk about the physics engine and object selection via mouse picking.</p>
<p>For Ambienome&#8217;s physics engine, I&#8217;m using <a href="https://github.com/sykopomp/squirl">SquirL</a>, a Common Lisp port of the popular <a href="http://chipmunk-physics.net/">Chipmunk</a> 2D game physics engine. I&#8217;m not far enough along yet to know how well it performs in my own game, but from running the demos, it certainly seems performant enough for my purposes. If it turns out to be somewhat sluggish, many Common Lisp implementations can perform some pretty aggressive optimization, given the right type declarations. As a last resort, I could create an FFI binding to the actual Chipmunk library, although that might not be any faster than a well-optimized Common Lisp port. One benefit of a binding to Chipmunk would be using its new features that have not been ported to SquirL (which hasn&#8217;t been updated in 2 years).</p>
<p><span id="more-859"></span> As I explained in the previous post, a creature in Ambienome is composed of a hierarchy of &#8220;parts&#8221;, or shapes. This hierarchical nature means that a child&#8217;s transformation (position, rotation, scale) are defined relative to the parent, and the parent&#8217;s transformation affects all the children (and the children&#8217;s children, and so on). But, SquirL/Chipmunk only has the concept of a body composed of a flat list of shapes; they don&#8217;t understand hierarchies. So, when generating the physical representation of a creature, the code must &#8220;walk&#8221; the hierarchy, converting each part&#8217;s parent-relative transformation to a root-relative transformation.</p>
<p>Actually, though, not every creature will be made of a single physical body. In SquirL/Chipmunk, each body is a <em>rigid</em> body, meaning its component shapes are not supposed to move relative to each other. Physical joints (springs, pivots, etc. &mdash; &#8220;constraints&#8221; in SquirL/Chipmunk parlance) only connect bodies, not shapes within a body. So, any creature that has parts connected via joints will have to be split up into multiple physical bodies. This would happen automatically behind the scenes, of course; Ambienome users don&#8217;t need to care about the underlying physical representation.</p>
<p>One potential pitfall is that if a part&#8217;s transformation is changed, the physical representation of it and everything lower in the hierarchy must be updated or regenerated. If a part is changing often, that could be a significant performance hit, and also cause problems with the physics engine. So, it may be that some creatures will have to be split up into multiple physical bodies, even if they don&#8217;t use explicit joints. A part that will move or rotate often could be automatically split into a separate physical body, then connected to the main body via a joint (or combination of joints) to hold it in place.</p>
<p>Unfortunately, SquirL/Chipmunk cannot handle scale changes in such a graceful way. So, it would still be necessary to regenerate the physical shapes after a scale change, with all the performance and simulation stability issues that entails. Of course, if that turns out to be a big problem, the ability for behaviors to change scale could be limited in some way. I might even disable it at first, then only add that ability later if it can be done without causing problems.</p>
<p>Two other things that I&#8217;ll need to address with regards to the physics engine, are static creatures and phantom creatures. Static creatures are creatures that don&#8217;t move, but other creatures can collide and bounce off of them. SquirL and Chipmunk both support fairly simple (but different) ways of accomplishing that, so the technical side is not a problem. But, I&#8217;ll have to give some thought to how this option is presented to users. For example, is the user able to make a static creature with non-static limbs, like an anemone whose base doesn&#8217;t move, but whose tendrils do? This has some implications about how creatures are built and structured; it may be necessary or desirable to explicitly divide creatures into segments (corresponding to SquirL/Chipmunk bodies), which are then divided into parts (corresponding to SquirL/Chipmunk shapes).</p>
<p>Phantom creatures are creatures that do not have a solid form, do not collide or bounce off other creatures, but can still move around. This can be accomplished easily in SquirL/Chipmunk by putting all phantom creatures on a designated layer (so they will not collide with non-phantom creatures), and putting them in the same group (so they will not collide with other phantom creatures). But, just like static creatures, the concept of phantom creatures has implications about how a creature is structured. Can some parts of the creature be phantom, while others are not? Ideally, this should be allowed, but it does suggest that my current concepts of creatures and parts needs to be reformed.</p>
<p>The final topic for this post is object selection via mouse picking. This isn&#8217;t always related to physics engine, but in this case, I&#8217;m planning to leverage the physics engine to make picking easier. SquirL and Chipmunk both have ways to check what shapes intersect a point, and Chipmunk additionally has ways to check for intersection with a line segment, axis-aligned bounding box, or shape.</p>
<p>This does mean, though, that all possibly selectable creatures must be added to the physics engine. If I used a different technique for mouse picking, only creatures that actually participate in the physics simulation would need to be added. But I don&#8217;t expect this to be much of a problem, because the only creatures that could have stayed out of the simulation would be creatures that are both phantom and static, which I think will be relatively rare.</p>
<p>There are <a href="http://www.opengl.org/resources/faq/technical/selection.htm">several other picking techniques available</a>. Two popular techniques for OpenGL applications are <a href="http://content.gpwiki.org/index.php/OpenGL:Tutorials:Picking">the GL_SELECTION rendering mode</a>, and <a href="http://content.gpwiki.org/index.php/OpenGL:Tutorials:Picking">unique color rendering</a>. These are certainly feasible, but implementing them would take time and effort I could spend on other things, and would add complexity to my code base. So, I&#8217;ll save them as backup plans, in case using the physics engine for mouse picking doesn&#8217;t work out.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/02/27/physics-engine-and-object-selection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data Structures and Serialization</title>
		<link>http://blog.jacius.info/2012/02/24/data-structures-and-serialization/</link>
		<comments>http://blog.jacius.info/2012/02/24/data-structures-and-serialization/#comments</comments>
		<pubDate>Sat, 25 Feb 2012 03:52:26 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>
		<category><![CDATA[Lisp]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=855</guid>
		<description><![CDATA[Lately, I&#8217;ve been tackling several separate, but interconnected, systems in Ambienome: data structures, serialization, object selection, and the physics engine. These are complex topics, so I&#8217;ve written this in two parts. In this first part, I talk about data structures and serialization, and in the second part I talk about the physics engine and object [...]]]></description>
			<content:encoded><![CDATA[<p>Lately, I&#8217;ve been tackling several separate, but interconnected, systems in Ambienome: data structures, serialization, object selection, and the physics engine. These are complex topics, so I&#8217;ve written this in two parts. In this first part, I talk about data structures and serialization, and in the second part I talk about <a href="http://blog.jacius.info/2012/02/27/physics-engine-and-object-selection/">the physics engine and object selection</a>.</p>
<p>Data structure simply means the way some data is structured or organized, either in memory while the program is running, or when the data is saved to a file or sent over a network. Is it stored in a hash table? An array? An instance of a class? What slots/members does the class have? How are different pieces of data related to each other? And so on.</p>
<p>Serialization is a topic very closely related to data structure. Serialization involves converting from one data structure to a simpler data structure, usually some human-redable text or a raw binary sequence with some specific order or pattern. The reverse process, deserialization, involves converting the simpler data structure back into the original structure (or a similar one). Serialization is most often used when saving data to a file or sending it over a network.</p>
<p>Personally, I consider binary serialization to be a measure of last resort, to be used only when performance is absolutely critical. Binary formats are notoriously fragile and difficult to extend, especially if they are poorly designed.</p>
<p><span id="more-855"></span>(I recently worked on a project where the previous programmer wrote code to &#8220;serialize&#8221; a C struct by copying a chunk of raw bytes from memory and sending it over the network. To &#8220;deserialize&#8221; it, they would &mdash; I kid you not &mdash; copy the bytes into memory and type-cast it to the struct type! They had given absolutely no thought to portability, extensibility, validation, or robustness. And the person who wrote it was ostensibly a professional programmer, and had been paid for the work.)</p>
<p>So, I use human-readable text formats whenever possible. Probably the two most popular formats for this kind of serialization are XML and JSON. But Lisp already has a simple, human-readable, portable, built-in serialization format: S-expressions, the same format used for Lisp code. I&#8217;m still experimenting with the structure, but here&#8217;s an example of a simple scene as it is serialized now:</p>
<p><code>
<pre>
(:instance :scene
 :props nil
 :creatures
 ((:instance :creature
   :name "Creature 1"
   :body
   (:instance :part
    :props
    ((:shape :label "Shape" :value :rectangle)
     (:angle :label "Angle" :type :angle :value 0)
     (:scale :label "Scale" :type :real :value 120)
     (:size :label "Size" :type :vec :value #C(1.0d0 1.0d0))
     (:pos :label "Position" :type :vec :value #C(75.0d0 150.0d0))
     (:depth :label "Depth" :type :real :value 0)
     (:color :label "Color" :type :color :value #(0.7 0.1 0.6))
     (:name :label "Name" :type :string :value nil))
    :children nil))))
</pre>
<p></code></p>
<p>It&#8217;s human-readable, very compact for how much information it expresses, and Lisp intrinsically knows how to read and print it. I might write a little bit of code to get rid of the colons (which indicate Lisp keyword symbols) to make it even easier for humans to read.</p>
<p>I should point out that even though the structure is serialized as lists, the data is actually stored in the program as class instances, arrays, and hash tables. They are converted to lists before being serialized, then inserted back into an array or hash table when deserialized. In addition to making the output easier for humans to read, adding this layer of abstraction means I can change the internal data structure while easily maintaining compatibility with older versions.</p>
<p>Besides decisions about whether to use lists, arrays, hash tables, or whatnot, I&#8217;ve also been experimenting with how the various kinds of objects relate to each other. As it is now, there are three main kinds of objects:</p>
<ul>
<li>Scene objects, which represent a particular scenario of creatures, scene-wide behaviors, and properties such as background color and the scene&#8217;s creator.</li>
<li>Creature objects, which represent a collection of parts with some behaviors and properties such as its name and creator. A creature directly holds a main part, called the body, of which all the other shapes are &#8220;descendants&#8221;.</li>
<li>Parts, which represent a shape, like a circle or triangle, with properties such as its size, color, density. A part can have &#8220;children&#8221;, meaning they are linked together in a hierarchy.</li>
</ul>
<p>One noteworthy thing about these data structures is the way object properties are stored. Instead of storing color, position, size, etc. directly as slots/members of a class instance, they are all stored together in the object&#8217;s &#8220;props&#8221; hash table. This makes it more flexible, as props can be added or removed at any time. At some point, scene creators will be able to add their own props that are used by custom behaviors. For that same purpose, props are stored with metadata about their type, label, and so on.</p>
<p>There&#8217;s another kind of object that I may be adding soon: joints, which are used with the physics engine to connect parts that move independently, but are joined together with a spring, pivot, or whatnot. But, I might just make joints another type of part. I&#8217;ll talk about this and other physics engine stuff in my next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/02/24/data-structures-and-serialization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Complicated Code and Creative Blocks</title>
		<link>http://blog.jacius.info/2012/02/02/complicated-code-and-creative-blocks/</link>
		<comments>http://blog.jacius.info/2012/02/02/complicated-code-and-creative-blocks/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 21:01:09 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=843</guid>
		<description><![CDATA[The past several weeks have been a struggle, productivity-wise. First, I spent quite a lot of time working on proto-slots. That may seem productive, but the amount of effort I put into polishing and documenting it was way out of proportion to the benefit I would get from it. I think I did a pretty [...]]]></description>
			<content:encoded><![CDATA[<p>The past several weeks have been a struggle, productivity-wise.</p>
<p>First, I spent quite a lot of time working on <a href="https://github.com/jacius/proto-slots">proto-slots</a>. That may seem productive, but the amount of effort I put into polishing and documenting it was way out of proportion to the benefit I would get from it. I think I did a pretty good job on that project, but I also recognize now that I was using it as a way to avoid actually working on Ambienome.</p>
<p>It was about three weeks ago that I realized what was happening, so I tried to force myself to focus on Ambienome. That didn&#8217;t really work, and I just ended up with a serious creative block. I spent about two weeks making almost no progress. My code had been accruing unnecessary complexity, mostly due to exploring a lot of unfamiliar territory (Lisp, and OpenGL), which made it difficult to work on when my motivation was not very high. Each time I would try to focus on Ambienome, I&#8217;d run into some obstacle, grimace, and reflexively go find some way to distract myself. (In hindsight, it was probably not wise to start a challenging new project at the beginning of winter, since my energy levels and motivation always dip during the winter.)</p>
<p>(Those two weeks weren&#8217;t a complete loss, though; I did beat a lot of games! :P If you&#8217;re curious: <a href="http://dungeonsofdredmor.com/">Dungeons of Dredmor</a>, <a href="http://bindingofisaac.com/">The Binding of Isaac</a>, <a href="http://limbogame.org/">Limbo</a>, <a href="http://www.mumbojumbo.com/game/Glowfish/prod370033?technology=WINDOWS">Glowfish</a>, <a href="http://www.swingswingsubmarine.com/games/blocks-that-matter/">Blocks That Matter</a>, and a couple others that I can&#8217;t recall at the moment.)</p>
<p><span id="more-843"></span>I finally broke through the creative block about a week ago, by unplugging the internet, shutting out all distractions, and just tackling my code head-on. I spent 3 days just simplifying and cleaning up my code to make further development feasible. All told, I managed to eliminate 9 classes:</p>
<ul>
<li><code>job</code>, which acted as a central coordinating structure for the OpenGL rendering pipeline. The important functionality was transformed into methods of the <code>program</code> class, which is slightly lower-level coordinating structure for the rendering pipeline. The rest of the code was scrapped.</li>
<li><code>uniform</code> and <code>attribute</code>, which represented OpenGL shader uniforms and attributes. These classes were also reduced into methods of <code>program</code>, and the unnecessary code scrapped.</li>
<li><code>rectangle</code>, <code>triangle</code>, and <code>circle</code>, which represented instances of those geometric shapes. They were reduced into a <code>render-shape</code> generic function, with a method implemented for each shape based on a keyword. For example, to render a circle you&#8217;d do <code>(render-shape :circle ...)</code>. Lisp&#8217;s method dispatching system is pretty handy sometimes!</li>
<li><code>shape</code>, which was the parent class of the three shapes mentioned above. Aside from the rendering code, which (as I said) became methods, this class also stored the shape&#8217;s transformation (position, rotation, scale), and other properties such as color. I moved this functionality to the <code>part</code> class, which represents a creature body part.</li>
<li><code>group</code>, which held multiple shapes that would move together, just like SVG&#8217;s <code>g</code> element. Instead, I decided that it&#8217;s simpler and more intuitive to allow body parts to be parented to other parts. To handle the case of an invisible pivot point, the parent shape can be made invisible, in which case it&#8217;s functionally equivalent to a group.</li>
<li><code>prop</code>, which represented a property of a shape, such as its color. The idea behind this class was that it would contain not only the data, but also some metadata (its type, human-readable name, etc.) that could be used later to generate an appropriate user interface to edit the property. For example, the color property would have some metadata indicating that the data was a color, so it should be edited using a color swatch widget. I decided to just store the data and metadata in hash tables instead.</li>
</ul>
<p>My code is now much leaner and more function-oriented than before, and much more approachable and easier to work with. I actually  eliminated (temporarily, I think) the need for my proto-slots library &mdash; which, after all the work I put into it, is either really funny or really frustrating.</p>
<p>Yesterday and today, I&#8217;ve been making progress (not a great deal, but enough) on new code, specifically the ability to serialize and deserialize creatures and their body parts, so that they can be saved and loaded from file. I&#8217;m nearly done with this, but I&#8217;m not sure yet what I&#8217;ll tackle next.</p>
<p>Perhaps I&#8217;ll try to plot out a more concrete roadmap, start to define and narrow the scope of the game, and lay out some specific tasks and goals. I&#8217;m sure my unorganized, exploratory approach is a significant cause of my slow progress. It would be good to have some concrete milestones to chase after, and maybe even some deadlines to push myself forward. What a radical notion!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/02/02/complicated-code-and-creative-blocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mini-project: proto-slots</title>
		<link>http://blog.jacius.info/2012/01/05/mini-project-proto-slots/</link>
		<comments>http://blog.jacius.info/2012/01/05/mini-project-proto-slots/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 06:35:07 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Lisp]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=838</guid>
		<description><![CDATA[I&#8217;ve just released proto-slots, a mini-project I created as part of Ambienome. From the README: proto-slots provides a macro for defining prototypal accessor methods so that CLOS instances will support protoypal inheritance. Prototypal inheritance means that an instance&#8217;s slots can inherit values from another instance, known in these docs as the &#8220;base object&#8221; (but more [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released <strong><a href="https://github.com/jacius/proto-slots">proto-slots</a></strong>, a mini-project I created as part of <a href="http://blog.jacius.info/category/projects/ambienome/">Ambienome</a>. From the README:</p>
<blockquote><p>proto-slots provides a macro for defining prototypal accessor methods so that CLOS instances will support protoypal inheritance. Prototypal inheritance means that an instance&#8217;s slots can inherit values from another instance, known in these docs as the &#8220;base object&#8221; (but more commonly known elsewhere as the &#8220;prototype&#8221;).</p></blockquote>
<p>I wrote the first version of what eventually because the def-proto-slots macro to solve a problem I described in my previous post:</p>
<blockquote><p>But, for each shape instance to have its own color (or other such data in the future), each shape instance must have its own job, because the color would be a uniform contained in that job. If I set the color in the base job, all instances of that kind of shape would have the same color. But if each instance has its own job, I lose the benefit of having the vertex data stored in one place.</p>
<p>I solved this by letting a job have a &#8220;parent&#8221;, from which it inherits anything it’s missing, such as a program or elements. For vertex attribs and uniforms, the inheritance works by merging the parent’s list of attribs/uniforms with the child&#8217;s list, with any of the child&#8217;s attribs/uniforms taking precedence when it has the same name as one of the parent&#8217;s.</p></blockquote>
<p>I realized later that I was going to need prototypal inheritance for other parts of Ambienome, too. For example, I&#8217;m pretty sure the creature class will use this pretty heavily. So, I took my ad hoc macro, made it more flexible (it now supports different &#8220;inheritance strategies&#8221;), and polished it up. Along the way I decided to release it as a separate library, to maybe save someone else the trouble of implementing this same sort of thing.</p>
<p>proto-slots is <a href="https://github.com/jacius/proto-slots">available at GitHub</a>, released under the X11/MIT license. If you find a bug, <a href="https://github.com/jacius/proto-slots/issues">make an issue</a>. To submit a patch, fork my repo and send a pull request.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2012/01/05/mini-project-proto-slots/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Colored Shapes</title>
		<link>http://blog.jacius.info/2011/12/17/colored-shapes/</link>
		<comments>http://blog.jacius.info/2011/12/17/colored-shapes/#comments</comments>
		<pubDate>Sat, 17 Dec 2011 23:19:51 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=831</guid>
		<description><![CDATA[I got a bit sidetracked while working on creature components, but still ended up making important progress for the overall system. First, I created a new transform class by abstracting and cleaning up the shape class&#8217;s position, angle, and size attributes and methods. I also created a transformable &#8220;mixin&#8221; class, which can be used by [...]]]></description>
			<content:encoded><![CDATA[<p>I got a bit sidetracked while working on creature components, but still ended up making important progress for the overall system.</p>
<p>First, I created a new <code>transform</code> class by abstracting and cleaning up the <code>shape</code> class&#8217;s position, angle, and size attributes and methods. I also created a <code>transformable</code> &#8220;mixin&#8221; class, which can be used by any class that has a transform. (Lisp doesn&#8217;t have mixins in the same sense that Ruby does, but since Lisp supports multiple inheritance, you can get more or less the same effect by designing a class in a mixin-ish style.) The transformable class provides accessors for the transform&#8217;s position, angle, and size, so that you can treat them as if they were direct slots of the object holding the transform.</p>
<p>Next, I decided to enhance the shape class so that shapes can have a color. This turned out to be somewhat challenging, because of how I had designed the OpenGL wrapper classes.</p>
<p><span id="more-831"></span>I have a <code>job</code> class that holds a program object (which is a collection of compiled shaders linked together) and the vertex attribs, uniforms, and elements used to render a certain thing (such as a shape). For memory efficiency, each kind of shape (rectangle, triangle, or circle) has a base job which holds the generated vertex data and elements. </p>
<p>But, for each shape instance to have its own color (or other such data in the future), each shape instance must have its own job, because the color would be a uniform contained in that job. If I set the color in the base job, all instances of that kind of shape would have the same color. But if each instance has its own job, I lose the benefit of having the vertex data stored in one place.</p>
<p>I solved this by letting a job have a &#8220;parent&#8221;, from which it inherits anything it&#8217;s missing, such as a program or elements. For vertex attribs and uniforms, the inheritance works by merging the parent&#8217;s list of attribs/uniforms with the child&#8217;s list, with any of the child&#8217;s attribs/uniforms taking precedence when it has the same name as one of the parent&#8217;s. It&#8217;s wonderfully easy to do that in Lisp:</p>
<pre><code>(union (attribs parent) (own-attribs job)
       :key #'name :test #'string=)</code></pre>
<p>This code takes the attribs list from the parent, including any attribs the parent itself inherits from <em>its</em> parent, and the list of attribs belonging directly to the job, and performs a set union of those two lists, which discards duplicates. But what is a &#8220;duplicate&#8221;? By providing the <code>:key #'name</code>, I&#8217;m telling it to call the <code>name</code> function on each attrib, and then check the names to see if they are duplicates. The <code>:test #'string=</code> part tells it to use the <code>string=</code> function, which performs case-sensitive string comparison, to decide if the two names are the same. The result is that if an attrib in the parent&#8217;s list and an attrib in the child&#8217;s list have the same name, only the child&#8217;s is used (since it is given as a later argument to the <code>union</code> function).</p>
<p>While doing this, I noticed that the inheritance code was exactly the same for attribs and uniforms, except for the word &#8220;attrib&#8221; or &#8220;uniform&#8221;. So, I wrote a fairly simple, albeit long, macro to keep things <abbrev title="Don't Repeat Yourself">DRY. Then I wrote shorter macro to reduce the redundancy in the simpler inheritance behavior for the other slots, which only inherit from the parent if their slot is empty/null, but don&#8217;t have to perform any merging.</p>
<p>Now that jobs can have a parent, I can use each shape class base job (the job containing the vertex data and elements) as the parent for each shape instance&#8217;s job (the job containing the color and other instance-specific data). So, the instance&#8217;s job can inherit the vertex data and elements, while still having its own color. And later, I&#8217;ll be able to have base jobs at different levels of detail, and easily change the instances&#8217; parents whenever I want to change their level of detail.</p>
<p>After a bit more work, I finally had support for different colors in each shape instance. Victory!</p>
<p><img src="http://blog.jacius.info/wp-content/uploads/2011/12/colored_shapes.png" alt="Screenshot of a purple square, blue triangle, and orange circle." title="Colored Shapes" width="406" height="326" class="aligncenter size-full wp-image-832" /></p>
<p>It was a long detour, but my code base is much better for all the work. Now I can <em>finally</em> get around to shape groups and creature components!</abbrev></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2011/12/17/colored-shapes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shape Mesh Progress</title>
		<link>http://blog.jacius.info/2011/12/09/shape-mesh-progress/</link>
		<comments>http://blog.jacius.info/2011/12/09/shape-mesh-progress/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 18:26:13 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=826</guid>
		<description><![CDATA[Yesterday, I completed the code to generate triangle and circle meshes: The triangle looks like it&#8217;s too small, but it fits perfectly in the circle, and the circle fits perfectly in the square. Yay, geometry! Of course, when building a creature, they can be scaled to whatever size you like, and the algorithms can produce [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday, I completed the code to generate triangle and circle meshes:</p>
<p><img src="http://blog.jacius.info/wp-content/uploads/2011/12/meshes.png" alt="Screenshot of a rectangle mesh, a triangle mesh, and a circle mesh." title="Meshes" width="406" height="326" class="aligncenter size-full wp-image-828" /></p>
<p>The triangle looks like it&#8217;s too small, but it fits perfectly in the circle, and the circle fits perfectly in the square. Yay, geometry! Of course, when building a creature, they can be scaled to whatever size you like, and the algorithms can produce meshes at any level of detail. Eventually, I&#8217;ll make it so the game automatically adjusts the level of detail based on the shape&#8217;s size on the screen.</p>
<p>As I mentioned in the previous post, these aren&#8217;t the only shapes that will be available, but they are enough to let me move on to other things. One of the core concepts of Ambienome is that I can program new shapes later, even after the game has been released. If I&#8217;m feeling really clever, I could probably leverage Lisp&#8217;s power to allow users to program new kinds of shapes, too. That&#8217;s not a high priority, though.</p>
<p>Today I&#8217;ll start code-sketching the concept of components and creatures. A creature is built from one or more components, which are basically shapes with some associated behavior. Components can be grouped to move together, and groups can contain other groups, so it&#8217;s essentially a &#8220;tree&#8221; (hierarchy) of transformation nodes, with each &#8220;leaf&#8221; being a shape. This is the same concept as grouping in SVG or Flash, or parenting in 3D software like Blender or Maya.</p>
<p>After weeks of just studying and debugging OpenGL, it sure is nice to be making visible progress again!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2011/12/09/shape-mesh-progress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adventures with the OpenGL shader pipeline</title>
		<link>http://blog.jacius.info/2011/12/07/adventures-opengl-shader-pipeline/</link>
		<comments>http://blog.jacius.info/2011/12/07/adventures-opengl-shader-pipeline/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 18:31:41 +0000</pubDate>
		<dc:creator>John Croisant</dc:creator>
				<category><![CDATA[Ambienome]]></category>

		<guid isPermaLink="false">http://blog.jacius.info/?p=812</guid>
		<description><![CDATA[For the past several weeks, I&#8217;ve been learning &#8220;modern&#8221; OpenGL programming practices, by which I mean using a GLSL shader pipeline with vertex and fragment shaders. Even before starting Ambienome, I was already somewhat familiar with the old OpenGL &#8220;fixed function pipeline&#8221;, using glBegin/glEnd, glColor, glVertex, etc. Ambienome is going to be visually simple enough [...]]]></description>
			<content:encoded><![CDATA[<p>For the past several weeks, I&#8217;ve been learning &#8220;modern&#8221; OpenGL programming practices, by which I mean using a <a href="https://en.wikipedia.org/wiki/GLSL">GLSL</a> shader pipeline with vertex and fragment shaders.</p>
<p>Even before starting Ambienome, I was already somewhat familiar with the old OpenGL &#8220;fixed function pipeline&#8221;, using glBegin/glEnd, glColor, glVertex, etc. Ambienome is going to be visually simple enough that I probably could have used the fixed function pipeline, but I decided to learn the shader pipeline to improve my knowledge and skills, to allow nicer visual effects, and to leverage the GPU&#8217;s number-crunching power as much as I can.</p>
<p>Grokking the shader pipeline was a challenge. There are many separate concepts to learn, and then you must understand how they fit together. Also, there are fewer learning resources for the shader pipeline than there are for the older fixed function pipeline. I relied mostly on <a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html">Joe Groff&#8217;s &#8220;An intro to modern OpenGL&#8221; article series</a>, but if I were doing it over again, I might try to find a good book. Unfortunately, the selection is somewhat thin. I&#8217;m considering <a href="http://www.amazon.com/OpenGL-Shading-Language-Randi-Rost/dp/0321637631/"><i>OpenGL Shading Language</i><i></i></a> (the so-called &#8220;Orange Book&#8221;) or the <a href="http://www.amazon.com/OpenGL-ES-2-0-Programming-Guide/dp/0321502795/"><i>OpenGL ES 2.0 Programming Guide</i></a>. (OpenGL ES 2.0 is conceptually very similar to the OpenGL shader pipeline, and also very similar to WebGL.) Unfortunately, the reviews suggest those two are not very well written, organized, or proofread. <a href="http://www.amazon.com/Real-Time-Rendering-Third-Tomas-Akenine-Moller/dp/1568814240/"><i>Real-Time Rendering</i></a> looks like it might provide a good high-level understanding of shaders and rendering, but it&#8217;s not specific to OpenGL or GLSL, and I&#8217;m not really interested in advanced photorealistic shader effects. Maybe if there are any book stores still open in this town, I&#8217;ll see if any of these books are on the shelf so I can assess them before I buy.</p>
<p>Anyway, even after I had scraped together a modest understanding of the concepts behind the shader pipeline, applying that knowledge in practice took longer than I anticipated. It was fairly frustrating at times, partly due to some (minor) shortcomings of cl-opengl and lispbuilder-sdl, and partly due to me misinterpreting some vague parts of the OpenGL documentation. There were many times when I felt like putting the shader pipeline aside, and just using the fixed function pipeline for a while, so I could keep my momentum up. But I stubbornly stuck with it, and now I&#8217;ve got a working, reusable rendering framework built atop the shader pipeline. Huzzah!</p>
<p>My next task is to write code to algorithmically generate mesh data for several geometric primitives. Yesterday, I finished the code for a rectangle mesh built from triangle strips (well, actually one long strip with degenerate triangles connecting each row). Here&#8217;s a screenshot of a 10&times;10 rectangle mesh rendered in wireframe mode:</p>
<p><img src="http://blog.jacius.info/wp-content/uploads/2011/11/rectangle_mesh.png" alt="Screenshot of a rectangle mesh" title="Rectangle Mesh" width="406" height="326" class="aligncenter size-full wp-image-809" /></p>
<p>It&#8217;s not much to look at in itself. I could have achieved that in an afternoon using the fixed function pipeline! But that humble mesh, rendered here using the simplest possible vertex and fragment shaders, represents weeks of learning. Now that I have the basics working, I can write more interesting shaders to morph the shape and create cool visual effects. For example, Ambienome takes place underwater, so I&#8217;ll probably write a shader to make things sway and ripple as if they were being affected by a water current.</p>
<p>Next, I&#8217;ll be writing the code for a triangle mesh, and then a circle mesh. I have plans for more shapes, like teardrop, leaf, ring (circle with a hole in the middle), and tentacle (a Bézier curve with thickness controlled by another Bézier curve). But, I&#8217;m going to save those for later. Once I&#8217;ve got rectangle, triangle, and circle, I&#8217;m going to take a step back from the low-level foundation for a while, and start fleshing out higher-level concepts like components, creatures, and scenes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jacius.info/2011/12/07/adventures-opengl-shader-pipeline/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
