Terminal Trick

Posted by Gregor Schmidt
(2007-11-22)

Mostly off topic, but I wanted to share it anyway.

We terminal cowboys often have the same problem. I’m in my current workspace, represented by a certain directory. But I would like to open a new Terminal window pointing to exactly the same directory. Hitting [Apple]+[n](1) will open a new window, but is points to $HOME. (Sidenote: gnome-terminal knows its customers better. It opens at the same location. When I wanted to be at $HOME, I could easily enter cd and be there.)

But I’m working on Mac OS and nearly every application made by Apple is scriptable with AppleScript, so is Terminal. I fetched one of the “Open Terminal Here” scripts to open a terminal from Finder. But I could not get behind the syntax. It looks great and is got to get, but difficult to write, when unfamiliar with it. But I could extract the right portions to open a Terminal at a given directory. But how do I fetch this one. Hmm.

The solution is pretty simple. Use a language, where I know how to fetch the current directory: Ruby. There is a great gem called rb-appscript. It’s a Ruby-AppleScript bridge and does what I want. It’s not easy to fetch the syntax here as well, but I just wanted to translate two lines, trial and error did the job.

The Result

… is a litte ruby script placed in ‘/usr/local/bin’ called ot (Open Terminal) and it is not more but the following:

#!/usr/bin/env ruby -rubygems

require 'appscript'
include Appscript

term = app("Terminal")
term.activate
term.do_script(:with_command => "cd #{Dir.pwd}")

Now I can easily do what I want. If you are always using Terminal and calling the script only from one, you can even boil it down to three lines:

#!/usr/bin/env ruby -rubygems

require 'appscript'
Appscript::app("Terminal").do_script(:with_command => "cd #{Dir.pwd}")

The nicities of open source and open architectures. It was a pleasure.

(1): Yes I call the “command key” “apple key”, because everybody will instantly know what I mean. I’m not a fan of removing this icon from the keyboard.

EuRuKo 2007 coverage

Posted by Gregor Schmidt
(2007-11-10)

I will try to cover Euruko 2007 at my kind of tumblelog at soup.schmidtwisser.de.

October's Ruby User Group Meeting

Posted by Gregor Schmidt
(2007-10-05)

I just wanted to quickly share the slides from yesterday’s monthly meeting.

The one on Camping:

You may find the code from the hacking session at our rubyforge svn, if you like.

And the other on LiterateMaruku:

Thanks again, for the nice evening.

Camping, Markaby and ruby2ruby

Posted by Gregor Schmidt
(2007-10-01)

I wanted to use camping to a literate programming style wiki with markaby syntax. Literally I wanted to make the followin possible:

The Goal

Have a wiki page with the following content:

p "This page demonstrates Literate Markaby"

ruby_code do
  a = 1 + 1
  p "Output of a: #{a}"
end

And have the following output:

<p>This page demonstrates Literate Markaby</p>
<pre><code>a = 1 + 1
p "Output of a: #{a}"</code></pre>
<p>Output of a: 2</p>

Or it should look like this:

This page demonstrates Literate Markaby

a = 1 + 1
p "Output of a: #{a}"

Output of a: 2

The Tool

Markaby is Markup in Ruby. So the code entered as wiki markup will be eval’ed to get the output right. So when I would like to get the contents of the block passed to ruby_code I have to inspect live code. And there is one nice tool, that fits this task - ruby2ruby.

The Implementation

So all there is to do is to write a little camping helper, that implements the ruby_code method and generates the output.

STRIP_PROC = /^proc \{\n(.*)\n\}$/m

def ruby_code(&block)
  self.pre do
    self.code(block.to_ruby.gsub(STRIP_PROC, '\1'))
  end
  block.call
end

It is pretty easy, when you start in the middle. block.to_ruby gives you a string representation of the given block. Since it is a proc, ruby2ruby surrounds it accordingly. In this example the actual value would be

proc {
  a = (1 + 1)
  p("Output of a: #{a}")
}

The proc is okay, if we would like to execute the code once again, but in this case it is too much information. Therefore, the regular expression and gsub remove these characters. This string is then surrounded with html code and pre blocks, so it is marked up semantically.

I tested this code in a separte script with marbaky and ruby2ruby.

The stumbling block

But then, a simple require 'ruby2ruby' in the targeted camping app, breaks it. Strange Markaby::InvalidXhtmlErrors are raised, where no exception was raised before. In fact, the occurred at the first call of tag! with attribute arguments. Since I was not able to track this down, I send my question to the camping-list and got the right hint.

ruby2ruby defines NilClass#method_missing to always return nil, instead of raising an exception. A nearby comment calls it an Object-C hack. I call it a bad idea. Other applications may rely on this basic behaviour, Camping does. Undefining it again, after the requiring ruby2ruby solved the strange errors. But on the other hand, ruby2ruby may rely on the changed behaviour. So this could not be it.

A solution

By accident I came up with a working solution. Unfortunately I don’t know why I helped, but I guess a certain degree of meta-programming leads to this behaviour. Add a definition of tag! to your application and everthing is fine. This will look loke the following:

class MyApp::Mab
  def tag!(*g,&b)
    super
  end
end

Get it for free

If you now think, why should I solve that again, You already did, you are right. You can get all the fixes and methods for free, now. To use the code, simply add an include LiterateMarkaby to your application’s module. That’s it.

Ahh, of course you need to copy the following lines as well..

require "ruby2ruby"

module LiterateMarkaby
  STRIP_PROC = /^proc \{\n(.*)\n\}$/m
  def self.included(base)
    base.const_get(:Mab).class_eval do
      def tag!(*g,&b)
        super
      end
    end
    base.const_get(:Helpers).class_eval do
      def ruby_code(&block)
        self.pre do
          self.code(block.to_ruby.gsub(STRIP_PROC, '\1'))
        end
        block.call
      end
    end
  end
end

As you can see: even more meta programming. The first reason: Helpers need to be defined directly within the applications helper module. Otherwise Markaby does not find them. And the other reason was already discussed, we need a Mab#tag! in our module.

There is only one thing better than meta-magic, even more meta-magic.

Executable code in usage examples

Posted by Gregor Schmidt
(2007-09-13)

Today I wrote a basic usage document for ContextR. It will be part of the next gem release and therefor right at the hand of the user. What hit me was, that I wanted it to be executable. It is okay to write a bit of code and surround it with comments to explain it, but what bothered me, was that I had to use puts all over to demostrate example output.

But the reader cannot see the output of a line of code and the line itself at once. So you will start writing something like this.

puts "bla" * 3 # => "blablabla"

I think everybody has seen code like this somewhere. Probably in this blog. It works okay, the code stays executable and readable, but it is not easy to garantee, that the code and the comment are in sync. If you change your libary code (in this case the * method for String) and the code and comment act differently, the only person who is able to spot the error is the user, that tried the piece of code in his own project.

Make it a test case

And, by the way, executing a file with 20 to 30 puts lines in it does not give a good looking output. So what you want it to have the actual code and the expected output side by side. Sound like a test case to me. So you would change the above example to the following

class TestString < Test::Unit::TestCase
  def test_multiply
    assert_equal "blablabla", ("bla" * 3).to_s
  end
end

This is a lot of noise, that nobody wants to see. But we’ve got the advantage, that our manual can become part of our test suite and it will fail in the second, we change our libary - immediate feedback. Nothing is worse than having outdated documentation.

Get rid of the noise

So I tried to make it less noisy, but keep the test case approach. What I did was a bit of metaprogramming and dsl-ing. The result:

test_class(:TestString)

# introduction

example do
  output_of("bla" + "blub") == "blablub"
end

# some comment

example do
  output_of("bla" * 2) == "blabla"
  output_of("bla" * 3) == "blablabla"
end

The definition of the test_class is done only once, I group all examples of a file into one test class for example. All examples following a test_class definition are made to test_* methods within this class.

In the above example generates the following code, or to correct it generates an object structure, that acts like the following code:

class TestString < Test::Unit::TestCase
  def test_001
    assert_equal "blablub", ("bla" + "blub").to_s
  end

  def test_002
    assert_equal "blabla",    ("bla" * 2).to_s
    assert_equal "blablabla", ("bla" * 3).to_s
  end
end

At the end there is a fully functional TestClass that is executed automatically with all the others. And the execution of your document gives you the information whether it is still correct or not. Everything we wanted.

But there is one downside I could not solve elegantly yet. If you want to share variables from one example to the other, you have to use instance variables or global variables. And if you embed code, that is not part of an example, that should use the variables as well, there is no other option than globals. But I guess that this could be solved somehow. In my case it is sufficient.

The implementation

I simply added the following lines to my test_helper.rb

module ExampleTest
  module ObjectExtension
    def test_class(name)
      $last_test_class = Class.new(Test::Unit::TestCase)
      $last_test_case  = 0
      Object.const_set(name, $last_test_class)
    end

    def example(&block)
      $last_test_class.class_eval do
        define_method("test_%03d" % ($last_test_case += 1), &block)
      end
    end
  end

  module TestExtension
    def assert_to_s(expected, actual)
      assert_equal(expected, actual.to_s)
    end

    def output_of(object)
      Output.new(object, self)
    end

    class Output
      attr_accessor :object, :test_class
      def initialize(object, test_class)
        self.object = object
        self.test_class = test_class
      end
      def ==(string)
        test_class.assert_equal(string, object.to_s)
      end
    end
  end
end

class Test::Unit::TestCase
  include ExampleTest::TestExtension
end
class Object
  include ExampleTest::ObjectExtension
end

Feel free to use it in your projects and give me feedback if you do. If this makes sense to more than three people, I will most likely compile a gem and release it to the public.

An example (I love recursion)

If you would like to see the above in action, have a look at the ContextR introduction test. Lots of comment and some code examples in between. It is a lot more readable with syntax highlighting. And what happens when the file is executed?

$ ruby test/test_introduction.rb 
Loaded suite test/test_introduction
Started
...........
Finished in 0.003204 seconds.

11 tests, 18 assertions, 0 failures, 0 errors

Addendum

This causes some warning when your test are executed using the -w option, what they should, by the way. I am not sure, whether it is possible to avoid these or not. As far as I can see, RSpec, where I stole the == syntax has the same problems. Propably we should switch to a single = but this would not look right. I’m not sure.

Anyway, if I release it as a gem, it needs to have a name.

EuRuKo 2007

Posted by Gregor Schmidt
(2007-09-12)

Today the dates for Euruko 2007 where announced.

10th and 11th November 2007 - Vienna, Austria

I would give a talk about ContextR, but this was already covered successfully by Christian Neukirchen in 2005. So it would just be an update and nothing new. But I’m really thinking about getting there and meeting other ruby guys.

Air Berlin charges 89 € for the tickets
A Hotel room for 2 nights would be about 100 €
Conference fee about 25 €
Eat and Drink for 2 day about 100 €

That is 314 € - still the half of RailsConf Europe fee. We’ll see.

Update

Today, I actually booked the flight and hotel. It is 129.00 € for the flight (Air Berlin) and 74.00 € for a half a double room, which I am sharing with Martin.

And on the other hand. Its not yet official, but I have heard rumors stating that RailsConf Europe 2008 will be in Berlin as well. So I’ll start saving my money from now on. This will be about 50 € per month or 1.70 € a day. Stills sound like a lot of money. Anyway.

ContextR 0.1.0 released

Posted by Gregor Schmidt
(2007-09-12)

In the last weeks it was a bit silent around this page, my master’s thesis and ContextR. This will change again and the start will be a new version of ContextR, that was just released.

It features a reimplementation from the scratch including more dynamicy, a totally different syntax and some more niceties, that allow easier use of it in most cases. For demo purposes although, the syntax became slightly more explicit, but this will not be much of a problem.

There were several downside of the old syntax and I would like to list the here for future reference.

  • it was impossible to refactor wrapper code into layer scoped functions
  • it was not easily possible to reuse code in multiple layers or for multiple functions
  • it was not possible to remove behaviour definitions, since there was no way of addressing a single chunk of attached behaviour
  • syntax highlighting does not work for wrapper definitions

The shiny new API

From now on the layer specific behaviour is wrapped in plain old ruby modules (no more blocks). The introductory Education/Student example looks now like the following

class Student < Struct.new(:name, :address, :university)
  def to_s
    name
  end
end

class University < Struct.new(:name, :address)
  def to_s
    name
  end
end

This is a pretty simple class layout. But if you would like to get the address of a student under certain circumstances and the educational body in others or sometimes both, the new API comes into play.

module AddressMethods
  def to_s
    yield(:next) + " (" + yield(:receiver).address + ")"
  end
end

class University
  include AddressMethods => :address
end

class Student
  module EducationMethods
    def to_s
      yield(:next) + "; " + yield(:receiver).university.to_s
    end
  end

  include AddressMethods => :address
  include EducationMethods => :education
end

So what happened here? We are using plain old modules to define additional behaviour for our Student and Education classes. Just like we had done without ContextR - despite the strange yield(:next) instead of super and yield(:receiver) instead of self. I will try to get rid of these strangeness in one of the next iterations. Until then we have to live with them. include takes a Hash as argument now, which gives the layer name in which the code should be used.

So what does this do?

hpi = University.new("HPI", "Potsdam")
me = Student.new("Gregor", "Berlin", hpi)

me.to_s #=> "Gregor Schmidt"
hpi.to_s #=> "HPI"

ContextR::with_layer :address do
  me.to_s #=> "Gregor Schmidt (Berlin)"
  hpi.to_s #=> "HPI (Potsdam)"
end

ContextR::with_layer :education do
  me.to_s #=> "Gregor Schmidt; HPI"

  ContextR::with_layers :address do
    me.to_s #=> "Gregor Schmidt (Berlin); HPI (Potsdam)"
  end
end

The main difference in the new API is the different way of defining layer specific behaviour. The actual use of the different layers remains the same. In this short example we can already make use of the new possiblity to reuse code.

Hopefully I will demostrate more useful examples in the nearer future.

Where can I buy it?

sudo gem install contextr

To use it in your project you have to add these three lines to your code

require 'rubygems'
gem 'contextr'
require 'contextr'

I’m not sure, why I need three lines and not just the first and one of the others. Perhaps one of you has an idea.

Ruby is cheating on super

Posted by Gregor Schmidt
(2007-06-28)

The super call in Ruby differs in semantics from many other oo-languages. You are not simply refering to the class definition one level above, but just the method definition one level above. Additionally you may use super without arguments to tell the interpreter to use the same ones, the current method just received.

But this leaves one question open. How could you call super with no argument, while the current method received some. Besides super being a reserved word it should act as natural as possible and ideally feel like any message send. But it doesn’t, unfortunately.

Please look at the following sample code.

class BaseClass
  def method_with_default_parameter(arg0 = :default)
    arg0
  end
end

class InheritingClass < BaseClass
  def method_with_default_parameter(arg0)
    [ super,
      super(),
      super(arg0) ]
  end
end

And guess what happens when this is called

InheritingClass.new.method_with_default_parameter(:custom)
   # => [:custom, :default, :custom]

In some way this desired behaviour, but not what I would call least suprise. Ruby differentiates in this case between super and super(). This is only possible since the parser already knows super and nobody can emulate that with a custom message sends. A nasty trick that does not allow any api using yield to provide a similar behaviour in similar situations.

Could be corrected in 1.9. What do you think?

Camping Tips

Posted by Gregor Schmidt
(2007-06-07)

I’m still in the Ruby field. I just started to look at Camping a Ruby Microframework for web applications, written by the glorious _why. Since there is little information/documentation on the net, I’d like to point you to my favourite ones:

  • polzr.goes :Camping is a blog, that may be read as Camping tutorial and gives good code snippets to learn from
  • RDoc - I recommend the documentation delivered with the camping gem over the official one. You may access it easily with gem_server at your local machine. Although they contain the same information, I prefer the standard layout
  • and of course the Camping Wiki with information on installation and deployment and some useful hints here and there

Lax Specs

Posted by Gregor Schmidt
(2007-06-01)

Partly off topic, but we are all in the software business and every reader will know what I am talking about.

Yesterday evening I got the idea, that “The Hitchhiker’s Guide to the Galaxy” would be a great example of underspecification. So I will try to use this movie snippet in every new project to stress the need for good specs. Otherwise you will get answer for question, you never asked.

Introducing cache_annotations the other way round

Posted by Gregor Schmidt
(2007-06-01)

In one of my last articles I introduced my lasted gem cache_annotations. Today I think it was explained as black vodoo, which might be uncomfortable to most readers. Therefore, I’ll start again, but the otherway round and everybody will love its simplicity.

cache_annotations

With CacheAnnotation you may easily provide your methods with an often needed caching. Suppose you are using the following piece of code:

class A
  def a
    @a ||= "some heavy computing that should be" +
        " done only once"
  end
end

This could look so much better:

class A
  include CacheAnnotation
  
  cached
  def a
    "some heavy computing that should be done only once"
  end
end

Or even better for single argumented methods:

class A
  def b(arg0)
    @b ||= {}
    @b[arg0] ||= "some heavy computing in " +
                 "respect to #{arg0} " +
                 "that should be done only once"
  end
end

vs.

class A
  include CacheAnnotation
  
  cached
  def b(arg0)
    "some heavy computing in respect to #{arg0} " +
    "that should be done only once"
  end
end

Behind the scenes, CacheAnnotation replaces the method body with the caching code. So the two versions are equal concerning behaviour and speed. If you don’t want CacheAnnotation to derive the instance variable’s name from the method name, you may supply a custom one:

class A
  include CacheAnnotation
  
  cached :in => :@b_cache
  def b(arg0)
    "some heavy computing in respect to #{arg0} " +
    "that should be done only once"
  end
end

If you want to use CacheAnnotation on the class side, you have to use a special technique to add these methods. It is described pretty good on http://www.dcmanges.com/blog/27

class A
  module ClassMethods
    include CacheAnnotation

    cached
    def c
      "some heavy computing that should " +
            "be done only once"
    end
  end
  self.extend(ClassMethods)
end

Final Remarks

That’s all the voodoo. Generating a simple method for you, basically the same thing attr_* does.

You will find other chunks of repeated code and you should think, if this could be stripped of and be used in a declarative way.

cache_annotations release to the wild

Posted by Gregor Schmidt
(2007-05-28)

Ruby is all about keeping things simple, letting others do the simple work and being creative and not occupied. Have you ever thought about how often you are writing down the same idioms. Although they may look cleaner than in other languages it is cumbersome to write the same patterns over and over.

cache_annotations tries to eliminate one of these. And I encourage everybody to spot others and ged rid of these to. This is Ruby and it should look as lean and mean as possible. cache_annotations is a simple annotation-like, aop-inspired api that allows you to mark methods as functional. These will always return the same values, given the same parameters and do not produce any side effects. Examples would be any mathematical computation, database selects on a read-only db or between to updates.

Fibonacci example

I have a pretty easy and striking example to show the use and beauty of cache_annotations. The Fibonacci sequence. The following code will compute every fibonacci value corresponding to the recursive defintion on Wikipedia.

class Fibonacci
  module ClassMethods
    def compute(number)
      if number < 0
        raise ArgumentError.new(
            "Fibonacci is not defined for numbers < 0")
      elsif number < 2
        number
      else
        Fibonacci.compute(number - 2) + 
             Fibonacci.compute(number - 1)
      end
    end
  end
  self.extend(ClassMethods)
end

Fibonacci.compute(10) # => 55

But after looking closely to the code you may see, that esp. for larger numbers, this defintion is a killer. For each call it executes two recursive other calls and this eats stack levels. Besides that Fibonacci.compute(number - 2) is computed twice, one time in each recursive call. Finally computing Fibonacci.compute(100) takes ages - or at least longer than 10 seconds.

We have got two options here. Switch to a non-recursive function definition or avoid the double computation by caching results.

Enter cache_annotations

require 'rubygems'
require 'cache_annotations'

class Fibonacci
  module ClassMethods
    include CacheAnnotation
    
    cached :in => :@fibonacci_cache
    def compute(number)
      if number < 0
        raise ArgumentError.new(
            "Fibonacci is not defined for numbers < 0")
      elsif number < 2
        number
      else
        Fibonacci.compute(number - 2) + 
             Fibonacci.compute(number - 1)
      end
    end
  end
  self.extend(ClassMethods)
end

That’s it. No need to rewrite, not much more code. The compute function is automagically cached into an instance variable Hash named @fibonacci_cache. The performance inprovements are tremendous with two additional lines of code and no additional brain work.

The gem

Want to use it on your own? All you need to do is

sudo gem install cache_annotations

I just released it, so it may take a day to reach all rubyforge mirrors. Detailed information and other examples may be found in the API doc. If you have any problems, ideas or comments, feel free to leave a comment or drop me a line via mail.

API docs

Posted by Gregor Schmidt
(2007-05-22)

I’m working on and with ContextR for some time now. And since I am a proud member of the open source community, I registered ContextR at ohloh.net. It features a basic source code analysis, computing the lines of code for languages used and how many lines are used for comments.

The latter was a weak point for ContextR. But finally I managed to add significant documentation for all public interfaces. And there we go. ohloh states:

Across all Ruby projects on Ohloh, 16% of all source code lines are comments. For ContextR, this figure is 22%.

If you are interested in these, visit contextr.rubyforge.org/contextr.

ContextR - a context-oriented programming interface for Ruby

Posted by Gregor Schmidt
(2007-05-10)

During my master’s project, I am implementing an context-oriented programming (COP) language extension for Ruby - ContextR.

You may find more information about COP at www.swa.hpi.uni-potsdam.de/cop.

ContextR is hosted on RubyForge and is release as a gem. For additional information see the API documentation and the project page

Ruby User Group Berlin - ContextR

Posted by Gregor Schmidt
(2007-05-03)

I will hold a short introductory talk on context-oriented programming and ContextR, which will be the basis for my master’s thesis, tonight. I just finished my slides and just want to share them with you.

You may always find the current development version of ContextR on rubyforge.org/projects/contextr. When the first version is ready to release, I will let you know.

Update

We had great fun yesterday. Thanks to the boys and girls from id-media. I got great feedback and new ideas for ContextR. Thank you all.

In the second and larger part of the evening we talked about deployment of rails apps and heard an expert from meinprof.de - a well known german community site riding on rails. It looks like Apache 2.2, mod_proxy_balance and Mongrel clusters are the way to go. But the guys from meinprof raise the bar even higher with a super redundant setup. Starting with firewalls, load balancers, of course application servers and in the nearer future a mysql cluster. They seem to know, what they are doing.

attr_accessor on Steroids

Posted by Gregor Schmidt
(2007-04-24)

Every Ruby programmer knows the nice metaprogramming feature of att_reader, attr_writer, and attr_accessor. You use them, I use them, everybody does. There is nothing wrong with them. But how often do you write things like this:

  class Foo
    attr_accessor :bar

    def initialize
      self.bar = Hash.new
    end
  end

Or as well something like this:

  class Foo
    attr_writer :foo
    def foo
      @foo ||= Hash.new
    end
  end

I do. And this is simply annoying. It’s not nice and slow in certain occasions. I will support this with some easy benchmarks in MRI (Ruby 1.8.6)

Benching

I tested different scenarios. How long takes the initialization of a new Object. What about the first access and what about consequtive accesses. I benched them for each implementation strategy and tried to set the number of iterations to a maximum runtime of 2 seconds. As you would guess, testing the setting of a new value does not make much sense. It tried anyway and they are equal - so forget about it.

Strategy Initialization (1,000,000) First Access (100,000) Consequtive Access (4,000,000)
Initializer2.00.051.3
Custom Setter0.70.12.0

What we see is, that ( 0.1 is not close to a maximum value of 2.0 seconds, but just wait some lines and ) everything behaves as expected. The first implementation is expensive on initialization, the other is more expensive when it comes to reading.

I wonder if there is something, that could combine the pros of both concepts. As you already see, this one would be a lot more expensive on the first read, but there is no such thing as free lunch.

Meta Magic

Let’s look, what is already there. There is for example ActiveSupport’s Module extension called attr_accessor_with_default - currently only in the trunk. But it has two downsides.

  • It does not set the actual default value, it just returns on, if there is none. This may be right for certain cases, but not for me.
  • It uses module_eval with a string, and we have just learned, that this will not be good in the future

But I used that approach to implement my own idea. Its name is attr_accessor_with_default_setter. This is neither cool nor short, but it

  • does not clash with ActiveSupport’s naming and since it provides different semantics this would hurt
  • stresses the fact, that it actually sets the default value whenever it was accessed

attr_accessor_with_default_setter

  class Module
    def attr_accessor_with_default_setter( *syms, &block )
      raise 'Default value in block required' unless block
      syms.each do | sym |
        module_eval do
          attr_writer( sym )
          define_method( sym ) do | |
            class << self; self; end.class_eval do
              attr_reader( sym )
            end
            if instance_variables.include? "@#{sym}"
              instance_variable_get( "@#{sym}" )
            else
              instance_variable_set( "@#{sym}", block.call )
            end
          end
        end
      end
      nil
    end
  end

The implementation is pretty basic. It mixes the two approaches above. First of all it adds an attr_writer since it cannot hurt and it places a method as getter that sets the instance variable to the default value and afterwards replaces itself with the general attr_writer. Of course, somebody could have set the instance variable without using the default reader first - therefore whe have to check, whether it was already used, before applying the default value and that’s it.

The Usage

  class Foo
    attr_accessor_with_default_setter :bar do
      Hash.new
    end
  end

Pretty nice, despite the long name. But it was not my main goal to nice things up. Although there is one occasion, where it is actually a lot more DRY. Just imagine multiple instance variables that all have the same default value. This would become talkative with the other approaches.

  class Solution
    attr_accessor_with_default_setter :pros, :cons do
      Array.new
    end
  end

What else

Okay, now it has to run next to the other implementations in my tiny benchmark. I will repeat the other values for better comparison:

Strategy Initialization (1,000,000) First Access (100,000) Consequtive Access (4,000,000)
Initializer2.00.051.3
Custom Setter0.70.12.0
Meta Magic0.72.01.3

Perfomance of Different Default Value Implementations on MRI

It performs as expected. It is as fast on initialization and consequtive accessing as the best in these disciplines. Only one big downside: the first access is really slow. It has to module_eval, reflect on instance variables, and define a method. This takes a lot more time.

What we have learned

There is not single solution to this problem. If you want it fast, you have to evaluate the options. But I hope everybody is equipped with the needed knowledge now.

Annotation: The actual results may differ from interpreter to interpreter, but the overall / relative values will remain the same.

Performance of Dynamic Code Invokation

Posted by Gregor Schmidt
(2007-04-18)

In my new project I need to surround basic method with some wrapping code, which should be called dynamically, e.g. not each time, but under certain circumstances. In a first implementation by Christian Neukirchen this was done by adding the code in private methods and substituting the core method with code, that calls the other ones. Simple and charming.

But I will try a different approach. More details will follow later. For now I need to now, how to inject new code into a class or better a single object as fast as possible. To get the right feeling, a simple message send to the object will act as basic measuring unit.

Implementations

I came up with these options:

  • wrap your code into a block and call instance_eval on the object
  • wrap your code into a string and call instance_eval on the object
  • wrap your code into a method within that class and fetch the corresponding UnboundMethod. Bind that UnboundMethod to the object and execute it
  • a variation of the former, just include the binding into the bechmark

These result in the following code:


  require 'benchmark'
  
  class A
    def a
      true
    end
  end
  
  n = 1_000_000
  Benchmark.bm(30) do | b |
    instance = A.new
    b.report( "simple call" ) do
      n.times { instance.a }
    end
  
    instance = A.new
    block = lambda { true }
    b.report( "instance_eval with block" ) do
      n.times { instance.instance_eval( &block ) }
    end
  
    instance = A.new
    string = "true"
    b.report( "instance_eval with string" ) do
      n.times { instance.instance_eval( string ) }
    end
  
    method = A.instance_method( :a )
    instance = A.new
    bound_method = method.bind( instance )
    b.report( "bound method" ) do 
      n.times { bound_method.call }
    end                        
  
    method = A.instance_method( :a )
    instance = A.new
    b.report( "bind method each time" ) do
      n.times { method.bind( instance ).call }
    end
  end

That was easy…

And now the results

I tested it on Ruby 1.8.6 and Ruby’s YARV trunk (2007-04-12) and JRuby trunk (2007-03-31) on my MacBook. First of all the numbers:

Ruby 1.8.6 (MRI) Ruby 1.9 (YARV) JRuby
simple call 1.0 (0.42)* 1.0 (0.25) 1.0 (1.40)
eval with block 2.5 (1.08) 6.3 (1.57) 1.6 (2.28)
eval with string 7.3 (3.06) 48 (12.10) 26.5 (37.15)
bound method 1.2 (0.49) 1.8 (0.45) 1.2 (1.73)
bind method each time 2.7 (1.15) 4.3 (1.08) 3.1 (4.35)

All results in a nice graph

To make it clear, I did not compare the performance of MRI with YARV or JRuby - this is done elsewhere. I also did not optimize JRuby’s perfomance with some environment variables (see this article to see what should be done). First of all, I wouldn’t know which and then it wouldn’t change much, because I only compare JRuby with itself. I was only interested in the fastest implementation strategie.

And the winner is bound method. When I am able to cache the bound methods for all objects, then I have nearly no performance impact related to the inclusion of the “foreign code”.

Lessons learned

Do not call instance_eval in YARV or JRuby with a String regularly. No, no, no. It looks evil and it is really slow. The only advantage is that no closure has to be stored so it may be useful for light dynamic method definitions.

)* The numbers in brackets are seconds, the absolute results printed to stdout.

Written in Ruby - contd.

Posted by Gregor Schmidt
(2007-04-15)

Avi Bryant, creator of Seaside, brings down, what I tried to say in Written in Ruby. Only a Ruby implementation in Ruby will enable significant speed improvements and allow a future development with the current momentum.

Therefore go ahead and help the people with Rubinius.

Remark: Christian Neukirchen added another aspect … somehow … but I think, this is still another level.

International Methods

Posted by Gregor Schmidt
(2007-03-24)

I just recognized, that after setting the $KCODE to "u", either via command line ([ruby|irb] -Ku) or within the script, international method names are allowed in Ruby. Examples for these are available at Ruby-Mine, a German Ruby blog I just found at the [Ruby|Rails] User Group Berlin. I really have to show up there on their next meeting

Multiple Inheritance without MixIns

Posted by Gregor Schmidt
(2007-03-18)

This work is based on Maurice Codik's start from last year. I spent some hours on it today and I am willing to release it to the public. The basic implementation idea didn't change, but I had to change some strategies in order to implement a reasonable method resolution order. This may also mean, that the performance of message sends suffers from these changes. So this library is not meant to work in public software, but it may be used to fool around and see what is possible.

My main targets where a reasonable method resolution order (namely Python-2.3's) and the functionality of the main meta object and reflection protocol of ruby (see this post for some examples).

Download

You may download the library in its very first version (0.1) here. The RSpec file is available separately.

Update: The code is now available on GitHub

Specification

I have used Rspec to state my wishes.
Assuming, that A and B are direct subclasses of Object

A subclass of A and B

  • should answer with [A, B] when sended superclasses
  • should not list constants defined in its superclasses, when sent constants
  • should not answer true to const_defined? for constants defined in A or B
  • should answer true to const_defined? for constants defined in it
  • should list methods of its superclasses in instance_methods( true )

The Ancestors of a subclass of A and B

  • should contain A, B and Object
  • should have A as first element
  • should not include double entries
  • should contain A before B
  • should contain B before Object

An instance of a subclass of A and B

  • should be kind of its class
  • should be kind of its super classes
  • should be kind of its super super classes
  • should prefer its own methods over inherited ones
  • should be able to call inherited methods
  • should be able to combine inherited calls
  • should prefer methods defined in A over Object’s
  • should prefer methods defined in B over Object’s
  • should prefer methods defined in A over B’s (left first)
  • should be able to use method_missing
  • should be able to use method_missing in one of its parents
  • should answer respond_to?( 'some method in A' ) with true
  • should answer respond_to?( 'some method in B' ) with true
  • should answer respond_to?( 'some method in Object' ) with true
  • should be able to access constants defined in superclasses directly
  • should be able to use const_missing
  • should list methods of its superclasses in methods
  • should be able to use methods from A and B using own instance variables
  • should be able to use blocks for methods in superclasses

When A and B are subclassed by a class, they - should be informed via self.inherited( subclass )

I did not yet work on instance or class variables, as well as the behaviour of private or protected methods (who uses them anyway?). Please send me your ideas or bug reports. I am sure, that this is far from perfect.

List of callback methods

Posted by Gregor Schmidt
(2007-03-18)

If you ever wondered about the power of method_missing you were still missing a lot. Ruby has a whole bunch of meta callback methods. Since I always forget some of them, I will try to collect all of them in the following list, so everybody may benefit. If I missed something, please give me a hint.

ClassNamecorresponds to
Moduleincluded
Moduleextended
Moduleappend_featureinclude?
Moduleconst_missingconst_defined?
Modulemethod_added
Modulemethod_removed
Modulemethod_undefined
Classinherited
Objectsingleton_method_added
Objectsingleton_method_removed
Objectsingleton_method_undefined
Kernelat_exit
Kernelmethod_missingrespond_to?
Kernelset_trace_func
Kerneltrace_var
Kerneluntrace_var
ObjectSpaceeach_object

Most of this list is taken from this discussion on ruby-talk.

And of course there are all these nice collections, you may request.

ClassNameinclude super
Moduleancestors
Moduleconstants
Moduleincluded_modules
Moduleinstance_methodstrue
Moduleprivate_instance_methodstrue
Moduleprotected_instance_methodstrue
Modulepublic_instance_methodstrue
Moduleclass_variables
Classsuperclass
Objectmethods
Objectprivate_methodstrue
Objectprotected_methodstrue
Objectpublic_methodstrue
Objectsingleton_methodstrue
Objectinstance_variables

Please note, that most of the *methods have a parameter, which allows you to exclude inherited properties from the answer (as listed in the table).

Every ambitous Ruby programmer should have a look at these and come back each one or two months. These methods will allow you some shortcuts and more elegant solutions. As well, make sure, that these still work, after you introduced changes on the meta-level.

Introduction

Posted by Gregor Schmidt
(2007-03-18)

An overview of the code, I wrote. Not more not less

Mephisto Bloglines Plugin

Posted by Gregor Schmidt
(2007-03-03)

In order to prove my latest theory (ref: Written in Ruby) I just wrote my first Mephisto Plugin. You are now able to include your Bloglines blog roll into your mephisto blog. Since I may not give you anonymous svn access I provide a downloadable tgz. All the things you need to know may be found in the README. To install it, just extract the file to your vendor/plugins directory.

cd /tmp
wget http://www.nach-vorne.de/assets/2007/3/3/mephisto_bloglines.tgz
tar zxvf mephisto_bloglines.tgz /your/mephisto/dir/vendor/plugins

Restart your server afterwards and follow the instructions in the README. The code is licensed under the Ruby license. If you have any problems or feature requests, please leave a comment or drop me a line via mail.

Written in Ruby

Posted by Gregor Schmidt
(2007-03-01)

In this article I'ld like to point out, why "written in Ruby" is a pro and never a con for each Ruby related software, e.g. interpreter, libraries and IDE.

In her daily life a ruby programmer probably prefers c-libraries over native ruby ones, because of their tremendous speed advatages. Nobody likes to compare Rexml with libxml on that battle ground. But the usage of non-native tools hampers Ruby's general development. The need to improve the interpreters speed decreases. The quality of libraries may not be reviewed, like it could when written in a language every user of it understand.

I'ld like to cite popular examples here: Lisp and Smalltalk. Both based on a really really really small core written in whatever language and afterwards bootstrapped to be implemented in itself, running on byte code (I have no problem with a speedy AST interpreter, but I haven't seen one yet). Each and every Smalltalk user is able to change the inner windings of its standard library without speed loss usage of RubyInline (which is really great by the way, although I would feel better, if we wouldn't need it). This is where I would love to se Ruby in 2 to 5 years. And that is why I would prefer the Rubinius approach over YARV. Even porting the AST to Smalltalk byte code, as Avi Bryant proposes it, could work well. Just get rid of this old school c code, please.

But I will have a look on that in the future and comment on it, as something happens.

post: Did I mention, that the above statements are the reason, why this blog uses mephisto and not wordpress, although its feature set is more promising and the performance outstanding in comparison. Apache is c but mongrel is said to be Ruby in large parts although I didn't check.

Power to the People

Posted by Gregor Schmidt
(2007-03-01)

On Zen and the Art of Ruby Programming Antonio Cangiano compares the speed of several Ruby implementations.

Interesting to see, that YARV is that much faster. On my particular problem, which mainly consists of message sends and each-loops, I expirienced only 10 % improvements over the standard ruby distribution. So I should review my implementation to gain improvements there, no chance to get it for free on other interpreters.

ruby -e "puts 'Hello World'"

Posted by Gregor Schmidt
(2007-02-25)

Welcome. More to come lateron. At first I will fight with deployment.

ruby -e "puts 'Hello World'"

Update: Done. It works pretty well. Not superfast but acceptable. I use Apache2.2 with proxy_balancer and 2 Mongrel working in the back ... an a virtual server.

This blog will serve as documentation for my master's thesis and my regular thoughts on Ruby. Rails, Web2.0, and other buzz words that make you win. I hope you'll enjoy your stay. More information will come lateron, when I finally started working in it.

An Editor for Ruby

Posted by Gregor Schmidt
(2007-02-25)

In one of my first postings I'd like to mention, what I think, Ruby lacks today.

A good editor

I use vi, some use emacs, others like textmate. RadRails and/or RDT for Eclipse have a good feature set. Komodo Edit looks great. But they all have one great disadvantage. None of them is written in Ruby.

I think, the community needs a cross-plattform editor, written in Ruby and some cross-plattform gui toolkit, that renders nicely on the main ruby development systems - linux and mac os. It should be more than simple macros and text replacement (I'm refering to TextMate here).

I'd like to have autocompletion both context aware and on a pattern matching file based style (everything, that vi is able to do in version 6), a class browser for all classes and not just the current file, a refactoring wizard or helper or tool or view. To cut it short, I'd like to have the Smalltalk development tools for Ruby - with one exception: the base editor. The thing with that you edit texts in Squeak is really hard to love - perhaps you can get used to it after half a year. But one could do this better. I think the Smalltalk guys started with all the interesting stuff, as I would do, and forgot about the editor itself.

Why should it be written in Ruby? Because then it may be edited and extended by the ones who use it. That is the only way to ensure constant development.

I don't know who should build this editor, but I would spent money for that.