A blog quine and deferred type checks in Ruby
It took me some time to realize that my blogging could benefit from some automation. Indeed, I'm often doing some sort of literate programming to show the internals of some Ruby voodoo, using my xmp decorator to display execution results, which means that I cannot use something like WEB (or a language-independent tool like noweb).
This meta-entry shows how I usually blog, using a sort of "reverse|ruby weave" script I hacked in 15 (?) minutes, shown below. It extracts the code snippets so that I can scp them to the webserver, where they get prettified by my modified attach.rb plugin for hiki. The following (~90s) movie shows what I did to create this entry:
(I changed a few bits before actually posting this)
Staying on-topic: some Ruby, instance methods and deferred type checking
Here's a mildly surprising result: we can move instance methods up the klass chain:
class A def foo; "A#foo" end end a = A.new a.foo # => "A#foo" module B; end class A m = instance_method(:foo) B.class_eval{ define_method(:foo, m) } remove_method(:foo) end a.foo rescue "no method..." # => "no method..." class A; include B end a.foo # => "A#foo"
This works because the type check is deferred until the method is actually called (instead of being performed when the method is defined in the upper class/module):
class C; include B end C.new.foo # => # ~> -:53:in `foo': bind argument must be an instance of A (TypeError) # ~> from -:53
Here's the source code for rweave (remember it's a kludge):
#!/usr/bin/env ruby require 'fileutils' output_lines = [] replacements = {} snippets = {} file = ARGV[0] || "defout" ARGV.replace [] if !File.exist?(file) dir = "#{file}.files" state = :begin current_filename = nil current_file = nil ARGF.each do |line| case state when :begin case line when /^#(begin|sbegin)\(([^)]+)\)/ state = :want_end current_filename = $2 if $1 == "begin" FileUtils.mkdir_p dir current_file = File.open(File.join(dir, current_filename), "w") else current_file = nil end output_lines << line snippets[$2] = "" when %r{^//insert\(([^)]+)\)} state = :want_endinsert current_filename = $1 replacements[output_lines.size - 1] = $1 when %r{^#insert\(([^)]+)\)} state = :begin current_filename = $1 replacements[output_lines.size - 1] = $1 else output_lines << line end when :want_end case line when /^#end\(#{Regexp.escape(current_filename)}\)/ current_file.close if current_file state = :begin else snippets[current_filename] << line current_file.puts line if current_file end output_lines << line when :want_endinsert if md = %r{^//endinsert\(#{Regexp.escape(current_filename)}\)}.match(line) state = :begin end end end replacements.each_pair do |idx, snippetname| output_lines[idx] << "//insert(#{snippetname})\n" << snippets[snippetname] << "//endinsert(#{snippetname})" end puts output_lines
i'm impressed - nec (2005-12-16 (Fri) 00:26:16)
you rock!
and is this your actual typing speed?
mfp 2005-12-16 (Fri) 17:01:35
haha I "encoded" the gif at higher speed (don't remember the multiplicative constant). What you see in the animation seems to correspond roughly to 330 wpm. My typing speed depends on several factors, the most important being ambient temperature, posture, sleep deprivation. My speed ranges from as low as ~50wpm to ~110wpm. I'm a very lousy typist below 20-21C. That day was moderately cold so I must have done ~80wpm or so; the animation plays (maybe) 4X faster.
testing - mfp (2006-06-08 (Thr) 15:51:21)
did I just break comments in my last commit? answer: no
- 23 http://chneukirchen.org/anarchaia
- 22 http://www.artima.com/forums/flat.jsp?forum=123&thread=140806
- 15 http://www.earthceuticals.com
- 10 http://www.artima.com/buzz/community.jsp?forum=123
- 9 http://www.anarchaia.org
- 6 http://anarchaia.org
- 5 http://chneukirchen.org/anarchaia/archive/2005/12/15.html
- 4 http://anarchaia.org/archive/2005/12.html
- 3 http://search.live.com/results.aspx?q=ruby quine&src=IE-SearchBox
- 2 http://translate.google.com/translate?hl=ar&sl=en&u=http://eigenclass.org/hiki.rb?A+blog+quine&sa=X&oi=translate&resnum=1&ct=result&prev=/search?q=quine&start=90&hl=ar&lr=&sa=N
Keyword(s):[blog] [ruby] [quine] [meta] [instance] [method]
References: