Monday, January 19, 2009

Methodless Ruby


In an earlier post I have shown how Ruby can be used (or abused) as a language implementing different object models than the built in model. Ruby's built in model is Single Inheritance and Module Mixin as probably everybody reading this knows. If you have stumbled upon this blog and do not know Ruby's object model you might want to read about it first. E.g. in the famous Pickaxe Book.

The last time I was exploring object models I blogged about "Classless Ruby".
I was however still making use of modules and methods.

Today I will get rid of them too, well I will still write some Core class methods but once that is done there will be no more classes, no more modules, no more methods and no more instance variables.

The outcome will resemble prototypes, but the beauty of the whole, the beauty of Ruby, is that even that is just my implementation and different developement paradigms could be explored almost as easily.

'nuff ta'king for now...





TOC

Where To Put The Behavior?
A very revolutionary idea stolen from Perl 5! (five not 120)

But What Is Behavior, Now?
Hashes might still store proc objects for different purposes though.

Fixing Some Problems
Some of the shortcomings discovered so far can be fixed...

Quinctilie Vare, legiones hash redde![1]
I am much luckier than Quinctilius Varus, I can give the hash back.

Codereuse
Being lazy I want mixins an that kind of stuff, right!

Résumé
What did I actually do? Where shall I go?





Back to TOC
Where To Put Behavior?

I did not really think a long time about this, and I do not believe that there are many alternatives with the given constraints. Hashes really should do the job nicely.
They allow us to store the data and the behavior together ( we are not abandoning the encapsulation principle yet ). As I mentioned above that is exactly what Larry Wall did in Perl 5 and that allowed for some nice object oriented programs after all.

A straightforward shot at this might look like the following
 1 book = {
 2   :author => 'Mark Twain',
 3   :date   => 2364,
 4   :title  => 'Tom Sawyer meets Data',
 5   :image  => proc{ | myself |
 6     puts %<"#{myself[:title]}" by #{myself[:author]} was published in #{myself[:date]}>
 7 }
 8 }
 9
10 book[:image].call( book )
11


When we look at line #10 however we are not very happy, are we? Well we should not. There are two redundancies involved. Firstly we have to pass the receiver into the proc object again, and secondly we have to call the proc object recursively. We will get rid of this nuisance immediately.

1 class Hash
2   alias_method :__old_get__, :[]
3   def [] name, *args
4     value = __old_get__( name )
5     return value unless value && value.is_a? Proc
6     value.call( self, *args )
7   end
8 end


and now this works

1 book[:image] # --> "Tom Sawyer meets Data" by Mark Twain was published in 2364





Back to TOC
But What Is Behavior, Now?


We are very, very happy with our design, we can pass arguments into our new [] call syntax as the following example shows:
 1 book = {
 2   :author => 'Mark Twain',
 3   :date   => 2364,
 4   :title  => 'Tom Sawyer meets Data',
 5   :image  => proc{ | myself |
 6     puts %<"#{myself[:title]}" by #{myself[:author]} was published in #{myself[:date]}
 7     annotations: #{(myself[:annotations]||[]).join(", ")}>
 8   },
 9   :add_annotations => proc{ |myself, *annotations|
10     myself[ :annotations ] ||= []
11     myself[ :annotations ] += annotations
12   }
13
14 }
15
16 book[:add_annotations, "Edited by J-L.Picard", "Reviewed by William T. Riker"]
17 book[:image]


and we get the hoped for

"Tom Sawyer meets Data" by Mark Twain was published in 2364
annotations: Edited by J-L.Picard, Reviewed by William T. Riker


Thus I am happy again, and often when I am happy, there is something really, really wrong. One of the things that are wrong became apparent when I needed to store a proc object in the hash and that proc object was not implementing behavior of the object.
1 book[:adder] = proc{ | a, b | a + b }
2 a = book[:adder]


When running this I got of course an error

method-less-4.rb:34:in `block in
': undefined method `+' for # (NoMethodError)
from method-less-4.rb:10:in `call'
from method-less-4.rb:10:in `[]'
from method-less-4.rb:35:in `
'





Back to TOC
Fixing Some Problems

So far we have successfully bound behavior to data with procs. We have however introduced an ambiguity between Behavior members and Proc members in our objects.
Furthermore we have not yet introduced a generic object creation mechanism. No, dup will not suffice, but there is not needed much more.
Worse though, there is no object initialization mechanism either. We will fix these three issues now and then review what we have got, again.

Behavior is not Proc
Subclassing Proc shall give us the information we need to do the right thing when accessing an object's member. Furthermore a nice subclass factory method, e.g. Kernel#behavior will provide more readable code.

 1 
 2 Behavior = Class::new Proc
 3
 4 module Kernel
 5   def behavior &blk
 6     Behavior::new( &blk )
 7   end
 8 end
 9

In lines 1 to 8 we just subclass Proc and define a Kernel method that wraps the constructor call of Behavior which is the inherited one.
 9 
10 class Hash
11   alias_method :__old_get__, :[]
12   def [] name, *args
13     value = __old_get__( name )
14     return value unless value && value.is_a?( Behavior )
15     value.call( self, *args )
16   end
17 end
18

Thanks to our little sub-classing game before we can dispatch on Behavior now. By specifying Behavior with the behavior method, and Proces with the proc method (see lines 23, 27 & 31) we implement the desired behavior ( no pun intended ).

18
19 book = {
20   :author => 'Mark Twain',
21   :date   => 2364,
22   :title  => 'Tom Sawyer meets Data',
23   :image  => behavior{ | myself |
24     puts %<"#{myself[:title]}" by #{myself[:author]} was published in #{myself[:date]}
25     annotations: #{(myself[:annotations]||[]).join(", ")}>
26   },
27   :add_annotations => behavior{ |myself, *annotations|
28     myself[ :annotations ] ||= []
29     myself[ :annotations ] += annotations
30   },
31   :adder => proc{ | a, b | a + b }
32 }
33
34 book[:add_annotations, "Edited by J-L.Picard", "Reviewed by William T. Riker"]
35 book[:image]
36
37
38 book[:adder] = proc{ | a, b | a + b }
39 a = book[:adder]
40 p a.call( 40, 2 )

and we get

"Tom Sawyer meets Data" by Mark Twain was published in 2364
annotations: Edited by J-L.Picard, Reviewed by William T. Riker
42


Constructing and Initializing Objects
In order to construct objects we have to make sure that they do not share any data with the prototype. This holds even more as, in this kind of prototype programming any object can be used as the receiver of the construction message.
1 class Hash
2   def new initial_values = {}
3     dup
4     initial_values.inject( dup ){ | o, (k, v) |
5       o.update k => ( v.dup rescue v )
6     }
7   end
8 end

In the code above we just define a new method for a hash. N.B. This is an instance method and must not be confused with Hashes class method. Maybe a different name would have been in order, I honestly do not know. We duplicate the receiver and inject the initial values hash. That can than be used as follows.
 1 book = {
 2   :image  => behavior{ | myself |
 3     puts %<"#{myself[:title]}" by #{myself[:author]} was published in #{myself[:date]}
 4     annotations: #{(myself[:annotations]||[]).join(", ")}>
 5   },
 6   :add_annotations => behavior{ |myself, *annotations|
 7     myself[ :annotations ] ||= []
 8     myself[ :annotations ] += annotations
 9   }
10 }
11
12 i_robot = book.new( :title => "I Robot", :author => "Isaac Asimov", :date => 1950 )
13 pickaxe  = book.new( :title => "Programming Ruby 1.9", :author => "Dave Thomas", :date => "2009" )
14 pickaxe[:add_annotations, "Live Long and Ruby!", "and there was Andy Hunt", "... and Chad Fowler" ]
15
16 i_robot[ :image ]
17 pickaxe[ :image ]


which duly produces the following output:

"I Robot" by Isaac Asimov was published in 1950
annotations:
"Programming Ruby 1.9" by Dave Thomas was published in 2009
annotations: Live Long and Ruby!, and there was Andy Hunt, ... and Chad Fowler


Please also note that we could have written pickaxe = i_robot.new(...) in line #13 above, without any change in the semantics of the program.


Did I say Prototype?

I have used the term prototype rather nonchalantly so far. Maybe it is time to define a bit better what I understand under this term in this context.

A prototype is an object oriented model in which the behavior of any object can be shared by using this very object as a prototype. This is a little more general than e.g. the Javascript prototype model in which each object simply has a prototype and this prototype cannot be used as a member of the set of objects it defines.
In our case however that is perfectly possible.
That is the reason why the above remark about line #13 holds: Either book or i_robot can be used as a prototype, although they are perfectly members of the set of objects defined by the prototype.

Criticisms
Although I find it very amusing, amazing and instructive what I have done here I have to get my feet back on the ground again.

This design suffers from some serious drawbacks.

  • All members are accessible.

  • Calling behavior with blocks has a clumsy syntax (namely send :[],... do end).

  • Name Errors (e.g. behavior names misspelled ) are completely obfuscated.

  • There is one only constructor, it does not allow for different behavior depending on the prototype.

  • Last but not least, we have monopolized hashes. And that of course is completely inacceptable.


The public accessibility of all members is somehow not really an issue in some application contexts. The clumsy syntax can be worked around and probably the naming problem can be resolved by a different implementation of Hash#[] e.g. using #fetch.
However, the last two points are inacceptable.




Back to TOC
Quinctilie Vare, legiones hash redde!


Our first duty to the emperor Ruby is to give her her hashes back. I have lost them in the quest for new territory for the Ruby empire but luckily for me I can give them back (for a - however very little - prize ).

The solution of course is not to use instances of Hash as our Object -- Behavior glue. Well actually we still will use hashes, but specialized hashes, a lession learned from our Behavior class. Well let's do it:
 1 
 2 class BHash < Hash
 3   def [] name, *args
 4     value = super( name )
 5     return value unless value && value.is_a?( Behavior )
 6     value.call( self, *args )
 7   end
 8   def new *args
 9     dup.tap do | o |
10       o[:init, *args] if o.fetch( :init, nil ).is_a? Behavior 
11     end
12   end
13 end
14


First we have defined our subclass of Hash called BHash (for Behavior Hash). We can find the redefinition of the #[] method again and the generic constructor. Thus we have freed the core Hash class from all our achievements. Please do note that some other issues could be handled here easily now, as e.g. raising a NameError for access to undefined keys. This would make the code even longer though and not be of much technical interest here.

14
15 class Hash
16   def to_bhash
17     BHash::new.update self
18   end
19 end
20
21 module Kernel
22   def object a_hash
23     a_hash.to_bhash
24   end
25 end
26

In the next block of code we have handled the issue I had mentioned above, the small prize to pay for our sub-classing. This prize might even be a blessing in disguise because it frees the hash literal syntax, well for, hash literals.
Thus first I defined a convenient conversion method, that creates a BHash out from a Hash and then I provided a wrapper method in Kernel called object. This changes the look of file of our object definitions a little bit.

26
27 book = object :image  => behavior{ | myself |
28                 puts %<"#{myself[:title]}" by #{myself[:author]} was published in #{myself[:date]}
29     annotations: #{(myself[:annotations]||[]).join(", ")}>
30     },
31     :add_annotations => behavior{ | myself, *annotations |
32       myself[ :annotations ] ||= []
33       myself[ :annotations ] += annotations
34     },
35     :init => behavior{ | myself, title, others={} |
36       myself[ :title ] = title
37       myself.update others
38     }
39
40
41 gray = book.new( "The Picture of Dorian Gray", :author => "Oscar Wilde", :date => 1890 )
42 pickaxe  = book.new( "Programming Ruby 1.9", :author => "Dave Thomas", :date => 2009 )
43 pickaxe[:add_annotations, "Live Long and Ruby!", "and there was Andy Hunt", "... and Chad Fowler" ]
44
45 gray[ :image ]
46 pickaxe[ :image ]


And this code is satisfying our conditions above and produces the expected output:


"The Picture of Dorian Gray" by Oscar Wilde was published in 1890
annotations:
"Programming Ruby 1.9" by Dave Thomas was published in 2009
annotations: Live Long and Ruby!, and there was Andy Hunt, ... and Chad Fowler




 1 Behavior = Class::new Proc
 2
 3 module Kernel
 4   def behavior &blk
 5     Behavior::new( &blk )
 6   end
 7   def object a_hash
 8     a_hash.to_bhash
 9   end
10 end
11
12 class BHash < Hash
13   def [] name, *args
14     value = super( name )
15     return value unless value && value.is_a?( Behavior )
16     value.call( self, *args )
17   end
18   def new *args
19     dup.tap do | o |
20       o[:init, *args] if o.fetch( :init, nil ).is_a? Behavior 
21     end
22   end
23 end
24
25 class Hash
26   def to_bhash
27     BHash::new.update self
28   end
29 end
30 book = object :image  => behavior{ | myself |
31                 puts %<"#{myself[:title]}" by #{myself[:author]} was published in #{myself[:date]}
32     annotations: #{(myself[:annotations]||[]).join(", ")}>
33     },
34     :add_annotations => behavior{ | myself, *annotations |
35       myself[ :annotations ] ||= []
36       myself[ :annotations ] += annotations
37     },
38     :init => behavior{ | myself, title, others={} |
39       myself[ :title ] = title
40       myself.update others
41     }
42
43
44 gray = book.new( "The Picture of Dorian Gray", :author => "Oscar Wilde", :date => 1890 )
45 pickaxe  = book.new( "Programming Ruby 1.9", :author => "Dave Thomas", :date => 2009 )
46 pickaxe[:add_annotations, "Live Long and Ruby!", "and there was Andy Hunt", "... and Chad Fowler" ]
47
48 gray[ :image ]
49 pickaxe[ :image ]
50






Back to TOC
Code Reuse


Well we are all lazy, it's almost a hype ;). Seriously there is one feature we might miss at first sight, that of mixins. On second sight of course and knowing that we use a subclass of Hash as our behavior and state container we see that we can simply update the container with different behavior. A naive, but perfectly working approach would be to do the following:

1 class BHash < Hash
2   def add_behavior behavior
3     abort "Not a behavior #{behavior}" unless 
4       behavior.is_a? self.class  # a tailormade exception would be raised in production code, of course
5     update behavior
6   end
7 end


Given this primitive wrapper around Hash#update we can now extend our prototypes / objects as in the following code:
 1 isbn = object :set_isbn => behavior { |myself, isbn | myself[ :isbn ] = myself[ :add_isdn_check, isbn ] },
 2               :add_isdn_check => behavior { | _, isbn | 
 3                 # begin of boring cksum code
 4                 isbn + "*"
 5                 # end of boring chksum code
 6               }
 7
 8 book.add_behavior isbn
 9 hegel = book.new( "Hegel's Philosophy of Reality", :author => "Robert M. Wallace", :date => 2005 )
10 hegel[ :set_isbn, "521844843" ]
11 hegel[ :image ]
12 puts hegel[ :isbn ]
13

printing

"Hegel's Philosophy of Reality" by Robert M. Wallace was published in 2005
annotations:
521844843*





Back to TOC
Résumé


I have now implemented the basic devices needed for prototype based programming, and I am asking myself, What now?. As a matter of fact I am looking back on the code I have written I am missing some properties badly:

  • Call syntax is clumsy for blocks.

  • Code reuse does not allow access to overridden behavior.

  • Data and behavior are mixed.

  • Data and behavior is public.


Now I am sure, that all of these matters can be fixed, but shall this be done with hashes as the basic device?

I am really not sure and there is just one way to find out, implementing some of it and playing around with it...

And that is what I will be doing now. Thanks for having stepped by.

Wednesday, January 7, 2009

Streams, Lazy Programs for Lazy Programmers.


Streams are nothing new at all. Furthermore they have been introduced at least once into the Ruby World on James' excellent blog, Shades of Gray, with which many of the Ruby community are familiar, at least I hope ;). I can only encourage you to read the whole High Order Ruby series. For those looking for more reading on this topic the following link provides a gold mine; High Order Perl.

Although I had read James' blog entry about two years ago and was fascinated by it, I somehow never had the time to play around with streams. It took a second motivation which I found in a remarkable site: Structure and Interpretation of Computer Programs, Video Lecture. This was an absolute treasure for me. Looking at Abelson's presentation of Streams I really wanted to have that in Ruby.

For those who do not like my blah, blah, and that is probably about everybody save YHS, but ok it is my Blog after all, I have compiled a small TOC so that they do not have to read the dull stuff while I can still write it, yeah!





TOC

Streams in Ruby
A verbose introduction why, how, when I did what and why, how and when I did not do other things.

Diving into Streams
A step by step introduction into streams and their implementation in Ruby.

Ruby Meets Streams
Enumerable Ruby Objects can easily be seen as streams too.

Streams' Applications
And yes of course they do serve.





Back to TOC
Streams in Ruby

A stream is a lazy, potentially endless data structure. In Scheme a stream is constructed with the cons-stream special form. As an example Abelson constructs the stream of all integers as follows:
1 (define (integers-from start)
2 (cons-stream start (integers-from (1+ start) ) )
3 )
4 (define (integers)
5 (integers-from 0)
6 )

As such the cons-stream form constructs a stream by creating a Lisp cons cell with a car that consists of an already computed value, called head and a cdr that contains a promise to compute a new head and a new promise.

A practical side note: This was the most difficult thing to remember for me. The concept seems simple enough, but whenever I had a problem in my code I had forgotten that the promise has to return a new stream and not just a new head. For me the following two invariants on streams were the absolute cornerstone for understanding them:
  • While constructing a stream the tail is a promise and thus not evaluated.
  • The tail of a stream will always yield a stream again, potentially the empty stream.
Once these two rules sank into my brain it was amazing how easy stream manipulation can become.

Given the first of the two invariants above it is quite clear how to specify a
promise in Ruby, with code blocks.
We can therefore allready imagine how a cons_stream method will look like in Ruby.
1 def cons_stream head, &tail
2 # . . .
3 end
The result of the cons_stream call of course is an object implementing Streams in Ruby. This can easily be verified on the command line:
ruby -rlab419/functional/streams -e 'include Lab419::SimpleStream;p cons_stream( 42 ){ EmptyStream }'
#<Lab419::SimpleStream::Stream:0xb7d85664 @tail=#<Proc:0xb7d8572c@-e:1>, @head=42>

We can very well see that the promise is stored as a proc object and the head as an actual value.

Here however I will take a different path then James took, and I encourage you (again) to read his blog if you prefer the more idiomatic Ruby way to look at streams. I however really wanted
to emphasize on the abstraction streams constitute. And although it is wonderful how easily this can be done in Ruby, I believe that the stream paradigm itself merits to be looked at
at a more abstract level.
This said, my implementation gives you the best of the two worlds of course. The functional layer being only a wrapper around the Ruby Object layer you can use both at will.




Back to TOC
Diving into Streams

Let us have some fun now and play with streams:
1 include Lab419::SimpleStream
2 constant = cons_stream( 42 ){ constant }
3 p constant.head        # --> 42
4 p constant.tail.head   # --> 42
5 p constant.tail        # --> #<Lab419::SimpleStream::Stream:0xb7d68424
# @tail=#<Proc:0xb7d6867c@diving-into-streams-01.rb:2>, @head=42>


It is quite remarkable, that we can use constant inside the promise ( which is implemented as the code block, remember? ) without any problems [line #2]. No surprises in lines 3 & 4. And if we remember the second invariant line #5 is not going to surprise us either. Furthermore we can already see some of the internal representation of streams. As mentioned before it is a plain vanilla Ruby class, that exposes an Object Oriented interface to streams as well.

The aforementioned recursiveness of streams can be seen in the next example again.
1 include Lab419::SimpleStream
2 def integers from=0
3   cons_stream( from ){ integers( from + 1 ) }
4 end
5
6 i = integers
7 p i.head             # --> 0
8 p i.tail.tail.head   # --> 2

As soon as we have understood the lazy nature of the promise the recursive call to integers does not trouble us any more. You can compute the following without any problems:
1 42_420.times do
2   i = i.tail
3 end
4 p i.head


One of the big advantages of using streams is that we can exploit these cheap recursions of streams to formulate elegant recursive procedures without the danger of stack overflows and even those who could not be tail call optimized.

As an example let us consider the Fibonacci numbers as a stream. Then a natural definition of such a stream, let us call it fibo would be:


fibo is a stream for which the head is 0.
fibo is also a stream for which the head of its tail is 1.
fibo is eventually a stream for which the head of the tail of the tail is the
sum of the head and the head of the tail.


We will try now to translate this into Ruby, and we will see that this can be done in an analogous way, without any effort:
 1 include Lab419::SimpleStream
 2
 3 def add_streams lhs, rhs
 4   cons_stream( lhs.head + rhs.head ){
 5     add_streams( lhs.tail, rhs.tail )
 6   }
 7 end
 8
 9 def fibo
10   cons_stream( 0 ) {
11     cons_stream( 1 ){
12       add_streams( fibo, fibo.tail )
13     }
14   }
15 end
16
17 p fibo[0..6]

Running this program delivers

512/31 > ruby -rlab419/functional/streams diving-into-streams-03.rb
[0, 1, 1, 2, 3, 5, 8]


Please note, that this implementation of add_streams does not consider the possibility of finite streams, we will come to that later.
Another important point is that we can consider streams as Enumerables very easily too.

Actually this is about all, yes the power of streams has much to do with their simplicity. Everything else I will talk about now will not introduce anything new. It will however show some of the conveniences built into the implementation, and show us how to handle Finite Streams. It is somehow funny that they are the special case while infinite streams are the normal case.




Back to TOC
Ruby Meets Streams

Finite Streams
Finite Streams are just a special case of Infinite Streams. A mathematical definition of finite streams might look like the following:

A finite is a stream for which exists a promise delivering an empty stream.
An empty stream is defined as a stream for which the tail delivers an empty stream
and for which the behavior of head remains undefined.

Following this definition and having already an EmptyStream at our disposal it is straightforward to define a finite stream from a given number of objects:
1 def finite_stream *elements
2   return EmptyStream if elements.empty?
3   cons_stream( elements.shift ) { finite_stream( *elements  ) }
4 end


But as infinity is such an important concept for streams, we need a way to make finite streams infinite, the most logical approach is to cycle through them. Such a task is of course almost frivolously easy:
1 include Lab419::SimpleStream
2
3 def cyclic_stream elements, current=0
4   cons_stream( elements[current] ) { cyclic_stream( elements, current.succ % elements.size ) }
5 end
6
7 primes = cyclic_stream [ 2, 3, 5, 7 ]
8
9 p primes[0..9]


Ruby Objects as Streams
The implementation of streams in Labrador (branch lab419-functional-0.1 ) is quite straightforward and provides a functional interface as implemented in module Lab419::SimpleStream or an object oriented interface.
Please note that you can use all enumerables as streams by means of the #to_stream method, while String implements a #to_byte_stream method too.




Back to TOC
Streams' Applications

Without this section of this Blog entry one might be thinking that streams are a neat concept but that would be about all.

Abelson shows a very elegant solution of the N Queens problem by using streams. I will settle here for something less spectacular.

Streams as a Lexer
The name stream somehow induces a typical usage of streams. IOStreams can very
well be implemented as streams. The following example implements a very simple lexer that works as a stream.

 1 
 2 class String
 3   def next_token *tokens
 4     tokens.each do | token |
 5       if /^#{token}/ === self then
 6         return [ $1 || $& , self.sub( /^#{token}/, "" ) ]
 7       end
 8     end
 9   end
10   [ nil, nil ]
11 end
12
13 def lexer_stream io, line="", *tokens
14   line = io.readline.chomp if line.empty?
15   token, line = line.next_token( *tokens )
16   cons_stream( token ){ lexer_stream( io, line, *tokens ) }
17 rescue EOFError
18   EmptyStream
19 end
20
21 lexer = lexer_stream( $stdin, "", /\s*(\w+)/, /\s*(\d+)/, /\s*(.)/ )
22
23 until lexer.empty? do
24   puts lexer.head
25   lexer = lexer.tail
26 end
27


First we define a get_token helper in class String. This does not modifie its receiver but returns the parsed string and the rest of the line. It is really just a toy to test the stream part of the example.

Things become a little bit more interesting at line #13. A lexer_stream is constructed by getting the first token from the input (io) which is line buffered by means of line and defining the tail as a lexer_stream with the same io, the same tokens and the new line buffer. Simple?

And it works like charm.

In parsing it is sometimes convenient to implement a certain lookahead. Imagine how elegantly a parser can be written if it has the possibility to push tokens back on the input stream. With a stream based lexer this is a one-liner.

lexer = cons_stream( pushbacktoken ){ lexer }

So we will have
 1 
 2 class String
 3   def next_token *tokens
 4     tokens.each do | token |
 5       if /^#{token}/ === self then
 6         return [ $1 || $& , self.sub( /^#{token}/, "" ) ]
 7       end
 8     end
 9   end
10   [ nil, nil ]
11 end
12
13 def lexer_stream io, line="", *tokens
14   line = io.readline.chomp if line.empty?
15   token, line = line.next_token( *tokens )
16   cons_stream( token ){ lexer_stream( io, line, *tokens ) }
17 rescue EOFError
18   EmptyStream
19 end
20
21 def push_back a_stream, a_token
22   cons_stream( a_token ){ a_stream }
23 end
24
25 lexer = lexer_stream( $stdin, "", /\s*(\w+)/, /\s*(\d+)/, /\s*(.)/ )
26
27 until lexer.empty? do
28   if lexer.head == "break" then
29     lexer = push_back( "break", lexer )
30     puts "returning #{lexer.inspect}"
31     break
32   end
33
34   puts lexer.head
35   lexer = lexer.tail
36 end
37




That is about all, please check out the project at Rubyforge and thanx for your attention.



Update
thanks to Brian Candler

Brian pointed out correctly that Ruby Enumerators are lazy too in Ruby1.9, and almost lazy in 1.8. He made a nice contribution to Facets where he made them lazy in Ruby1.8 too.
Please check it out here on Rubyforge.

I knew actually that Enumerables and Enumerators could be lazy, but I ignored that Ruby1.9 had a new syntax which really encourages this kind of constructs.

1 x = Enumerator::new do | enator | 
2   loop do
3     enator.yield rand
4   end
5 end
6
7 p x.next
8 p x.next
9 p x.take( 10 )


As a matter of fact Generators, Fibers and Enumerators in 1.9 are very, very promising.

Sunday, September 30, 2007

Mixin and State, Any Problems?


Last week we were having a discussion about Ruby with a relative newbie who was wondering
about how Mixins and State work together.
I was sure that the discussion would be brief, explaining that all mixed in methods have full
access to its receivers state and that of course a Mixin could define initialize too.

And What About Class State?
... he said. Well, er, that is only a minor complication, I said. What exactly would you like to achieve?

We came up with a very simple, but useful, example. An Instance Tracker. It should allow us to easily
collect all instances of a class. The collected instances should than be accessible by a class method.

We decided to have some fun with TDD and specified the Tracker as follows:
  class TestInstanceTracker < Test::Unit::TestCase
def test_01_basic
a = Class::new {
include Tracker
}
a1 = a.new
assert_equal [a1], a.instances
a2 = a.new
assert_equal [a1, a2], a.instances
end # def test_01_basic
end # class TestInstanceTracker < Test::Unit::TestCase


Ok it did not take me a long time to figure it out, at first one had to assure that any new instance were added
to the instance collection, thus
  module Tracker
def initialize
self.class.instances << self
end

and than I had to labor that self.class.instances worked, therefore...
    def self.included into_a_class
into_a_class.instance_variable_set "@instances", []
class << into_a_class; attr_reader :instances end
end
end

Needless to say that code passed our testsuite (that was two assertions) brilliantly.
Now even if I had not read Kent Beck's eXtreme Programming,I had known that the testsuite was er incomplete.

As a matter of fact my collegue came up with this in no time
  def test_02_subclass
a = Class::new {
include Tracker
}
b = Class::new a
a1 = a.new
assert_equal [a1], a.instances
b1 = b.new
assert_equal [a1], a.instances
assert_equal [b1], b.instances
a2 = a.new
assert_equal [a1, a2], a.instances
assert_equal [b1], b.instances
end # def test_02_subclass

Yielding this nice little result

1) Error:
test_02_subclass(TestInstanceTracker):
NoMethodError: undefined method `<<' for nil:NilClass
./tracker2.rb:4:in `initialize'
test2.rb:24:in `new'
test2.rb:24:in `test_02_subclass'

And Subclasses?

Ok so he wants subclasses, yes sure, so would I, let us see...
As we are already telling the class we are included into to do some stuff, why not just tell it to include us
into any subclass which is created from itself

Such things can be done with the help of the class callback inherited.
  def self.included into_a_class
into_a_class.instance_variable_set "@instances", []
class << into_a_class
attr_reader :instances
def inherited by_class
by_class.send :include, Tracker
end
end
end # def self.included into_a_class

This again made the tests pass, which means that we had to come up with new tests.

And Module Inclusion?

He cannot be serious, what does he want?
Ah yes well, the following
  def test_03_includes
m = Module::new {
include Tracker
}
a = Class::new {
include m
}
b = Class::new a
a1 = a.new
assert_equal [a1], a.instances
b1 = b.new
assert_equal [a1], a.instances
assert_equal [b1], b.instances
a2 = a.new
assert_equal [a1, a2], a.instances
assert_equal [b1], b.instances
end # def test_03_includes

Actually it is pretty simple, when we are included into a class we do what we did so far:

  • Define the class instance variable

  • Define the class level accessor to the class instance variable

  • Tell the class to include us into all its subclasses via the self.inherited callback


When we are included into a module however, we have to do all the above again, that is in
  def self.included into_module
case into_module
when Module
#(1)

we have to put the exact code of the method at #(1) again.
Infinite code has some serious drawbacks though, very long development time being one that springs into mind first.

Ruby however let us define such a strange recursion without any problem:
  module Tracker
SelfIncludedProc = proc {
| into_a_module |
case into_a_module
when Class
into_a_module.instance_variable_set "@instances", []
class << into_a_module
attr_reader :instances
def inherited by_class
by_class.send :include, Tracker
end
end
when Module
class << into_a_module; self end.send :define_method, :included, &SelfIncludedProc
end # case into_a_module
}

class << self; self end.send :define_method, :included, &SelfIncludedProc

def initialize
self.class.instances << self
end
end

And that passes our tests again.

But there is one important test that does not pass:

This code just does not seem right

I thought about it a little bit and than the scales fell from my eyes, of course it is not right, I was doing two
things at the same place, coding and metacoding, so all I need to do is to tear these two parts apart.

The first and relatively uninteresting part is the application code that creates a class instance variable, its accessor and the automatic addition of new instances.

The second part is simply a kind of a Module that allows us to define class level code for
all subclasses and even via indirect inclusion.

That's what I want, I just have no idea how to call such a beast, so I called it RecModule,
great. I will accept all naming suggestions very cheerfully.



A Home Made Module Class

Let us have a look at the code:


class RecModule < Module
def recursive_included &blk
# Define a block that defines the included
inclusion = proc { | by_module |
super by_module
blk.call by_module if Class === by_module
class << by_module; self end.
send :define_method, :included, &inclusion
}
# Define included in base module
class << self; self end.
send :define_method, :included, &inclusion
end
end # class RecModule

Yep and?


Ok it will make more sense to you if we use it... but please note the repeating pattern of the way to define Module#included by means of a self referring block into our including modules.


M1 = RecModule.new {
recursive_included do |by_class|
class << by_class
attr_accessor :x
end
end
}

M2 = RecModule.new {
include M1
}
class A
include M2
end
B = Class::new A

A.x = 46
B.x = 42
p A.x # --> 46
p B.x # --> 42

I have implemented a recursive_include that will actually only execute its block for including
classes, but other similar tricks could have been used.


And Does It Really Work?


Best way to find out is to try it, I will just reimplement the InstanceTracker with the new idioms...



InstanceTracker = RecModule.new {
recursive_included do |by_class|
class << by_class
def instances
@__instances__ ||= []
end
end
end

def initialize *args, &blk
super
self.class.instances << self
end
}

M2 = RecModule.new {
include InstanceTracker
}
class A
include M2
end
B = Class::new A

A.new
B.new
A.new
p A.instances # --> [#<A:0x2b66028>, #<A:0x2b65fd8>]
p B.instances # --> [#<B:0x2b66014>]

Please note that M2 could even be a regular Module, I however think that using a RecModule reflects the intent of the code better, but that could be a matter of taste. For those who would prefer to use modules down the inclusion chain, it works perfectly too.


I am not sure that this is already the maximum I could have done in abstracting this functionality, but 14 lines of code for implementing such a basic InstanceTracker feels as about ok (10 lines would be better sigh).


There is however one thing that makes me quite nervous, I feel proud and pleased with myself about it...
Hopefully there will be some gentle reader who will tell me why I should not...

Saturday, August 18, 2007

No More Instance Variables in My Prototypes.

Last week we have seen a very simple but working implementation of the Prototype Paradigm in Pure Ruby. I have striven to implement it without orbiting too much around the classical Ruby Programming Paradigm using/ Classes and Modules. Using the exposed methods of the PPP API we can indeed forget about modules and classes at all, notwithstanding that they are doing the work behind the scenes of course.
By looking at our examples however, we see that we use instance variables for properties (or attributes) of our objects to remain in the OO jargon.
By defining attribute accessors this fact can be hidden but we can by no means avoid that instance variables are used directly to access the properties we have defined.

This week we will add a feature to the Prototype implementation that allows us to define properties without any usage of instance variables. We will define properties by means of closures, and we will allow a very simple way to define properties on a Per Object base as well as on a Per Prototype base.

Properties

Properties contain information attached to an object. In pure Ruby we use instance variables very often to represent properties. As a matter of fact we are talking about attributes and they are implemented with the well known attr_*
definitions:

class Person
attr_reader :name
attr_accessor :age
def initialize name, age=nil
@name = name
@age = age if age
end
end

spencer = Person.new "Tracy", 107
hepburn = Person.new "Katharine"

Obviously name and age are properties attached to each object and not shared amongst all objects of the same class. If we want such a beast in pure Ruby we can use Class Instance Variables1.
The classical example of such a shared property is to count instances of the class, and that is what the following code does:

class Person
attr_reader :name
attr_accessor :age
@count = 0
class << self
attr_accessor :count
end
def initialize name, age=nil
@name = name
@age = age if age
self.class.count += 1
end
end


spencer = Person.new "Tracy", 107
puts Person.count # -> 1
hepburn = Person.new "Katharine"
puts Person.count # -> 2



(1)The usage of Class Variables (starting with @@) has been discussed a lot on the Ruby-Talk ML and I adhere to a vast group of Rubyist who discourage their usage.



Can PPP do this too?

Well it can, now, but you have not seen the code yet;). Let us have a look how it is used before explaining the implementation. The code below is the equivalent to the above code but expressed in PPP.

require 'ppp'

person = new_proto {
proto_variable :count, 0
def init name, age=nil
obj_variable :name, name
obj_variable :age, age
self.count += 1
end
}

spencer = person.new "Tracy", 107
puts spencer.count # -> 1
hepburn = person.new "Katharine"
puts person.count # -> 2

There are some differences, as a matter of fact per object variables and per prototype variables are syntactically identical, please note too, that, like in Pure Ruby, you cannot assign to a prototype without an explicit receiver, hence the self.count += 1 above, the same has to be done for object variables:


person.ext_proto {
def birthday
self.age += 1
end
}


Looking under the Hood

I decided to use closures, I just dislike the @ sign I guess;)


class Object
def singleton; class << self; self end end
end

First of all I monkey-patched Object with the singleton method above, this is used very frequently by many Metaprogramming Gurus, so I need that too. Seriously you will see soon why this is useful.


class Prototype
def obj_variable varname, value, readonly = false
variable = value
singleton.instance_eval do
define_method varname do variable end
end
return if readonly
singleton.instance_eval do
define_method "#{varname}=" do | val | variable = val end
end
end # def obj_variable varname, value, readonly = false
end

Then the definition of obj_variable goes right into the Prototype class, that is why we use it in the init method and not inside the prototype block.
Please note the usage of the closure. The local variable called variable is created in the first line of the method and then we use two metaprogramming tools, instance_eval and define_method to define the accessor methods to the property. As both of these use blocks we have created a closure to access the local variable variable. Nobody can take this away from us anymore.


class Module
def proto_variable varname, value, readonly=false
variable = value
define_method varname do variable end
return if readonly
define_method "#{varname}=" do |val| variable = val end
end # def proto_variable varname, value
end # class Module

The definition of proto_variable has to go into Module of course. That is the context in which the block of new_proto or ext_proto is interpreted in.
Note the same technique as above only that we do not need the singleton here, we want the method to be defined in the prototype itself as this behavior is shared between the prototype and its objects.

Is This Good For Something?
Sure, allows me to write a Blog :). But maybe I can convince you of the Beauty and Usefulness of the PPP by means of the example of the open-proto implementation.
The open-proto implementation mimics open-struct and Facet's open-object behavior. Properties can be created on the fly:

require 'labrador/exp/open-proto'

my_open = new_proto(Prototype::OpenProto) {
def greeting
puts "I am #{name} and I have a value of #{value}"
end
}
my_object = my_open.new :name => "Fourty Two"
puts my_object.name
my_object.value = 222

another = my_object.new :name => "Fourty Six", :value => 42
my_object.greeting
another.greeting


Properties are defined on the fly, on a per object base and either by assignment or in the constructor.
It amazed myself how easy it was to implement this behavior (as it is in Pure Ruby I admit ;).

class Prototype
OpenProto = new_proto do
def init params={}
params.each_pair do |k,v|
obj_variable k, v
end
end

def method_missing name, *args, &blk
super name, *args, &blk if
args.size != 1 or
blk or
name.to_s[-1] != ?=
obj_variable name.to_s[0..-2], args.first
end
end
end

I make this 17 lines of Ruby Code.

Conclusion:

I hope you have enjoyed the journey, gentle reader, if you would like to play around with this programming style maybe you would like to have a look at Labrador as PPP and open-proto are part of version 0.1 of the Lazy Programmer's Best Friend.
I have uploaded the two files labrador/exp/ppp and labrador/exp/open-proto in an extra file called labrador-experimental-0.1 you can download all that from Rubyforge.

Saturday, August 11, 2007

And this week, Prototypes, The Conclusion

Last time I followed a path I was put on by the excellent work of Ara T. Howard, and I stopped at a very naive implementation of the Prototype Programming Paradigm. (Yet another PPP;).

It was the fast (and late) conclusion of some days of refelection and testing of ideas, it is far from ideal...
The thing that disturbes me most is that I tempted to deal with data ( c.f. Prototype#deepdup), and I did not even do it well.
Dealing with data is a bad idea anyway, we are talking behavior here, and data should not influence the conceptional decisions to be taken.

Freed from any data concerns I came up with the following code, but before throwing it at you, gentle reader, I would like to comment the concept I am following here.
In order to avoid unneccessary confusion (I will not avoid necessary confusion, those who read my posts at ruby-talk know why ;), I will use Prototype (capitalized) whenever I refer to the implementation ( a Ruby class ), and prototype (lowercase) whenever I refer to a prototyped object (an instance of Prototype as a matter of fact).

And What Is A Prototype Anyway?

A prototype is an object that has its behavior closely attached to itself. It playes the role of a class and an instance of that class at the same time.
Remember, it was the main motivation of my last post to get rid of classes at all in our programs.
I losely follow a definition of prototype as defined here.

It is the Prototype class, yes we use classes for implementation of this nevertheless ;), that will take care of gluing behavior into the prototype object.
The basic instrument to do so is the __proto__ attribute Prototype defines for its instances.
We will see shortly that __proto__ is indeed a Module that will be included into new modules replacing it as soon as a prototype will be extended with new functionality.

It is important to remember that Ara T. Howard and Pit Capitain had to do very much work (as interesting and sophisticated it was) to allow for dynamic method redefinition for class based methods.
Our classless approach rips this burden off our shoulders of course, all methods a prototype responds to are module based (via the standard Ruby extend).

Inheritance & Method Resolution Order

Inheritance is therefore implemented by method inclusion into the __proto__ attribute of a prototype.

We have a prototype p which has stored its behavior in its __proto__ attribute. This is indeed an invariant of this PPP implementation:
A prototype is always extended by the module kept in its __proto__ attribute.
Whenever we want to extend a p with some new behavior it is done via a new module, either given as a module or by constructing one on the fly from a given block.
This new module will become the value ot the p's __proto__ attribute but not before including the value of the old value of the prototype's __proto__ attribute into the module. Thus the old behavior is not lost.
The code for doing this is factorized into Prototype's private extend_one method and is simple enough:

  def extend_one mod
proto = __proto__
mod.instance_eval { include proto } if proto
self.__proto__ = mod
extend mod
end


As mentioned above the Prototype class implements an attribute __proto__. The constructor allows us to indicate behavior to be inherited as follows, a list of modules ( of whihch the last will be the last in the inheritance chain ) and an optional block of which a module will be constructed.
The module constructed from the block is the last to be inherited into the __proto__ chain.

The following example shows the method resolution order as described above.


   module A
def a; 42 end
def b; 46 end
def c; 39 end
end
module B
def b; 52 end
end
p = Prototype.new( A, B ){
def c; 60 end
}

puts p.a # --> 42
puts p.b # --> 52
puts p.c # --> 60

And here goes the definition of Prototype#initialize which does the work to arrive at the result shown above:


PrototypeError = Class::new StandardError

class Prototype
attr_accessor :__proto__
def initialize *args, &blk
ext_proto *args
ext_proto Module::new( &blk ) if blk
end # def initialize *args, &blk
...
end # class Prototype



How To Use It, The Prototype API

We want of course some simple way to create prototypes new clones or copies of a prototype or to extend prototypes.
The following interface methods can be used for this task:


class Prototype

def ext_proto *args, &blk
args.each do
| arg |
case arg
when Module
extend_one arg
else
begin
extend_one arg.__proto__
rescue NoMethodError
raise PrototypeError,
"Cannot extend an object with a non Module or non Prototype object"
end
end # case arg
end # args.each
extend_one Module::new( &blk ) if
blk or args.empty?
self
end # def ext_proto
end # class Prototype

module Kernel
def new_proto superobject=nil, *mods, &blk
begin
superobject.dup
rescue TypeError, NoMethodError
Prototype.new
end.ext_proto( *mods, &blk )
end
end # module Kernel

Thus we will be allowed to create a new prototype with


   new_proto nil, Comparable do
def <=> other
...
end
end

Or we might like to write more explicit code:



module Printable
def to_s; inspect end
end

sortable = new_proto
sortable.ext_proto Printable, Comparable do
def <=> other
name <=> other.name
end
attr_accessor :name
def init name
self.name = name
end
end

puts [sortable.new( "Vilma" ),
sortable.new( "Angie" ) ].sort
##<Prototype:0x2b64110 @name="Angie", @__proto__=#<Module:0x2b643f4>>
##<Prototype:0x2b641c4 @name="Vilma", @__proto__=#<Module:0x2b643f4>>


No More Classes! No More Modules?

Although I do not see any technical problem to use modules directly, it might be more consistent an approach not to do so anywmore.
We have got rid of class why not get rid of module too? This kind of paradigm change can do a lot to your programming style.

The alternative would be to use prototypes and anonymous module blocks exclusively (still being able to do a "include mod" in the block of course).
In this alternative way the code above would look as follows:


printable = Prototype.new {
def to_s; inspect end
}
sortable = new_proto printable, Comparable do
...

Note that we still allow modules in the inheritance chain, this seems quite useful for the usage of predefined modules.

And What About Object Initialization?
This is the last missing piece of our puzzle, Prototype defines a new method that will call an init method for the newly created object, if it exits that is of course.
Not much magic here


class Prototype
def new *args, &block
o = dup
o.extend __proto__
o.instance_eval {
init( *args, &block )
} if respond_to? :init
o
end # def new *args, &block
end # class Prototype

Please note that our only concern is to disassociate the new object from the generating prototype object. It is completely up to the user to manage the data, data can be shared between a generator object and a generated object by means of references pointed to by instance variables defined for the generator.
Example for shared data between generator prototype and generated prototype:


   printable = Prototype.new {
def to_s; inspect end
}

dog = new_proto printable do
attr_accessor :name
def init name=nil
self.name = name if name
end
end
vilma = dog.new %q{vilma}
angie = vilma.new
angie.name << "& angie"

puts vilma
puts angie
##<Prototype:0x2b64304 @__proto__=#<Module:0x2b64458>, @name="vilma& angie">
##<Prototype:0x2b6428c @__proto__=#<Module:0x2b64458>, @name="vilma& angie">


The PPP Implementation
Here goes the whole implementation:


PrototypeError = Class::new StandardError

class Prototype
attr_accessor :__proto__
def initialize *args, &blk
ext_proto *args
ext_proto Module::new( &blk ) if blk
end # def initialize *args, &blk

def ext_proto *args, &blk
args.each do
| arg |
case arg
when Module
extend_one arg
else
begin
extend_one arg.__proto__
rescue NoMethodError
raise PrototypeError,
"Cannot extend an object with a non Module or non Prototype object"
end
end # case arg
end # args.each
extend_one Module::new( &blk ) if blk or args.empty?
self
end # def ext_proto

def new *args, &block
o = dup
o.extend __proto__
o.instance_eval {
init( *args, &block )
} if respond_to? :init
o
end # def new *args, &block

private
def extend_one mod
proto = __proto__
mod.instance_eval { include proto } if proto
self.__proto__ = mod
extend mod
end
end

module Kernel
def new_proto superobject=nil, *mods, &blk
begin
superobject.dup
rescue TypeError, NoMethodError
Prototype.new
end.ext_proto( *mods, &blk )
end
end # module Kernel


Performance?

Performance is bad of course, Prototype based code is about 10 times slower than class based code, as my first benchmarks have shown.

Wednesday, August 1, 2007

Classless Ruby, a Paradigm Change?

What are classes for in Ruby?

That seems quite a stupid question at first, let us see if we can work to a point where the question makes more sense.

The whole thing started in my mind by a recent post of Ara T. Howard, implementing a neat meta-programming trick allowing to redefine methods.

Method Redefinition
The basic idea was to allow to redefine a method in a class by still having access to the redefined method via the super call.
Without looking at the implementation this is what Ara wanted to achieve.

The implementation, heavily influenced by Pit Captain, can be found here, have a look here if you are interested in Ruby Metaprogramming, it is really top notch code.

class C
def foo() 'f' end
def bar() 'b' end
def foobar() foo + bar end
end

c = C.new
p c.foobar # => "fb"

class C
redefining do
def foo() super + 'oo' end
end
end

p c.foobar # => "foob"

class C
redefining do
def bar() super + 'ar' end
end
end

p c.foobar # => "foobar"

class C
redefining do
def foo() super.reverse end
def bar() super.reverse end
end
end

p c.foobar # => "oofrab"

It is indeed a nice feature to have, a very modular inheritance mechanism. If you have looked at the implementation above, surely you have had a look at the implementation already;), you will see that it is rather complicated.
There are two reasons for that, firstly there is no way to tell Ruby to accept block parameters in a block, thus the following just will not be possible in Ruby 1.8, this will fortunately change in 1.9.


define_method( :my_method ) {
|*args, &blk|
...
}

And secondly there is a well defined behavior of directly defined methods being looked up before mixed-in methods.
When Ara published his redefining code first I had the urge to write this much, much simpler and I almost succeeded, actually I knew that the code was not doing what Ara wanted, but I felt that the simplicity of the solution was worth looking into it.
I also preferred to define the meta-code in class Module rather than in class Class.

A Naive Approach


  class Module
def redefine &blk
include Module::new( &blk )
end
end


Now this does some pretty neat tricks already, let us look at one example:
  module M
def m; 1 end
end

module N
include M
redefine do
def m; super + 1 end
end
end

class A
include N
redefine do
def m; super + 1 end
end
end

puts A.new.m # --> 3

Unfortunately we cannot redefine a method that has been declared in a class as it will be looked up first, that is why Ara and Pit went through so much trouble to save the method, remove it from the class and put it on a call stack, they did not do that (only) for fun.
In order to demonstrate it change the definition of class A as follows


  class A
def m; 41 end
redefine do
def m; super + 1 end
end
end

puts A.new.m


The deception of not getting the right answer is great of course.
But how can we get 42? Yes, of course, by using Ara's and Pit's code...
Actually I fell in love with my naive code above.
I am well aware of its limitations, but why not just continue walking on this road? We will see where that gets us.
I was quite pleased with the journey.


Mixin Rules, Or Does It Not?

The first idea to allow redefinition is simply to use redefine for the definition of the methods in the class.
This would also allow to explicitly forbid redefinition for conventional methods, the following example does not even use redefine as it is just too simple, we explicitly mix an anonymous module in.

  class Mixin
include Module::new {
attr_reader :a
def initialize a
@a = a
end
def increment
@a += 1
end
}
def old_style; "old_style" end
end # class Mixin

m = Mixin.new 46
puts m.a # --> 46
m.increment
puts m.a # --> 47
puts m.old_style # --> "old_style"

class Mixin
include Module::new {
def increment
super
@a += 2
end

def old_style
super << "::new_style"
end
}
end

m.increment
puts m.a # --> 50!!
puts m.old_style # --> "old_style"


Let us imagine, for the sake of argument, that you like this idiom, are you going to write the following code pattern forever?


class MyClass
include Module::new {
...


Probably not, why not mimic Ruby's class keyword a little bit and hide the implementation details in a Kernel method?

module Kernel
def new_style_class name, superclass=Object, &block
begin
Object.const_get( name )
rescue
Object.const_set( name, Class::new( superclass ) )
end.
instance_eval{ include Module::new( &block ) }
end
end # module Kernel

new_style_class :A do
attr_reader :value, :version
def initialize
@version=1
@value =0
end

def set_value v
@value = v
end
end

a = A.new
puts a.version
a.set_value 52
puts a.value

new_style_class :A do
def initialize
@version=2
end
end
puts A.new.version


Note that the such created new_style_class is a straight forward Ruby class that you can use and monkey patch as any other Ruby class.

Did I Say Classless?

Easy enough, let us just forget about Class.

Instead of creating the classic Ruby class and storing it in the class constant, why not just creating objects with a Kernel method, a little bit like in Javascript.

Then we extend them with our anonymous modules on the fly.

I will finish this post with some code demonstrating the usage of classless Ruby but please note how Ara's brilliant idea is still there, just look into Object#ext_object.

PrototypeError = Class::new( StandardError )
class Prototype
attr_accessor :__proto__
class << self
alias_method :orig_new, :new
def new *args, &block
o=orig_new( *args, &block )
o.__proto__ = Module::new
o
end
end

def deepdup
o = dup
instance_variables.each do |ivar|
val = instance_variable_get( ivar )
val = val.dup rescue val
o.instance_variable_set( ivar, val )
end
o
end
end # class Prototype

module Kernel
def new_object superobject=nil, &block
begin
superobject.deepdup
rescue NoMethodError
Prototype.new
end.ext_object( &block )
end
end # module Kernel

class Object
def ext_object &block
raise PrototypeError,
"Not a prototype" unless
respond_to?( :__proto__) && Module === __proto__
old_proto = __proto__
self.__proto__ = Module::new( &block )
__proto__.instance_eval{ include( old_proto ) }
extend __proto__
end

def clone &block
new_object( self, &block )
end
end # class Object

my_object = new_object {
attr_accessor :a, :b
def to_s; "#@a, #@b" end
}
my_object.a = 52
my_object.b = 60
other = my_object.clone {
def reset; @a=@b=nil end
}
puts my_object # --> 52, 60
puts other # --> 52, 60
other.reset
puts my_object # --> 52, 60
puts other # --> ,