John Fremlin's blog2012-01-05T06:41:04ZBits of hash to avoid a clash2012-01-05T06:41:04Z/hash-collision-avoidance<div class='blog-entry-story'><p>Suppose you have n objects which you cannot for some reason index sequentially, but for each one you can create a hashed value, and instead of transmitting the objects you want when possible to transmit the hashed values, in order to save communication bandwidth. Now if the hashes have fewer bits than those necessary to encode all the possible objects there will certainly be collisions where a hash value does not uniquely identify an object. Suppose this is acceptable if the probability of collision is less than or equal to p. How many bits of a perfectly distributed hash does one need, or equivalently if the hash can take values from 0 to h-1 inclusive, how large should h be?</p><p>This is related to the birthday collision demonstration &mdash; in a classroom of children it is expected that two will share the same birthday.</p><p>The probability of no collision q = 1-p is 0 if h &lt; n and otherwise the product (1 - k/h) for k from 1 to n. Now if we look at the powers of h, then this is 1 - n(n+1)/2h + a<sub>2</sub>/h<sup>2</sup> - a<sub>3</sub>/h<sup>3</sup> + &hellip; where the coefficients a<sub>i</sub> are functions of n. Now if we say that h &gt; n(n+1) then we can show elementarily that a<sub>i+1</sub> &lt; a<sub>i</sub> by comparing the components of the constituent sum, so q &gt; 1 - n<sup>2</sup>/2h.</p><p>Therefore given p = 1-q, the probability of collision we are willing to tolerate, we have h &lt; n<sup>2</sup>/2p so we simply choose an h as large as n<sup>2</sup>/2p to keep us very safe.</p></div>WPA supplicant and TKIP pairwise cipher2011-10-03T11:49:26Z/wpa-pairwise-tkip<div class='blog-entry-story'><p>On some wifi routers, the CCMP WPA pairwise cipher does not work with wpa_supplicant, though the key is correct, but the TKIP cipher will work. The router advertises Pairwise Ciphers (2) : TKIP CCMP.</p><p>wpa_supplicant says <pre> State: 4WAY_HANDSHAKE -> 4WAY_HANDSHAKE WPA: RX message 1 of 4-Way Handshake from xx:xx:xx:xx:xx:xx (ver=2) WPA: PTK derivation - A1=xx:xx:xx:xx:xx:xx A2=xx:xx:xx:xx:xx:xx WPA: PMK - hexdump(len=32): [REMOVED] WPA: PTK - hexdump(len=48): [REMOVED] WPA: WPA IE for msg 2/4 - hexdump(len=24): WPA: Sending EAPOL-Key 2/4 Authentication with xx:xx:xx:xx:xx:xx timed out. </pre> or <pre> WPA: 4-Way Handshake failed - pre-shared key may be incorrect </pre></p><p>To workaround, add pairwise=TKIP to the entry in wpa_supplicant.conf. </p></div>Designing user interfaces to computer systems2011-09-27T02:51:39Z/ui-design<div class='blog-entry-story'><p>It's hard to make a functional user interface and impossible to make one that delights everybody. Especially when designing a website there is a huge temptation to simply expose functionality in the easiest way possible. But this is backwards because probably a vast number of users will interact with the website and any unintuitive behaviour means they in the aggregate waste vast amounts of time. </p><p>Instead of exposing functionality in the easiest way, one should add expected behaviours &mdash; if the user presses the delete key, what should happen? If a user clicks on any part of the page, probably he or she some intent in mind and if one were watching, one could guess it. Guess ahead of time and add the behaviour! Each user action signifies an intent that it is unkind to ignore. </p></div>Doubling and shuffling grains to make a pile2011-08-24T00:00:00Z/doubling-and-shuffling-grains<div class='blog-entry-story'><p>There is an old story that a munificent king demanded to bounteously reward a sage: the sage requested that the king give him one grain for the first square of the chess board, two grains for the second, four grains for the fourth, and so on doubling the amount each square. There being 64 squares on the chessboard the munificence of the monarch was exceeded and he beheaded the sage. Here is an even more dangerous mechanism which involves only six squares (piles) but vastly more than 2<sup>64</sup> profit.</p><p>Starting with an ordered set of n piles of grains, you can perform one of two moves: double a grain by removing one from a pile and adding two to the pile on the right of it, or shuffle by removing a grain and then swapping the positions of the two piles immediately on the right. The objective is to create as many grains as possible. Piles cannot be created, so the doubling move cannot be used on the rightmost pile, and the shuffling move cannot be used on the rightmost or the one just to the left of that. Given six piles each with a single grain, can you create exactly 2010<sup>2010<sup>2010</sup></sup> grains?</p><p>This is <a href="http://michaelnielsen.org/polymath1/index.php?title=Imo_2010">IMO 2010 problem 5</a>. It seems there are solutions all over the web now including at that polymath link; however, I'm not sure that they convey the glorious magnificence of the system.</p><p>Now suppose we define a function f(n, b, e) as the maximum number of grains that one can obtain with n piles, the leftmost containing b grains and the rightmost e grains, and all the rest empty. Surprisingly, this function grows very quickly in n, rather in the manner of Knuth's arrow operator.</p><p>Now f(1,h,h) = h, f(2, b, e) = 2b + e. The first indication of fun comes with f(3, b, e) &ge; 2<sup>b</sup>e or 2<sup>b+1</sup>&mdash; with three piles, double all the grains in the middle pile into the right pile, then use the left pile to swap this pile back into the middle and double it again.</p><p>The real heart is that the swapping rule effectively allows a reapplication of the function f(n-1, ...) to its previous value. This can be extended to n &gt; 3, provided b &ge; 2: spend one grain by doubling to the right and then using one of the new grains to double again to the right to fill the intervening piles with one grain each, and then use these grains to shuffle the pile at the end back into the second from leftmost position, and then use another grain in the leftmost to bring the pile into the first from leftmost. Therefore f(n,b,e) &ge; f(n,b-2,f(n-1,e+4,0)) for n &ge; 4 and b &ge; 2.</p><p>With six piles with a single grain 1 1 1 1 1 1, we initially double to get 2 2 2 0 7, then apply the exponential rule for n = 3 to get 2 2 0 0 28, and then the repeated exponential (tetration) rule for n = 4 to get 2 0 0 0 2<sup>33</sup>, and then using the reapplication rule we have to evaluate 2<sup>33</sup>+4 0 0 0, in comparison to our target of 2010<sup>2010<sup>2010</sup></sup>. As we can waste grains by shuffling empty piles, we need not worry if we exceed the target.</p><p>In other words, we need to get a lower bound for the tetration f(4, 2<sup>33</sup>+4, 0). This is by the reapplication rule greater than exponentiation repeated 2<sup>32</sup> times, or 2 &uarr; &uarr; 2<sup>32</sup> in Knuth's notation.</p><p>Is this clearly greater than c = 2010<sup>2010<sup>2010</sup></sup>? Suppose we take log base 2. Then log<sub>2</sub> c < 11 2010<sup>2010</sup> and log<sub>2</sub> log<sub>2</sub> c < 4 + 11 . 2010 < 25 000.</p><p>But log<sub>2</sub> log<sub>2</sub> 2 &uarr; &uarr; 2<sup>32</sup> is just 2 &uarr; &uarr; (2<sup>32</sup> - 2) and 2 &uarr; &uarr; 4 &gt; 65 000 so we have an scale of headroom that is difficult to relate to quantities in our universe.</p><p>From the two rules of moving and adding one to the right, and removing and shuffling, a system is created that makes more grains than one can comfortably represent with exponential notation. Amazing! </p><p>Thanks to David B for bringing the problem to my attention, it was a lot of fun, and many thanks to Rob Backhouse for proofreading and improving the method. </p></div>BTRFS hard links in the same directory limit is too small2011-08-21T16:13:46Z/btrfs-hard-links-limit<div class='blog-entry-story'><p><a href="http://en.wikipedia.org/wiki/Btrfs">BTRFS</a> is a next generation filesystem for Linux that has some pleasant features which set it apart from ext4. For example, checksums, snapshots, and online defragmentation. In many respects it is inspired by <a href="http://en.wikipedia.org/wiki/ZFS">ZFS</a>.</p><p>I was converting a filesystem from ext4 to btrfs when I came upon a problem: it seems that BTRFS supports only 256 hard-links for files in the same directory (that is, up to 256 names for the same inode in one directory) though across directories you can have up to 2<sup>32</sup> names for the same inode.</p><p>This restriction causes btrfs-convert 0.19 to crash out with a segfault and no helpful message: something like btrfs-convert: segfault at ffffffffcfb25fb9 ip 000000000040f9f1 sp 00007fffddefb398 error 6 in btrfs-convert[400000+21000].</p><p>It seems a priori that there should not be any need for more than 256 names for the same file in the same directory. However, the GNUS mailreader's nnmaildir backend uses hardlinks to mark email messages read, and instead of creating a separate inode for each marked message, uses a hardlink to a single markfile. This means that there maybe thousands of hardlinks to the same inode in a single directory.</p><p>You can use the command find -type f -links +255 to locate such troublesome files, however this will not indicate whether the links are in the same directory or not, so there can be false positives.</p><p>The reason designing file-systems and other system infrastructure is hard is that the range of at first glance nonsensical configurations that people will expect to work seamlessly. I hope that as BTRFS matures it will be able to handle these use-cases &mdash; the nnmaildir link hack to use the filesystem as a mark database is not altogether unreasonable. </p></div>Splitting sticks2011-06-26T00:00:00Z/splitting-sticks<div class='blog-entry-story'><p>A rather nice puzzle with thanks to Mr Chen and Mr B: given a stick of integer length n &gt; 1, split it at an integer point below n, multiply the product of the two pieces and for each piece larger than length 1, do the same thing. What is the sum of all the products?</p><p>The answer follows &mdash; maybe you would like to take a moment to puzzle it out by yourself?</p><p>Firstly, why should the sum of the products not depend at all on the strategy? If one were not restricted to integer divisions in some way, then the strategy would probably become important, depending how the puzzle were then defined. The use of multiplication indicates area; the use of integers indicates blocks. Given that we must have area, we have defined a shape &mdash; it should have some symmetry as we can rotate the stick, and balance the increase in one piece of the split with an equal and opposite decrease &mdash; thus we guess a triangle.</p><p>We therefore present a visualisation of the problem as a triangle with n-1 1x1 blocks all on a line, n-2 blocks above them, n-3 above those stacked from the left until at the top left a single 1x1 block stands. The choice of point to split the stick now resolves to a choice of block on the diagonal - given a choice of such a block k &lt; n, subtract it and the k x k square underneath and to the left of it from the stack of blocks; this leaves up to two triangular piles corresponding to the up to two remaining pieces with length greater than one; each triangle is of the right size so the analogy holds and the answer is the area of the first triangle of blocks: (n-2)(n-1)/2.</p><p>Alternatively, one can trivially see it algebraically by induction, but that is less fun. </p></div>A new information security stone age: the no-Santa clause2011-04-30T00:00:00Z/infosec-stone-age<div class='blog-entry-story'><p>[And now a guest post from my good friend, <a href="mailto:tk281@web.de">Thomas Köppe</a>.]</p><p>We have been taught that the internet can be made to keep our bank data and our work documents and our love letters secure (whatever that means, but who doesn't want to feel secure?), as long as we look out for the little padlock in the address bar. But a major link in the security chain that makes all this happen has been compromised. The attitude of our modern information society is dangerously askew.</p><p>Last month, one of the so-called certificate authorities (CA), which issue the cryptographic certificates that websites use to prove their authenticity to the user, and which contemporary browsers are practically hard-coded to trust, has been involved in a major security breach. The US-based CA, called Comodo, was conned into issuing fraudulent certificates to an unknown entity (presumed of Iranian origin) for major websites including (but not limited to) Google, Yahoo, Skype and Mozilla. Anyone who holds such a certificate, which browsers trust automatically, can pretend to be that website and link themselves into your communication, eavesdropping and perhaps tampering with the information you believe to come from the genuine source.</p><p>In the wake of the recent security fiasco at Comodo [<a href="http://www.wired.com/threatlevel/2011/03/comodo-compromise/">1a</a>, <a href="http://www.h-online.com/open/news/item/SSL-meltdown-forces-browser-developers-to-update-1213358.html">1b</a>], I was at first pleasantly surprised that this event made it into the mainstream news [<a href="http://www.bbc.co.uk/news/technology-12847072">2a</a>, <a href="http://bits.blogs.nytimes.com/2011/03/24/iranian-hackers-suspected-in-recent-security-breach/">2b</a>], but then it struck me: Almost everybody who is going to get this news flash from any of the mainstream sources will respond (if at all) with a perplexed frown, a mental shrug and move on to something more tangible or relevant to their lives. The Comodo hack has demonstrated one of the greatest weaknesses of the way we currently deal with <em>trust</em> on the internet, which has potentially profound implications, but it will be nigh impossible to get anyone concerned about this, let alone change their every day Internet behaviour.</p><p>In fact, whenever I do suggest to friends and colleagues things that could help make their information security a little more robust, it is almost invariably clear that they won't change their behaviour, given that <q>everything works just fine as it is,</q> and they <q>have nothing to hide.</q> (For those interested in the details: for example, SSH is another secure protocol that is generally accepted to do a very good job, but the price is that the user has to make a trust decision every time they connect to a new peer.)</p><p>At this point I would like to invoke what I call the <q>No Santa</q> Clause: nothing is free. It was once considered a milestone on the way to adulthood to shed one's belief in a universal benefactor who would bring things and ask nothing in return. Yet, in a turn most curious, our modern society seems to be turning this on its head, and when faced with computer technology, enlightened, educated adults are now more and more of the conviction that they should just get lots of stuff for free.</p><p>Before the advent of computers, it was generally possible for most people to understand large parts of their every-day environment, or at least know in principle how they could come by the understanding. A. C. Clarke's <q>sufficiently advanced technology</q> was certainly not magic to us, and while an uncontacted South American tribe might be genuinely incapable of fathoming what makes a car move, none of us consider cars magic and could, at gunpoint, explain the basic idea of a combustion engine. But it is worth remembering that the combustion engine is just a miniature version of a steam engine (as are nuclear power plants), and steam engines have been around for centuries.</p><p>However, with the advent of computers, we are facing a new situation, quite possibly a first in the history of civilisation. To most people, modern computers and networks are quite literally <em>magic</em>. We have simply <em>no</em> idea what makes them work. All we know is that if I edit my Google Spreadsheet in London today, I can open a browser in Calcutta tomorrow and continue writing. How does any of this work? <q>I don't care, it just does, leave me alone.</q> More and more of modern people's lives are being transferred entirely into the cloud, this magical vapour that has your photos and knows your friends wherever you are.</p><p>But wait &mdash; a service which allows you to access your entire <em>life</em> from anywhere in the world, instantly, and safely and securely? This really is a <em>big</em> deal, a huge service! And now we must wake up and realise that there is no Santa Claus: This service is not free. Perhaps (for the first time since the inception of money millennia ago) this service does not require us to pay money. But what it does require is responsibility.</p><p>The world of online information processing and security is a complex and complicated one indeed. But it is where most of our lives are now taking place. Just like we demand car drivers to pass a test and drive responsibly, we absolutely must demand of everyone who uses computers and networks as integral parts of their lives to do so responsibly. And this simply requires a certain extent of understanding of the subject matter. Security design is an art that <em>nobody</em> understands at this point, and there are no secure systems. (Anyone who claims otherwise is either dishonest or incompetent.) As security experts repeatedly put it [<a href="http://www.lightbluetouchpaper.org/2011/03/24/can-we-fix-federated-authentication/">3a</a>, <a href="http://www.cs.auckland.ac.nz/~pgut001/pubs/usability.pdf">3b</a>], everyone in the security chain avoids making the critical decisions and passes the burden around like a hot potato, until it eventually lands in the hands of the _one_ person who is least capable of making the right choice: The user. Anyone who has wildly clicked browser certificate warnings away in anger knows what I mean.</p><p>For the first time it would appear that many people are using tools that are way above their own level of competence, but they do so with little worry or desire to improve that competence. People's attitude has made a leap for which I struggle to find a historic precedent: from having observed at the end of the last century that computers can make some things easier, we have suddenly and inexplicably leapt to the immodestly entitled assumption that computers should make everything entirely free and easy. Nowadays, a suggestion that one should think about one's tools before using them will only earn you confused looks, and possibly accusations of elitism, neediness or lack of a sex life. Companies that <a href="http://www.microsoft.com">specialise</a> on making tools for people who like to work above their limitations have certainly helped foster this attitude, but what happened &mdash; why do we believe that everything should be easy and just work?</p><p>I think complaining of our collective failure to understand security design is not helpful. Sure, there are a lot of things hardware and software vendors could improve. But ultimately, questions of security and trust require the user, you, to make a decision, and you will need enough basic understanding of How Stuff Works to make those calls. As it stands, our civilisation has come full circle, and it is no longer the Amazonian tribe (who doesn't use SSL), but it is us modern, enlightened people for whom most of our everyday technology is now so advanced that it is magic. If we continue to build a world in which the inner workings of most of our waking lives are understood only by a tiny elite of wizards, we may truly be coming around to face a medieval future. Santa hopes you have been good. </p></div>Meta-programming normally2011-04-27T19:57:19Z/metaprogramming-normally<div class='blog-entry-story'><p>There was a time at Bell Labs when the so-called Area 10 from where so much of UN*X sprang evangelised the <q>the dual view of programs as both tools and text</q> (Derman: My Life as a Quant). Tools like the yacc parser generator and lex were invented there. Nowadays the fashion has swung to <a href="http://golang.org/src/pkg/go/parser/parser.go">handwriting</a> those things which were once generated. Programming systems have become more expressive, and integrated with debugger and editor environments so the benefits of a specialised language are lower and the costs in terms of loss of convenience higher.</p><p>The increased expressiveness of modern mainstream programming languages over the FORTRAN of yore paradoxically has caused an explosion in boilerplate as people painstakingly reimplement operator precedence in their parsers by hand. </p><p>Full meta-programming is a huge boon to the development of application specific software, which is in the end, any large project. There is an unfortunate hysteresis in that using an application specific language brings vast costs: it is expensive to start using a new language (which as a project becomes sufficiently large is inevitable). Then it is expensive to maintain the separate compilation stage or auxiliary systems, and then expensive to redesign or replace the language once its deficiencies become unbearable (which as the project ages is also inevitable).</p><p>Given &mdash; for example &mdash; that the increased expressiveness of C++0x allows much to be done without macros that used to need macros, what advantage does first-class meta-programming have over template-based or type-system structured meta-programming? Well, clearly, a huge reduction in complexity: what is the point of wedging a Turing complete template language to be executed at compile time over a Turing complete base language, when one language would suffice perfectly well?</p><p>It is now quite possible to flexibly define and register functions for an RPC layer purely in C++; it is even possible to do it relatively neatly handling type-conversions without overhead at compile time. It was not before; should all the systems that have been built to do this be abandoned? </p><p>One problem still unsolvable in C++ or weaker systems like Scala, etc. is that one cannot define readily define types that should be represented in memory in a special way (for example, position independently or with persistence to a backing store). For example, in tpd2 there is a set of objects (including comments on this blog) that are automatically persisted to disk. These are defined with a custom "defrecord" instead of a standard "defstruct" and that is all; there is no need for runtime reflection to determine the static type of the object.</p><p>Fully flexible first-class meta-programming has the advantage there is a single language to learn, not a language and then language within it for specifying dependent types. It is most important as projects grow. Metaprogramming is all about scaling; scaling a codebase is hard enough without being shocked by new techniques. Meta-programming should be a normal tool not an extra-ordinary one. </p></div>Uncompromising meta-programming2011-03-10T00:00:00Z/uncompromising-metaprogramming<div class='blog-entry-story'><p>Meta-programming is using programs to generate or transform programs, like a compiler, it's <a href="reflecting-on-meta-programming">difficult to explain how it can be both easy and useful</a>. One simple example is efficient serialization: automatically generating converters for between in-memory and network or disk data-representations as efficiently as writing the conversion programs by hand. There is no compromise between efficiency and syntax.</p><p>As another example, in <a href="https://github.com/vii/teepeedee2">tpd2</a>, which is designed for high performance, meta-programming is used to allow a convenient syntax for outputting HTML templated strings with performance as good as hand generated code, compile time safety in terms of spell-checking of attributes and that TD (table cell) elements appear only inside TR (table row) elements, etc.</p><p><em>Syntax</em> becomes independent of implementation: meta-programming explicitly allows convenient syntax, without repetitive drudgery while achieving optimal behaviour: having efficient code is possible without compromising syntactical elegance and forcing the human programmer to repeatedly apply optimization tricks to complicate the program, making it harder to understand and modify.</p><p>The basic syntax for the HTML generation in TPD2 is in appearance like a function call: (&lt;h1 "Hello") returns "&lt;h1&gt;Hello&lt;/h1&gt;", and nested tags with attributes are handled: so that (&lt;p "This is a " (&lt;a :href "link.html" "link")) goes to "&lt;p&gt;This is a &lt;a href="link.html"&gt;link&lt;/a&gt;&lt;/p&gt;". Anywhere a literal string appears a function can be called instead, or a variable substituted, so that dynamic generation of content is easy. This syntax can be naively implemented by defining functions &lt;p, &lt;a, &lt;h1 etc.</p><p><em>Efficiency</em> can be achieved with this simple syntax: an example might be <pre> (defun greet (name) (&lt;div (&lt;h1 "Hello " name) (&lt;p "Pleased to meet you, " name ", thanks for reading."))) </pre> </p><p>Performing string concatenations at runtime is O(n<sup>2</sup>), but not running string concatenations means that the scatter gather IO must be used with small fragments which is inefficient in the kernel as each fragment needs to be access checked, and having many fragments puts pressure on the GC. In fact in tpd2, string concatenation was wasting the majority of time in some benchmarks.</p><p>With a naive implementation, the &lt;h1 would boil down to (strcat "&lt;h1&gt;" "Hello " name "&lt;/h1&gt;"), or even worse and there would be no way to merge the "&lt;div&gt;" with the "&lt;h1&gt;" tags. With Lisp's convenient meta-programming, where the &lt;div operator is no longer a function, however, it can inspect its arguments and perform an optimization across boundaries: in this case transforming the greet function to the optimal (given an optimal strcat operator which is complicated in itself):</p><p><pre> (defun greet (name) (strcat "&lt;div&gt;&lt;h1&gt;Hello " name "&lt;/h1&gt;&lt;p&gt;Pleased to meet you, " name "&lt;/p&gt;&lt;/div&gt;")) </pre></p><p><em>Guaranteed safety</em> achieved through static analysis of the properties of the program, even domain specific ones is better than turning up bugs in time consuming testing; properties are proved rather than gathering statistical evidence about them. The domain specific transformations with meta-programming techniques naturally tend to allow compile time checks.</p><p>For example, with the tpd2 HTML generation, attributes are spell-checked so that, for example, an href attribute is not allowed in an &lt;p&gt; element. This would be impossible to check with HTML validation tools unless every codepath that could generate HTML were exercised. Additionally, the HTML DTD specifies that only some tags can appear in others; for example, a &lt;div&gt; cannot appear in an &lt;h1&gt;. Where possible, violations of these constraints are also reported at compile time; however, as tag contents can be generated by arbitrary programs, it is not possible to find all violations. In fact, this brings up a major weakness of Lisp meta-programming: a sophisticated compiler may have a strong understanding of the potential control flow with powerful constant propagation and type inference, but that is not exposed to the macro-expansion facilities.</p><p>I hope I have been able to present a practical example of the utility of convenient meta-programming; of course many more sophisticated things are possible (like compiling regular expressions to machine code or allowing convenient definition of object relational mappings). It allows one to keep a pretty syntax while achieving optimal machine code generation and simultaneously increasing safety. Additionally, it a natural interface barrier between the application programmer and the systems programmer that allows either to comfortably modify their design and implementation independently. No compromise is necessary and none is made. </p></div>Reflecting on meta-programming2011-02-20T15:44:05Z/reflecting-on-meta-programming<div class='blog-entry-story'><p>I've been having revealing conversations with people in the Scala and F# communities where I discover that my definition of meta-programming is not widely shared. Personally, I think that the two most misunderstood computer languages are C++ and Lisp: and one reason for that is that they both offer real meta-programming &mdash; in the sense not of Ruby's dynamic reflection and redefinition, but in the sense that one can write programs to write other programs.</p><p>Reflection, in terms of looking at what functions and types have already been defined, is in my view normal programming &mdash; however, fiddling around dynamically at run-time depending on the compile-time definitions of the program, while probably ugly and inefficient, is able to work around problems that would naturally be solved with meta-programming facilities, if they were available. This does not excuse their absence, just makes it slightly less unbearable and introduces unnecessary runtime costs.</p><p>Can one come up with a well-defined real-world example task that can be solved with meta-programming but not reflection? Of course not &mdash; meta-programming does not make a system more than Turing complete. In the same way that anything achievable with subroutines can be achieved with gotos. The argument that must be advanced for meta-programming is more nuanced: for someone who has never imagined a function call, then a tangled spaghetti of goto statements is all they see before them.</p><p>Writing programs to write programs is a powerful tool which naturally side-steps whole classes of systemic deficiencies; being able to do it fluidly in Lisp rather than in a contrived and round-about fashion with C++ template trickery renders it appropriate for many more tasks. I hope to present a few strong examples from the tpd2 project in greater detail - more are welcome!</p></div>