{ |one, step, back| } http://onestepback.org/index.cgi Jim Weirich's Blog en-us { |one, step, back| } http://onestepback.org http://onestepback.org/images/jwface.gif How did you get started in software development. http://onestepback.org/index.cgi/Tech/Programming/SoftwareDevelSteps.red <h2>Tagged</h2> <p>Looks like <a href="http://objo.com/2008/6/7/how-did-you-get-started-in-programming">Joe O&#8217;Brien</a> tagged me for answers to the following questions. He, in turn, was tagged by <a href="http://joshholmes.com/">Josh Owens</a>, who in turn was tagged by <a href="http://www.jeffblankenburg.com/index.html">Jeff Blankenburg</a>. It looks like <a href="http://www.codinggeekette.com">Sarah Dutkiewicz</a> and <a href="http://michaeleatonconsulting.com/blog/archive/2008/06/04/how-did-you-get-started-in-software-development.aspx">Micheal Eaton</a> started this.</p> <p>OK, sounds like fun. Here goes.</p> <h2>How old were you when you started programming?</h2> <p>I was introduced to programming in high school by reading a book on the topic. The book taught me how to write machine code for a strange decimal-based machine. Unfortunately, there was no actual computer involved in the process. Shoot, who had computers back then? Certainly not our high school (the personal computers? not invented yet!)</p> <p>In college, I learned a smattering of <span class="caps">FORTRAN</span>. Just enough to drive a Calcomp plotter to plot data from my undergraduate physics courses. But didn&#8217;t really get into programming until my junior year in college. (Story continued in next question)</p> <h2>How did you get started in programming?</h2> <p>So, I was planning out the courses for my junior year in college and I had a hole in my math courses. The math class I needed was not offered that semester, so my adviser suggested taking a computer programming course. He said it would be useful and, who knows, I might enjoy it.</p> <p>So I signed up for an introduction to <span class="caps">FORTRAN</span> course, figuring it would be easy because I already knew a little bit of <span class="caps">FORTRAN</span>. I show up on the first day of class and after a few preliminaries the instructor jumps right into some code, that looked like this:</p> <pre><code>(de member (pip deck) (cond ((null deck) nil) ((eq pip (car deck)) t) (t (member pip (cdr deck)))))</code></pre> <p>I remember scratching my head and thinking this was the strangest <span class="caps">FORTRAN I</span> had ever seen. I was totally confused for about three days, then something clicked on the third day of class. I suddenly &#8220;<em>got</em>&#8221; what the instructor was trying to get across and it all made perfect sense.</p> <p>If you haven&#8217;t figured it out yet, the instructor taught us Lisp as part of an introduction to <span class="caps">FORTRAN</span>. The instructor turned out to be Daniel Friedman, the author of <a href="http://www.amazon.com/Little-LISPer-Third-Daniel-Friedman/dp/0023397632"><em>The Little Lisper</em></a>, and was well known in the Lisp community. That small exposure to Lisp hooked me on programming from that point on. I took as many CompSci courses as I could in my remaining year and a half in college. I eventually graudated with a BS in Physics, but had a strong background in Computer Science as well.</p> <h2>What was your first language?</h2> <p>Technically, <span class="caps">FORTRAN</span> was my first language. But Lisp is the language I fell in love with and is what got me hooked on programming.</p> <h2>What was the first real program you wrote?</h2> <p>I have a very clear memory of the very first program I wrote professionally. The reason it is so clear is that this was the first program I wrote that was intended for actual use by someone who wanted it. Everything else up to that time was done for my own personal enjoyment or to satisfy some course requirement.</p> <p>The program calculated the &#8220;critical angles&#8221; of &#8220;pieces&#8221;. I was given the requirements by Anne Exline, a senior programmer, and proceeded to write the program to spec. It took a few days, but when I was done I showed the result to Anne and she was pleased with the result.</p> <p>The funny thing is that I had no idea what a &#8220;piece&#8221; was nor what was so critical about the angles I was calculating. I was so excited about writing an actual program that I did not ask until the software was done. When asked, Anne just looked at me funny and said &#8220;Rocket Pieces&#8221;. When Cape Canaveral lauches a rocket, they track it very carefully to make sure it stays on course. If it strays, the range safety officer is required to activate the self destruct. The critical angles are those angles that would cause the &#8220;rocket pieces&#8221; to land outside the safety area of the flight path.</p> <p>So, my very first professional program was not only useful, it might actually save lives.</p> <h2>What languages have you used since you started programming?</h2> <p>Languages I have used as part of my professional career (in roughly chronological order) include <span class="caps">FORTRAN</span>, various assembly languages, <span class="caps">FORTH</span>, C, PL/M, C++, Java, Ruby.</p> <p>Languages I have used in addition to those mentioned above: Pascal, Perl, Eiffel, and Lisp/Scheme.</p> <p>Languages I can read, but never wrote anything significant in them: Ada, Python, Erlang, Smalltalk, <span class="caps">SNOBOL</span>, Algol, Pascal.</p> <h2>What was your first professional programming gig?</h2> <p>I was hired by the <span class="caps">RCA</span> Missile Test project in Cape Canaveral, Florida as a Near Real Time Analyst. Duties included programming various launch related software (e.g. the critical angle program mentioned above) and working launch support.</p> <p>The launch support was the &#8220;Near Real Time&#8221; part of the job description. From the moment a rocket is launched until it reaches orbital velocity, any malfunction could cause it to fall back to earth. During this initial portion of the launch, the launch is monitored in &#8220;real-time&#8221; so that we know exactly where it would land if the engines were to cut off <span class="caps">NOW</span>. Trajectory calculations had to be done in fractions of a second and updated constantly in real time.</p> <p>After the rocket reaches oribital velocity (usually somewhere between 8 and 14 minutes into its flight), it won&#8217;t fall back to earth. At this point the real time trajectory program is shut down and the near real time program is started. The near real time program can take a few minutes to calculate a more exact orbital prediction and then send that prediction to downrange radars (e.g. the the <a href="http://en.wikipedia.org/wiki/Ascension_Island">Ascension Island</a> station) that won&#8217;t see the rocket until about 20 minutes after launch. It was the job of the Near Real Time analyst to run that program and provide oribital predictions for downrange station.</p> <h2>If there is one thing you learned along the way that you would tell new developers, what would it be?</h2> <p>Find something that you enjoy and do that. Life is too short to work in a job that you dislike.</p> <h2>What’s the most fun you’ve ever had … programming?</h2> <p>Oh, the fun I have had. This story still makes me smile.</p> <p>My first computer was a single board <span class="caps">Z80</span> microcomputer with 4 KB of memory. I wrote a small <span class="caps">FORTH</span>-like interpreter for it and hacked a version of the animal game in <span class="caps">FORTH</span>. The animal game is a program that plays 20 questions to figure out what animal you are thinking of. It constructs a binary tree where each node is a question and the subtrees are the yes and no answers to the question. To play the game, all the program does is walk the tree, ask the question at the current node and follow either the <span class="caps">YES</span> branch or the NO branch as appropriate.</p> <p>If the program guesses wrong, it will ask you for your animal and a question that will distinguish your animal from the one it guessed. It then adds your question to the tree. By this extremely simple mechanism, it is able to expand its knowledge base. (see <a href="http://www.rubyquiz.com/quiz15.html">Ruby Quiz #15</a> for more details).</p> <p>I had just finished the program and had seeded it with a single animal, a mouse. I turned to my wife and asked her to play the game. She thinks of an animal and starts the program, which immediately asked her &#8220;Is it a mouse?&#8221;. She turned to me with surprise and said &#8220;How did it know?&#8221;. Of course, the animal she picked was a mouse.</p> <p>I don&#8217;t think I have ever impressed anyone with my programming skills as much as she was impressed with that game.</p> <h2>Who&#8217;s up next?</h2> <p>I&#8217;m tagging the following people. Remember, this is entirely voluntary so don&#8217;t feel obligated to answer. But I&#8217;m betting the answers are interesting:</p> <ul> <li><a href="http://mysterycoder.blogspot.com/">Chris Nelson</a></li> <li><a href="http://clarkware.com/cgi/blosxom">Mike Clark</a></li> <li><a href="http://gilesbowkett.blogspot.com/">Giles Bowkett</a></li> <li><a href="http://railsstudio.com/">Mark Windholtz</a></li> <li><a href="http://www.vanderburg.org/Blog">Glenn Vanderburg</a></li> </ul> Rails Conf 2008 Summary http://onestepback.org/index.cgi/Tech/Conferences/RailsConf2008/RailsConf2008Summary.red <h2>Conference Summary Video</h2> <p>Wow, what a great conference! There was a lot of energy flowing at RailsConf this year. Overall I&#8217;d rate this year as head and shoulders above last year. I&#8217;m not going cover much here, but will direct you attention to a <a href="http://www.railsenvy.com/2008/6/2/Railsconf-videos">Rails Envy VideoCase</a> that Greg Pollack put together. The video is a series of very short interviews with a number of presenters giving summaries of their own talks. The only downside with the video is that I wish it was available <em>before</em> the conference. I see there were a number of interesting talks that I missed.</p> <h2>Followup on the &#8220;Modelling Dialogue&#8221;</h2> <p>Joe O&#8217;Brien, Chris Nelson and myself did a dialogue style presentation on the difference between object modelling and data modelling. The most common question I got after the talk was requests for book titles to learn more about object oriented modelling. Here are the books that Joe, Chris and I have recommended:</p> <ul> <li><em><a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_bbs_sr_1?ie=UTF8&#38;s=books&#38;qid=1212463473&#38;sr=1-1">Domain Driven Design</a></em>&#8212;Eric Evans</li> <li><em><a href="http://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445/ref=sr_1_1?ie=UTF8&#38;s=books&#38;qid=1212502027&#38;sr=1-1">AgileSoftware Development, Principles, Patterns, and Practices</a></em>&#8212;Bob Martin</li> <li><em><a href="http://www.amazon.com/Refactoring-Improving-Existing-Addison-Wesley-Technology/dp/0201485672/ref=pd_bbs_sr_1?ie=UTF8&#38;s=books&#38;qid=1212465268&#38;sr=1-1">Refactoring: Improving the Design of Existing Code</a></em>&#8212;Martin Fowler</li> </ul> Artichoke Music Rocks http://onestepback.org/index.cgi/Tech/Conferences/RailsConf2008/ArtichokeMusic.red <p style="float: right; padding: 0.5em;"><a href="http://www.artichokemusic.com/index2.htm"><img border="0" src="http://www.artichokemusic.com/LogocommUnity-sm.jpg"/></a></p> <p>The Musician&#8217;s Birds of a Feather gathering at RailsConf was great. We had a room full people, two guitars, a ukulele, a flute, several harmonicas and an improvised drum set. Unfortunately, one of the guitars was an electric travel guitar which had a dead battery, therefore no way to really hear it.</p> <p>However, the other guitar was a nice Epiphone accoustic which was passed from player to player. It became the quickly became the basis for most of the music performed that night.</p> <p>I want to thank <a href="http://www.artichokemusic.com/index2.htm">Artichoke Community Music</a> for supplying the guitar. Travelling with a guitar by plane is a big pain, so I arrived with nothing to bring to the music <span class="caps">BOF</span>. I called several local music stores looking for a guitar that I could rent for an evening. Artichoke music said they had a &#8220;not-for-profit&#8221; guitar that they would let me borrow for a day. Not many stores would do that for an out-of-town stranger.</p> <p>So, if you&#8217;re in Portland looking for a good guitar store, check out the great people at <a href="http://www.artichokemusic.com/index2.htm">Artichoke Community Music</a>.</p> Test Driven Studio in June 2008 http://onestepback.org/index.cgi/Tech/Conferences/TestingInRails/TddStudioJune2008.red <p><em>Joe O&#8217;Brien and I will be leading another Test Driven Studio in Denver, June 9-11.</em></p> <p style="float: right; padding: 0.5em;"><a href="http://pragmaticstudio.com/images/studio/tdd-with-rails-icon.jpg"><img border="0" src="http://onestepback.org/images/pragstudio/studio-medium.gif"/></a></p> <h2>Testing, Colorado, June &#8230; What&#8217;s not to like?</h2> <p>About 8 years ago I come upon a technique that radically changed the way I developed code. I was reading Martin Fowler&#8217;s &#8220;Refactoring&#8221; book and came across this paragraph:</p> <p style="padding-left:3em;"><em>&#8220;Whenever I do refactoring, the first step is always the same. I need to build a solid set of tests for that section of code. The test are essential because even though I follow refactorings structured to avoid most of the opportunities for introducing bugs, I&#8217;m still human and still make mistakes. Thus I need solid tests.&#8221; </em>&#8212;Martin Fowler</p> <p>Chapter 4 of &#8220;Refactoring&#8221; was my first introduction to JUnit and got me interested in &#8220;Test First Design&#8221; (what we now tend to call &#8220;Test Driven Development&#8221;). Although I wrote <em>good</em> code before, the confidence I had in my code took a dramatic leap forward after I started adopting <span class="caps">TDD</span> practices.</p> <p>On June 9 through 11, <a href="http://objo.com">Joe O&#8217;Brien</a> and I will have the pleasure of leading the next Pragmatic Programmer&#8217;s <a href="http://pragmaticstudio.com/testing-rails">Test-Driven Development with Rails Studio.</a> in Denver. We will have an opportunity to share with you some of our experiences in using <span class="caps">TDD</span> with Ruby and Rails.</p> <p>There are still seats available, so its not too late to sign up. More information is available <a href="http://pragmaticstudio.com/testing-rails">here</a>.</p> Lisp in Ruby http://onestepback.org/index.cgi/Tech/Ruby/LispInRuby.red <p style="padding-left:3em;"><em>I stumbled across <a href="http://bc.tech.coop/blog/080101.html">this</a> and it got me thinking &#8230;</em></p> <h3>Update</h3> <p style="padding-left:3em;"><em>I&#8217;ve updated the Textile formatter on the site and the code for this entry is now displaying correctly. The previous version was swalling the == operators in the code.</em></p> <h2>Lisp 1.5 Programmer&#8217;s Manual</h2> <p>I stumbled across <a href="http://bc.tech.coop/blog/080101.html">this</a> in Bill Clementson&#8217;s blog and remembered using the Lisp 1.5 Prgrammers manual from the college years. I have strong memories of pouring over that particular page in the manual and attempting to understand all the nuances.</p> <p>If you&#8217;ve never read the Lisp 1.5 Programamers Manual, page 13 is the guts of a Lisp Interpreter, the &#8220;eval&#8221; and &#8220;apply&#8221; functions. It is written in Lisp, although the notation used is a bit funky. The entire interpreter (minus two utility functions) is presented on a single page of the book. Talk about a concise language definition!</p> <h2>In Ruby?</h2> <p>I had often thought about implementing a Lisp interpreter, but back in the &#8220;old days&#8221;, the thought of implementing garbage collection and the whole runtime thing was a bit daunting. This was in the day before C, so my implementation language would have been assembler &#8230; yech.</p> <p>But as I was reviewing the page, I realized that with today&#8217;s modern languages, I could problably just convert the funky M-Expressions used on page 13 directly into code. So &#8230; why not?</p> <h2>The Code</h2> <p>Here is the complete Ruby source code for the Lisp interpreter from page 13 of the Lisp Programmers manual:</p> <pre> # Kernel Extensions to support Lisp class Object def lisp_string to_s end end class NilClass def lisp_string "nil" end end class Array # Convert an Array into an S-expression (i.e. linked list). # Subarrays are converted as well. def sexp result = nil reverse.each do |item| item = item.sexp if item.respond_to?(:sexp) result = cons(item, result) end result end end # The Basic Lisp Cons cell data structures. Cons cells consist of a # head and a tail. class Cons attr_reader :head, :tail def initialize(head, tail) @head, @tail = head, tail end def ==(other) return false unless other.class == Cons return true if self.object_id == other.object_id return car(self) == car(other) &#38;&#38; cdr(self) == cdr(other) end # Convert the lisp expression to a string. def lisp_string e = self result = "(" while e if e.class != Cons result &lt;&lt; ". " &lt;&lt; e.lisp_string e = nil else result &lt;&lt; car(e).lisp_string e = cdr(e) result &lt;&lt; " " if e end end result &lt;&lt; ")" result end end # Lisp Primitive Functions. # It is an atom if it is not a cons cell. def atom?(a) a.class != Cons end # Get the head of a list. def car(e) e.head end # Get the tail of a list. def cdr(e) e.tail end # Construct a new list from a head and a tail. def cons(h,t) Cons.new(h,t) end # Here is the guts of the Lisp interpreter. Apply and eval work # together to interpret the S-expression. These definitions are taken # directly from page 13 of the Lisp 1.5 Programmer's Manual. def apply(fn, x, a) if atom?(fn) case fn when :car then caar(x) when :cdr then cdar(x) when :cons then cons(car(x), cadr(x)) when :atom then atom?(car(x)) when :eq then car(x) == cadr(x) else apply(eval(fn,a), x, a) end elsif car(fn) == :lambda eval(caddr(fn), pairlis(cadr(fn), x, a)) elsif car(fn) == :label apply(caddr(fn), x, cons(cons(cadr(fn), caddr(fn)), a)) end end def eval(e,a) if atom?(e) cdr(assoc(e,a)) elsif atom?(car(e)) if car(e) == :quote cadr(e) elsif car(e) == :cond evcon(cdr(e),a) else apply(car(e), evlis(cdr(e), a), a) end else apply(car(e), evlis(cdr(e), a), a) end end # And now some utility functions used by apply and eval. These are # also given in the Lisp 1.5 Programmer's Manual. def evcon(c,a) if eval(caar(c), a) eval(cadar(c), a) else evcon(cdr(c), a) end end def evlis(m, a) if m.nil? nil else cons(eval(car(m),a), evlis(cdr(m), a)) end end def assoc(a, e) if e.nil? fail "#{a.inspect} not bound" elsif a == caar(e) car(e) else assoc(a, cdr(e)) end end def pairlis(vars, vals, a) while vars &#38;&#38; vals a = cons(cons(car(vars), car(vals)), a) vars = cdr(vars) vals = cdr(vals) end a end # Handy lisp utility functions built on car and cdr. def caar(e) car(car(e)) end def cadr(e) car(cdr(e)) end def caddr(e) car(cdr(cdr(e))) end def cdar(e) cdr(car(e)) end def cadar(e) car(cdr(car(e))) end </pre> <h2>An Example</h2> <p>And to prove it, here&#8217;s an example program using Lisp. I didn&#8217;t bother to write a Lisp parser, so I need to express the lists in standard Ruby Array notation (which is converted to a linked list via the &#8220;sexp&#8221; method).</p> <p>Here&#8217;s the ruby program using the lisp interpreter. The Lisp system is very primitive. The only way to define the function needed is to put them in the environment structure, which is simply an association list of keys and values.</p> <pre> require 'lisp' # Create an environment where the reverse, rev_shift and null # functions are bound to an appropriate identifier. env = [ cons(:rev_shift, [:lambda, [:list, :result], [:cond, [[:null, :list], :result], [:t, [:rev_shift, [:cdr, :list], [:cons, [:car, :list], :result]]]]].sexp), cons(:reverse, [:lambda, [:list], [:rev_shift, :list, nil]].sexp), cons(:null, [:lambda, [:e], [:eq, :e, nil]].sexp), cons(:t, true), cons(nil, nil) ].sexp # Evaluate an S-Expression and print the result exp = [:reverse, [:quote, [:a, :b, :c, :d, :e]]].sexp puts "EVAL: #{exp.lisp_string}" puts " =&gt; #{eval(exp,env).lisp_string}" </pre> <p>The program will print:</p> <pre><code>$ ruby reverse.rb EVAL: (reverse (quote (a b c d e))) =&gt; (e d c b a)</code></pre> <p>All I need to do is write a Lisp parser and a <span class="caps">REPL</span>, and I&#8217;m in business!</p> <h2>The Example in Standard Lisp Notation</h2> <p>If you found the Ruby-ized Lisp code hard to read, here is the reverse funtions written in a more Lisp-like manner.</p> <pre> (defun reverse (list) (rev-shift list nil)) (defun rev-shift (list result) (cond ((null list) result) (t (rev-shift (cdr list) (cons (car list) result))) )) </pre> Presenting Code ... An Update http://onestepback.org/index.cgi/General/PresentingCodeUpdate.red <p style="padding-left:3em;"><em>I received some feedback on the &#8216;Presenting Code&#8217; post from yesterday.</em></p> <h2>Presenting Code &#8230; An Update</h2> <p>I got lots of feedback on the &#8220;Presenting Code&#8221; post. In addition to <a href="http://beust.com/weblog">Cédric Beust&#8217;s</a> initial comments, the following people had something to say on the topic:</p> <p><a href="http://johnwilger.com/">John Wilger</a> asked on Twitter why I didn&#8217;t use &#8220;file:&#8221; (rather than &#8220;http:&#8221; and a local web server). Unfortunately, Keynote will not do a web view from a &#8220;file:&#8221; style <span class="caps">URL</span>.</p> <p><a href="http://www.madstop.com/">Luke Kanies</a> reports that he does something similar. He uses Vim (rather than Ruby + the Syntax gem) to generate the highlighted <span class="caps">HTML</span>. He also adds:</p> <blockquote> <p><em>In general, this method works out great, but the one thing I would say is that you should <strong>always</strong> uncheck &#8220;automatic update&#8221;. Otherwise, you&#8217;ll find that it tries to update 10 seconds before your presentation starts and your web server isn&#8217;t available.</em></p> </blockquote> <p>Ok, that&#8217;s good advice. <span class="caps">BTW</span>, I would be very interested in a script (AppleScript or Ruby+OSA) that would iterate over the pages in a Keynote presentation and refresh all the WebViews. Any takers?</p> <p><a href="http://blog.grayproductions.net/">James Edward Gray II</a> and <a href="http://www.clarkware.com">Mike Clark</a> mentioned the <span class="caps">HTML</span> output bundle. James gives the following details:</p> <ul> <li>Select Bundles → TextMate → Create <span class="caps">HTML</span> From Document (or Create <span class="caps">HTML</span> From Document With Line Numbers, if you prefer)</li> <li>Preview the document in TextMate with Window ⇢ Show Web Preview</li> <li>Highlight and Edit → Copy the content you want from the <span class="caps">HTML</span> window</li> <li>Switch to Keynote and Edit → Paste</li> </ul> <p>Mike (who credits <a href="http://codefluency.com">Bruce Williams</a> as his source for this tip) also provided a <a href="http://s3.amazonaws.com/pragmaticstudio/textmate-keynote.mov">video</a>.</p> <p>Couple of items on the above:</p> <ol> <li>When creating the <span class="caps">HTML</span> from the document, convert the whole document. Once in Web Preview mode you can cut and paste only what you want.</li> <li>Choose a TextMate theme with a background that matches the background in your presenetation to get the best effect for your colors.</li> </ol> <p><a href="http://drnicwilliams.com/">Dr. Nic</a> also mentions a &#8220;Copy as <span class="caps">RTF</span>&#8221; TextMate bundle. (I&#8217;m not sure if this is the same as James and Mike&#8217;s hint above or something different).</p> <p>Finally, <a href="http://mysterycoder.blogspot.com/">Chris Nelson</a> confirms (via Twitter): &#8220;AFAIK there is no equivalent of web views in OpenOffice :(&#8220;</p> Presenting Code http://onestepback.org/index.cgi/General/PresentingCode.red <p style="padding-left:3em;"><em>This exchange on twitter got me thinking&#8230;</em></p> <h2>Twittering &#8230;</h2> <p>I noticed the following twitter conversation this evening between <a href="http://twitter.com/objo" title="Joe O'Brien">objo</a> and <a href="http://twitter.com/superchris" title="Chris Nelson">superchris</a>:</p> <blockquote> <p><strong><span style="color:blue;">superchris:</span></strong> any good recommendations on showing code samples in OpenOffice Impress?</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">objo:</span></strong> @superchris yeah, get a mac and use Keynote</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">objo:</span></strong> otherwise, I would screenshot emacs</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">superchris:</span></strong> @objo.. ya know, i almost added &#8220;And I&#8217;ll smack anyone who says get a Mac&#8221; but ran out of space</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">superchris:</span></strong> @objo&#8230; but actually your idea of using NetBeans screenshots is pretty good</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">objo:</span></strong> @superchris you never listen &#8230;. <span class="caps">EMACS</span> not netbeans. Come on man.</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">superchris:</span></strong> @objo just being helpful by translating for you.. :)</p> </blockquote> <blockquote> <p><strong><span style="color:blue;">superchris:</span></strong> planning to code with NetBeans on linux forever for no other reason but to annoy @objo</p> </blockquote> <h2>ScreenShots &#8230; Yuck!</h2> <p>The problem Chris is trying to solve is putting code snippets into a presentation. There just isn&#8217;t a good way to do this in modern presentation programs.</p> <p>In the old days, I would generate my presentation completely in <span class="caps">HTML</span> from a simple text markup file. The generation process was controlled by rake. This allowed me to changed the code, run the unit tests and rebuild the presentation all with a simple rake command. Eventually, I got up to speed with <span class="caps">CSS</span> and could make some really nice looking presentations, all from <span class="caps">HTML</span>.</p> <p>Although I could get nice looking slides with <span class="caps">CSS</span>, it was a lot of work getting it to work just so. Eventually, I abandoned that approach and swithed to a modern slide presentation program (Keynote in my case).</p> <p>Although generating the slides is a bit easier in Keynote (or PowerPoint, or Open Office Impress), reproducing code for technical talks is much harder. You generally have two choices:</p> <ol> <li>Cut and paste the code text into Keynote losing any syntax highlighting you might have had, or</li> <li>Take a screen shot of the code in your fancy editor, preserving the syntax highlighting but losing the &#8220;text&#8221; nature of the code.</li> </ol> <p>Neither option is pleasant. The former punishes the audience by making the code harder to read, the latter punishes you making the presentation hard to change. (I once saw Dave Thomas giving a Ruby talk and he noticed that he had a minor typo in the code. He switched to edit mode in Keynote with the intent of fixing it on the spot, then he realized that the code was in a graphic image and was uneditable).</p> <p>Of the two options, I&#8217;ve been using the text cut&#8217;n&#8217;paste technique for most things. In the twitter conversation above, Chris is considering the edit snapshot technique.</p> <h2>Other Options?</h2> <p>I&#8217;ve heard rumors of someone working on a script that will insert code snippets into the Keynote data file directly. Unfortunately, as far as I know, they are still rumors at this time.</p> <p>But here&#8217;s another idea. I&#8217;ve prototyped this, and think it will work. But be warned I haven&#8217;t tried this on a really presentation yet.</p> <h2>Presenting Code &#8230; A Proof of Concept</h2> <p>While perusing the options in Keynote, I noticed an insert option called &#8220;Web View&#8221;</p> <p><img src="http://onestepback.org/images/rublog/present_code/present_code_web_view.jpg" alt="" /></p> <p>It turns out that this option allows you to include a web page in your presentation. For example, here is my blog inserted directly into the presentation. Clicking on the &#8220;web view&#8221; object will show an &#8220;update&#8221; button that will refresh that page from the web.</p> <p><img src="http://onestepback.org/images/rublog/present_code/present_code_blog.jpg" alt="" /></p> <p>So, all I have to do is get the code onto a web page, formatted nicely with syntax highlighting, and Keynote will suck it into the presentation, more or less automatically for me. Cool.</p> <p>Getting it formatted is easy. That&#8217;s just a small little Rake task with a good syntax highlighting library. I used <code>Syntax</code> (its a gem, docs on Rubyforge), but there are other options out there.</p> <p>Here&#8217;s the rakefile:</p> <pre class="ruby"> #!/usr/bin/env ruby require "rake/clean" CLOBBER.include('*.html') task :default =&gt; :extract task :extract =&gt; "hello.html" file "hello.html" =&gt; "hello.rb" do extract "hello.html", "hello.rb" end </pre> <p>and here is the <code>rakelib/extract.rake</code> library:</p> <pre class="ruby"> #!/usr/bin/env ruby require 'syntax/convertors/html' def extract(outfile, infile) open(outfile, "w") do |out| out.puts "&lt;html&gt;" out.puts " &lt;head&gt;" out.puts " &lt;style type=\"text/css\"&gt;" out.puts %( .ruby { font-size: 24pt; font-weight: bold; } .ruby .normal {} .ruby .comment { color: #888; font-style: italic; } .ruby .keyword { color: #A00; font-weight: bold; } .ruby .method { color: #077; } .ruby .class { color: #074; } .ruby .module { color: #050; } .ruby .punct { color: #447; font-weight: bold; } .ruby .symbol { color: #099; } .ruby .string { color: #944; } .ruby .char { color: #F07; } .ruby .ident { color: #004; } .ruby .constant { color: #07F; } .ruby .regex { color: #B66; } .ruby .number { color: #D55; } .ruby .attribute { color: #377; } .ruby .global { color: #3B7; } .ruby .expr { color: #227; }) out.puts " &lt;/style&gt;" out.puts " &lt;/head&gt;" out.puts " &lt;body&gt;" out.puts " &lt;pre class=\"ruby\"&gt;" code = open(infile) { |f| f.read } convertor = Syntax::Convertors::HTML.for_syntax("ruby") html = convertor.convert(code) out.puts html out.puts " &lt;/pre&gt;" out.puts " &lt;/body&gt;" out.puts "&lt;/html&gt;" end end </pre> <p>Edit the <span class="caps">CSS</span> styles above to tweek the output to exactly the colors you want. I&#8217;ve added a large font-size line to make the code big enough for teh presentation (I hate small code fonts in presentations, you can ask <a href="http://twitter.com/objo">objo</a> about my rants on <em>that</em> topic.)</p> <p>Now we need to get the code on a web page. No need to get fancy here. I have a script called <code>servefiles</code> that will start a webrick process that serves files from the current directory. Just start it up with &#8220;servefiles 3333&#8221; (the 3333 is the port to use). Servefiles will display its <span class="caps">URL</span> in its startup message, like so:</p> <pre class="shell"> $ servefiles 3333 URL: http://tardis.local:3333 [2008-03-23 00:47:37] INFO WEBrick 1.3.1 [2008-03-23 00:47:37] INFO ruby 1.8.6 (2008-03-03) [i686-darwin9.2.0] [2008-03-23 00:47:37] INFO WEBrick::HTTPServer#start: pid=874 port=3333 </pre> <p>Here&#8217;s the code for <code>servefiles</code>:</p> <pre class="ruby"> #!/usr/bin/env ruby require 'webrick' include WEBrick dir = Dir::pwd port = (ARGV.first || (12000 + (dir.hash % 1000))).to_i puts "URL: http://#{Socket.gethostname}:#{port}" s = HTTPServer.new( :Port =&gt; port, :DocumentRoot =&gt; dir ) trap("INT"){ s.shutdown } s.start </pre> <p>Now all we have to do is cut and paste the <span class="caps">URL</span> given by <code>servefiles</code> into keynote and append the <span class="caps">HTML</span> file name we wish to add to our presentation:</p> <p><img src="http://onestepback.org/images/rublog/present_code/present_code_hello.jpg" alt="" /></p> <p>Now, to update the code in the presentation, I need to:</p> <ol> <li>Edit the original code base (and run unit tests against it).</li> <li>Run rake</li> <li>Press the &#8220;Update Now&#8221; button in Keynote.</li> </ol> <p>Not bad.</p> <h2>It&#8217;s Just a Proof of Concept</h2> <p>Just be warned, I haven&#8217;t tried this in a real presentation yet. I&#8217;ve just spent an hour or so seeing if all the pieces would work together. There are some obvious things to explore.</p> <ul> <li>The extraction code could be enhanced to pull snippets from files based on tags. Or even better, being able to say &#8220;Extract Method m from Class C&#8221;.</li> </ul> <ul> <li>I&#8217;m using a fixed font size, but extract could easily take the font size as an argument or even calculate the proper font size given the amount of text found in the snippet.</li> </ul> <ul> <li>I&#8217;ve not played with the &#8220;Update automatically&#8221; checkbox in the Keynote dialog. I&#8217;m not sure <em>when</em> it automatically updates, but it is possible that using it might mean you don&#8217;t even need step three above.</li> </ul> <p>I will probably experiment some more with then in my next code heavy presentation. Let me know if you try this and how it work for you.</p> <h2><span class="caps">UPDATE</span></h2> <p><a href="http://beust.com/weblog/">Cédric Beust</a> points out that cutting and pasting from Eclipse to PowerPoint does preserve syntax highlighting. I verified the same is true for Eclipse and Keynote. However all the other IDEs and editors I tried (NetBeans, Coda, TextMate, Emacs) will paste as plain, uncolored text in Keynote. So, if you are going the cut and paste route, you might want to consider using Eclipse for the cut source.</p> <p>Just for kicks I tried the presentation software in OpenOffice with the same result. Eclipse copies will preserve highlighting, none of the others will.</p> <p>So, there you have it.</p> New Blog Name http://onestepback.org/index.cgi/Humor/RenameTitle.red <p style="padding-left:3em;"><em>Ryan Tomayko has pointed out, my blog title does not conform to standard Ruby coding conventions. We need to fix this.</em></p> <p><a href="http://tomayko.com/">Ryan Tomayko</a> has done a <a href="http://tomayko.com/writings/your-clever-weblog-title">review of blogs using code snippets</a> as there title and has pointed out that mine does not conform to generally accepted Ruby coding standards. You see, in &#8220;{&nbsp;|&nbsp;one,&nbsp;step,&nbsp;back&nbsp;|&nbsp;}&#8221; I use spaces between the vertical bars and the argument names. Proper Ruby code would never be written that way.</p> <p>He&#8217;s right. So in order to promote better Ruby coding practices, I&#8217;m renaming the blog to &#8220;{&nbsp;|one,&nbsp;step,&nbsp;back|&nbsp;}&#8221;.</p> <p>Let it never be said that I ignore standards.</p> <p style="padding-left:3em;">An aside: The use of {||} in the title was inspired by a Smalltalk logo that used [|]. See the powered by banner at the bottom of the sidebar in <a href="http://www.cincomsmalltalk.com/blog/blogView">James Robertson&#8217;s blog</a> for an example.</p> On my wall ... http://onestepback.org/index.cgi/Tech/Programming/DarthTest.red <p><img src="http://onestepback.org/images/rublog/DarthTest.jpg" alt="" /></p> <p>(from <a href="http://www.flickr.com/photos/sebastian_bergmann/2282734669/sizes/o/">here</a>)</p> The Arc Challenge http://onestepback.org/index.cgi/Tech/Ruby/ArcChallenge.red <p style="padding-left:3em;"><em>Paul Graham issues the Arc Challenge &#8230; who could resist?</em></p> <h2>Paul Graham&#8217;s Arc Challenge</h2> <p>You can read about the Arc Challenge here: <a href="http://www.paulgraham.com/arcchallenge.html">The Arc Challenge</a>. Go ahead a read it now, but I will summarize the challenge.</p> <p><strong>Write a web program such that:</strong></p> <ul> <li>The first page of the program displays nothing but a text box and a submit button. You enter some arbitrary text and press the submit button, which takes you to &#8230;</li> </ul> <ul> <li>The second page is nothing but a single link labeled &#8220;click here&#8221;. The <span class="caps">URL</span> linked to must not contain the text entered in the first step (i.e. you are not supposed to pass the text as a parameter on the link). Clicking the link takes you to &#8230;</li> </ul> <ul> <li>The third page which contains &#8220;You said: <span class="caps">XXX</span>&#8221; (where <span class="caps">XXX</span> is the text you entered in the first step).</li> </ul> <p>Here&#8217;s a screen cast demoing my solution to the Arc Challenge. (We will show the code shortly).</p> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="466" height="281"> <param name="movie" value="http://content.screencast.com/bootstrap.swf"></param> <param name="quality" value="high"></param> <param name="bgcolor" value="#FFFFFF"></param> <param name="flashVars" value="thumb=http://content.screencast.com/media/762eebca-fa50-49f8-9b88-dc7652bd3c9a_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&#38;content=http://content.screencast.com/media/499ec89e-b124-4dcb-bcd0-e74f6fac495f_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000084.swf&#38;width=466&#38;height=281"></param> <param name="allowFullScreen" value="true"></param> <param name="scale" value="showall"></param> <param name="allowScriptAccess" value="always"></param> <embed src="http://content.screencast.com/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="466" height="281" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/762eebca-fa50-49f8-9b88-dc7652bd3c9a_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&#38;content=http://content.screencast.com/media/499ec89e-b124-4dcb-bcd0-e74f6fac495f_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000084.swf&#38;width=466&#38;height=281" allowFullScreen="true" scale="showall"></embed> </object> <h2>Paul&#8217;s Solution</h2> <p>Paul has been working on designing Arc, his ideal programming language for the future. Given Paul&#8217;s language preferences, it is no surprise that Arc is very Lisp-like. Here is Paul&#8217;s solution written in Arc:</p> <pre class="testcode"> (defop said req (aform [w/link (pr "you said: " (arg _ "foo")) (pr "click here")] (input "foo") (submit))) </pre> <p>Paul points out that the solution is very short and elegant, only 23 nodes in the codetree. I&#8217;m sure I don&#8217;t quite understand exactly what it is doing (I&#8217;d love to see a step by step explanation of the code). He wonders what it would look like in other languages.</p> <p>Several people have responded with solutions in their own languages. I&#8217;ve seen a <a href="http://www.lukas-renggli.ch/blog/take-the-arc-challenge?_s=BXjPNOJFnBmoYxtA&#38;_k=lERhwwWC">Smalltalk Solution</a> as well as a <a href="http://arc-challenge.heroku.com/">Ruby solution</a> (which pretty closely mimics the Arc code from Paul) on the <a href="http://arclanguage.org/item?id=722">Arc Language Forum</a> page that was setup for responses.</p> <h2>Continuation Web Servers</h2> <p>The Arc challenge is a perfect candidate for a continuation based server solution. And I recalled that Chad Fowler and I had written a demo continuation based server for the <a href="http://onestepback.org/articles/callcc/">Continuations Demystified</a> talk we did at RubyConf 2005. (Look for the &#8220;Poor Man&#8217;s Seaside Demo in that presentation.) I wondered how easy it be to code up an Arc challenge solution using that code base.</p> <p>The key to a continuation based server is that it allows the programmer to code in a linear fashion. All the request/response nature of web interaction is completely hidden from you as a programmer.</p> <p>For example, let&#8217;s pretend we wanted to solve the Arc challenge using a terminal and command line rather than a web based solution. How would you write it? Probably something like this:</p> <pre class="rubycode"> text = gets puts "click here" gets puts "You said: #{text}" </pre> <p>Simple, linear programming. (OK, printing &#8220;click here&#8221; is silly in a text program, but you get the idea). You ask a question and read a response. You pause for a click. You then tell the user what the result is.</p> <p>Ask. Pause. Tell.</p> <p>Those are our basic abstract operations for this problem. Lets rewrite our text based solution using these abstractions. We&#8217;ll put this in a file called &#8220;arc_challenge.rb&#8221;.</p> <pre class="rubycode"> Conversation.interact do |io| text = io.ask io.pause("click here") io.tell("You said: #{text}") end </pre> <p>I&#8217;ve introduced three operations (methods) that are provided by an I/O object (let&#8217;s ignore the interact line for now). &#8220;ask&#8221; will ask the user for input, returning the string. &#8220;pause&#8221; will pause until the user indicates he/she is ready to continue (e.g. pressing return in our command line version). &#8220;tell&#8221; sends the given string to the user.</p> <p>So, what does &#8220;Conversation.interact&#8221; do? It creates the environment where the user have a conversation with the program. The interation is controlled through our ask/pause/tell functions provided by the I/O object passed to the interact block.</p> <p>Here is an implementation of a text based conversation.</p> <pre class="rubycode"> class TextBased def interact yield(self) end def ask(prompt=nil) print prompt, " " if prompt gets.chomp end def pause(prompt="") print prompt, " " if prompt gets end def tell(message) puts message end end Conversation = TextBased.new </pre> <p>To run the text based conversation, just require the text. Here&#8217;s a demo:</p> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="465" height="238"> <param name="movie" value="http://content.screencast.com/bootstrap.swf"></param> <param name="quality" value="high"></param> <param name="bgcolor" value="#FFFFFF"></param> <param name="flashVars" value="thumb=http://content.screencast.com/media/1ae5f9ce-5bc5-4360-8cbc-83b165a434ab_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&#38;content=http://content.screencast.com/media/90dd373a-0352-4710-acb1-6b18620a5609_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000080.swf&#38;width=465&#38;height=238"></param> <param name="allowFullScreen" value="true"></param> <param name="scale" value="showall"></param> <param name="allowScriptAccess" value="always"></param> <embed src="http://content.screencast.com/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="465" height="238" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/1ae5f9ce-5bc5-4360-8cbc-83b165a434ab_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&#38;content=http://content.screencast.com/media/90dd373a-0352-4710-acb1-6b18620a5609_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000080.swf&#38;width=465&#38;height=238" allowFullScreen="true" scale="showall"></embed> </object> <h2>Arc on the Web</h2> <p>Well, anybody can solve the challenge in text mode. How much work do we have to do to get it on the web.</p> <p>The answer: Zero!</p> <p>The code Chad and I wrote for <a href="http://onestepback.org/articles/callcc/">Continuations Demystified</a> includes a web-based version of the conversation object that is ready to go. All we have to do is plug it in and run it. No changes are required to our basic Arc challenge solution.</p> <p>Again, a screen demo:</p> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="538" height="352"> <param name="movie" value="http://content.screencast.com/bootstrap.swf"></param> <param name="quality" value="high"></param> <param name="bgcolor" value="#FFFFFF"></param> <param name="flashVars" value="thumb=http://content.screencast.com/media/a8773d13-5fe0-46f2-adcf-8ae4830c6e53_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&#38;content=http://content.screencast.com/media/2918dffc-1f80-401b-8063-d8c8bb908016_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000082.swf&#38;width=538&#38;height=352"></param> <param name="allowFullScreen" value="true"></param> <param name="scale" value="showall"></param> <param name="allowScriptAccess" value="always"></param> <embed src="http://content.screencast.com/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="538" height="352" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/a8773d13-5fe0-46f2-adcf-8ae4830c6e53_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&#38;content=http://content.screencast.com/media/2918dffc-1f80-401b-8063-d8c8bb908016_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000082.swf&#38;width=538&#38;height=352" allowFullScreen="true" scale="showall"></embed> </object> <p>Yes, we know that although we now have our Arc Challenge on the web, we haven&#8217;t quite conformed to the exact requirements of the challenge. We will handle that next.</p> <h2>The Final Arc Solution</h2> <p>The problem is that the current Web based conversation object makes all kinds of assumptions that are not appropriate for the final Arc solution.</p> <p>In particular, we need to change:</p> <ul> <li>Get rid the head line, restart link and other extraneous <span class="caps">HTML</span> elements.</li> </ul> <ul> <li>Don&#8217;t keep a running log of the conversation. When you move to a new page, you start from scratch.</li> </ul> <ul> <li>The &#8220;click here&#8221; should be a real link, not just a text box where you can press enter.</li> </ul> <p>To get to here, we will have to make some modifications to the conversation web library. It turns out the changes are pretty straight forward. The whole interaction framework is controlled by the Conversation object that implements ask/pause/tell methods. You can see the changes made for the Arc challenge in the &#8220;noecho_web_based.rb&#8221; file (see the end of this post for the availability of the source code).</p> <h2>The Final Conversation Based Solution</h2> <p>In cased you missed it, here is the Arc Challenge Solution:</p> <pre class="rubycode"> Conversation.interact do |io| text = io.ask io.pause("click here") io.tell("You said: #{text}") end </pre> <p>Yep, it&#8217;s the exact same file we used for the text based solution. I don&#8217;t know if it is as elegant as Paul&#8217;s version, but I certainly find it easy to read and understand. (Rerun the <a href="http://www.screencast.com/t/mFoZAA7N">very first screen cast</a> in this posting if you want to see it in action again).</p> <p>If you want to look at the code, there is a <a href="http://onestepback.org/download/conversations.tgz">tarball</a> available that contains all the continuation server demo code from <a href="http://onestepback.org/articles/callcc/">Continuations Demystified</a> talk, as well as the two new files I added for the Arc challenge. &#8220;arc_challenge.rb&#8221; is the actually solution and &#8220;noecho_web_based.rb&#8221; is the conversation library that renders the solution in the style set forth by the challenge.</p> <p>Enjoy.</p>