<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-107818332672551112</id><updated>2012-01-05T09:05:14.960+01:00</updated><category term='merging'/><category term='books'/><category term='Computer supported cooperative work'/><category term='Dependency Injection'/><category term='thoth'/><category term='debugger'/><category term='software change'/><category term='benchmark'/><category term='histoory'/><category term='software cartography'/><category term='algorithms'/><category term='book recommendation'/><category term='sprint'/><category term='pharo'/><category term='GOODS'/><category term='psychology'/><category term='git'/><category term='comparison'/><category term='sandstoneGOODS'/><category term='casting'/><category term='productivity'/><category term='seaside'/><category term='J'/><category term='tacit programming'/><category term='neurology'/><category term='tree objects'/><category term='computer science'/><category term='mathematica'/><category term='jls'/><category term='research'/><category term='sandstoneDB'/><category term='java'/><category term='codemap'/><category term='hackerdom'/><category term='smalltalk'/><category term='gofer'/><category term='intent'/><category term='point-free programming'/><category term='RDBMS'/><category term='language'/><category term='phexample'/><category term='format'/><category term='tech books'/><category term='pluquet'/><category term='ODBMS'/><category term='RESTful'/><category term='dojo'/><category term='human computer interaction'/><category term='euler'/><category term='languages'/><category term='Seuss'/><category term='unit testing'/><category term='reviewing'/><category term='Erwann Wernli'/><category term='programming practice'/><category term='raymond'/><category term='compiler'/><category term='ide'/><title type='text'>Niko Schwarz's science and programming</title><subtitle type='html'>Here I'll post things related to my research that don't fit in 140 characters (&lt;a href="http://twitter.com/nes1983"&gt;twitter.com/nes1983&lt;/a&gt;), as well as programming-related things that I do and come across.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>44</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-9128655542717183194</id><published>2011-12-13T20:17:00.002+01:00</published><updated>2011-12-13T20:23:20.437+01:00</updated><title type='text'>TextMate 2.0 alpha is out</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;a href="http://blog.macromates.com/2011/textmate-2-0-alpha/"&gt;Things that did NOT make it into the alpha:&lt;/a&gt;&lt;blockquote cite="http://blog.macromates.com/2011/textmate-2-0-alpha/"&gt;&lt;ul&gt;&lt;li&gt;Split views: Yes, I actually had this on the alpha milestone, I’m not overly excited about this feature myself, but I know it’s a very common request, so eventually it should find its way into the application.&lt;/li&gt;&lt;li&gt;Full screen mode: This is mainly because we are hesitant to go Lion-only so we are holding back with “lionizing” TextMate till we feel confident we can fully drop backwards compatibility.&lt;/li&gt;&lt;li&gt;Performance: Overall performance is fine, but there are still edge-cases that we haven’t looked into, for example the long lines issue which also exists in 1.x or opening files that exhaust TextMate’s memory space.&lt;/li&gt;&lt;li&gt;Bundle editor: While a proof-of-concept bundle editor is included, it is provisional, has some flaws, and not how we envision the final bundle editor to be.&lt;/li&gt;&lt;li&gt;Settings: Not everything in the Preferences window has an effect at the moment and several menu settings are not sticky, some even revert when switching tabs. Those can be set via &lt;code&gt;.tm_properties&lt;/code&gt; — more about this in an upcoming post.&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; I, for one, can't actually start it. It crashes upon load.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-9128655542717183194?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/9128655542717183194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/12/textmate-20-alpha-is-out.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/9128655542717183194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/9128655542717183194'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/12/textmate-20-alpha-is-out.html' title='TextMate 2.0 alpha is out'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-5934875859371586200</id><published>2011-12-11T17:58:00.001+01:00</published><updated>2011-12-11T21:43:21.244+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Lack of excitement for Pharo 1.4 seems symptomatic</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Here's Lukas Renggli, the working horse that pulls Smalltalk behind him, &lt;a href="http://www.mail-archive.com/pharo-project@lists.gforge.inria.fr/msg56045.html"&gt;announcing his plans for Pharo 1.4, or his lack thereof:&lt;/a&gt;&lt;br /&gt;&lt;blockquote cite="http://www.mail-archive.com/pharo-project@lists.gforge.inria.fr/msg56045.html"&gt;Just to repeat myself: With Pharo 1.4 having uncountable changes in core parts of the system and with the system including more and more forked and increasingly incompatible versions of packages (AST, RB, FS, Shout, Regex, …) I am unwilling to go through the same pain as with Pharo 1.3 again. In the current state, I don't see any of the code I am involved with (including Seaside, Magritte, Pier, OB, PetitParser, …) to move forward. I suspect that moving to another development platform soon causes less pain than to move to adopt the next Pharo :-(&lt;/blockquote&gt;In a word, nobody wants to upgrade to new versions of Pharo. But that was the whole point of Pharo: progress, moving ahead. There isn't a Smalltalk with traction right now. You can &lt;a href="http://stackoverflow.com/questions/8426981/squeak-or-pharo-for-the-beginning-smalltalker"&gt;watch the Smalltalk community fail to answer which part of the Smalltalk universe is worth looking at at Stackoverflow&lt;/a&gt;.&lt;br /&gt;Compare this with &lt;a href="http://mattgemmell.com/2011/12/05/latest-version/"&gt;the spirit in the Objective-C/Cocoa world:&lt;/a&gt;&lt;br /&gt;&lt;blockquote cite="http://mattgemmell.com/2011/12/05/latest-version/"&gt;It’s OK to support only the newest version of iOS.&lt;/blockquote&gt;Now, you might say that this isn't a fair comparison, because writing iOS apps is the key to a new and exciting and fast-growing market, the mobile platform. But I think that's the same argument that &lt;a href="http://www.marco.org/2011/12/07/eric-schmidt-android-leads-the-iphone"&gt;Eric Schmidt is getting wrong about Android:&lt;/a&gt; “Whether you like Android or not, you will support that platform”. As Gruber points out, he's having cause and effect backwards: developers love programming for iOS, and only therefore is iOS as exciting as it is.&lt;br /&gt;Smalltalk simply isn't as inviting to developers as it used to be.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-5934875859371586200?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/5934875859371586200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/12/lack-of-excitement-for-pharo-14-seems.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/5934875859371586200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/5934875859371586200'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/12/lack-of-excitement-for-pharo-14-seems.html' title='Lack of excitement for Pharo 1.4 seems symptomatic'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-2362287588019042612</id><published>2011-12-05T10:15:00.001+01:00</published><updated>2011-12-05T10:18:35.443+01:00</updated><title type='text'>I'm thru with the GPL</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Free software is great. Seeing your own project being used and maintained by somebody else is great, too. But being expunged from the version history is a really bitter thing to experience. I'm moving my projects to &lt;a href="http://en.wikipedia.org/wiki/Apache_License"&gt;Apache License&lt;/a&gt;, which requires attribution.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-2362287588019042612?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/2362287588019042612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/12/im-thru-with-gpl.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2362287588019042612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2362287588019042612'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/12/im-thru-with-gpl.html' title='I&apos;m thru with the GPL'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-9035425425767360301</id><published>2011-08-30T17:45:00.005+02:00</published><updated>2011-09-01T10:35:23.761+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='point-free programming'/><category scheme='http://www.blogger.com/atom/ns#' term='tacit programming'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Point-free programming in Smalltalk</title><content type='html'>Smalltalk does not, ordinarily, support &lt;a href="http://en.wikipedia.org/wiki/Tacit_programming"&gt;point-free programming.&lt;/a&gt;  Point-free programming is programming without "points", or variables. In a loop, rather than assigning every item to loop over to a variable, you only write which function should be called on them. &lt;br /&gt;&lt;br /&gt;Pharo Smalltalk has limited support for that. There, you can write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#(1 2 3 4) select: #even     -&gt; #(2 4)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above is implemented using an easy equivalence. Every block that sends only one message is equivalent to the selector of that message. Thus, the above is equivalent to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#(1 2 3 4) select: [:e | e even]    -&gt; #(2 4)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Which is just standard Smalltalk. The equivalence can be made work by implementing &lt;code&gt;#value:&lt;/code&gt; etc. on Symbol.&lt;br /&gt;&lt;br /&gt;Well, of course this is rather limited, we still haven't got rid of blocks. We still need blocks for everything that does not only send one message. You can push a little farther by allowing composition of symbols:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;{'100' . '20' . '3'} sort: #&lt;= * #first.     -&gt;  #('100' '20' '3') &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The idea is to read the asterisk as "after", like the &lt;a href="http://en.wikipedia.org/wiki/Function_composition"&gt;function compositor in Mathematics&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So you read this as "sort the area by less than, after first was applied". Thus, the strings are sorted by their first letter. Awesome, eh?&lt;br /&gt;&lt;br /&gt;This is not standard Pharo, but it can be implemented in a couple of minutes. &lt;a href="http://snipt.net/nikoschwarz/point-free-programming-for-smalltalk-1"&gt;The code is on Snipt&lt;/a&gt;, but it's more easily written than read.&lt;br /&gt;&lt;br /&gt;This can still not replace blocks. For example, the following block still cannot be expressed point-free: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[:a | Transcript show: a]&lt;/pre&gt;.&lt;br /&gt;&lt;br /&gt;But nothing is easier than inventing a syntax for that (can you implement it in Pharo, so it'll work?):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; Transcript delayedSend: #show: &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, for blocks where the left-hand-side is the argument:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; [:stream | stream nextPutAll: 'hello']&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I propose that could be written as follows  (can you implement it in Pharo, so it'll work?):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Delayed nextPutAll: 'hello'&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Open questions&lt;/h4&gt;&lt;br /&gt;Would it be more enjoyable to write entirely point-free in Smalltalk? What do you think?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-9035425425767360301?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/9035425425767360301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/08/point-free-programming-in-smalltalk.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/9035425425767360301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/9035425425767360301'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/08/point-free-programming-in-smalltalk.html' title='Point-free programming in Smalltalk'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-3870268211591578217</id><published>2011-01-24T13:56:00.007+01:00</published><updated>2011-01-24T16:12:10.956+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comparison'/><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='languages'/><title type='text'>How to obtain the current time in a number of standard APIs:</title><content type='html'>&lt;p&gt;I googled for the programming language plus "current time", and obtained the following methods. &lt;a href="http://www.r-chart.com/2010/08/github-stats-on-programming-languages.html"&gt;The programming languages  are the most popular languages on github.&lt;/a&gt; &lt;p&gt;&lt;a href="http://www.ruby-doc.org/core/classes/Time.html"&gt;Ruby:&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;now = Time.new&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.rgagnon.com/javadetails/java-0106.html"&gt;Java:&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Date now = Calendar.getInstance().getTime();&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.saltycrane.com/blog/2008/06/how-to-get-current-date-and-time-in/"&gt;Python:&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;now = datetime.datetime.now()&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://bytes.com/topic/c-sharp/answers/568228-current-time-c"&gt;C#:&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;DateTime now = DateTime.Now;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.plus2net.com/php_tutorial/php_date_time.php"&gt;PHP:&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;now = time()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/1684904/getting-current-time-in-string-in-custom-format-in-objective-c"&gt;Objective C:&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;now = [NSDate date]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.webdevelopersnotes.com/tips/html/getting_current_time_using_javascript.php3"&gt;JavaScript:&lt;/a&gt; &lt;/p&gt;&lt;pre&gt;&lt;code&gt;var now = new Date();&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://bytes.com/topic/c/answers/550366-getting-current-time-milliseconds"&gt;C++ (well, this is really C)&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;time_t now = time(NULL);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These are the standard methods in the standard APIs. Nonetheless, they introduce &amp;#8220;Hidden global state&amp;#8221; into your application (&lt;a href="http://googletesting.blogspot.com/2008/11/clean-code-talks-global-state-and.html"&gt;see Slide 16 on &amp;#8220;Clean Code Talks - Global State and Singletons&amp;#8221; in the Google testing blog&lt;/a&gt;). Hidden global state makes your code hard to test, yet it is ubiquitous. Somebody should do something about that! (Yes, I&amp;#8217;m working on it :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-3870268211591578217?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/3870268211591578217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/01/how-to-obtain-current-time-in-number-of.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3870268211591578217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3870268211591578217'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2011/01/how-to-obtain-current-time-in-number-of.html' title='How to obtain the current time in a number of standard APIs:'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8759753181479861186</id><published>2010-10-27T16:34:00.003+02:00</published><updated>2010-10-27T16:39:03.425+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ide'/><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Full text search in Pharo?</title><content type='html'>Pharo does have something like full text search across all methods, and it works like this: Rightclick the text you'd like to search for, and choose "extended search" from the options. Then, choose "method source with it." A progress bar will appear, and you should get your answer within a minute. That has to do with the source not being loaded into Pharo at all times, it is read on demand out of the sources file. &lt;br /&gt;&lt;br /&gt;However, the compiled sources are in memory from the start. While you can't meaningfully search compiled sources, you can search the string literals within. Again, rightclick the text you'd like to search for, and choose "extended search" from the options. But now, choose "method strings with it." That will bring up a list of all methods that contain the selected text as a string literal—instantly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8759753181479861186?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8759753181479861186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/full-text-search-in-pharo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8759753181479861186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8759753181479861186'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/full-text-search-in-pharo.html' title='Full text search in Pharo?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8902583132063582209</id><published>2010-10-12T15:44:00.004+02:00</published><updated>2010-10-12T15:49:54.544+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>One of my most-hated methods in Pharo</title><content type='html'>&lt;pre&gt;&lt;br /&gt;    TestCase&gt;fail&lt;br /&gt;         ^self assert: false&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What's wrong? Well, I often write &lt;code&gt;self fail&lt;/code&gt; at the end of a unit test to remind myself that the test isn't yet done. Now, if I run the test, I care whether an assertion failed or whether the test solely failed. Of course I have no right to expect should detailed feedback from a test runner. But at least I shouldn't be misinformed. But that's exactly what happens. The TestRunner reports that an assertion failed if you call fail, even if none did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8902583132063582209?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8902583132063582209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/one-of-my-most-hated-methods-in-pharo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8902583132063582209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8902583132063582209'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/one-of-my-most-hated-methods-in-pharo.html' title='One of my most-hated methods in Pharo'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-5025337576130413053</id><published>2010-10-12T11:31:00.003+02:00</published><updated>2010-10-12T11:39:23.694+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugger'/><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><title type='text'>Why's the Smalltalk debugger not focused on more in Smalltalk IDEs?</title><content type='html'>I can't help but wonder why Smalltalk's lovable trait of letting you develop in the debugger isn't leveraged far more by the IDEs. Suppose you just noticed that a method call doesn't have enough arguments. That is, you wrote this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;self doSomething.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But you should have written:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;self doSomethingWith: anArgument&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well now, that's a fantastic situation for refactoring, isn't it? You could automatically rename the method in the receiver, and you'd know quite precisely who that receiver is. Little of that is leveraged. But of course, if Smalltalk is to play any serious role in the future, we should play by our strengths. &lt;br /&gt;&lt;br /&gt;Well, here's a strength: the most powerful debugger in any modern IDE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-5025337576130413053?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/5025337576130413053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/whys-smalltalk-debugger-not-focused-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/5025337576130413053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/5025337576130413053'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/whys-smalltalk-debugger-not-focused-on.html' title='Why&apos;s the Smalltalk debugger not focused on more in Smalltalk IDEs?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-7605943711383525975</id><published>2010-10-08T16:52:00.005+02:00</published><updated>2010-10-08T17:06:15.309+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><title type='text'>A more robust doesNotUnderstand:?</title><content type='html'>Smalltalk makes it really convenient to write code in the debugger. So, how I often work is as follows:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write a rough skeleton that calls "self fail" at some point.&lt;br /&gt;&lt;li&gt;Write a unit test that calls the skeleton with real data.&lt;br /&gt;&lt;li&gt;Finish the skeleton in the debugger, where I have test data right at hand to see if things work as intended.&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Well, that's alright as far as it goes, but you can't work like that with &lt;code&gt;doesNotUnderstand:&lt;/code&gt; methods.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;doesNotUnderstand: aMessage&lt;br /&gt; self fail.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you now call a non-existing method on an object of a thus modified class, you've built an endless recursion that is so close to the VM that you can't get into a debugger anymore. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.iam.unibe.ch/~akuhn/blog/2010/pharo-superpower-respond-to-any-message/"&gt;Smalltalk's &lt;code&gt;doesNotUnderstand:&lt;/code&gt; method is a dangerous superpower.&lt;/a&gt; And perhaps that's why just about nobody overwrites it in a standard Pharo image. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Open problems&lt;/h3&gt;&lt;br /&gt;Do you know a more robust implementation? &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Non-existing calls inside the handler for such should be caught, I think. &lt;br /&gt;&lt;li&gt;It should work nicely with code completion. (Code completion seems to be an integral part of just about every current approach to help programmer's productivity, so it better work nice.)&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-7605943711383525975?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/7605943711383525975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/more-robust-doesnotunderstand.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7605943711383525975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7605943711383525975'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/more-robust-doesnotunderstand.html' title='A more robust doesNotUnderstand:?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-2762919991570270747</id><published>2010-10-01T16:04:00.009+02:00</published><updated>2010-10-01T17:30:46.154+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>expandMacrosWith:</title><content type='html'>In Pharo, there's a very useful method &lt;code&gt;String&gt;expandMacrosWith:&lt;/code&gt;, virtually without documentation. It's much like printf in C. I guess it's easily understood from a few examples, so here go:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;"&amp;lt;1s&gt; is replaced by the first argument, a string.&lt;br /&gt; &amp;lt;n&gt; is a newline, &amp;lt;t&gt; is a tab. &lt;br /&gt; % escapes brackets."&lt;br /&gt;'&amp;lt;1s&gt;&amp;lt;n&gt;&amp;lt;t&gt;%&amp;lt;inject&gt;&amp;lt;n&gt;&amp;lt;t&gt;^&amp;lt;1s&gt;' expandMacrosWith: 'player'&lt;br /&gt;➔&lt;br /&gt;'player&lt;br /&gt; &amp;lt;inject&gt;&lt;br /&gt; ^player'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"p calls printString":&lt;br /&gt;'&amp;lt;1p&gt;' expandMacrosWith: #(1 2 3)&lt;br /&gt;➔&lt;br /&gt;'#(1 2 3)'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"? prints one string or another, depending on a Boolean"&lt;br /&gt;'Dear &amp;lt;1?Mr:Mrs&gt; &amp;lt;2s&gt;, your contract has expired.' &lt;br /&gt;  expandMacrosWith: false   with: 'Smith'&lt;br /&gt;➔&lt;br /&gt;'Dear Mrs Smith, your contract has expired.'&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-2762919991570270747?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/2762919991570270747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/expandmacroswith.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2762919991570270747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2762919991570270747'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/10/expandmacroswith.html' title='expandMacrosWith:'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-3258817217372047146</id><published>2010-09-29T09:41:00.005+02:00</published><updated>2010-09-29T09:46:03.527+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='sprint'/><category scheme='http://www.blogger.com/atom/ns#' term='dojo'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Pharo dojo in Bern, October 23–24</title><content type='html'>There will be a Pharo dojo in Bern. The announcement reads:&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://www.moosetechnology.org/events/2010-10-22-dojo"&gt;We will organize a joint Pharo sprint / Moose dojo during October 23-24, in Bern (at the Software Composition Group, University of Bern). There will be free food and drinks! &lt;br&gt;Some action points are mentioned on the dedicated page (of course, other ideas and interests are welcome as well).&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For planning purposes, please let me, &lt;a href="mailto:tudor.girba@gmail.com"&gt;Tudor Girba&lt;/a&gt;, know if you will attend.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-3258817217372047146?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/3258817217372047146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/pharo-dojo-in-bern-october-2324.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3258817217372047146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3258817217372047146'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/pharo-dojo-in-bern-october-2324.html' title='Pharo dojo in Bern, October 23–24'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-339432866982229495</id><published>2010-09-27T16:58:00.008+02:00</published><updated>2010-09-27T18:08:15.834+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Dependency injection aids copy and paste coding</title><content type='html'>In the presence of good documentation or sample code, I love to copy and paste directly out of the documentation or even unit tests, straight into my code.&lt;br /&gt;&lt;br /&gt;For example, I was wondering how to add an instance variable to a class in Pharo Smalltalk. Well, I just search my code base for occurrences of addInstanceVariable, and I find this test: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;testAddInstanceVariable&lt;br /&gt; | refactoring |&lt;br /&gt;    refactoring := AddInstanceVariableRefactoring &lt;br /&gt;        variable: 'asdf'&lt;br /&gt;        class: RBTransformationRuleTest.&lt;br /&gt;     self executeRefactoring: refactoring.&lt;br /&gt;     self assert: ((refactoring model classNamed: &lt;br /&gt;         #RBTransformationRuleTest) &lt;br /&gt;              directlyDefinesInstanceVariable: 'asdf')&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well, that's great, the first few lines are what I need. Some more browsing shows that line 6 is deeply irrelevant for me: the test uses a highly artificial way of executing the test, different from the canonical one.&lt;br /&gt;&lt;br /&gt;Is any of that surprising? Not really. There's some papers establishing that this is how a lot of people work: forking work off sample code, but only if it's complex enough to match the use case (cite?). &lt;br /&gt;&lt;br /&gt;I think it has an interesting implication for writing unit tests: They should be as close as possible to the intended end user usage. In the example above, my hunch is that the unit test wasn't written in the way that the end user would use the library, because the author feared side effects.&lt;br /&gt;&lt;br /&gt;I think here we see one of the great strengths of dependency injection: by moving the part of the unit test that avoids side effects to another level of abstraction, the unit test itself can look exactly as if it had side effects, and thus can serve better as a basis for new work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-339432866982229495?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/339432866982229495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/dependency-injection-aids-copy-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/339432866982229495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/339432866982229495'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/dependency-injection-aids-copy-and.html' title='Dependency injection aids copy and paste coding'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1082411127439615172</id><published>2010-09-27T12:11:00.003+02:00</published><updated>2010-09-27T12:20:53.478+02:00</updated><title type='text'>Circular problem solving in computer science</title><content type='html'>Here's the rules: Find a genuine problem in a framework called X. Then write your solution in framework Y that depends on X. Then, rewrite X using Y such that the problem goes away.&lt;br /&gt;&lt;br /&gt;Because rewriting of X depends via Y on some older version of X, I give bonus points for using a framework that allows calling older versions of X from within X.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1082411127439615172?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1082411127439615172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/circular-problem-solving-in-computer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1082411127439615172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1082411127439615172'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/circular-problem-solving-in-computer.html' title='Circular problem solving in computer science'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1415864569595823038</id><published>2010-09-22T17:00:00.003+02:00</published><updated>2010-09-22T17:07:48.336+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='Seuss'/><title type='text'>Three degrees of inversion of control.</title><content type='html'>&lt;a href="http://martinfowler.com/articles/injection.html"&gt;Inversion of control is a paradigm by Martin Fowler that advocates for separating things that don't belong together during object creation.&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;What exactly should be split from what? Different frameworks answer the question slightly differently. They do at least 1 of these three:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Eliminate direct constructor calls.&lt;/b&gt; All dependency injection frameworks do that.&lt;br /&gt;&lt;li&gt;&lt;b&gt;Strictly separate business logic from object creation.&lt;/b&gt; Google Guice, among others, allows that, but doesn't enforce that.&lt;br /&gt;&lt;li&gt;&lt;b&gt;Eliminate all static references.&lt;/b&gt; Newspeak makes all lookups dynamic, thereby eliminating global state.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;All three are compatible with one another. Can they be combined in practice? I'm working on it …&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1415864569595823038?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1415864569595823038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/three-degrees-of-inversion-of-control.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1415864569595823038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1415864569595823038'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/09/three-degrees-of-inversion-of-control.html' title='Three degrees of inversion of control.'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-4670056951668125157</id><published>2010-07-22T10:34:00.003+02:00</published><updated>2010-07-22T10:38:50.317+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='programming practice'/><title type='text'>In unit tests, why are failures yellow but errors red?</title><content type='html'>It's confusing, isn't it? Errors are displayed red, which looks scary, while failures are displayed yellow, which looks inviting. But, debugging a test failure, you don't get a trace of a clue what caused the failure. While debugging an error, you have the stack trace right there and know exactly where to look.&lt;br /&gt;&lt;br /&gt;When SUnit lists yellow and red failed unit tests, I invariably start with the red ones. They're usually easier to fix.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-4670056951668125157?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/4670056951668125157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/07/in-unit-tests-why-are-failures-yellow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4670056951668125157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4670056951668125157'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/07/in-unit-tests-why-are-failures-yellow.html' title='In unit tests, why are failures yellow but errors red?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-7064351388477458868</id><published>2010-06-22T23:12:00.002+02:00</published><updated>2010-06-22T23:25:50.396+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='psychology'/><category scheme='http://www.blogger.com/atom/ns#' term='book recommendation'/><category scheme='http://www.blogger.com/atom/ns#' term='neurology'/><title type='text'>Book tip: Computing the mind</title><content type='html'>I'd like to discuss why, without having finished the book yet, I hand over heels love the book:&lt;a href="http://www.amazon.de/Computing-Mind-How-Really-Works/dp/0195320670"&gt; Computing the mind, subtitled "How the mind really works", by Shimon Edelmann.&lt;/a&gt; I have to admit that I didn't have the highest hopes when I opened the book. I went so far as to skip the first couple of pages, to get to the fun parts a bit quicker. As I write these blog post, page 1 lies open on my desk, and it's the most beautiful start a non-fiction book could hope to offer:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;If you are reading this in the first couple of decades of the third millennium of the common era, chances are that (1) the human brain is the most complex toy you'll ever come near, let alone get to play with, and (2) you're trapped inside one for the foreseeable future.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And then, on page 78, we get this teaser for what's to come later:&lt;br /&gt;&lt;blockquote&gt;Claim: the brain is a programmable digital computer. If this were true, the brain would be like hardware to the mind's software. This claim does not stand up to scrutiny, mainly because in the brain it is not possible to separate the "program" from the architecture that executes it. It is very important to remember, however, that a digital computer can simulate the operation of a brain (because a digital computer can simulate any physical system down to an arbitrary precision), and hence the mind. The ramifications of the realization that the mind is what the brain does are far-reaching and profound; I shall describe and discuss them in later chapters.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;He had me long before page 78, though. He quotes Karl Popper throughout the book. This book is amazing in clarity, it's funny, and it's mind-opening.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-7064351388477458868?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/7064351388477458868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/06/book-tip-computing-mind.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7064351388477458868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7064351388477458868'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/06/book-tip-computing-mind.html' title='Book tip: Computing the mind'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-375174894845690187</id><published>2010-05-23T14:08:00.003+02:00</published><updated>2010-05-23T14:16:05.854+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='raymond'/><category scheme='http://www.blogger.com/atom/ns#' term='hackerdom'/><title type='text'>Friendly advice from Eric S Raymond</title><content type='html'>My favorite quote from "The cathedral and the bazaar," p. 207:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;If you're attracted to hacking because you don't have a life, that's okay too---at least you won't have trouble concentrating. Maybe you'll get a life later on. &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I love the book, but I think the first two essays would have been enough to read, that's "The cathedral and the bazaar" and "homesteading the noosphere." The others are far from neutral and not full of insight like the first two. The first two are an insightful analysis of the psychology and culture of hackerdom.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-375174894845690187?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/375174894845690187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/05/friendly-advice-from-eric-s-raymond.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/375174894845690187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/375174894845690187'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/05/friendly-advice-from-eric-s-raymond.html' title='&lt;a href=&quot;http://catb.org/esr/writings/homesteading/&quot;&gt;Friendly advice from Eric S Raymond&lt;/a&gt;'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-6302715490870844362</id><published>2010-05-04T14:37:00.001+02:00</published><updated>2010-05-04T14:38:21.192+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reviewing'/><title type='text'>The burden of the reviewer</title><content type='html'>The paper I'm reviewing treats an interesting topic without much love. I'm getting sick of reading other people's papers. If this goes on, I'll just write my own papers.&lt;br /&gt;&lt;br /&gt;By the way, I'm still taking really long for reviewing. An hour of work and I'm on page … 2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-6302715490870844362?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/6302715490870844362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/05/burden-of-reviewer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/6302715490870844362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/6302715490870844362'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/05/burden-of-reviewer.html' title='The burden of the reviewer'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-66320790073046719</id><published>2010-03-25T22:19:00.006+01:00</published><updated>2010-03-25T22:33:47.171+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='format'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='tree objects'/><title type='text'>Git tree objects, how are they stored?</title><content type='html'>A git tree is git&amp;#8217;s internal representation for directories. Trees have entries which are either trees themselves, or blobs. &lt;br /&gt;&lt;br /&gt;The general format is: First 4 bytes declaring the object type. In our case, those four bytes are &amp;#8220;tree&amp;#8221;, ASCII-encoded. Then comes a space, and then the entries, separated by nothing. &lt;br /&gt;The exact format is the following. All capital letters are &amp;#8220;non-terminals&amp;#8221; that I&amp;#8217;ll explain shortly. &lt;br /&gt;&lt;pre&gt;&lt;code&gt;    tree (ZNA FNS)*&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;where&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;N is the NUL character&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Z is the size of the object in bytes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A is the unix access code, ASCII encoded, for example&gt; 100644 for a vanilla file.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;F is the filename, (I&amp;#8217;m not sure about the encoding. It&amp;#8217;s definitely ASCII-compatible), NUL-terminated.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;S is the 20 byte SHA hash of the entry pointed to, 20 bytes long.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Here&amp;#8217;s an example. Say we have a directory with two files, called test and test2. The SHA of the directory is &lt;code&gt;f0e12ff4a9a6ba281d57c7467df585b1249f0fa5&lt;/code&gt;. You can see the SHA-hashes of the entries in the output of &lt;br /&gt;&lt;pre&gt;&lt;code&gt;    $ git cat-file -p f0e12ff4a9a6ba281d57c7467df585b1249f0fa5&lt;br /&gt;    100644 blob 9033296159b99df844df0d5740fc8ea1d2572a84    test&lt;br /&gt;    100644 blob a7f8d9e5dcf3a68fdd2bfb727cde12029875260b    test2&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(To reproduce this, the file test should contain the ASCII-encoded characters &amp;#8220;hallo&amp;#8221; (not \n-terminated), the file test2 should contain the ASCII-encoded characters &amp;#8220;bla\n&amp;#8221; (yes, \n-terminated)).&lt;br /&gt;&lt;br /&gt;That is converted into the following object (uncompressed): &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_h7uHoQdb3pA/S6vT6X6N7eI/AAAAAAAABHk/3r1CTka7Wm4/s1600/sample+git+tree+object.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 87px;" src="http://4.bp.blogspot.com/_h7uHoQdb3pA/S6vT6X6N7eI/AAAAAAAABHk/3r1CTka7Wm4/s400/sample+git+tree+object.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5452684773666188770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finally, the file is deflated and stored on disk. For deflation, zlib is used. For my experiments I used the ruby zlip package. The following tiny &lt;a href="http://snipt.net/nikoschwarz/peek-into-git-http://snipt.net/nikoschwarz/peek-into-git-objects"&gt;script&lt;/a&gt; reads the tree from disk and inflates it, so you can look at it:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    require 'zlib'&lt;br /&gt;    require 'fileutils'&lt;br /&gt;    File.open("objects/f0/e12ff4a9a6ba281d57c7467df585b1249f0fa5") { |f|&lt;br /&gt;        puts Zlib::Inflate.inflate(f.read)&lt;br /&gt;    }&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-66320790073046719?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/66320790073046719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/git-tree-objects-how-are-they-stored.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/66320790073046719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/66320790073046719'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/git-tree-objects-how-are-they-stored.html' title='Git tree objects, how are they stored?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_h7uHoQdb3pA/S6vT6X6N7eI/AAAAAAAABHk/3r1CTka7Wm4/s72-c/sample+git+tree+object.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-2699273851352255852</id><published>2010-03-22T15:33:00.001+01:00</published><updated>2010-03-22T15:34:53.003+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='psychology'/><category scheme='http://www.blogger.com/atom/ns#' term='Computer supported cooperative work'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><category scheme='http://www.blogger.com/atom/ns#' term='human computer interaction'/><title type='text'>Why psychology and computer science should go together</title><content type='html'>&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/nfQ_8ofaFkM&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/nfQ_8ofaFkM&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-2699273851352255852?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/2699273851352255852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/why-psychology-and-computer-science.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2699273851352255852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2699273851352255852'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/why-psychology-and-computer-science.html' title='Why psychology and computer science should go together'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-4709782343677750723</id><published>2010-03-20T13:51:00.007+01:00</published><updated>2010-07-22T13:44:01.731+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jls'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='casting'/><title type='text'>You can't cast  Object[] to String[] in Java</title><content type='html'>Consider this snippet: &lt;br /&gt;&lt;code&gt;String[] str = (String[]) new Object[] { "Bla!"};&lt;/code&gt;.&lt;br /&gt;That gives a &lt;code&gt;ClassCastException&lt;/code&gt;. The short version of an explanation: an array instantiated by new &lt;code&gt;Object[]&lt;/code&gt; is of a different class than one by new &lt;code&gt;String[]&lt;/code&gt;. For the full glory of that fact, please see the&lt;a href="http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html"&gt; Java Language Specification&lt;/a&gt;. As a teaser, I'll quote this snippet and its output from it:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;class Test {&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  int[] ia = new int[3];&lt;br /&gt;  System.out.println(ia.getClass());&lt;br /&gt;  System.out.println(ia.getClass().getSuperclass());&lt;br /&gt; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;which prints:&lt;br /&gt;&lt;code&gt;class [I&lt;/code&gt;&lt;br /&gt;&lt;code&gt;class java.lang.Object&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-4709782343677750723?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/4709782343677750723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/you-cant-cast-object-to-string.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4709782343677750723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4709782343677750723'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/you-cant-cast-object-to-string.html' title='You can&apos;t cast  Object[] to String[] in Java'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-6553464316919676593</id><published>2010-03-18T23:21:00.001+01:00</published><updated>2010-03-18T23:21:23.543+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='tech books'/><title type='text'>Thick tech books</title><content type='html'>&lt;a href="http://prog21.dadgum.com/65.html"&gt;James Hague&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;"In order for a book to sell," said my publisher, "it's got to be thick. 600 pages thick."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Well, that about explains why tech books suck so badly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-6553464316919676593?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/6553464316919676593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/thick-tech-books.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/6553464316919676593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/6553464316919676593'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/thick-tech-books.html' title='Thick tech books'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-7405152908981067296</id><published>2010-03-18T21:34:00.007+01:00</published><updated>2010-03-19T11:21:28.588+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='histoory'/><category scheme='http://www.blogger.com/atom/ns#' term='pluquet'/><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='research'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>How to test post-conditions</title><content type='html'>A pretty good student, Joshua Muheim, just asked me what  the simplest way was to check postconditions. And my answer was the following:&lt;br /&gt;&lt;br /&gt;Joshua, this is a research question! To the best of my knowledge, currently and in practice, developers use steamroller tactics to check postconditions. The standard way to verify that the LHC works as intended, in a method &lt;code&gt;exterminate&lt;/code&gt; on a class &lt;code&gt;EarthPopulation&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;exterminate&lt;br /&gt;    | oldSize | &lt;br /&gt;    oldSize := self size.&lt;br /&gt;    LHC switchOn.&lt;br /&gt;    self size should &amp;lt; oldSize.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;That is, you copy whatever you intend to change and then compare new with old value. It isn&amp;#8217;t difficult to imagine that this can lead to trouble if whatever you want to change isn&amp;#8217;t cloneable. &lt;b&gt;And of course it isn't possible to switch off the overhead of these assertions.*&lt;/b&gt; And that&amp;#8217;s where &lt;a href="http://portal.acm.org/citation.cfm?id=1640118"&gt;Histoory&lt;/a&gt; (by Pluquet et al) comes to the rescue. Not only does it work independent of the cloneability, it also provides a much cleaner syntax:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;exterminate&lt;br /&gt;    [LHC swithOn]&lt;br /&gt;        postCond: [:old | old size should &amp;lt; self size]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Alas, it isn&amp;#8217;t in the latest flavor of any programming language, so I truly hope that Histoory will make it into &lt;a href="http://www.pharo-project.org/"&gt;Pharo&lt;/a&gt; :).&lt;br /&gt;&lt;br /&gt;&lt;small&gt;* I added this sentence after Joshua's correct observation of this problem.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-7405152908981067296?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/7405152908981067296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/how-to-test-post-conditions.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7405152908981067296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7405152908981067296'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/how-to-test-post-conditions.html' title='How to test post-conditions'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-2533162331894217142</id><published>2010-03-16T09:07:00.005+01:00</published><updated>2010-03-16T09:13:48.682+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='book recommendation'/><title type='text'>Book on algorithm design</title><content type='html'>Recently, Sedgewick's algorithms book slipped through my hands again. It's a great book. I'd just like to point to a newer algorithms book that is thinner, and funner to read, and if you just want to browse for an hour or two, this is surely worth your while. That's &lt;a href="http://www.amazon.com/Algorithm-Design-Jon-Kleinberg/dp/0321295358"&gt;Algorithm design&lt;/a&gt;, by Jon Kleinberg, and Éva Tardos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-2533162331894217142?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/2533162331894217142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/book-on-algorithm-design.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2533162331894217142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2533162331894217142'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/book-on-algorithm-design.html' title='Book on algorithm design'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-2861245550946522827</id><published>2010-03-15T14:02:00.003+01:00</published><updated>2010-03-15T14:07:13.275+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='merging'/><category scheme='http://www.blogger.com/atom/ns#' term='software change'/><category scheme='http://www.blogger.com/atom/ns#' term='intent'/><title type='text'>Software merging, commit messages</title><content type='html'>What is the intent of a change? How do you merge conflicting changes? The current state of the art is dire. There's a survey, A &lt;a href="http://ieeexplore.ieee.org/Xplore/login.jsp?url=http://ieeexplore.ieee.org/iel5/32/21607/01000449.pdf%3Farnumber%3D1000449&amp;authDecision=-203"&gt;state-of-the-art survey on software merging &lt;/a&gt;, but it's summary may be that there's no silver bullet to automated merging without understanding the intent of a commit.&lt;br /&gt;&lt;br /&gt;How do you understand the intent of a commit? The best technique I am aware of today is … having the author provide a clear description of his intent. There's a paper about that, quite worth your while: &lt;a href="http://portal.acm.org/citation.cfm?id=1151374.1151392"&gt;Semantic patches considered helpful&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I told you that the situation is dire, didn't I?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-2861245550946522827?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/2861245550946522827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/software-merging-commit-messages.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2861245550946522827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2861245550946522827'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/03/software-merging-commit-messages.html' title='Software merging, commit messages'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8062716707246524978</id><published>2010-02-28T21:36:00.004+01:00</published><updated>2010-02-28T22:01:14.947+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='codemap'/><category scheme='http://www.blogger.com/atom/ns#' term='software cartography'/><title type='text'>Distance measure between software artifacts</title><content type='html'>&lt;p&gt;There's currently some interest in software visualization, which tries to speed up your understanding of source code by leveraging your brain's great ability to discern patterns in images. Below is  shot of &lt;a href="http://http://scg.unibe.ch/research/softwarecartography"&gt;Codemap&lt;/a&gt;, visualizing &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_h7uHoQdb3pA/S4rUzdFmCbI/AAAAAAAABHQ/Q28xCCR2jyQ/s1600-h/awesome-software-visualization-of-codemap-software-cartography.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 388px; height: 400px;" src="http://4.bp.blogspot.com/_h7uHoQdb3pA/S4rUzdFmCbI/AAAAAAAABHQ/Q28xCCR2jyQ/s400/awesome-software-visualization-of-codemap-software-cartography.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5443397080077175218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To draw a map such as the above, you need an underlying metric that tells you how far apart the code artifacts should be. (You probably won't be able to draw a map where the distances are exactly what you want them to be, but you may get close.) Now, what is used as a metric between software artifacts (islands, in the above image)? Codemap uses the vocabulary of the artifact, that is: artifacts that use many same words will end up closer together in the overall drawing.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A botfly moves along a herd of cattle. It finds every of the beasts hospitable, but it can't live without a herd. Thus, Richard Dawkins calls the herd the botfly's "Archipelago" (in &lt;a href="http://richarddawkins.net/thegreatestshowonearth"&gt;The greatest show on earth&lt;/a&gt;, p. 253). This inspires me to a metric which is supposed to measure similarity of software artifacts. The idea is to assume that if two artifacts are hospitable to the same code snippet, then they should provide similar environments. Thus, you could measure how in the evolution of a software program, snippets wandered from one place to another, and assume that whenever a code snippet is moved from one artifact to another, these two artifacts increase in our metric's similarity.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;It seems difficult to bring forth evidence that software maps aid understanding in the first place, thus I wouldn't know how to show that a metric like the one outlined above is any better than a comparison of metrics. Yet, there's some momentum in the field, so I'll save up the idea for a point in time when more light will be shed on the benefits of software visualization.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8062716707246524978?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8062716707246524978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/02/distance-measure-between-software.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8062716707246524978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8062716707246524978'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/02/distance-measure-between-software.html' title='Distance measure between software artifacts'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_h7uHoQdb3pA/S4rUzdFmCbI/AAAAAAAABHQ/Q28xCCR2jyQ/s72-c/awesome-software-visualization-of-codemap-software-cartography.gif' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1228838974904659944</id><published>2010-01-09T19:34:00.005+01:00</published><updated>2010-03-19T11:26:06.113+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='Erwann Wernli'/><title type='text'>On Erwann Wernli's idea of having the VM take care of dependency injection</title><content type='html'>&lt;div&gt;&lt;p&gt;My dear friend Erwann asks in his blog whether dependency injection should not be the task of the virtual machine. He considers code like this:&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;List l = new ArrayList();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;He then notices (correctly, to my mind), that this statement contains more detail than the developer meant to express. "Whether the list is a new one or not, I don’t care, all I need is an empty one," Erwann writes. Fair enough.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;There's real problems connected with the observation. The Java specification rules that &lt;code&gt;new&lt;/code&gt; has to allocate a new object. Hence, the method&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;static void slack() {&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;code&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;new Object();&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;return;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;cannot be optimized into a nop. Now, I believe you've already thought of a code snippet that cannot be optimized due to this rule. And of course it gets worse if the language forces us to use &lt;code&gt;new&lt;/code&gt; all the time.  it is the only way to get an object, even though we would have been fine with an old one, should it fulfill our criteria.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;Here's the solution he proposes:&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;List l = obtain list ( size=0 );&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;To undo the awkwardness, he proposes hiding this monstrum in syntactic sugar, although it isn't clear to me what the sugar should look like in this instance.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;Besides avoiding the &lt;code&gt;new&lt;/code&gt; operator, his proposal leaves the concrete type of variable &lt;code&gt;l&lt;/code&gt; open. He now proposes that depending on the "context," the VM can do voodoo to determine exactly which class may be most appropriate at the point in time. As an example, he cites changing the default FileInputStream to a zipped version of itself, as disk space runs low.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;I find his thinking interesting, because it asks the good old question of who's responsible for what in programming. Having the machine figure stuff out for you is great if the figuring out is easy or secondary. Everyone loves Ruby's &lt;code&gt;ActiveRecord&lt;/code&gt;, which creates the database table belonging to an entity class of yours all by itself. But choosing the right kind of a list? That's harder. There's a disadvantage to having the machine figure stuff out for you: your program gains in being opaque. The text-file that stores your program code would diverge further from the code to be executed at run time, because important decisions about the code are delayed to the run-time of the program. Since us humans can only see text, this is a real drawback.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;I'm obviously sceptical to ubiquitious dependency injection, and I'm not the only one. Here's what Russ Olsen has to say about the matter (In his book &lt;a href="http://designpatternsinruby.com/"&gt;Design Patterns in Ruby&lt;/a&gt;):&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;  &lt;blockquote&gt;The best way to go wrong with any of the object creation techniques that we have examined … is to use them when you don't need them. Not every object needs to be produced in a factory. In fact, most of the time you will want to create most of your objects with a simple &lt;code&gt;MyClass.new&lt;/code&gt;. … Remember, chances are You Ain't Gonna Need It.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;Well, we have to balance our skepticism against what voodoo may bring us. Suffice it to say that I don't really believe that I want the VM to have any say in whether I zip my files or not. If I write a file to the disk that then the bash will assume to be a plain text email message, it better not be zipped on 5 % of my clients' computers. Another advantage of the voodoo is that we may also get to re-using objects that are laying around anyhow, waiting to be garbage collected. There's charm to that idea, although I wonder if the picture is as rose as Erwann paints it. After all, you'd need to find an object to be disposed first. Object Pooling sucks up memory and CPU cycles for their management.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;Let me summarize that I'm skeptical about the solution that is proposed. Nonetheless, Erwann raises legitimate and important questions, such as: Don't our languages force the developer to supply and commit to more detail than the developer wishes? A mismatch between the mental model of the developer and the programming language is a flaw that deserves our tending to.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;There's one little afterthought. Erwann claims that the mismatch he identified can be tackled only by making both language and VM aware of the problem. I believe the strength and beauty of Smalltalk is to come a far way in allopwing new ways of doing things, without having to dig to the VM and the language (&lt;a href="http://blog.bitquabit.com/2009/05/20/your-language-features-are-my-libraries/"&gt;See the blog post by Benjamin Pollack: Your Language Features Are My Libraries&lt;/a&gt;). Well, I think that Newspeak's late binding of class names could implement all of Erwann's ideas in a library. Here's the idea: If you type &lt;code&gt;Array.new&lt;/code&gt;, then you may expect Array to point to a specific and global class in a namespace that is the same everywhere. What if all lookups had to go through a "lobby," as it were, and each module could not &lt;em&gt;demand&lt;/em&gt; the module, it would have to be &lt;em&gt;passed&lt;/em&gt;. Then, we could have the lobby figure out what List.new is supposed to mean, and have it be context-dependent. (Newspeak is a dream of a programming language. It breaks my heart to see how it isn't used widely. See &lt;a href="http://en.wikipedia.org/wiki/Newspeak_(programming_language)"&gt;the Wikipedia article&lt;/a&gt; for an overview.)&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;h1 id="summary"&gt;Summary&lt;/h1&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;Programming languages do not currently reflect the mental model of the developer in instructions as easy as&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;List l = new ArrayList();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;They specify more details than the programmer wishes to, and as a result, optimizations and opportunities for automation are lost. I suspect that Newspeak would be a great platform for experiments, and I'd like to thank Erwann Wernli for sharing his concerns. His blog is great by the way. Please go and read it!&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;Here is Erwann Wernli's article: &lt;a href="http://www.ewernli.com/web/guest/should-di-and-gc-be-unified?p_p_id=58&amp;amp;p_p_lifecycle=1&amp;amp;p_p_state=normal"&gt;Erwann Wernli: Should DI and GC be unified?&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1228838974904659944?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1228838974904659944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/01/on-erwann-wernlis-idea-of-having-vm.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1228838974904659944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1228838974904659944'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2010/01/on-erwann-wernlis-idea-of-having-vm.html' title='On Erwann Wernli&apos;s idea of having the VM take care of dependency injection'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-7078471359829171085</id><published>2009-12-17T18:57:00.005+01:00</published><updated>2009-12-17T19:15:54.977+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><category scheme='http://www.blogger.com/atom/ns#' term='thoth'/><title type='text'>ThothCompiler revamped</title><content type='html'>ThothCompiler has been revamped very near completely. Get it by executing:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;Gofer it&lt;br /&gt;    squeaksource: 'ASTBridge';&lt;br /&gt;    addPackage: 'ThothCompiler';&lt;br /&gt;    load&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then go to the Preference Browser (System-&gt;Preferences in the world menu) and choose ThothCompiler for the option "whichCompiler".&lt;br /&gt;&lt;br /&gt;ThothCompiler allows you to use a modern AST in Pharo, rather than the 20 year old default one. The code is parsed with Lukas' really fast RBParser and then transformed to the 20 year old nodes, from there compiled. What's the advantage?&lt;br /&gt;&lt;br /&gt;Well, you can transform the modern AST nodes before compilation! It has a great visitor API, that lets you do all kinds of transformations. You can use ThothCompiler as is just to feel fancy, or better: subclass it and overwrite the &lt;code&gt;transform:&lt;/code&gt; method, in which you can transform the AST to your liking.&lt;br /&gt;&lt;br /&gt;ThothCompiler is now used in &lt;a href="http://scg.unibe.ch/research/helvetia"&gt;Helvetica&lt;/a&gt; (albeit under the name of &lt;code&gt;RBCompiler&lt;/code&gt;, because things can never have enough names!).&lt;br /&gt;&lt;br /&gt;Changes since the last &lt;a href="http://smalltalkthoughts.blogspot.com/2009/09/introducing-thothcompiler.html"&gt;blog post&lt;/a&gt;: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Now uses the RBParser, which is much faster than SmaCC&lt;br /&gt;&lt;li&gt;No more dependency on the NewCompiler or AST package&lt;br /&gt;&lt;li&gt;Adds a preference to the system (in the system menu), where you can choose the compiler, even when you can't compile anymore :)&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-7078471359829171085?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/7078471359829171085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/12/thothcompiler-revamped.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7078471359829171085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7078471359829171085'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/12/thothcompiler-revamped.html' title='ThothCompiler revamped'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8382281608657989253</id><published>2009-12-15T12:12:00.002+01:00</published><updated>2009-12-15T12:16:00.374+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>What to keep in mind when playing with compilers in Pharo</title><content type='html'>If you play with the compiler in Pharo, here's an urgent hint: don't lock yourself out of your image! If you break the compiler, you want to have something to fall back to. So here's what you do.&lt;br /&gt;&lt;br /&gt;The compiler for the system is whatever Behavior compilerClass returns, so change that method to read out a preference:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;Behavior&gt;compilerClass&lt;br /&gt; "Answer a compiler class appropriate for source methods of this class."&lt;br /&gt; |default|&lt;br /&gt; default := Compiler.&lt;br /&gt; ^(Smalltalk classNamed:  (Preferences valueOfPreference: #whichCompiler ifAbsent: [^ default]) ) ifNil: [default] &lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That's step 1. Second step is to create the preference, so you can read it out at all:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Preferences addTextPreference: #whichCompiler category: #compiler default: 'Compiler' balloonHelp: 'Compiler to be used throughout the system' .&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That's it, you're set. Happy hacking!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8382281608657989253?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8382281608657989253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/12/what-to-keep-in-mind-when-playing-with.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8382281608657989253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8382281608657989253'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/12/what-to-keep-in-mind-when-playing-with.html' title='What to keep in mind when playing with compilers in Pharo'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-7145888493094475572</id><published>2009-11-30T00:16:00.004+01:00</published><updated>2009-11-30T00:21:04.720+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><category scheme='http://www.blogger.com/atom/ns#' term='J'/><title type='text'>Code beauty, J vs. Mathematica</title><content type='html'>I drew the equivalent kernel of a smoothing spline in J.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_h7uHoQdb3pA/SxMBSZLwz2I/AAAAAAAABFg/wm22C1cEXWE/s1600/Equivalent+kernel+of+smoothing+spline.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 205px;" src="http://3.bp.blogspot.com/_h7uHoQdb3pA/SxMBSZLwz2I/AAAAAAAABFg/wm22C1cEXWE/s320/Equivalent+kernel+of+smoothing+spline.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5409668992911593314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;br /&gt;&lt;small&gt;&lt;code&gt;&lt;pre&gt;t =: i: 10 j. 1000&lt;br /&gt;y=:(%2) * (^-|t% (%2)) * sin(( (|t)* (%:2) % 2 )+ (pi%4))&lt;br /&gt;plot t;y&lt;/pre&gt;&lt;/code&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;This is the Mathematica version: &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_h7uHoQdb3pA/SxMBoiGJNfI/AAAAAAAABFo/HOrgZJdXpI0/s1600/forhoney.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 249px;" src="http://1.bp.blogspot.com/_h7uHoQdb3pA/SxMBoiGJNfI/AAAAAAAABFo/HOrgZJdXpI0/s320/forhoney.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5409669373261067762" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-7145888493094475572?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/7145888493094475572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/code-beauty-j-vs-mathematica.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7145888493094475572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/7145888493094475572'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/code-beauty-j-vs-mathematica.html' title='Code beauty, J vs. Mathematica'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_h7uHoQdb3pA/SxMBSZLwz2I/AAAAAAAABFg/wm22C1cEXWE/s72-c/Equivalent+kernel+of+smoothing+spline.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1391515580200574209</id><published>2009-11-29T20:37:00.008+01:00</published><updated>2009-11-30T09:37:00.118+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='language'/><category scheme='http://www.blogger.com/atom/ns#' term='J'/><title type='text'>The J programming language</title><content type='html'>Today I went through the first few tutorials of the J programming language. J is a treat. The human language has many devices that keep things short and explicit. While in context-oriented programming people are still wondering how to properly identify and model the "context" of a statement, natural language already goes and changes the behaviour of nouns by specifying them more precisely with adjectives. Compare that with modern object-oriented programming languages, which only have nouns (classes) and verbs (methods) at best. &lt;br /&gt;&lt;br /&gt;The J language tries to harness the power of the natural languages by providing nouns, verbs, adverbs, conjunctions, and comparatives. I'd love to see an OO version with adjectives.&lt;br /&gt;&lt;br /&gt;The tutorials are splendid and the IDE helpful, which I won't elaborate on &lt;a href="http://prog21.dadgum.com/48.html"&gt;because James Hague wrote such a nice piece about the fact&lt;/a&gt;. Oh, and he raves about the built-in plotting. Here's some turtle geometry, similar to an example that they provide:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_h7uHoQdb3pA/SxLYyRocvLI/AAAAAAAABFY/DZi4f41T3Rw/s1600/J+example.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 315px;" src="http://2.bp.blogspot.com/_h7uHoQdb3pA/SxLYyRocvLI/AAAAAAAABFY/DZi4f41T3Rw/s320/J+example.png" border="0" id="BLOGGER_PHOTO_ID_5409624460663504050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The source code was:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;show repeat 20;'point (n =: n+1) fd 1 rt 15'[n=: _2&lt;br /&gt;   to 'goreturn a b';'goto b goto a'&lt;br /&gt;   to 'goreturnall a'; 'goreturn for a,.i.20'&lt;br /&gt;   show goreturnall for i.20&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;small&gt;The article is over. Just one last thing: There's a funny glitch in the tutorials. The tutorials assume that you have some familiarity with Hilbert matrices and alternating binomial coefficients. But you are not expected to know how to handle a mouse:   &lt;blockquote&gt;The color window can be moved away from text that it may obscure by clicking on the top bar, holding the button down, and dragging it to a new position before releasing the mouse button –– Chapter 2, lesson 2 in the J tutorial&lt;/blockquote&gt;.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1391515580200574209?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1391515580200574209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/j-programming-language.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1391515580200574209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1391515580200574209'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/j-programming-language.html' title='The J programming language'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_h7uHoQdb3pA/SxLYyRocvLI/AAAAAAAABFY/DZi4f41T3Rw/s72-c/J+example.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8466394974481599856</id><published>2009-11-21T22:24:00.005+01:00</published><updated>2009-11-21T22:53:08.718+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='phexample'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>And it's done, Phexample has no more lolcats</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_h7uHoQdb3pA/SwhbO4jXAuI/AAAAAAAABFI/iEvGaJLAZhk/s1600/Yet_another_lolcat.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 229px;" src="http://1.bp.blogspot.com/_h7uHoQdb3pA/SwhbO4jXAuI/AAAAAAAABFI/iEvGaJLAZhk/s320/Yet_another_lolcat.jpg" border="0" alt="Image from Wikipedia, see http://en.wikipedia.org/wiki/File:Yet_another_lolcat.jpg for the author. CC license." id="BLOGGER_PHOTO_ID_5406671663915270882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Lolcats have left the building, Phexample reads easier now.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Stack new isEmpty should not be true.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;To get a meaningful error message out of this test, you're faced with a small dilemma. The Phexample framework lies in the should method, thus, for all that should sees, it is called on true, so the test might as well have been&lt;br /&gt;&lt;br /&gt;&lt;code&gt;true should not be true&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Now, to squeeze a reasonable error message out of this, such as "isEmpty should return false, but got true," it helps finding the unexecuted code snippet in the caller. Thus, the execution depends on who called you. Maybe not perfectly object-oriented, but context-oriented! There we have a new buzz-word: COP, context-oriented programming. &lt;br /&gt;&lt;br /&gt;I learned a few things on the way: Bytecodes in Smalltalk have different sizes, thus you can't just walk backwards from where you are. The containing method must be read forwards, and once you hit the position of the current execution, you know you're a bit too far. Also, you find the current stack frame using the pseudo-variable &lt;code&gt;thisContext&lt;/code&gt;, &lt;a href="http://stackoverflow.com/questions/1770401/how-to-find-the-current-stack"&gt;though there are some performance issues with it&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;By the way, you can't really ice and copy the stack (someone forbade it in the source, for whatever reason), you're analyzing it as it is being used for the current computation. A bit scary, but it works quite nice. Pharo ftw! Try this in JavaScript!&lt;br /&gt;&lt;br /&gt;Get the latest version of Phexample at &lt;a href="http://www.squeaksource.com/phexample.html"&gt;SqueakSource (there's a Gofer-Script on that page that will do the downloading for you!&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8466394974481599856?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8466394974481599856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/and-its-done-phexample-has-no-more.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8466394974481599856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8466394974481599856'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/and-its-done-phexample-has-no-more.html' title='And it&apos;s done, Phexample has no more lolcats'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_h7uHoQdb3pA/SwhbO4jXAuI/AAAAAAAABFI/iEvGaJLAZhk/s72-c/Yet_another_lolcat.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-4867165234419895696</id><published>2009-11-19T21:04:00.008+01:00</published><updated>2009-11-20T11:50:33.713+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='phexample'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Phexample's lolcats syntax</title><content type='html'>In this post I'll clear my throat on what there is to come. The number one criticism of Phexample is that &lt;a href="http://www.iam.unibe.ch/pipermail/moose-dev/2009-November/003041.html"&gt;Phexample sometimes reads like lolcats&lt;/a&gt;, because real code that asserts that a stack be empty reads like&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;code&gt;stack should not be isEmpty&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The complaint feels like an instance of the complaint of how stupid it is that in OSX you need to drag CDs to the waste bin to eject them, or how in Windows the bin stands on the desk. Of course the metaphor is broken there, but you only notice it because the metaphor works great.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;And now you compare that to the usual alternative, which is assert. The first thing you know about assert is that nobody can remember which one is the expected and which is the actual value (I'll take this fact and some of the below discussion from &lt;a href="http://grahamis.com/blog/2009/06/05/assertions_actual_or_expected_first/"&gt;Josh Graham's discussion of the assert syntax&lt;/a&gt;). We're talking about assertEquals(stack.isEmpty, true). Or the other way around. I certainly can't remember that either. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In Java, improvements have been suggested:&lt;br /&gt;&lt;code&gt;assertEquals(expected(true), actual(stack.isEmpty()); &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I find that while Phexample does not allow you to express your examples in a way that completely parses as natural language, it certainly reads easy enough and gives a natural and easy distinction between the expected and the actual.&lt;br /&gt;&lt;br /&gt;So there's my analogy: no other testing framework is required to express its tests in a way that perfectly parses as human language. Only because the tests already look so close to perfection is it that people single out the mismatch and decry it. I don't think this is an interesting problem worth solving at all.&lt;br /&gt;&lt;br /&gt;Yet, the criticism follows Phexample wherever it goes, so I'll try and allow phrases like&lt;br /&gt;&lt;br /&gt;&lt;code&gt;stack isEmpty should be true&lt;/code&gt;.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The difficulty in making the above code work is that the testing framework is only activated after isEmpty was evaluated already. Which means that it isn't in the stack anymore, so we need to analyze the source code to find out which method caused the failure to display a meaningful error message.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-4867165234419895696?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/4867165234419895696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/phexamples-lolcats-syntax.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4867165234419895696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4867165234419895696'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/phexamples-lolcats-syntax.html' title='Phexample&apos;s lolcats syntax'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8645223661077027295</id><published>2009-11-04T12:14:00.005+01:00</published><updated>2009-11-19T21:39:57.659+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='gofer'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Telling other people how to install your code</title><content type='html'>Previously, I created dirty ScriptLoader tricks to make it easier for others to download my code. &lt;br /&gt;&lt;br /&gt;I am pleased to find out that Gofer is even easier than my dirty tricks, well without being a dirty trick: &lt;a href=http://www.lukas-renggli.ch/blog/gofer&gt;Gofer on Lukas's blog&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8645223661077027295?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8645223661077027295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/telling-other-people-how-to-install.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8645223661077027295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8645223661077027295'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/telling-other-people-how-to-install.html' title='Telling other people how to install your code'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-825757043721994967</id><published>2009-11-04T12:05:00.012+01:00</published><updated>2009-11-25T00:15:49.419+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='phexample'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Phexample, because examples expand on one another</title><content type='html'>Imagine you want to test the Stack class, and your first test just&lt;br /&gt;creates a test and checks if it's empty.&lt;br /&gt;&lt;br /&gt;Then in your second test, you create the same empty stack, but now&lt;br /&gt;push an element 'apple' and check if the size is one.&lt;br /&gt;&lt;br /&gt;Then in your third test, you do all the same, and then you pop the&lt;br /&gt;element and check that it is an apple.&lt;br /&gt;&lt;br /&gt;Wouldn't it be great if you could write your test cases such that they&lt;br /&gt;could expand on one another? If you didn't need to copy paste the code&lt;br /&gt;of the previous test and just say that you require the previous one!&lt;br /&gt;&lt;br /&gt;Well, that's what PhExample lets you do. And as a bonus, tests are&lt;br /&gt;ignored if the test they expand on does not pass. This gives you less&lt;br /&gt;failed tests, because examples are executed only if the examples they&lt;br /&gt;expand on pass too! That gives you the simplest failing examples in&lt;br /&gt;your set to look at!&lt;br /&gt;&lt;br /&gt;And best of all, you can run all examples with ye old TestRunner!&lt;br /&gt;&lt;br /&gt;The example discussed above would read in code as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;EGExample subclass: #ForExampleStack&lt;br /&gt;       …&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;shouldBeEmpty&lt;br /&gt;       "Create the empty stack"&lt;br /&gt;       | stack |&lt;br /&gt;       stack := Stack new.&lt;br /&gt;       stack should be isEmpty.&lt;br /&gt;       stack size should = 0.&lt;br /&gt;       ^ stack&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;shouldPushElement&lt;br /&gt;       "Push one element"&lt;br /&gt;       | stack |&lt;br /&gt;       stack := self given: #shouldBeEmpty.&lt;br /&gt;       stack push: 42.&lt;br /&gt;       stack should not be isEmpty.&lt;br /&gt;       stack size should = 1.&lt;br /&gt;       stack top should = 42.&lt;br /&gt;       ^ stack&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;shouldPopElement&lt;br /&gt;       "And pop it again"&lt;br /&gt;       | stack |&lt;br /&gt;       stack := self given: #shouldPushElement.&lt;br /&gt;       stack pop should = 42.&lt;br /&gt;       stack should be isEmpty.&lt;br /&gt;       stack size should = 0.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Find the code at &lt;a href=http://www.squeaksource.com/phexample.html&gt;http://www.squeaksource.com/phexample.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can install it as follows using &lt;a href=http://www.lukas-renggli.ch/blog/gofer&gt; Gofer&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; Gofer new&lt;br /&gt;  squeaksource: 'phexample';&lt;br /&gt;  addPackage: 'Phexample';&lt;br /&gt;  load &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The repository is write-global, so feel free to drop your ideas!&lt;br /&gt;&lt;br /&gt;PhExample is based on JExample by Lea Haensenberger, Adrian Kuhn, and&lt;br /&gt;Markus Gaelli. See &lt;a href=http://scg.unibe.ch/research/jexample&gt;JExample&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-825757043721994967?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/825757043721994967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/phexample-because-examples-expand-on.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/825757043721994967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/825757043721994967'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/11/phexample-because-examples-expand-on.html' title='Phexample, because examples expand on one another'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-2159156840825195404</id><published>2009-09-30T17:00:00.007+02:00</published><updated>2009-11-19T21:40:45.744+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><category scheme='http://www.blogger.com/atom/ns#' term='thoth'/><title type='text'>Introducing ThothCompiler</title><content type='html'>ThothCompiler combines the strengths of the two most popular smalltalk compilers. It takes the extensibility and wealth of the AST implementation from the NewCompiler and combines it with the most important asset of the old Compiler that per default ships with Squeak: it actually works.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Installation&lt;/h4&gt;&lt;br /&gt;The installation is fantastically easy. Go to &lt;a href="http://www.squeaksource.com/ASTBridge.html"&gt;Thoth on Squeaksource&lt;/a&gt; and get &lt;code&gt;ASTBridgeLoader&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;In a workspace, then execute:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ASTBridgeLoader load&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Add the method compilerClass to the CLASS side of your class to set the compiler for the class. Thoth installs itself as the default compiler of the image. If you're unhappy with that, for example because you don't like the lack of error messages when you accept uncompilable code, you can choose for each class which compiler is to be used. &lt;code&gt;Behavior&gt;compilerClasss&lt;/code&gt; sets the default. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;How do I hack into it?&lt;/h4&gt;&lt;br /&gt;Subclass ThothCompiler and override #compile:in:classified:notifying:ifFail:  and  #evaluate:in:to:notifying:ifFail:logged:  Transform the AST before &lt;code&gt;generate&lt;/code&gt; is called. Perhaps I should provide some infrastructure here …&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;How it works&lt;/h4&gt;&lt;br /&gt;It is a really simple thing: It uses the parser of the NewCompiler, then transforms the AST into the old model, and then uses the backend of the old compiler to compile.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-2159156840825195404?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/2159156840825195404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/09/introducing-thothcompiler.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2159156840825195404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/2159156840825195404'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/09/introducing-thothcompiler.html' title='Introducing ThothCompiler'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-8811285230735648537</id><published>2009-09-16T16:58:00.003+02:00</published><updated>2009-11-19T21:41:06.146+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Blocks in Smalltalk can have their own temporary variables</title><content type='html'>Did you know that the following appears to be Smalltalk code? Runs fine in the current Pharo. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;[:a | |b| 2] value: 3&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-8811285230735648537?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/8811285230735648537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/09/blocks-in-smalltalk-can-have-their-own.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8811285230735648537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/8811285230735648537'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/09/blocks-in-smalltalk-can-have-their-own.html' title='Blocks in Smalltalk can have their own temporary variables'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1261365081664208243</id><published>2009-09-06T14:13:00.012+02:00</published><updated>2009-09-07T00:14:18.711+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='euler'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><title type='text'>Explaining Mathematica with the Solution for Problem 59 from Project Euler</title><content type='html'>The solution to problem 59 is perhaps helpful to see what Mathematica is good at and how it basically works. The task is &lt;a href="http://projecteuler.net/index.php?section=problems&amp;id=59"&gt;here&lt;/a&gt;. Let me summarize it. The task contains a link to a text file full of numbers. These numbers together are an encrypted text, the password being three lowercase letters. The decryption works like this: You convert the password into its ASCII values, and then XOR the first byte of the encrypted text with the ASCII value of the first letter in the password. You iterate this for all three letters, and then start over with the first letter of the password for the fourth number in the encrypted text. And so forth, until you are done. The task is to find the password.&lt;br /&gt;&lt;br /&gt;Ok, so, the first thing Mathematica rocks at is importing. Here it probably isn't a big deal, but I find it noteworthy anyhow … getting the encrypted file is this: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;text &lt;br /&gt;  = Import["http://projecteuler.net/project/cipher1.txt", "csv"]  &lt;br /&gt;  //  First ; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here, Import leaves a pair of braces around the real result, which the First function disposes of.&lt;br&gt;&lt;br /&gt;Now the idea of my checking is this. I'll take every third character from the encrypted file and store it in a list. Then I will try for each possible first letter of the password which letter would yield the most printable characters in the decrypted text. I will use this very narrow definition of a printable character:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; printable[a_] := 65 &lt;= a &lt;= 90 &lt;br /&gt;  ~Or~ 97 &lt;= a &lt;= 122&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One thing we cannot see here in Blogger is that Mathematica allows Mathematical typesetting, thus presenting this definition with a beautiful vee for an or and the inequalities look like inequalities.&lt;br /&gt;&lt;br /&gt;The next task is to give each letter of the password a score. Let us assemble the procedure from the ground up. The goal is to build a function which takes every third element of the encrypted text, applies BitXor with the key, and then counts how many characters are displayable. &lt;br /&gt;&lt;br /&gt;Getting every third element from the encrypted text, starting with the 1&lt;sup&gt;st&lt;/sup&gt; letter, is expressed as &lt;br /&gt;&lt;br /&gt;&lt;code&gt;text[[1 ;; ;; 3]]]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We can refer to the result of the previous computation as &lt;code&gt;%&lt;/code&gt;. Let us try 103 as the first letter of the password, that would be the letter "g." Then we decrypt as follows: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;BitXor[103,%]&lt;/code&gt;. &lt;br /&gt;&lt;br /&gt;And finally, we count the printable letters in the resulting list. Mathematica provides a Count function. Count is a nice function to demonstrate something rather unique to Mathematica: patterns. Let us first see our code, which counts printable letters:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Count[%, _?printable]&lt;/code&gt;. &lt;br /&gt;&lt;br /&gt;Here, &lt;code&gt;_?printable&lt;/code&gt; is the pattern. The underscore stands for "anything", and the question mark specifies that the anything must evaluate to true when passed into the following function, printable. This is a very simple pattern, you can do cooler things, like the pattern {1,2,_}, which matches lists of three elements whose first two elements must be 1 and 2. &lt;br /&gt;&lt;br /&gt;Now altogether the score function looks like this, where i ranges between 1 and 3:&lt;br /&gt;&lt;pre&gt;score[i_, letter_] := &lt;br /&gt; Count[BitXor[letter, text[[i ;; ;; 3]]] , _?printable]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The task states that valid candidates for the letters of the password must be lowercase. These have ASCII codes between 79 and 122. The function SelectMaximizer is an invention of mine. It chooses the element of a list which maximizes a function that can be supplied. The supplied function will be score, of course, so we can find the first letter as &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SelectMaximizer[Range[97, 122], &lt;br /&gt;  score[1, #] &amp;amp;]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The confusing thing here is the closure, &lt;code&gt;score[1, #] &amp;amp;&lt;/code&gt;. In Mathematica, everything that ends in an ampersand is a closure, or a local function. The hash symbol is the argument. We need it because score accepts two arguments (the position of the letter in the password, and the actual letter). Where we'd like to use only the second as an argument. &lt;br /&gt;&lt;br /&gt;The function call will dutifully find the character "g" as the first letter of the password. To find all 3, we use the Table function. The Table function an expression with an undefined variable, &lt;i&gt;i&lt;/i&gt;, and then tell it to use that variable as an iterator, assuming values from 1 to 3. The following code thus finds all three letters of the password: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;password = &lt;br /&gt;  Table[ SelectMaximizer[Range[97, 122], &lt;br /&gt;  score[i, #] &amp;amp;], {i, 3}];&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To decrypt the text with our password, we partition the encrypted text into runs of three, which we can then BitXor. Mathematica ships with a Partition function. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;Partition[text, 3]&lt;/code&gt; returns a list partitions of length 3 of text text. Map function applies a closure to each element of a list. For example, &lt;code&gt;Map[Range[4],#*#&amp;amp;]&lt;/code&gt; computes the first four square numbers.&lt;br /&gt;&lt;br /&gt;Our first shot at a decoding function is thus:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Map[BitXor[password, #] &amp; , Partition[text, 3]&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;We almost get it right. Unfortunately, the encrypted text's length is not divisible by three, and thus partition just 'swallows' the last letter. We can tell Partition to attach the remaining letter to the list. We use a little bit of trickery, because simply attaching the last letter would attach a list of length 1 to the list of partitions, but our partitions must have length 3 for the BitXor to work. Well, we can tell Partition to add the left-overs, and then pad to the length of 3 with the password itself, which will then become 0 after the Xor, so we're really appending null bytes to the string.&lt;br /&gt;&lt;br /&gt;Together, the decoding function is now &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;decode[p_] := Map[BitXor[p, #] &amp;amp; ,&lt;br /&gt;   Partition[text, 3, 3, 1, p]]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;where &lt;code&gt;p&lt;/code&gt; stands for password.&lt;br /&gt;&lt;br /&gt;For what it's worth, the password is "god" and the result is chapter one of the Gospel of John. The task still requires us compute the sum of the ASCII codes of the decoded text. Our &lt;code&gt;decode&lt;/code&gt; function really returns a nested list, to compute the sum of all entries, we could either use Flatten to reduce it to depth 1, or we could tell the Total function to operate on the second level of a nested list. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Total[decode[password], 2]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;which returns 107359.&lt;br /&gt;&lt;br /&gt;The complete code is &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;text = &lt;br /&gt;Import["http://projecteuler.net/project/cipher1.txt",&lt;br /&gt;   "csv"] //  First ;&lt;br /&gt;&lt;br /&gt;printable[a_] := 65 &lt;= a &lt;= 90 ~Or~  97 &lt;= a &lt;= 122&lt;br /&gt;&lt;br /&gt;score[i_, letter_] := &lt;br /&gt; Count[BitXor[letter, text[[i ;; ;; 3]]] , _?printable]&lt;br /&gt;&lt;br /&gt;decode[p_] := Map[BitXor[p, #] &amp;amp; , &lt;br /&gt;  Partition[text, 3, 3, 1, p]]&lt;br /&gt;&lt;br /&gt;password = &lt;br /&gt;  Table[ SelectMaximizer[Range[97, 122], &lt;br /&gt;  score[i, #] &amp;amp;], {i, 3}];&lt;br /&gt;&lt;br /&gt;Total[decode[password], 2] &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The complete code is can be downloaded as a &lt;a href="http://dl.getdropbox.com/u/321703/problem59/crypt%20task%20beautiful.nb"&gt;complete code for problem 59 Mathematica notebook&lt;/a&gt; or as a &lt;a href="http://dl.getdropbox.com/u/321703/problem59/crypt%20task%20beautiful.pdf"&gt;complete code for problem 59 pdf file&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1261365081664208243?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1261365081664208243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/09/explaining-mathematica-with-solution.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1261365081664208243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1261365081664208243'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/09/explaining-mathematica-with-solution.html' title='Explaining Mathematica with the Solution for Problem 59 from Project Euler'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-3827916625346055356</id><published>2009-08-14T21:30:00.012+02:00</published><updated>2009-09-07T00:10:42.177+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><category scheme='http://www.blogger.com/atom/ns#' term='benchmark'/><title type='text'>A Small Mathematica Vs C Benchmark</title><content type='html'>Sometimes I get frowned upon because I do expensive computations in Mathematica. Some expensive computations will be very fast in Mathematica, of course. Try computing (10^4)//Factorial. &lt;br /&gt;&lt;br /&gt;But what about the cheap computations that you could as well do in C? The Euler Project gave me the change to try it out with an easy problem. I was solving &lt;a href="http://projecteuler.net/index.php?section=problems&amp;id=9"&gt;problem 9 from project Euler&lt;/a&gt;, which in short searches for natural numbers&lt;span style="font-style:italic;"&gt; a&amp;lt;b&amp;lt;c&lt;/span&gt;, such that a^2+b^2=c^2, and a+b+c=1000.&lt;br /&gt;&lt;br /&gt;The C-program that finds these numbers is &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;int main(void) {&lt;br /&gt; for(int a = 1; a &lt; 10000; a++) {&lt;br /&gt;  for(int b = a + 1; b &lt;= 10000; b++) {&lt;br /&gt;   int c = 1000 - a - b;&lt;br /&gt;   if(a * a + b * b == c * c) {&lt;br /&gt;    printf("%d\n",a*b*c);&lt;br /&gt;    return 0;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that I de-optimized a little bit by bounding a and b in [1,10,000], which is ten times greater than it should be. The result is still correct, but now it's slow enough so that we can measure something. &lt;br /&gt;&lt;br /&gt;The run-time in C is 0.016 seconds on my machine&lt;br /&gt;&lt;br /&gt;Bringing this to Mathematica is more than straightforward:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Module[{a, b, c},&lt;br /&gt;  For[a = 1, a &lt;= 10000, a++,&lt;br /&gt;   For[b = a + 1, b &lt;= 10000, b++,&lt;br /&gt;    c = 1000 - a - b;&lt;br /&gt;    If[a a + b b == c c, Return[a b c]]&lt;br /&gt;    ]&lt;br /&gt;   ];&lt;br /&gt;  0&lt;br /&gt;  ][]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now the run-time is at 8.5 seconds. But! Mathematica can compile! To something faster, that is. It's as easy as wrapping a Compile around the computation. We get:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Compile[{},&lt;br /&gt; Module[{a, b, c},&lt;br /&gt;  For[a = 1, a &lt;= 10000, a++,&lt;br /&gt;   For[b = a + 1, b &lt;= 10000, b++,&lt;br /&gt;    c = 1000 - a - b;&lt;br /&gt;    If[a a + b b == c c, Return[a b c]]&lt;br /&gt;    ]&lt;br /&gt;   ];&lt;br /&gt;  0&lt;br /&gt;  ]&lt;br /&gt; ]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And now we're down to 0.38 seconds. Just as a reminder:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;CAPTION&gt;Table 1. Run times of the Euler project 9 algorithm in seconds. M stands for Mathematica&lt;/CAPTION&gt;&lt;thead&gt;&lt;tr&gt; &lt;th&gt;C&lt;/th&gt;  &lt;th&gt;uncompiled M &lt;/th&gt; &lt;th&gt;compiled M&lt;/th&gt; &lt;/tr&gt;&lt;tbody align="right"&gt;&lt;tr&gt; &lt;td&gt;0.16 &lt;td&gt; 8.53 &lt;td&gt; 0.38&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Which brings me to the following &lt;span style="font-weight:bold;"&gt;conclusion&lt;/span&gt;: For basic arithmetic computation, Mathematica will slow you down by a factor 40, if you use it only casually, or by a factor of 2 if you have some experience with it (Not everything is nicely compilable, so this is a bit optimistic). &lt;br /&gt;&lt;br /&gt;Mathematica taketh away, but it also giveth: The library functions are fast, and there's plenty of them. You can treat Mathematica just like any scripting language: If the operations in your inner loop are costly, Mathematica is good for you! Otherwise, you pay a price for a wide range of library-functions. And it is worth delving into that library.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-3827916625346055356?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/3827916625346055356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/08/small-mathematica-vs-c-benchmark.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3827916625346055356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3827916625346055356'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/08/small-mathematica-vs-c-benchmark.html' title='A Small Mathematica Vs C Benchmark'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1344537729355127248</id><published>2009-07-06T10:32:00.005+02:00</published><updated>2009-11-19T21:41:44.095+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Pharo – perhaps Squeak 2.0?</title><content type='html'>Saturday, two days ago, I had the pleasure of being present at the&lt;a href="http://www.adrian-lienhard.ch/blog?dialog=pharo-sprint-in-bern-july-4-2009"&gt; Berne Pharo sprint&lt;/a&gt;. It was not my first contact with &lt;a href="http://www.pharo-project.org"&gt;Pharo&lt;/a&gt;, but close. &lt;br /&gt;&lt;br /&gt;If I understand it correctly, then Pharo emerged because Squeak was torn into too many directions. Squeak was the one platform for child education, multimedia websites, and webserver development. Some code in the Squeak image was never released under a free licence, and the Squeak-licence itself is not an OSI-certified open-source licence. Squeak has more than 2000 open issues in its bugtracker, &lt;a href="http://bugs.squeak.org/view_all_bug_page.php"&gt;Mantis&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Pharo is a fork from Squeak that aims at removing cruft and turnung Squeak smalltalk into a more traditional programming environment, with a small core, stable and fast-evolving.&lt;br /&gt;&lt;br /&gt;I am slightly suspicious about the reducing of the Image size. I don't know anything about it, but I still recall how in an interview, Dan Ingalls spoke about the advantages of an image that is NOT split into packages, where everything calls everything. I recall for myself that when I wrote a web application that was to send emails by itself, I was delighted to see that an SMTP client is included in a standard image already. It was fantastically easy to send an email message. On the other hand, I discovered at least one bug in the SMTP client code.&lt;br /&gt;&lt;br /&gt;Still, I will use Pharo, and not Squeak, henceforward. The user interface is revised and does not look childish anymore. The number of open issues is small, and despite the alpha status, Pharo appears to be a lot more stable than Squeak. Pharo is already used as the reference implementation of &lt;a href="http://seaside.st"&gt;Seaside&lt;/a&gt;, and thus, it is only a matter of time until it will draw a significant share of the Smalltalk world into using it for web development.  Depending on how well it will manage to faciliate the installation of external packages, I would like to believe that for non-educational purposes, Pharo will take over all of the Squeak world, and serve as Squeak 2.0.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1344537729355127248?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1344537729355127248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/07/pharo-perhaps-squeak-20.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1344537729355127248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1344537729355127248'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/07/pharo-perhaps-squeak-20.html' title='Pharo – perhaps Squeak 2.0?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-4089194537267647675</id><published>2009-05-26T10:40:00.001+02:00</published><updated>2009-11-19T21:42:07.681+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='RESTful'/><category scheme='http://www.blogger.com/atom/ns#' term='seaside'/><category scheme='http://www.blogger.com/atom/ns#' term='benchmark'/><title type='text'>How fast is Comanche?</title><content type='html'>The other day I came across &lt;a href="http://tlug.jp/meetings/2008/11/serving-dynamic-webpages-in-less-then-a-millisecond_john-fremlin_handout.pdf"&gt;this guy who wants to serve webpages in less than a millisecond&lt;/a&gt;. Without parallelization. So, his web page is really simple, it looks like this: &lt;code&gt;&amp;lt;h1&gt;Hello TWUG!&amp;lt;/h1&gt;&lt;/code&gt;. &lt;br /&gt;&lt;br /&gt;His point is that things like Twitter are difficult to scale across several machines. The slowness of dynamic pages, he claims, is tried to be made up by advanced caching strategies. He goes on to check how fast certain languages are at serving dynamic content. He gets these numbers: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_h7uHoQdb3pA/Shu8q4QeaoI/AAAAAAAAA1c/SnvADZWUXgA/s1600-h/performance+figures.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 296px;" src="http://3.bp.blogspot.com/_h7uHoQdb3pA/Shu8q4QeaoI/AAAAAAAAA1c/SnvADZWUXgA/s320/performance+figures.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5340069228019870338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Clearly, his machine is faster than mine, because serving the same file statically, my Apache (single-threaded using httpd -X) can do only 1850  requests per second, that is 0.5 ms per request. (I use this benchmark: &lt;code&gt;httperf --hog --num-conn 10000 --uri http://localhost:9090/?name=Niko&lt;/code&gt;). Here are the numbers I get:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_h7uHoQdb3pA/ShvYQCYuN4I/AAAAAAAAA1k/Gi1JAZyw-Z8/s1600-h/performances.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 226px;" src="http://4.bp.blogspot.com/_h7uHoQdb3pA/ShvYQCYuN4I/AAAAAAAAA1k/Gi1JAZyw-Z8/s320/performances.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5340099553207924610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Anyway, I find interesting to mention that Comanche is not far from Apache. Comanche can serve the same page dynamically (the name is a GET parameter) in 1.1 ms, for which Apache takes statically 0.5 ms. As for Apache-php vs. Comanche, I'd call it a tie. &lt;br /&gt;&lt;br /&gt;The Squeak code for the Http server would be this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;ma := ModuleAssembly core.&lt;br /&gt;ma addPlug: [:request | HttpResponse fromString: &lt;br /&gt;   (String streamContents: [:s| &lt;br /&gt;   s nextPutAll:'&amp;lt;h1&gt;Hello! '; &lt;br /&gt;   nextPutAll:( request  fields at: 'name'); &lt;br /&gt;   nextPutAll: '&amp;lt;/h1&gt;']).].&lt;br /&gt;(HttpService startOn: 9090 named: 'Example') module: ma rootModule&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By this way, as the above snippet suggests, a standard Seaside installation for Squeak is quite able to make RESTful applications. Just  avoid the Seaside framework and plug right into the Comanche web server.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;For completeness, the PHP-code:&lt;/h4&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;h1&gt;Hello &amp;lt;?=$_REQUEST['name']?&gt;&amp;lt;/h1&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Update&lt;/h4&gt;&lt;br /&gt;By the way, this seems to be about 10 % faster:&lt;br /&gt;&lt;pre&gt;s:=(HttpService on: 8080 named: 'Example Http Service').&lt;br /&gt;s onRequestDo: [ :request |&lt;br /&gt; HttpResponse fromString: &lt;br /&gt;  (String streamContents: [:s| s nextPutAll:'&amp;lt;h1&gt;Hello! '; &lt;br /&gt;  nextPutAll:( request  fields at: 'name'); &lt;br /&gt;  nextPutAll: '&amp;lt;/h1&gt;']) ].&lt;br /&gt;s start&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-4089194537267647675?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/4089194537267647675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/how-fast-is-comanche.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4089194537267647675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/4089194537267647675'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/how-fast-is-comanche.html' title='How fast is Comanche?'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_h7uHoQdb3pA/Shu8q4QeaoI/AAAAAAAAA1c/SnvADZWUXgA/s72-c/performance+figures.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-288144887733321881</id><published>2009-05-21T18:30:00.001+02:00</published><updated>2009-11-19T21:42:24.521+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='pharo'/><title type='text'>Adding new properties to a class</title><content type='html'>When you load a new toy into Squeak and toy with it in a workspace, that is usually fun. So much more fun than creating a new class. I always suspect that I use the Squeak tools all wrong, but honestly, to create a new class with a couple of properties, it takes me fivethousand clicks to set all the instance variables, set the accessors and get them all properly initialized.&lt;br /&gt;&lt;br /&gt;So, I still don't know if there might not be a much easier way to do it, but I'm fine with what I've dreamt up today. If I want to add a new instance variable to a class, including all accessors, I call this from a workspace:&lt;br /&gt;&lt;br&gt;&lt;code&gt;ManyManyRelation addPropertyName: #oneLot&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;And if I want to initialize the property to something, I use this:&lt;br /&gt;&lt;br&gt;&lt;code&gt;ManyManyRelation addPropertyName: #otherLot lazyInitializeWith: [Set new]&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The following method goes to the instance side of Class:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;addPropertyName: aSymbol&lt;br /&gt;  self addInstVarName: aSymbol.&lt;br /&gt;  self compileAccessorsFor: aSymbol&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And then:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;compileAccessorsFor: aSymbol&lt;br /&gt;&lt;br /&gt;"Compile instance-variable accessor methods&lt;br /&gt;  for the given variable name "&lt;br /&gt;   self compileSilently: aSymbol asString , '&lt;br /&gt;       ^ ' , aSymbol classified: 'access'.&lt;br /&gt;   self compileSilently: aSymbol asString , ': anObject' &lt;br /&gt;        , aSymbol , ' := anObject' classified: 'access'&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You can now call something like &lt;code&gt;ManyManyRelation addPropertyName: #oneLot&lt;/code&gt;, and it adds an instance variable to ManyManyRelation, including both accessors.&lt;br /&gt;&lt;br /&gt;Let's push it one step further.  Hooking into initialize really doesn't feel right––if objects are about modelling the real world, then what exactly corresponds to object initialization? While still not being optimal, the following creates lazy initizers in the accessors.&lt;br /&gt;&lt;br /&gt;The following two methods go as instance methods into Class:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;addPropertyName: aSymbol lazyInitializeWith: aBlock&lt;br /&gt;   self addInstVarName: aSymbol.&lt;br /&gt;   self compileAccessorsFor: aSymbol lazyInitializeWith: aBlock&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;compileAccessorsFor: aSymbol lazyInitializeWith: aBlock &lt;br /&gt;    | initializeCommand decompileString |&lt;br /&gt;    decompileString := aBlock decompileString.&lt;br /&gt;    initializeCommand := decompileString copyFrom: &lt;br /&gt;                2 to: decompileString size - 1.&lt;br /&gt;    self compileSilently: aSymbol asString , '&lt;br /&gt;        ^ ' , aSymbol , ' ifNil: [ ' , aSymbol , &lt;br /&gt;          ' := ' , initializeCommand , ']'  classified: 'access'.&lt;br /&gt;    self compileSilently: aSymbol asString , ': anObject&lt;br /&gt;    ' , aSymbol , ' := anObject' classified: 'access'&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You use it by calling &lt;code&gt;ManyManyRelation addPropertyName: #otherLot lazyInitializeWith: [Set new]&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;By the way, I would refrain from using &lt;code&gt;(CreateAccessorsForVariableRefactoring variable: #hasMany class: OneManyRelation classVariable: false) execute&lt;/code&gt;, which is what happens when you create accessors using OmniBrowsers, the reason being it behaves strangely when the object already responds to a message, most typically like name.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-288144887733321881?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/288144887733321881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/creating-new-classes-in-smalltalk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/288144887733321881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/288144887733321881'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/creating-new-classes-in-smalltalk.html' title='Adding new properties to a class'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-1707268154779393832</id><published>2009-05-17T20:05:00.000+02:00</published><updated>2009-05-17T22:19:57.518+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Use relational databases and lock yourself out from your own data</title><content type='html'>&lt;p&gt;Searching a certain pattern in a graph of your data is the most exciting task. I learned that by writing a Master's thesis on algorithms that solve NP-hard problems. I know that years of research have gone into people trying to come up with smart algorithms that try to answer really difficult questions on graphs. I also know that researchers carefully take care that each of these graph problems really stands for a computation problem of great significance to real life computing. Graph algorithms help you find travelling routes, understand the preferences of your customers, and help you find the optimal arrangement of your office. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;I am talking about graphs defined by your data. If your application has interesting objects, then maybe they form an interesting graph and perhaps this way of thinking brings you a fantastically fast algorithm that serves your business logic. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you have an interesting query on your data,  it may not  even be POSSIBLE to formulate the query in SQL. Such a query might be: I have a band, give me the &lt;a href="http://theinf1.informatik.uni-jena.de/publications/cluster-editing-stamped.pdf"&gt;cluster&lt;/a&gt; of similar bands!&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A relational database promises you to solve all your data searching problems if you give it all your data. That's a REALLY big promise. In fact it's esoteric. Why would a search path optimizer be able to do what otherwise researchers write papers on? If you have an interesting SQL query, then I bet you that your database is rather slow in answering it. Perhaps it hides it by computing the answer to the query long before the query actually shows up, but the cost is still quite high. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;For interesting queries on your data, I suggest you do not trust the esoteric and thoroughly overrated RDBMS query optimizers. Trust your brain and come up with a smart graph algorithm. If you use a relational database, you have locked yourself out from your own data. That is because getting a single object that equals one data row out in a RDBMS takes typically about 20 ms. If you navigate through the graph of your objects and each step costs you 20 ms, you know just exactly how many steps through your graph are still ok if you plan to deliver the rendered website in less than a second. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Object databases, instead, show a fantastic speed when you are navigating through the object graph. Give object databases a shot and find your web application soaring all of a sudden. And let's stop pretending that RDMBSs are easy. I've spent more time than I'd like to admit pondering about the access paths that a query optimizer chose and just how exactly to nudge it to to something smarter. Which index to create? How much memory for what? RDBMSs don't think for you, they force to first ponder a smart access strategy and then ponder  how to nudge the RDBMS into taking it.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Relational databases are slothful, bulky, and overall a great waste of time. Yours and the computer's. I avoid them wherever I can and I recommend you to do the same.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-1707268154779393832?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/1707268154779393832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/use-relational-databases-and-lock.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1707268154779393832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/1707268154779393832'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/use-relational-databases-and-lock.html' title='Use relational databases and lock yourself out from your own data'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107818332672551112.post-3317323609677247345</id><published>2009-05-14T15:54:00.002+02:00</published><updated>2009-11-19T21:43:40.412+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='ODBMS'/><category scheme='http://www.blogger.com/atom/ns#' term='GOODS'/><category scheme='http://www.blogger.com/atom/ns#' term='sandstoneDB'/><category scheme='http://www.blogger.com/atom/ns#' term='sandstoneGOODS'/><title type='text'>SandstoneGOODS</title><content type='html'>&lt;p&gt;SandstoneGOODS brings &lt;a href="http://onsmalltalk.com/sandstonedb-simple-activerecord-style-persistence-in-squeak"&gt;SandstoneDB&lt;/a&gt; (you might have to click that link twice) a backend to the GOODS object database. Using SandstoneGOODS, you can have the easiest thinkable persistence and transaction safety for your objects coupled with reasonable performance and scalability in Squeak Smalltalk.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;SandstoneDB is the coolest OODBMS I am aware of, but until now there were only two ways of using it: either from Squeak using only one Squeak instance, or from a full-blown Gemstone. SandstoneGOODS allows to use SandstoneDB and one session per client in squeak seaside, which, &lt;a href="http://gemstonesoup.wordpress.com/2008/08/19/1-session-per-vm-another-scaling-alternative/"&gt;some argue&lt;/a&gt;, is a very performant way to host Seaside web pages.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So, how does it work?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; get a working copy of GOODS from &lt;a href="http://www.garret.ru/goods.html"&gt;http://www.garret.ru/goods.html&lt;/a&gt; and install it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Put the following file into the directory where you want the database to reside:&lt;br /&gt;&lt;pre&gt;1&lt;br /&gt;0: localhost:6000&lt;/pre&gt;&lt;br /&gt;and call this file goods.cfg.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Enter a shell and navigate to the directory where you put the goods.cfg file. Execute &lt;code&gt;goodsrv goods&lt;/code&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Start up Squeak and install SandstoneGOODS (and all its requirements, namely GOODS, BTree, SandstoneDb).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;shut down the image and restart it&lt;br /&gt;&lt;/li&gt;&lt;li&gt;You're ready to go! Use SandstoneDb as described by &lt;a href="http://onsmalltalk.com/sandstonedb-simple-activerecord-style-persistence-in-squeak"&gt;Ramon Leon&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Performance&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;I can execute 1000 small commits in 30 seconds: &lt;br&gt;&lt;br /&gt;&lt;code&gt;[ 1000 timesRepeat:[  SDChildMock new save] ] timeToRun. &lt;/code&gt;&lt;p&gt;&lt;br /&gt;I can execute one commit of 1000 small objects in 3 seconds: &lt;br&gt;&lt;br /&gt;&lt;code&gt;[  SDActiveRecord commit:[ 1000 timesRepeat:[ SDChildMock new save ] ] ] timeToRun. &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; Read speed is excellent: reading 5000 objects from the db can be done in 1 second:&lt;br&gt;&lt;br /&gt;&lt;code&gt;[SDChildMock findAll ] timeToRun&lt;/code&gt;--and once they're in cache, they are read in 0.1 seconds.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Altogether, I think SandstoneGOODS totally rocks and you can write your whole app using SandstoneGOODS faster than it took you before to write the ORM mapper definitions. Please tell me any bugs you find at niko.schwarz@googlemail.com. The repository allows public writing. You can find the sourcode &lt;a href="http://www.squeaksource.com/SDGoodsStore.html"&gt;on squeaksource&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/107818332672551112-3317323609677247345?l=smalltalkthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smalltalkthoughts.blogspot.com/feeds/3317323609677247345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/sandstonegoods.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3317323609677247345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107818332672551112/posts/default/3317323609677247345'/><link rel='alternate' type='text/html' href='http://smalltalkthoughts.blogspot.com/2009/05/sandstonegoods.html' title='SandstoneGOODS'/><author><name>Niko</name><uri>http://www.blogger.com/profile/13371452869186247861</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_h7uHoQdb3pA/TKi5q5NNqnI/AAAAAAAABIU/0EMiDhus4dU/S220/IMG_1250.JPG'/></author><thr:total>6</thr:total></entry></feed>
