The Artima Developer Community
Sponsored Link

Ruby Code & Style
If It's Not Nailed Down, Steal It
Pattern Matching, S-Expressions, and Domain Specific Languages in Ruby
by Topher Cyll
May 23, 2006

<<  Page 5 of 5

Advertisement

Go, Turtle. Go!

Okay, let’s put multi to use again and build a method to run Logo S-expressions. We can put this in the initialize method along with the code to initialize our instance variables.

  def initialize
    @x, @y  = 100, 100
    @angle  = 0
    @buffer = "" 
    @pen    = true

    amulti(:run, :right, Numeric)   {|sym, r, rest| turn(r) ; run(rest)  }
    amulti(:run, :left, Numeric)    {|sym, l, rest| turn(-l) ; run(rest) }
    amulti(:run, :forward, Numeric) {|sym, f, rest| move(f) ; run(rest)  }
    amulti(:run, :penup)            {|sym, rest| @pen = true ; run(rest) }
    amulti(:run, :pendown)          {|sym, rest| @pen = false ; run(rest)}
    amulti(:run, :repeat, Numeric, Array) do |sym, i, code, rest|
      i.to_i.times{ run(code) }
      run(rest)
    end
    amulti(:run) {}
  end

So what’s going on here?

The ‘run’ function takes a list of commands and arguments and consumes them as appropriate. The first two definitions pull the :right or :left command off the list along with a number of degrees to rotate. The turn() function does the dirty work. Note that all of the ‘run’ bodies recurse on the remaining arguments.

The definition that matches :forward moves the turtle, :penup and :pendown sets the value of @pen, and, finally, :repeat takes a number of times to repeat and an array of code to run. So let’s try this out.

(You can download the complete source here)

Testing Time

Running this code …

  logo = Logo.new
  logo.eval %q{
    repeat 4 (forward 100 right 90)
    forward 50 right 90 forward 100
  }
  puts logo.render

... gives us:

Logo output 2

Looks right!

Let’s Quit While We’re Ahead

Pattern-matching multiple dispatch, S-expressions, and Logo, that’s a pretty good haul. So next time you’re missing Haskell, or Lisp, or something really weird like Logo, why not just stick with Ruby? Of course, you might have to steal a few things first …

Resources

[0] DSLs in OCaml
http://www.venge.net/graydon/talks/mkc/html/index.html

[1] Internal versus External DSLs
http://www.martinfowler.com/articles/languageWorkbench.html

[2] Why’s (Poignant) Guide to Ruby
http://poignantguide.net/ruby/

[3] Introduction to Logo
http://mckoss.com/logo/

About the Author

Topher Cyll is a software engineer in Portland, Oregon, who’s lucky enough to write about half of his projects in Ruby. Topher wrote the Multiple Dispatch and S-Expression RubyGems used in this article. He also volunteers on the Tech Team of the progressive political group The Oregon Bus Project and is an active member of the Portland Ruby Brigade.

<<  Page 5 of 5


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us