Interesting trival example of why open classes are good?

Hi,

I am trying to explain why the fact that Ruby's classes are never
closed is advantageous. I can only think of relatively complex examples
like Rails plugins. Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

Thank you,
Peter

Peter Michaux wrote:

Hi,

I am trying to explain why the fact that Ruby's classes are never
closed is advantageous. I can only think of relatively complex examples
like Rails plugins. Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

That is way too easy.

···

---------------------------------

#!/usr/bin/ruby -w

class Fixnum
  def odd?
    return self & 1 == 1
  end
end

10.times do
  puts rand(30).odd?
end

---------------------------------

There is no "odd?" function in Fixnum, but adding one is trivial.

Examples abound where this open-class business comes in handy.

--
Paul Lutus
http://www.arachnoid.com

Peter Michaux:

I am trying to explain why the fact that Ruby's classes are never
closed is advantageous. I can only think of relatively complex examples
like Rails plugins. Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

You may want to have a look at the facets code to get some ideas.

Kalman

Open classes also are a real boon when you're coding something
interactively in irb.

···

--
Lou.

Hi,

Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

The example below probably isn't what you're after, but as David said
it's pretty tricky to justify open classes in a self-contained example
this short.
It's just over 30 lines.

One other good example of their usefulness springs to mind though - I've
seen a few projects (I think RCov is one, though I could be wrong) that
have an extension replace some of their 'default' (ruby-implemented)
methods with ones implemented in C, for better performance or
integration. Obviously the benefit being that, if you can support the
native extension you get the improvements, but if not you can still use
the pure-ruby implementation, without changing your code at all.

Anyway, here's the (contrived) example:

#!/usr/bin/env ruby
class User
  def initialize(name, email)
    @name, @email = name, email
  end
  attr_accessor :name, :email
end

class Instrument
  class << self
    def on_call(clz, imethods = clz.instance_methods)
      clz.class_eval do
        imethods.each do |m|
          unless m =~ /^__/
            alias_method "__uninst_#{m}", m
            define_method(m) do |*args|
              r = __send__("__uninst_#{m}", *args)
              yield(self, m, args, r)
              r
            end
          end
        end
      end
    end
  end
end

Instrument.on_call(User, [:initialize, :name, :email]) do |slf, name,
args, r|
  puts "#{slf}.#{name} (#{args.inspect}) => #{r.inspect}"
end

u = User.new("billy", "billy@example.com")
puts "Username is: #{u.name}"
puts "Email is : #{u.email}"

puts "Uninst name: #{u.__uninst_name}"

···

On Sun, 2006-10-29 at 16:45 +0900, Peter Michaux wrote:

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk

Have you heard of the `cgi_multipart_eof_fix' gem? It was recently released to
patch an exploit in Ruby's CGI class which could be used to bring down Mongrel.
You load the gem and it patches the class during runtime. Rather than needing
to rebuild a patched Ruby.

Also, it's not just about adding methods, removing methods is a really handy
thing, too.

_why

···

On Sun, Oct 29, 2006 at 04:45:13PM +0900, Peter Michaux wrote:

I am trying to explain why the fact that Ruby's classes are never
closed is advantageous. I can only think of relatively complex examples
like Rails plugins. Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

Suppose you have written a word processor. Or at least
something that converts plain-text-with-markup to HTML, or TXT,
or PDF.

Since all to_html methods of all classes (Document, Header,
Section, TOC, Image, etc) work together closely to generate
HTML, you can define them in one file, instead of scattering
this functionality over dozens of files.

The main script (abc.rb) requires a couple of files:

require "abc_base"
require "abc_to_txt"
require "abc_to_html"
require "abc_to_pdf"

For me, it's often pointless to group all methods of one class
in one big file, like you have to do in Java. How do
Header#to_html and Header#to_pdf work together? Do they work
together? If not, why should I define them in the same place?

gegroet,
Erik V. - http://www.erikveen.dds.nl/

> I am trying to explain why the fact that Ruby's classes are never
> closed is advantageous. I can only think of relatively complex examples
> like Rails plugins. Does anyone have an interesting, standalone example
> showing the utility of open classes in under 30 lines? under 20?

That is way too easy.

---------------------------------

#!/usr/bin/ruby -w

class Fixnum
  def odd?
    return self & 1 == 1
  end
end

10.times do
  puts rand(30).odd?
end

---------------------------------

There is no "odd?" function in Fixnum, but adding one is trivial.

Thanks for the example. I like it and I'll use it.

Examples abound where this open-class business comes in handy.

Do you know of a nice little example that doesn't modify a built in
Ruby class? I didn't realize I wasn't specific enough in my request.

Thanks again,
Peter

Hello !

---------------------------------

There is no "odd?" function in Fixnum, but adding one is trivial.

  Not for long :wink: -> RCR337

  Vince

···

--
Vincent Fourmond, PhD student
http://vincent.fourmond.neuf.fr/

Peter Michaux wrote:

Hi,

I am trying to explain why the fact that Ruby's classes are never
closed is advantageous. I can only think of relatively complex examples
like Rails plugins. Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

I have some code where I'm unpacking utf-8 text into arrays of integers all the time. So I could have 'unpack' all over the place, but I just did:

class String
   def explode
     self.unpack('U*')
   end
end

  -Tim

'ello --

Peter Michaux wrote:

Do you know of a nice little example that doesn't modify a built in
Ruby class? I didn't realize I wasn't specific enough in my request.

# --- dynamic/X/here.rb

  class X
    def here
      puts "Here I am!"
    end
  end

# ---

  class X
    def method_missing(s, *a, &b)
      begin
        require 'dynamic/X/#{s}'
        send(s, *a, &b)
      rescue LoadError
        super
      end
    end
  end

  X.new.here #=> "Here I am!"

It's interesting pattern, don't you think? If you have large chunks of
code that only get used once in a while it's a way to speed up initial
load times. Actually you could write an entire program this way --with
each method in a different file (but that can be a chore to maintain).
In anycase it's an example of what you can do with open classes.

T.

Hi --

I am trying to explain why the fact that Ruby's classes are never
closed is advantageous. I can only think of relatively complex examples
like Rails plugins. Does anyone have an interesting, standalone example
showing the utility of open classes in under 30 lines? under 20?

...

Do you know of a nice little example that doesn't modify a built in
Ruby class? I didn't realize I wasn't specific enough in my request.

That's harder, because if I give you an example like:

   class C
     def m
     end
   end

   class C
     def n
     end
   end

I might as well have written it in one definition block :slight_smile:

One possible use of this open-class feature is to put a class
definition in more than one file. The Ruby library does this, for
example, with the Date class. The pros and cons are probably pretty
self-explanatory.

David

···

On Sun, 29 Oct 2006, Peter Michaux wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Hello !

Do you know of a nice little example that doesn't modify a built in
Ruby class? I didn't realize I wasn't specific enough in my request.

  I can give you that: in a meta system I'm writing, I want to be able
to build Qt widgets and to generate command-line parsers from a simple
definition. For the sake of simplicity, all this should reside in one
class. But I definitely don't want to link to Qt for a command-line-only
app. So here is my design:

common.rb:
class SomeClass
  def parse_command_line(...)
  end
end

qt.rb
class SomeClass
  def create_qt_stuf(...)
  end
end

  Then, I always have command-line generation available (it's a standard
ruby lib), but if I want Qt, I just need to require 'qt.rb' in addition
to 'common.rb'.

  Works great, and rdoc parses everything correclty, which is even greater !

  Vince

···

--
Vincent Fourmond, PhD student
http://vincent.fourmond.neuf.fr/

Hi,

Examples abound where this open-class business comes in handy.

Do you know of a nice little example that doesn't modify a built in
Ruby class? I didn't realize I wasn't specific enough in my request.

It isn't little, but xampl in Ruby makes heavy use of this capability (see my sig for links). I'd think that most code-generators could take advantage of open-classes.

It also allows you to organise your source code, at least partially, on a functional basis rather than a class basis.

It is also kind of central to the implementation of Ruby's definition of methods on objects, usually class objects, but not necessarily, allowing you to do stuff like:

class Basics
   def initialize(name)
     @name = name
   end
   def tag
     return "#{@name} says"
   end
   def hello
     puts "#{tag}: hello"
   end
   def method_missing(s, *a, &b)
     puts "#{tag}: pardon?"
   end
end

a = Basics.new('a')
b = Basics.new('b')

a.hello
b.hello

a.bye
b.bye

def b.bye
     puts "#{tag}: bye"
end

a.bye
b.bye

Cheers,
Bob

···

On 29-Oct-06, at 3:10 AM, Peter Michaux wrote:

Thanks again,
Peter

----
Bob Hutchison -- blogs at <http://www.recursive.ca/hutch/&gt;
Recursive Design Inc. -- <http://www.recursive.ca/&gt;
Raconteur -- <http://www.raconteur.info/&gt;
xampl for Ruby -- <http://rubyforge.org/projects/xampl/&gt;

A side-effect of this is that when working with a team, you are less
likely to need to merge changes in your SCM tool.
Imagine if every piece of ActiveRecord were in one file. Rails would
probably just be getting around to 'Hello, world' about now.

···

On 10/29/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

On Sun, 29 Oct 2006, Peter Michaux wrote:

>>> I am trying to explain why the fact that Ruby's classes are never
>>> closed is advantageous. I can only think of relatively complex examples
>>> like Rails plugins. Does anyone have an interesting, standalone example
>>> showing the utility of open classes in under 30 lines? under 20?
>>
...
> Do you know of a nice little example that doesn't modify a built in
> Ruby class? I didn't realize I wasn't specific enough in my request.

That's harder, because if I give you an example like:

   class C
     def m
     end
   end

   class C
     def n
     end
   end

I might as well have written it in one definition block :slight_smile:

One possible use of this open-class feature is to put a class
definition in more than one file. The Ruby library does this, for
example, with the Date class. The pros and cons are probably pretty
self-explanatory.