Avanced Ruby Studio, Day 3

Notes after the jump.

Aside: They brew insanely strong coffee at the Sheraton…

Domain Specific Language

  • Discussions comparing DSLs to expressive DSLs
    • Me: I don’t believe that there’s a difference but Ruby brings us closer to English in our DSLs
    • DT: Which causes a whole new level of confusion because while it reads easily it’s hard to write
    • DSLs, to him, represent a domain-specific form of abstraction
  • Rake
    • CF: Dependency-oriented DSL
    • Me: Now that is a nifty abstraction to capture the purpose of Rake
  • Dhaka
  • JDWP DSL CF: cites an example of a Java Debugger Wire Protocol implementation that Rich Kilmer wrote by copying the documentation into a Ruby file and simply reformatting the docs into valid Ruby code.

    • Readable to SUN developers
    • DT: DSL is retargetable – specifies intent, not implementation
  • Implementation tricks

    • method_missing
  • CF: Most DSLs are block based

  • To instance_eval or not to instance_eval
    • instance_eval is constraining because it redefines self
    • DT: The DSL is a promise (Me: a contract? interface…) that should be consistent
  • Consider context: who will use the DSL?

This is a good discussion.

  • DSL anti-patterns
    • False familiarity
    • method_missing and respond_to> together
    • If you support one then you should support the other
    • Cluttering namespaces (flexibility)

break & exercise (write a morse code generator for a given pattern

  class MorseEncoder
    CHARS = {
      :a => "._",
      :b => "_...",
      :c => "_._.",
      :d => "_..",
      :e => "."
    }

    def initialize
      @msg = []
    end

    def encode(&block)
      instance_eval(&block).reverse.join(" ")
    end

    def method_missing(name, *args)
      @msg << CHARS[name]
    end
  end

  morse = MorseEncoder.new
  puts morse.encode { b e a d }

Extremely pleased how much more comfortable I’ve become with my use of blocks and closures over the period of this class. This course has provided some good brain strengthening exercises.

Exotic Control Flow

  • DT: “I don’t know what BASIC is. The dribbling old fool of programming langauages”
    • Likens exception handling to “goto on steroids”
    • Implies that goto is not necessarily harmful
    • It’s up to the individual programmer
  • DT: “Experts know when to break the rules”
  • LOL: Don’t not use positive logic
  • throw and catch

    • This is not Java’s throw/catch – almost the opposite (that’s raise and rescue)
    • catch takes a label and executes a block
    • throw takes a label and optional arguments
    • Causes Ruby to unwind the call stack to the first catch that matches
      • The optional parameter is the return value to provide from the catch
    • Real use: open-uri
    • Me: This would elminate so much code from my current project in the office – if they hadn’t already writen it in Java…
  • Continuations

    • callcc
    • requires a block with one parameter (the conitnuation)
    • Executes the block
    • When a continuation is called, execution resumes immediately after the continuation’s block
    • All control structures can be implemented via continuations

Lunch and Exercise

# Write the methods start_loop and end_loop so that the following does what you'd expect:

i = 0

again = start_loop

puts i
i += 1

end_loop(again) unless i > 5

… which is solved by:

def start_loop
  callcc { |cont| cont }
end

def end_loop(continuation)
  continuation.call(continuation)
end

… which was less code than I expected. Admittedly, I didn’t know at the time that Continuation#call’s parameter is returned by callcc but it made sense so I tried it. Principle of least surprise FTW!

I won a gold star for niftiest continuation implementatio for this exercise. Yay, me!

Debugging & Profiling

  • ruby -d
    • Sets $DEBUG
    • caller: call stack, file names, and line numbers (Me: handy stuff!!)
  • ruby-debug gem
    • Insert a debugger call into Ruby code to dump into the debugger from the runtime
    • Also requires requiring the gem (duh)
    • Inside the debugger, can launch into irb in the current context
  • gdb

    • Attach to the running Ruby VM
    • gdb gdb_path_to_Ruby_bin Ruby_VM_PID
  • Ruby ‘profile’ library

    • Me: Woops, didn’t know about this library!
    • ruby -r profile my_program_name
    • Profiling specific parts of code
    • Profiler__::start_profile
    • Profiler__::stop_profile
    • Profiler__::print_profile
  • Question about memory profiling
    • No known available tools
    • ObjectSpace – roll your own
    • DT: modified new to add a timestamp to every Object to add a timestamp to allow searching for super-stale objects
  • Exploring how objects are interacted with
    • Slide 329
    • Undef all of the methods on an object and then see what errors occur

JRuby

  • Java garbage collection
  • Hotspot
  • Java threads (native)
  • rake war:standalone:create
  • IronRuby promises Ruby in the browser

Distributed Programming

  • DRb (Me: cake)
  • Rinda (Me: been there done that)
    • UDP broadcasts
  • Custom Protocol Implementation
    • Transport mechanism
    • Encoding mechanism
  • GServer
  • NetSSH
  • Slide 396 for Multicast in Ruby
    • IPs 224.0.0.0 to 239.255.255.255 are multicast reserved addresses
  • Slide 398 shows a simple proc running on a WEBRick server: 7 lines of code. ;)
  • Rack
    • Sits on top of any web server and provides a WEBRick-like API
  • open-uri
    • rest-open-uri – patches open-uri to support other HTTP methods

Posted by evan on Friday, May 09, 2008

blog comments powered by Disqus