<?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'><id>tag:blogger.com,1999:blog-5098591171030974653</id><updated>2009-08-31T17:41:13.501-07:00</updated><title type='text'>slightly new, but it smacks of genius.</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-1013872298742093741</id><published>2009-08-31T17:18:00.000-07:00</published><updated>2009-08-31T17:41:13.691-07:00</updated><title type='text'>Manual CPSing in the database</title><content type='html'>I'm currently implementing text notes for &lt;a href="http://nodictionaries.com/"&gt;NoDictionaries&lt;/a&gt;.  You enter a really insightful comment, you need to log in to post your comment, so you log in and your comment is there.&lt;br /&gt;&lt;br /&gt;A pretty convenient way of going about is to have a hash table of closures, and store the continuation of the commit, continuation-passing style.&lt;br /&gt;&lt;br /&gt;However, it'd be better to persist data in the database.  (What happens if you restart the server?)&lt;br /&gt;&lt;br /&gt;Here's how committing a text note works in NoDictionaries: when you POST /add-note, you basically make the note , except the associated text word's id is the negative of the correct id, and the user id is whatever user id you have, whether a real database row or just the time in seconds of your first page view.  Then you're redirected to GET /commit-note, which makes sure you're logged in (and takes you on a round-trip to the login/signup if necessary), verifies the id of the note, the id of your user id, and the negativity of the text word id.  You can spoof it if you know the database id of an uncommited note, the database id of the word it's associated with, and the permanent or temporary user id that the person submitted it has, so you'd basically have to snoop on their wifi for that split second when they're filling out the login/signup form.&lt;br /&gt;&lt;br /&gt;It still feels like a kludge.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-1013872298742093741?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/1013872298742093741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=1013872298742093741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/1013872298742093741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/1013872298742093741'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2009/08/manual-cpsing-in-database.html' title='Manual CPSing in the database'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-2679639276094400921</id><published>2009-08-31T09:05:00.000-07:00</published><updated>2009-08-31T09:25:28.374-07:00</updated><title type='text'>DB indices</title><content type='html'>I think it'd be pretty nifty to get a daily summary of which indices would have been much handier to have: for example, snapshot my DB at 4am, record the day's GETs/POSTs/PUTs/DELETEs, index the hell out of my tables (creating 2^n indices for each combination of columns), give me statistics based on speed of completing a day's work, the IO and RAM required, and let me tweak the parameters, and then upgrade my box or add indices or whatever.&lt;br /&gt;&lt;br /&gt;(This is poorly thought out, but interesting nonetheless.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-2679639276094400921?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/2679639276094400921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=2679639276094400921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/2679639276094400921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/2679639276094400921'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2009/08/db-indices.html' title='DB indices'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-7198612634669688799</id><published>2009-05-27T07:43:00.000-07:00</published><updated>2009-05-27T18:11:17.076-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zlib'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='bzip'/><category scheme='http://www.blogger.com/atom/ns#' term='memcache-client'/><category scheme='http://www.blogger.com/atom/ns#' term='monkeypatching'/><category scheme='http://www.blogger.com/atom/ns#' term='dirty hacks'/><category scheme='http://www.blogger.com/atom/ns#' term='lzma'/><category scheme='http://www.blogger.com/atom/ns#' term='awesomely dirty hacks'/><category scheme='http://www.blogger.com/atom/ns#' term='compression'/><title type='text'>Ruby's memcache-client 1.7.2 does NOT support compression; patch it in with 7 lines of code</title><content type='html'>The Ruby memcache-client 1.7.2 code seems like the most popular memcached client.  Alas, &lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-style: italic; "&gt;&lt;a href="http://github.com/mperham/memcache-client/blob/1ab648c4444d92a4d2c8882004622a2ad08687cc/lib/memcache.rb#L103"&gt;memcache-client 1.7.2 does not recognize :compress =&gt; true&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;, &lt;a href="http://www.google.com/search?q=ruby+memcache-client+%22%3Acompression+%3D%3E+true%22"&gt;all the demos out there notwithstanding&lt;/a&gt;.&lt;div&gt;Let's fix this by monkeypatching Zlib compression into Marshal.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;br /&gt;require 'zlib'&lt;br /&gt;&lt;br /&gt;module Marshal&lt;br /&gt;  @@load_uc = method :load&lt;br /&gt;  @@dump_uc = method :dump&lt;br /&gt;  def self.load(v) @@load_uc[Zlib::Inflate.inflate(v)] end&lt;br /&gt;  def self.dump(v) Zlib::Deflate.deflate(@@dump_uc[v]) end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And there we go!  Four lines of patching Marshal.load for a better memory footprint.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To dissect each phrase of that sentence:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;"Four lines": I wanted just to try how well zlib would work on my Marshalled ActiveRecord objects and html fragments, and it did so handily, almost 3:1.  Indeed, the only reason I poked around at the source code is because one of my largest but still highly-compressible HTML fragments was 1.2MB, over the size limit.  I've since gone back to storing large HTML fragments on disk (uncompressed), having found many more values to store in Memcached.&lt;/li&gt;&lt;li&gt;"patching Marshal.load": monkeypatching Marshal is not as bad as String.  Chances are, you use the Marshal format as a blob, and you keep your Marshal files to yourself (and leave external serialization to friendlier fare like JSON).  So, all in all, it's much easier to change the Marshal format than mucking through the memcache-client code.&lt;/li&gt;&lt;li&gt;"better memory footprint": instead of Zlib, try LZMA, with slightly smaller compressed sizes than BZIP and faster decompression times, good properties for cache compression.  But Zlib is already in the standard library, so it's a good first approximation.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;The ersatz alias_method_chaining feels kludgy, as does Ruby's distinction between methods and lambdae.  Ah well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thoughts?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-7198612634669688799?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/7198612634669688799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=7198612634669688799' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/7198612634669688799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/7198612634669688799'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2009/05/rubys-memcache-client-172-does-not.html' title='Ruby&apos;s memcache-client 1.7.2 does NOT support compression; patch it in with 7 lines of code'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-7892634361222614135</id><published>2009-03-29T14:21:00.000-07:00</published><updated>2009-03-29T14:23:05.333-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='verité'/><category scheme='http://www.blogger.com/atom/ns#' term='picasso'/><category scheme='http://www.blogger.com/atom/ns#' term='bargains'/><category scheme='http://www.blogger.com/atom/ns#' term='turpentine'/><title type='text'>Reality</title><content type='html'>&lt;blockquote&gt;When art critics get together they talk about Form and Structure and Meaning. When artists get together they talk about where you can buy cheap turpentine. -- Picasso&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-7892634361222614135?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/7892634361222614135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=7892634361222614135' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/7892634361222614135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/7892634361222614135'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2009/03/reality.html' title='Reality'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-5662696445329819641</id><published>2009-02-24T09:38:00.000-08:00</published><updated>2009-02-24T14:51:26.273-08:00</updated><title type='text'>A Full Web Service with HTTP caching in 7 lines</title><content type='html'>Two lovely gems, sinatra and rack-cache.  Sinatra is pretty easy web-service-creation, and Rack::Cache is pretty easy http caching.  Together?  Jubilation.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'sinatra'&lt;br /&gt;require 'rack/cache'&lt;br /&gt;&lt;br /&gt;use Rack::Cache&lt;br /&gt;&lt;br /&gt;get('/quadruple/:n') {&lt;br /&gt;  sleep 1&lt;br /&gt;  response.headers['Cache-Control'] = 'max-age=1000000'&lt;br /&gt;  (params[:n].to_i * 4).to_s&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and then &lt;pre&gt;ruby sinatra-add.rb -e production&lt;/pre&gt; and you're done.&lt;br /&gt;&lt;br /&gt;There are, of course, many other fiddly bits to configure Rack::Cache with, like &lt;code&gt;use Rack::Cache, :entitystore =&gt; 'file:/tmp/'&lt;/code&gt; if you don't want to keep it all in a hash in memory, and &lt;code&gt;:verbose =&gt; false&lt;/code&gt; if you don't want that in your logs, but that's basically it.&lt;br /&gt;&lt;br /&gt;It's pretty amazing: that's a real live web service, with HTTP caching, in 7 gentle lines.  (I don't count the closing brace, nor the sleep 1, which is purely for effect.)&lt;br /&gt;&lt;br /&gt;Anyone know an easier way in any other language?  Either in number of lines, or in directness of code?&lt;br /&gt;&lt;br /&gt;Also, how bad would it be to authbind that to port 80, and just let it go open to the world?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Update: It's interesting to me for the same reason PHP is interesting, both as a social commentary on the bits of plumbing we've agreed upon as useful, and as an aid to wrapping an HTTP interface around some Ada code with its own homegrown database.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-5662696445329819641?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/5662696445329819641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=5662696445329819641' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5662696445329819641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5662696445329819641'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2009/02/full-web-service-with-http-caching-in-7.html' title='A Full Web Service with HTTP caching in 7 lines'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-890170100843611887</id><published>2007-12-01T15:18:00.000-08:00</published><updated>2007-12-02T11:49:49.187-08:00</updated><title type='text'>Top five contradictory positions of Ron Paul Graham.</title><content type='html'>1.  &lt;a href="http://en.wikipedia.org/wiki/Political_positions_of_Ron_Paul#Secure_borders_and_legal_immigration"&gt;Supports secure borders&lt;/a&gt;, but &lt;a href="http://www.bookshelf.jp/texi/onlisp/onlisp_15.html"&gt;writes macros for variable capture&lt;/a&gt;.&lt;br /&gt;2.  &lt;a href="http://en.wikipedia.org/wiki/Political_positions_of_Ron_Paul#Rejection_of_conspiracy_theory"&gt;Rejects conspiracy theories of 9/11&lt;/a&gt;, but funded &lt;a href="http://reddit.com/"&gt;a social news website&lt;/a&gt; &lt;a href="http://google.com/search?q=9%2F11+conspiracy+theory+site%3Areddit.com"&gt;full of 9/11 conspiracy theories&lt;/a&gt;.&lt;br /&gt;3. &lt;a href="http://ronpaulblimp.com/"&gt;Will launch an ad blimp in two weeks&lt;/a&gt;, but &lt;a href="http://paulgraham.com/submarine.html"&gt;remains cynical about submarine-style PR campaigns&lt;/a&gt;.&lt;br /&gt;4.  &lt;a href="http://en.wikipedia.org/wiki/Ron_Paul#Internet_popularity"&gt;Says he doesn't organize his supporters on the internet&lt;/a&gt;, but &lt;a href="http://google.com/search?q=ask+pg+site%3Anews.ycombinator.com"&gt;provides a Q&amp;amp;A internet forum&lt;/a&gt;.&lt;br /&gt;5.  &lt;a href="http://en.wikipedia.org/wiki/Political_positions_of_Ron_Paul#Opposition_to_inflation_and_the_Federal_Reserve"&gt;Opposes inflation&lt;/a&gt;, but &lt;a href="http://www.paulgraham.com/accgen.html"&gt;supports accumulator generators&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Leave more in the comments...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-890170100843611887?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/890170100843611887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=890170100843611887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/890170100843611887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/890170100843611887'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/12/top-five-contradictory-positions-of-ron.html' title='Top five contradictory positions of Ron Paul Graham.'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-5769308924652937529</id><published>2007-11-24T16:23:00.000-08:00</published><updated>2007-11-24T17:41:43.115-08:00</updated><title type='text'>Anti-Features?, or, Never attribute to malice what can be explained by math.</title><content type='html'>Apparently, if you buy a cheap camera, and you can't save an uncompressed picture, that's treacherous computing, that's an &lt;a href="http://www.fsf.org/blogs/community/antifeatures"&gt;anti-feature&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It's not.  The camera won't stop working if you correctly patch in a different chip set.&lt;br /&gt;&lt;br /&gt;And assuming the worst, assuming that the chips are exactly the same in an expensive camera, it still doesn't matter.  The native resolution is still small on the cheap camera--that's mostly what makes it cheap--so you'll be better off buying the high-resolution expensive camera.&lt;br /&gt;&lt;br /&gt;Of course, if you really want a camera that you can program, you might like &lt;a href="http://gizmodo.com/gadgets/hack-attack/xo-laptop-hacked-to-remotely-run-roomba-round-rooms-322343.php"&gt;an XO that drives a Roomba&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-5769308924652937529?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/5769308924652937529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=5769308924652937529' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5769308924652937529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5769308924652937529'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/11/anti-features-or-never-attribute-to.html' title='Anti-Features?, or, Never attribute to malice what can be explained by math.'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-86675774648474401</id><published>2007-06-06T19:42:00.000-07:00</published><updated>2007-06-07T11:36:42.371-07:00</updated><title type='text'>cheap illustrations.</title><content type='html'>I'm a cheap nerd, so I printed myself an enormous wall decoration last August 2006:  it's Pi, in a textual fractal.  (&lt;a href="http://poetaexmachina.net/pi2.gif"&gt;This&lt;/a&gt; is it to two levels, and the one in my room is to five.)  3'x5', $10 from Kinko's.  Nice conversation piece.&lt;br /&gt;&lt;br /&gt;I've been &lt;a href="http://poetaexmachina.net/books"&gt;printing&lt;/a&gt; more things recently, I've been thinking about combining text and images, and an &lt;a href="http://bestlatin.net/"&gt;author&lt;/a&gt; of &lt;a href="http://www.lulu.com/content/370912"&gt;two&lt;/a&gt; &lt;a href="http://www.lulu.com/content/431684"&gt;books&lt;/a&gt; on classical themes bemoaned the expensiveness of art in an email today.  (Illustrating an book on Aesop's Fables, specifically.)&lt;br /&gt;&lt;br /&gt;Most art schools have &lt;a href="http://intranet.risd.edu/departments/workstudy/search/default.asp"&gt;job boards&lt;/a&gt;; the artists can be of varying qualities, but sketches in pen are quick to do, and hard to do badly.  (Lots of approximate lines.)  Twenty seconds a sketch, which is a not-too-fast speed, scan one as you're doing the next one, and you've got a hundred in an hour.&lt;br /&gt;&lt;br /&gt;Has anyone used Flickr for (cc)by-sa images?  I wonder if that's cheaper.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-86675774648474401?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/86675774648474401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=86675774648474401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/86675774648474401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/86675774648474401'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/06/cheap-illustrations.html' title='cheap illustrations.'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-1578356783587769465</id><published>2007-05-21T06:46:00.000-07:00</published><updated>2007-05-21T07:07:40.703-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='amazingly bad apis'/><category scheme='http://www.blogger.com/atom/ns#' term='pontification'/><category scheme='http://www.blogger.com/atom/ns#' term='amazingly good small pieces loosely joined'/><category scheme='http://www.blogger.com/atom/ns#' term='metamorphoses'/><title type='text'>Amazingly bad APIs?</title><content type='html'>There are some &lt;a href="http://paulbuchheit.blogspot.com/2007/05/amazingly-bad-apis.html"&gt;amazingly bad APIs in Java&lt;/a&gt;, so Paul Buchheit says.  The best API is system(), or backticks.&lt;br /&gt;&lt;br /&gt;The end result is basically an ImageMagick conversion (kudos to a &lt;a href="http://linear1.org/gm/archives/00000162.php"&gt;useful incantation&lt;/a&gt; for the less than sign):&lt;br /&gt;&lt;br /&gt;mogrify -geometry "220x133&gt;" -antialias -quality 90 /tmp/c.jpg /tmp/c-thumb.jpg&lt;br /&gt;&lt;br /&gt;You wouldn't write an encyclopedia in limericks (though &lt;a href="http://en.wikipedia.org/wiki/Metamorphoses"&gt;it's been done before&lt;/a&gt;), so there's no need to use a general purpose programming language to manipulate images.  Small Pieces Loosely Joined is pretty popular for Unix, CGI/REST, Erlang, Messenger RNA, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-1578356783587769465?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/1578356783587769465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=1578356783587769465' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/1578356783587769465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/1578356783587769465'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/05/amazingly-bad-apis.html' title='Amazingly bad APIs?'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-5789871590573052195</id><published>2007-05-02T17:31:00.000-07:00</published><updated>2007-05-02T18:03:48.125-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='drm'/><category scheme='http://www.blogger.com/atom/ns#' term='09 something something c0'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>microsoft knows drm.</title><content type='html'>&lt;span style="font-family: lucida grande;"&gt;I've been hearing a lot about this string of hexadecimal numbers.  It starts with 09, ends with c0, and I think it has f9 and 88 somewhere inside.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: lucida grande;"&gt;Let's ask Microsoft search what it is!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: lucida grande;"&gt;require('open-uri') &amp;&amp;amp; puts(open('http://search.msn.com/results.aspx?q=09+f9+88+c0') {|f| f.read}.downcase.gsub(/&lt;[^&gt;]+&gt;/,'').tr('^0-9a-f','').scan(/09.+?c0/).inject(Hash.new(0)) {|h,nu| h[nu]+=1;h}.sort_by {|str,freq| freq}.last.first&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: lucida grande;"&gt;Whew!&lt;br /&gt;&lt;br /&gt;For non-Rubyists:&lt;/span&gt;&lt;span style="font-family: lucida grande;"&gt; require we can open urls like files, and put this string:  open the msn search page for all pages that have 09, f9, 88, and c0, read it in one gulp into lowercase, regexp out all html tags, translate out any character that's not a hex digit, scan for all substrings that start with 09 and end with c0, make a histogram* of the array, sort by most popular, and take the most popular string.&lt;br /&gt;(* Inject a hash table through the array of scanned substrings; the strings are the keys, the frequencies are the values; add one to the value every time you see any string, starting at zero.)&lt;br /&gt;&lt;br /&gt;Remember folks, this is Microsoft's suggested answer to the &lt;a href="http://weblog.raganwald.com/2007/05/128-bit-programming-challenge.html"&gt;128-bit programming challenge&lt;/a&gt;&lt;/span&gt;&lt;a href="http://weblog.raganwald.com/2007/05/128-bit-programming-challenge.html"&gt;&lt;span style="font-family: lucida grande;"&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: lucida grande;"&gt; posed earlier today, so like love, and Cambridge weather, it's just temporary.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-5789871590573052195?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/5789871590573052195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=5789871590573052195' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5789871590573052195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5789871590573052195'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/05/microsoft-knows-drm.html' title='microsoft knows drm.'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-2807520186048915414</id><published>2007-04-26T08:42:00.000-07:00</published><updated>2007-04-26T08:47:30.500-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='urls'/><category scheme='http://www.blogger.com/atom/ns#' term='fark'/><category scheme='http://www.blogger.com/atom/ns#' term='tinyurl'/><category scheme='http://www.blogger.com/atom/ns#' term='copyrights'/><title type='text'>fark is grabbing copyrights?</title><content type='html'>&lt;span style="font-family: lucida grande;"&gt;Some would think so.  But if you read really closely, you're not submitting anything meaningful, you're submitting a web link.  And if they want the copyright of that web link, then, ok, TinyURL it.  They'll have the copyright to a TinyURL uid.  And the copyright to any images on the page stay where they were.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: lucida grande;"&gt;Pretty simple.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-2807520186048915414?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/2807520186048915414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=2807520186048915414' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/2807520186048915414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/2807520186048915414'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/04/fark-is-grabbing-copyrights.html' title='fark is grabbing copyrights?'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-1320965996795289445</id><published>2007-04-08T16:28:00.000-07:00</published><updated>2007-04-08T16:54:46.164-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='faux currying'/><category scheme='http://www.blogger.com/atom/ns#' term='hash tableaux'/><category scheme='http://www.blogger.com/atom/ns#' term='katastrophe'/><category scheme='http://www.blogger.com/atom/ns#' term='irb'/><title type='text'>kata 6.</title><content type='html'>prag dave's &lt;a href="http://codekata.pragprog.com/2007/01/kata_six_anagra.html"&gt;anagrams&lt;/a&gt; resonated with me, because i'm working on hashing text down.&lt;br /&gt;&lt;br /&gt;so follow along in irb, if you have /usr/share/dict/words:&lt;br /&gt;&lt;br /&gt;class Symbol&lt;br /&gt;  def to_proc(*args) lambda {|*a| a.first.send self, *(args+a[1..-1])} end&lt;br /&gt;  alias [] to_proc&lt;br /&gt;end  # for faux currying&lt;br /&gt;&lt;br /&gt;w = File.readlines('/usr/share/dict/words').map {|w| w.strip.downcase}.uniq ;:done&lt;br /&gt;h = Hash.new([])&lt;br /&gt;w.each {|word| nu = word.split('').sort.join; h[nu]+=[word]} ;:done&lt;br /&gt;anas = h.values.find_all {|v| v.size &gt; 1} ;:done&lt;br /&gt;puts anas.map(&amp;:join[',']) # all anagram n-tuples&lt;br /&gt;puts "---"&lt;br /&gt;puts anas.sort_by(&amp;amp;:size)[-30..-1].map(&amp;:join[',']) # the top by set size&lt;br /&gt;puts "---"&lt;br /&gt;puts anas.sort_by {|a| a.first.size}[-30..-1].map(&amp;amp;:join[',']) # the top by word size&lt;br /&gt;&lt;br /&gt;in fairness, the symbol-currying is in "sym2proc.r", so it's really just 10 lines of code, but that's the general idea.&lt;br /&gt;(lots of the library functions look haskelly, but ruby just felt better for string processing)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-1320965996795289445?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/1320965996795289445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=1320965996795289445' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/1320965996795289445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/1320965996795289445'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/04/kata-6.html' title='kata 6.'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-3456408758717909787</id><published>2007-03-08T15:41:00.000-08:00</published><updated>2007-03-09T02:25:05.307-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='de usu fructuque lingarum'/><category scheme='http://www.blogger.com/atom/ns#' term='sussman'/><category scheme='http://www.blogger.com/atom/ns#' term='json'/><category scheme='http://www.blogger.com/atom/ns#' term='eval'/><title type='text'>eval is amazing.</title><content type='html'>&lt;span style="font-family:lucida grande;"&gt;In terms of things, eval is much bigger than JSON callbacks, even bigger than Lisp itself.  It's big like the ribosome --- eval is how things come alive.&lt;br /&gt;&lt;br /&gt;For example, I'm rendering urls and associated metadata in the browser from a ruby cgi script.  Instead of some big XML specification, I'm just passing an array of strings from server to client.  It's &lt;span style="font-style: italic;"&gt;big_array&lt;/span&gt;.inspect in Ruby, and eval(&lt;span style="font-style: italic;"&gt;inspectedBigArray&lt;/span&gt;) in Javascript. No monadic parsers, no macro magic; inspect and eval, code I don't even have to write myself.  (And if the  inspected big array is too big, the browser can start lysis; so it goes.)&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:lucida grande;"&gt;&lt;br /&gt;G J Sussman: Programming is a good medium for expressing poorly-understood and sloppily-formulated ideas: exactly the opposite of people who'd want to plague me with type theory.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-3456408758717909787?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/3456408758717909787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=3456408758717909787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/3456408758717909787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/3456408758717909787'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/03/eval-is-amazing.html' title='eval is amazing.'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5098591171030974653.post-5630717285948719973</id><published>2007-02-23T06:16:00.000-08:00</published><updated>2007-02-23T06:27:09.420-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='poesie'/><category scheme='http://www.blogger.com/atom/ns#' term='nyc'/><category scheme='http://www.blogger.com/atom/ns#' term='de origine nominis'/><title type='text'>origins</title><content type='html'>&lt;span style="font-family: lucida grande;"&gt;Some people call it disclaimers, some call it biscuiting, some youthful naïveté.  When I was 16, my &lt;a href="http://www.janestreet.com/"&gt;poetry teacher&lt;/a&gt; had told us that the only unwritten preface we were allowed to give to any piece was "It's slightly new, but it smacks of genius."&lt;/span&gt;&lt;a href="http://janestreet.com"&gt;&lt;span style="font-family: lucida grande;"&gt;&lt;/span&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5098591171030974653-5630717285948719973?l=slightlynew.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://slightlynew.blogspot.com/feeds/5630717285948719973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5098591171030974653&amp;postID=5630717285948719973' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5630717285948719973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5098591171030974653/posts/default/5630717285948719973'/><link rel='alternate' type='text/html' href='http://slightlynew.blogspot.com/2007/02/origins.html' title='origins'/><author><name>lee</name><uri>http://www.blogger.com/profile/16737006640455843661</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08113613678551726480'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>