[ANN] prototype-0.1.0

NAME

   prototype.rb

URIS

   http://codeforpeople.com/lib/ruby/
   http://rubyforge.org/projects/codeforpeople/

SYNOPSIS

   prototype.rb implements the prototype design pattern

     http://en.wikipedia.org/wiki/Prototype-based_programming

   for ruby

WHY

   prototype based programming can look very nice :wink:

EXAMPLES

···

__________________________________________
   ~ > cat samples/a.rb
   __________________________________________
   require 'prototype'

   singleton = Prototype.new{
     @a, @b = 40, 2

     def answer() @a + @b end
   }

   p singleton.answer

   __________________________________________
   ~ > ruby samples/a.rb
   __________________________________________
   42

   __________________________________________
   ~ > cat samples/b.rb
   __________________________________________
   require 'prototype'

   DB = Prototype.new{
     host 'localhost'
     port 4242

     def connect() p [host, port] end
   }

   p DB
   p DB.host
   p DB.port
   DB.connect

   __________________________________________
   ~ > ruby samples/b.rb
   __________________________________________
   "localhost"
   4242
   ["localhost", 4242]

   __________________________________________
   ~ > cat samples/e.rb
   __________________________________________
   require 'prototype'

   proto = prototype{
     @a = 40
     @b = 2
   }

   p(proto.a + proto.b)

   ~ > ruby -Ilib samples/e.rb
   42

   __________________________________________
   ~ > cat samples/f.rb
   __________________________________________
   require 'prototype'

   a = prototype{ attributes 'a' => 4, 'b' => 10, 'c' => 2 }

   b = prototype{ a 4; b 10; c 2 }

   c = prototype{ @a, @b, @c = 4, 10, 2 }

   [a, b, c].each{|obj| p(obj.a * obj.b + obj.c) }

   ~ > ruby -Ilib samples/f.rb
   42

   __________________________________________
   ~ > cat samples/g.rb
   __________________________________________
   require 'prototype'

   a = prototype

   b = prototype(a){ @a, @b, @c = 4, 10, 2 }

   a.extend{ def answer() a * b + c end }

   p b.answer

   ~ > ruby -Ilib samples/g.rb
   42

DOCS

   see

     lib/*rb
     samples/*rb

-a
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Very nice!

The only thing I see, is that your use of the term 'prototype' betrays
a Class-based OOP background. Ie. You're usimg "prototype" as one would
"class" and "instantiate" them albiet via a deep clone. Using a neutral
term like 'object' does away with that.

  a = object{ a 1; b 2; c 3 }

T.

If I may offer a "patch" to your synopsis, IMO a prototype based object model is not a "design pattern".

SYNOPSIS

   prototype.rb implements a prototype-based object model

Just my 2c.

···

On Jul 12, 2006, at 7:37 PM, ara.t.howard@noaa.gov wrote:

SYNOPSIS

  prototype.rb implements the prototype design pattern

That is the name of the model. See: Prototype-based programming - Wikipedia

···

On 12-Jul-06, at 10:45 PM, transfire@gmail.com wrote:

Very nice!

The only thing I see, is that your use of the term 'prototype' betrays
a Class-based OOP background. Ie. You're usimg "prototype" as one would
"class" and "instantiate" them albiet via a deep clone. Using a neutral
term like 'object' does away with that.

--
Jeremy Tregunna
jtregunna@blurgle.ca

"One serious obstacle to the adoption of good programming languages is the notion that everything has to be sacrificed for speed. In computer languages as in life, speed kills." -- Mike Vanier

How about this:

···

On 13/07/06, transfire@gmail.com <transfire@gmail.com> wrote:

The only thing I see, is that your use of the term 'prototype' betrays
a Class-based OOP background. Ie. You're usimg "prototype" as one would
"class" and "instantiate" them albiet via a deep clone. Using a neutral
term like 'object' does away with that.

  a = object{ a 1; b 2; c 3 }

---

require 'prototype'

def Prototype(&blk)
  return Prototype.new(&blk)
end

singleton = Prototype do
  @a, @b = 40, 2

  def answer() @a + @b end
end

p singleton.answer

---

Paul.

yes. i actually first coded up

   Object{ @a = 42; attr 'a' }

and alias for object

but reconsidered since the word 'object' is so often used. in any case it's
trivial to alias in your own code...

-a

···

On Thu, 13 Jul 2006 transfire@gmail.com wrote:

Very nice!

The only thing I see, is that your use of the term 'prototype' betrays
a Class-based OOP background. Ie. You're usimg "prototype" as one would
"class" and "instantiate" them albiet via a deep clone. Using a neutral
term like 'object' does away with that.

a = object{ a 1; b 2; c 3 }

T.

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

hmmm. the thing is that prottotyping, in ruby, is not an object model but a
design pattern based on top of normal classes and inheritence. since,
obviously, ruby does not directly support prototypical objects... still, your
point is well taken. i'll make an ammendment. maybe

   prototype.rb supports a prototypical programming style in ruby.

cheers.

-a

···

On Thu, 13 Jul 2006, Logan Capaldo wrote:

On Jul 12, 2006, at 7:37 PM, ara.t.howard@noaa.gov wrote:

SYNOPSIS

  prototype.rb implements the prototype design pattern

If I may offer a "patch" to your synopsis, IMO a prototype based object model is not a "design pattern".

SYNOPSIS

prototype.rb implements a prototype-based object model

Just my 2c.

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Jeremy Tregunna wrote:

>
> Very nice!
>
> The only thing I see, is that your use of the term 'prototype' betrays
> a Class-based OOP background. Ie. You're usimg "prototype" as one
> would
> "class" and "instantiate" them albiet via a deep clone. Using a
> neutral
> term like 'object' does away with that.

That is the name of the model. See: Wikipedia, the free encyclopedia
Prototype-based_programming

I'm not sure what your point is. I'm, aware of what it is called. But,
by "model" are you referring to "Prototype" or just the style of
programming? If the former, then here too it brings with it
preconetption of class-based OOP. What I trying to get across is that
there is deeper sense to this then class-oriented programmers generally
grasp. With Prototype-based OOP, you should not start by thinking about
what is Dog. Rather you should just create a dog. Later, if you need a
different dog, you copy your first and change it as needs be. You do
not cookie-stamp a fromal prototype. In a way the term prototype is
unfortuante. Perhaps "Instance-only programming" would convey the idea
better. Of course in practice one often does create Formal entities
nonetheless --as library tools, but even so, the bottom lines is that
there should be no dichotomy between prototype and non-prototype. There
just isn't any such thing in Prototype-OOP.

T.

···

On 12-Jul-06, at 10:45 PM, transfire@gmail.com wrote:

the latest release has both 'Prototype' and 'prototype' methods. both

   prototype{ a 42 }

and

   Prototype{ a 42 }

are now valid.

cheers.

-a

···

On Thu, 13 Jul 2006, Paul Battley wrote:

On 13/07/06, transfire@gmail.com <transfire@gmail.com> wrote:

The only thing I see, is that your use of the term 'prototype' betrays
a Class-based OOP background. Ie. You're usimg "prototype" as one would
"class" and "instantiate" them albiet via a deep clone. Using a neutral
term like 'object' does away with that.

  a = object{ a 1; b 2; c 3 }

How about this:

---

require 'prototype'

def Prototype(&blk)
return Prototype.new(&blk)
end

singleton = Prototype do
@a, @b = 40, 2

def answer() @a + @b end
end

p singleton.answer

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

I'm not sure what your point is. I'm, aware of what it is called. But,
by "model" are you referring to "Prototype" or just the style of
programming? If the former, then here too it brings with it
preconetption of class-based OOP. What I trying to get across is that
there is deeper sense to this then class-oriented programmers generally
grasp. With Prototype-based OOP, you should not start by thinking about
what is Dog. Rather you should just create a dog. Later, if you need a
different dog, you copy your first and change it as needs be. You do
not cookie-stamp a fromal prototype. In a way the term prototype is
unfortuante. Perhaps "Instance-only programming" would convey the idea
better. Of course in practice one often does create Formal entities
nonetheless --as library tools, but even so, the bottom lines is that
there should be no dichotomy between prototype and non-prototype. There
just isn't any such thing in Prototype-OOP.

I've been working with, and assisting in development of the prototype programming language Io for the past 2 years, I'm fully aware of the design principals one should utilize when working within the confines of a prototype-based language. As far as how people use it; it is my experience that those familiar with class based OOP tend to take about 3 weeks or so before they start to understand that you don't define a template first; you instead define your object, and from that make copies modifying as needed. That said however, just because it looks like someone is writing in a class-based style, doesn't mean they are. Generally speaking quite a few occasions will you find yourself cloning an object which seemingly is acting like a class (not being used itself except as a template for other objects). In cases like this, I don't know what your problem is; this comes up quite a bit, and is often the simpler of the two choices -- reconstruct the object based on all previous objects, or construct a template holding basic values which then a few objects will clone from. If you have a system like Io or NewtonScript which use a differential inheritance model, only the changes from the object you are cloning will be attached to your object, so you can change this template at a later time, and anything that any object that cloned from it hasn't changed, will receive those changes as well when they're used. To be honest, I think this satisfies a lot of conditions. Nobody is saying that class-based programming is without its merits, and certainly writing in a seemingly class-based style in a prototype language is possible, and often the simpler case.

To address your dog point more directly, incase I have to spell it out for you. It is often the case where you have say a Kennel which in this case, let's think of it like a data structure that houses only Dog-like objects. It is more efficient to define (in a system like Io or NewtonScript at least) a singular Dog object, and then define dogs from that. I.e.,

Kennel := Object clone
Kennel dogs := list
Kennel addDog := method(aDog, dogs atIfAbsentPut(aDog))

Dog := Object clone
Dog newSlot("colour")
Dog newSlot("size")
Dog newSlot("kind")
Dog newSlot("name")

/* newSlot creates a setter slot and a value slot */

Now, if you're Kennel is going to house a lot of Newfoundland dogs, it may be worth while to make a clone of Dog called NewfoundlandDog (or similar); unless of course, a very small minority are going to be anything but NewfoundlandDog's, in which case, I'd make Dog above representative of a newfoundland (setting "kind" to "Newfoundland") then for any non newfoundland types, i'd just as an example:

Fred := NewfoundlandDog clone
Fred setKind("Malamute")
...

And similar for other dogs (cloning Fred for other Malamutes, etc).

It makes sense in a differential inheritance system to do this kind of thing since it eliminates a lot of repeating.

That said, I understand ruby doesn't have a differential inheritance system, but these decisions can be applied to Ruby when using a prototype design pattern. It just makes sense; the nice thing is, it's not required, which is what differentiates it from class-based programming.

···

On 13-Jul-06, at 5:12 AM, transfire@gmail.com wrote:

T.

--
Jeremy Tregunna
jtregunna@blurgle.ca

"One serious obstacle to the adoption of good programming languages is the notion that everything has to be sacrificed for speed. In computer languages as in life, speed kills." -- Mike Vanier

i don't know too much about prototype based coding - but are you saying this
is 'normal/correct/intended' behaviour?

   jib:~/eg/ruby/prototype/prototype-0.2.0 > cat b.rb

   require 'prototype'

   a = prototype{ x 42 }

   b = a.clone

   a.extend{ y 42 }

   b.x 42.0

   p a.x #=> 42
   p a.y #=> 42

   p b.x #=> 42.0
   p b.y #=> 42

   jib:~/eg/ruby/prototype/prototype-0.2.0 > ruby -Ilib b.rb
   42
   42.0
   42

my understanding is that the above is generally accepted behaviour - but i'm
not sure.

cheers.

-a

···

On Fri, 14 Jul 2006, Jeremy Tregunna wrote:

If you have a system like Io or NewtonScript which use a differential
inheritance model, only the changes from the object you are cloning will be
attached to your object, so you can change this template at a later time,
and anything that any object that cloned from it hasn't changed, will
receive those changes as well when they're used.

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Jeremy Tregunna wrote:

I've been working with, and assisting in development of the prototype
programming language Io for the past 2 years, I'm fully aware of the
design principals one should utilize when working within the confines
of a prototype-based language. As far as how people use it; it is my
experience that those familiar with class based OOP tend to take
about 3 weeks or so before they start to understand that you don't
define a template first; you instead define your object, and from
that make copies modifying as needed. That said however, just because
it looks like someone is writing in a class-based style, doesn't mean
they are. Generally speaking quite a few occasions will you find
yourself cloning an object which seemingly is acting like a class
(not being used itself except as a template for other objects). In
cases like this, I don't know what your problem is; this comes up
quite a bit, and is often the simpler of the two choices --
reconstruct the object based on all previous objects, or construct a
template holding basic values which then a few objects will clone
from. If you have a system like Io or NewtonScript which use a
differential inheritance model, only the changes from the object you
are cloning will be attached to your object, so you can change this
template at a later time, and anything that any object that cloned
from it hasn't changed, will receive those changes as well when
they're used. To be honest, I think this satisfies a lot of
conditions. Nobody is saying that class-based programming is without
its merits, and certainly writing in a seemingly class-based style in
a prototype language is possible, and often the simpler case.

To address your dog point more directly, incase I have to spell it
out for you. It is often the case where you have say a Kennel which
in this case, let's think of it like a data structure that houses
only Dog-like objects. It is more efficient to define (in a system
like Io or NewtonScript at least) a singular Dog object, and then
define dogs from that. I.e.,

Kennel := Object clone
Kennel dogs := list
Kennel addDog := method(aDog, dogs atIfAbsentPut(aDog))

Dog := Object clone
Dog newSlot("colour")
Dog newSlot("size")
Dog newSlot("kind")
Dog newSlot("name")

/* newSlot creates a setter slot and a value slot */

Now, if you're Kennel is going to house a lot of Newfoundland dogs,
it may be worth while to make a clone of Dog called NewfoundlandDog
(or similar); unless of course, a very small minority are going to be
anything but NewfoundlandDog's, in which case, I'd make Dog above
representative of a newfoundland (setting "kind" to "Newfoundland")
then for any non newfoundland types, i'd just as an example:

Fred := NewfoundlandDog clone
Fred setKind("Malamute")
...

And similar for other dogs (cloning Fred for other Malamutes, etc).

It makes sense in a differential inheritance system to do this kind
of thing since it eliminates a lot of repeating.

That said, I understand ruby doesn't have a differential inheritance
system, but these decisions can be applied to Ruby when using a
prototype design pattern. It just makes sense; the nice thing is,
it's not required, which is what differentiates it from class-based
programming.

I think maybe you took what I was saying for more than my intended
point. I was only sayng that I think the use of the word "Prototype" in
Ara's implementation conveys too much the prior notions of class-based
OOP, and that the more general term, 'Object' would be more fitting.
Then I was trying to explain why.

Interestingly, your example uses the very word 'Object'.

Other than that, I understand and agree with everything you are saying.

T.

If you have a system like Io or NewtonScript which use a differential
inheritance model, only the changes from the object you are cloning will be
attached to your object, so you can change this template at a later time,
and anything that any object that cloned from it hasn't changed, will
receive those changes as well when they're used.

i don't know too much about prototype based coding - but are you saying this
is 'normal/correct/intended' behaviour?

[snip]

No I'm not saying that at all.

my understanding is that the above is generally accepted behaviour - but i'm
not sure.

It is. My whole post before was in regards to ... not sure what his name is -- but whomever I was replying to -- his objection to using objects like templates; I tried to demonstrate that it's a perfectly acceptable design pattern in prototype-based languages, citing two examples.

···

On 13-Jul-06, at 6:29 PM, ara.t.howard@noaa.gov wrote:

On Fri, 14 Jul 2006, Jeremy Tregunna wrote:

--
Jeremy Tregunna
jtregunna@blurgle.ca

"One serious obstacle to the adoption of good programming languages is the notion that everything has to be sacrificed for speed. In computer languages as in life, speed kills." -- Mike Vanier

I think maybe you took what I was saying for more than my intended
point. I was only sayng that I think the use of the word "Prototype" in
Ara's implementation conveys too much the prior notions of class-based
OOP, and that the more general term, 'Object' would be more fitting.
Then I was trying to explain why.

Ah, okay, sorry.

Interestingly, your example uses the very word 'Object'.

Well, in the Io programming language, to which my example was written in, the root object is called of all things, "Object", just like Ruby, Smalltalk, Java, and countless other OO languages.

···

On 13-Jul-06, at 10:21 PM, transfire@gmail.com wrote:

--
Jeremy Tregunna
jtregunna@blurgle.ca

"One serious obstacle to the adoption of good programming languages is the notion that everything has to be sacrificed for speed. In computer languages as in life, speed kills." -- Mike Vanier

my understanding is that the above is generally accepted behaviour - but
i'm not sure.

It is.

ok. that's what i really wanted to know. reading on wikipedia it's apparent
different langs have gone different ways - i just wanted to make sure my
approach was middle of the road 'normal'.

My whole post before was in regards to ... not sure what his name is -- but
whomever I was replying to -- his objection to using objects like templates;
I tried to demonstrate that it's a perfectly acceptable design pattern in
prototype-based languages, citing two examples.

you were talking with tom. he thinks about these things more than most on
this list - so i value his opinion. yet i still find myself wanting imediate
objects quite often...

cheers.

-a

···

On Fri, 14 Jul 2006, Jeremy Tregunna wrote:
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Jeremy Tregunna wrote:

Well, in the Io programming language, to which my example was written
in, the root object is called of all things, "Object", just like
Ruby, Smalltalk, Java, and countless other OO languages.

:smiley:

Why do they never choose "Thing"? :wink:

They have their resons (:

mar

[*] List of fictional elements, materials, isotopes and subatomic particles - Wikipedia

···

On 7/14/06, transfire@gmail.com <transfire@gmail.com> wrote:

Jeremy Tregunna wrote:

> Well, in the Io programming language, to which my example was written
> in, the root object is called of all things, "Object", just like
> Ruby, Smalltalk, Java, and countless other OO languages.

:smiley:

Why do they never choose "Thing"? :wink: