I'll have the duck!

I promised myself I'd shut-up for awhile, maybe I still should, but I
just couldn't help myself with this one...

Today I wrote

    data = data.transform

but I meant to write

    data = transform(data)

While I knew data would be hash, I certainly didn't want to write a new
Hash method just for this --you reserve extensions for really general
reusable stuff, right? Besides I wanted to remain open to duck typing
and hence any hash-like object.

That's when it hit me. We haven't yet taken the full duck type plunge.
We've just strapped a quasi-duck onto an old oop type dog. We're still
defining our methods base on types, not duck types. But what would
defining on duck type mean intead? As it turns out it measn defining on
method dependencies.

Take #transform. Forget what "class" it belongs to. What does it do?
For the sake of this dialog lets say it does this:

  def transform
    data.to_a
  end

Simple. Now, if I want to call #transform on data, all it needs to do
is repond_to #to_a. It need not matter at all what class it is. So
imagine if you will, that instead of "classes" and "methods", we could
define "ducks" and "quacks".

  duck to_a
    quack transform
       self.to_a
    end
  end

Now anything that responded to #to_a could use #transform. I'm not sure
how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

T.

duck == mixin

Consider the Enumerable mixin.

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong later."

From this principle, all of life and physics may be deduced.

there's a language called "self" that has no classes, only prototypes. if you
can find some material on that, i think you'll find it interesting.

regards,

···

On Mon, 24 Jul 2006 08:09:58 +0900, transfire@gmail.com wrote:

Now anything that responded to #to_a could use #transform. I'm not sure
how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

--
Ron Jeffries
www.XProgramming.com
I'm giving the best advice I have. You get to decide if it's true for you.

I promised myself I'd shut-up for awhile, maybe I still should, but I
just couldn't help myself with this one...

So did I :wink:

Today I wrote

    data = data.transform

but I meant to write

    data = transform(data)

While I knew data would be hash, I certainly didn't want to write a new
Hash method just for this --you reserve extensions for really general
reusable stuff, right?

I fail to see this point at 100%, I think this is what subclassing is for,
but I am really oppused to ducktyping, one needs to be, I am afraid of
things all agree on.
Well I love ducktyping but I call it protcolling and I want early checking,
and I seem to be alone.
Sorry if I go offtopic.

Besides I wanted to remain open to duck typing

and hence any hash-like object.

Yeah great, you see that is what troubles me, it is completely cool to talk
about hash-like object, but what is a hash-like object? Which messages must
a hash-like object respond to? All of Hash, I suppose, thus a subclass, or
only some, then we can talk about protocols again, but the failure to be
able to define the protocol just worries me.
Again very important: The failure to be able, not to have to, I am 100% for
the enabeling approach, but who enables constraints and protocol checking?

That's when it hit me. We haven't yet taken the full duck type plunge.

Good!

We've just strapped a quasi-duck onto an old oop type dog.

Poor animal.

We're still

defining our methods base on types, not duck types.

This duck risks to get bitten into it's tail, by itself. I have the
feeling that method delegation (was this the english name (patrimoine de
méthode)?) is all you are doing.
But pleas get me straight if I read you wrong.

  But what would

defining on duck type mean intead? As it turns out it measn defining on
method dependencies.

Take #transform. Forget what "class" it belongs to. What does it do?
For the sake of this dialog lets say it does this:

I am losing you there :frowning:

  def transform
    data.to_a
  end

Simple.

Well if you say so :wink:

Now, if I want to call #transform on data, all it needs to do

is repond_to #to_a. It need not matter at all what class it is. So
imagine if you will, that instead of "classes" and "methods", we could
define "ducks" and "quacks".

  duck to_a
    quack transform
       self.to_a
    end
  end

Now anything that responded to #to_a could use #transform. I'm not sure
how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

Is this a protocol you try to define, sorry if I am too stupid to get it,
could you explain to an old dog, as a friendly duck?

T.

Cheers

Robert

···

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

--
Deux choses sont infinies : l'univers et la bêtise humaine (j'y suis, j'y
reste); en ce qui concerne l'univers, je n'en ai pas acquis la certitude
absolue.

- Albert Einstein

From: transfire@gmail.com [mailto:transfire@gmail.com]
Sent: Monday, July 24, 2006 1:10 AM

[...]
Now anything that responded to #to_a could use #transform.
I'm not sure
how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

T.

Like this *evil grin* ? (Ok, there are still classes...)

···

------------------------------------------------------------------------
----
class Object
    def method_missing sym, *args
        @@ducks.select{|d| d.first == sym}.each do |duck|
            return send(duck[1], *args) if duck.last.all?{|i|
respond_to? i}
        end
        super
    end
    
    def self.duck sym, real , *interface
        (@@ducks ||= ) << [sym, real, interface]
    end
end

def i_next_to_s
    succ.to_s
end

def f_next_to_s
    ceil.to_s
end

Object.duck :next_to_s, :i_next_to_s, :succ, :to_s
Object.duck :next_to_s, :f_next_to_s, :ceil, :to_s

p(41.next_to_s) #=> "42"
p('A'.next_to_s) #=> "B"
p(5.5.next_to_s) #=> "6"
------------------------------------------------------------------------
----

cheers

Simon

Now anything that responded to #to_a could use #transform. I'm not

sure

how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

:slight_smile: I was thinking things like this a while ago, and a clever friend
pointed me to predicate classes (see google). The idea with them is that
you define a predicate such as "supports the method 'each'". You could
call this predicate Enumerable. The predicate is a declaration of your
interface requirements. You can then add methods to this Enumerable
predicate class, such as min, max, inject, etc. From then, anything that
is Enumerable will also support the things you put in to Enumerable.
Pretty cool.

I liked the idea, anyway. I like it because I think it would make it
easier to take things that you've already got, things that someone has
given to you perhaps, and say new things about them based on the fact
that they've pretty much got the interface you're looking for (if they
don't quite have the right interface, you can use predicate classes to
give them the additional "glue" that they need).

I also like it because I don't think that there's anything especially
fundamental about classes. With predicate classes, all you're really
saying is that "if I've got something that can do x and y, then I know
that I can equally validly think of it as something that can do z".

[I should point out here that I don't imagine Predicate Classes are "the
answer"; I'm just pointing to them as being interesting.]

Class hierarchies almost always seem arbitrary and task oriented to me.
That works well when you've a particular task in mind, but I think it
falls over when the task changes, or when you're more interested in the
information in some objects, rather than what they are currently being
used for.

I also think they're an impediment to being agile because you're
building up a hierarchy that may not exist. Sure, you can refactor, and
perhaps you've got automated tools that do that, but you shouldn't need
to. You, and any part of your program or someone else's, ought to be
able to look at some existing objects in any way they choose. You should
be able to say anything you like about your particular way of looking at
those things.

While I like Ruby a great deal (and I really mean that: it's made
programming fun again, for me), I don't think contemporary OO is all
that. Something that's wonderful about Ruby though, is that I think it's
got every chance of being the platform in which people find that out,
and find a better way.

On the other hand, I could be wrong, in which case Ruby's already there :slight_smile:

Cheers,
  Benjohn

I'm not sure what the best place for this is; sorry. The following are
my views:
  What we know as 'duck typing' is not really a programming paradigm,
but a set practices as Mr. Black says--merely the "yin" end of the
type-checking continuum. I first learned about it, although of course
not by that name, from studying C++ templates, where also the
prevailing wisdom is that you shouldn't assume anything more about your
library's client's code than is absolutely necessary. The 'duck
typing' moniker that marks it as a novelty is most useful against the
background of static languages, where type-checking helps prevent
runtime errors. For Ruby, where *every* error is runtime, duck typing
is the raw form of its behavior, and should be recognized as quickly as
possible, because it isn't always good. At its utmost, duck typing is
the total absence of validation. You are saying that nothing about
your client's program is worth trying to predict, that 'if it works, it
works,' and if it doesn't, he'll know because it just blew up.
  Hmm. I see where type-checking came from. As far as Ruby best
practices go, I think 'duck typing' just means using respond_to?() more
than kind_of?() and include?(). If you really wanted to, dumping class
use entirely and turning Ruby into a prototype-based language wouldn't
be too hard: you'd use Object::new() only, define only singleton
methods, and extend objects with clone(); and if you wanted to
delegate, you'd keep an array of references of "parent" objects,
Perl-style.
  Personally, I feel that Ruby needs more, rather than less, type
safety, to balance its natural inclination otherwise and because no
amount of 'duck typing' disaffirms that erroneous behavior is best
caught as soon as possible. But I don't think anyone would advocate a
return to rigid inheritance checking, which realization the deprecation
of type() notably indicates.

I much prefer its (less mature) derivative, Io. Everything is a message to something else, and everything is a prototype. Very simple, very powerful (even, dare I say, more powerful than Ruby, albeit a bit less pretty).

- Jake McArthur

···

On Jul 23, 2006, at 9:45 PM, Ron Jeffries wrote:

On Mon, 24 Jul 2006 08:09:58 +0900, transfire@gmail.com wrote:

Now anything that responded to #to_a could use #transform. I'm not sure
how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

there's a language called "self" that has no classes, only prototypes. if you
can find some material on that, i think you'll find it interesting.

regards,

--
Ron Jeffries
www.XProgramming.com
I'm giving the best advice I have. You get to decide if it's true for you.

Well... i don't think mixins are exactly that :slight_smile:
what trans proposes is more like excessive duck-typing

imagine a duck
you can make it quack
and you know - what the duck quacks can be processes in many ways...

Duck.quack.record.to_tape.copy.to_cd.send_to producer

might be a bit excessive, but in essential that's it...
i've learned that kind of 'method' in Dylan, where you define that stuff a bit
different - you have a kind of reversed dispatcher that adds classes to
methods and decides which method to use given what object you operate on.

little syntax help - the stuff in <> are classes, <duck> and <fish> are
subclasses of <animal>

···

On Monday 24 July 2006 11:40, John Carter wrote:

duck == mixin

Consider the Enumerable mixin.

########################################

define method to-s (animal :: <animal>)
color(animal)
end

define method color (duck :: <duck>)
"brown"
end

define method color (fish :: <fish>)
"grey"
end

########################################

the methods are not added to the object - they look like that afterwards:
(using ruby for that, so it looks a bit nicer :wink:

def color (x)
if x === Animal
if x === Fish
"grey"
elsif x === Duck
"brown"
end
end
end

don't want to hang around in dylan for too long, but this was a new way (at
least for me) to express methods...
now, this could be driven further

you could attach methods to objects that respond to specific methods

########################################

methods to_a
def compact
delete_if{|e| e.nil? }
end

def sum
inject{|s,v| s+v}
end
end

class Foo
def to_a
[1,2,3,nil]
end
end

Foo.new.compact.sum
# 6

########################################

something like that...
i find that is true ducktyping :slight_smile:
however... the beauty is in the eye of the beholder, so it might look
butt-ugly to someone else :expressionless:

i just kinda like the idea itself - the implementation in ruby would be
enormous work (as i imagine it at least) - and would slow down ruby
further...

these assumptions are just in my honest opinion :slight_smile: might as well be pretty
neat to integrate and work with... but i have my doubts...

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong
later."

From this principle, all of life and physics may be deduced.

Robert Dober wrote:
<snip>

and hence any hash-like object.

Yeah great, you see that is what troubles me, it is completely cool to talk
about hash-like object, but what is a hash-like object? Which messages must
a hash-like object respond to? All of Hash, I suppose, thus a subclass, or
only some, then we can talk about protocols again, but the failure to be
able to define the protocol just worries me.

That's the whole point. Duck-typing means that your class only needs to define the methods (of Hash, in this case) that the called method (transform here) needs, *not* the whole Hash class, *without* having to specify a protocol. If you want to specify a protocol, there's one example of how to do it here:

http://www.erikveen.dds.nl/monitorfunctions/index.html#6.0.0

Again very important: The failure to be able, not to have to, I am 100% for
the enabeling approach, but who enables constraints and protocol checking?

See above. Second time I've used that link in this thread :slight_smile:

···

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

--
Alex

benjohn@fysh.org wrote:

I also like it because I don't think that there's anything especially
fundamental about classes. With predicate classes, all you're really
saying is that "if I've got something that can do x and y, then I know
that I can equally validly think of it as something that can do z".

The concept really piqued my interest, and since ruby gives us such nice
metaprogramming abilities, why not do it?

module DuckTyping
   @@quacks = Hash.new{ |h,k| h[k] = {} }

   def ducktype(*reqs, &block)
     o = Object
     before = o.methods
     o.class_eval(&block)
     after = o.methods

     for methodname in (after - before)
       @@quacks[methodname.to_sym][reqs] = o.instance_method(methodname.to_sym)
       o.send(:remove_method, methodname.to_sym)
     end
   end

   def ducktype_method(methodname)
     @@quacks[methodname.to_sym].each do |reqs, m|
       if reqs.all?{ |r| self.respond_to?(r) }
         return m
       end
     end
     return nil
   end

   def method_missing(methodname, *args, &block)
     if m = ducktype_method(methodname)
       m.bind(self).call(*args, &block)
     else
       super
     end
   end
end
Object.module_eval{ include DuckTyping }

ducktype :quack do
   def quack_loudly
     quack.upcase
   end
end

class Duck
   def quack
     "quack!"
   end
end

class Dog
   def bark
     "woof!"
   end
end

Duck.new.quack_loudly #=> "QUACK!"
Dog.new.quack_loudly #=> NoMethodError

nifty?

Hi --

I'm not sure what the best place for this is; sorry. The following are
my views:
  What we know as 'duck typing' is not really a programming paradigm,
but a set practices as Mr. Black says--merely the "yin" end of the
type-checking continuum. I first learned about it, although of course
not by that name, from studying C++ templates, where also the
prevailing wisdom is that you shouldn't assume anything more about your
library's client's code than is absolutely necessary. The 'duck
typing' moniker that marks it as a novelty is most useful against the
background of static languages, where type-checking helps prevent
runtime errors. For Ruby, where *every* error is runtime, duck typing
is the raw form of its behavior, and should be recognized as quickly as
possible, because it isn't always good. At its utmost, duck typing is
the total absence of validation. You are saying that nothing about
your client's program is worth trying to predict, that 'if it works, it
works,' and if it doesn't, he'll know because it just blew up.

True, though that's partly why test-driven development is so big among
Rubyists.

  Hmm. I see where type-checking came from. As far as Ruby best
practices go, I think 'duck typing' just means using respond_to?() more
than kind_of?() and include?().

At some point in the past I think I posited a distinction between
"soft duck typing" and "hard duck typing" :slight_smile: Very much along the
lines you're describing: soft duck typing involves the "extra" layer
of respond_to? and hard duck typing doesn't. respond_to? is certainly
a sensible precaution to take, in many cases, and one that operates in
the orbit of the object itself (as opposed to kind_of?).

(I'm not quite sure what you mean about include?....)

If you really wanted to, dumping class
use entirely and turning Ruby into a prototype-based language wouldn't
be too hard: you'd use Object::new() only, define only singleton
methods, and extend objects with clone(); and if you wanted to
delegate, you'd keep an array of references of "parent" objects,
Perl-style.

It seems to me (though I don't know any of the prototyped languages in
any depth) that Ruby indeed gives you both: a per-object universe, and
a class system. Ultimately, the former sort of "wins", in the sense
that classes are objects and so on... but actually I think the two are
in a nice balance.

  Personally, I feel that Ruby needs more, rather than less, type
safety, to balance its natural inclination otherwise and because no
amount of 'duck typing' disaffirms that erroneous behavior is best
caught as soon as possible.

True -- but it may have to do with how one defines "possible" :slight_smile: One
could say that no amount of early checking can change the fact that
the only absolute way to know what sending a message to an object will
do is to send the message to the object. In practice, one settles for
non-absolute ways, not only because they tend to work but because
they're all that's available. But I'm always fascinated by the
singularity of a Ruby method call: there's nothing else around it that
really, absolutely pertains to it.

But I don't think anyone would advocate a
return to rigid inheritance checking, which realization the deprecation
of type() notably indicates.

Actually the deprecation of type, I believe, has a different cause.
As I understand it, in early Rubies there were problems parsing:
obj.class, so a name other than "class" had to be used for that
method. Now that obj.class can be parsed, "type" is no longer needed
-- and, as Matz has said, it's problematic because it discourages duck
typing.

David

···

On Tue, 25 Jul 2006, Dumaiu wrote:

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
Ruby for Rails => RUBY FOR RAILS (reviewed on
                                     Slashdot, 7/12/2006!)
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
dblack@wobblini.net => me

Ron Jeffries <ronjeffries@acm.org> writes:

Now anything that responded to #to_a could use #transform. I'm not sure
how far this can be taken. Can classes be undone altogegther? But in
anycase, it seems very cool, and I wonder what kind of overall effect
it could have on coding?

there's a language called "self" that has no classes, only prototypes. if you
can find some material on that, i think you'll find it interesting.

While you're at it, have a look at Slate, that also removes single-dispatch.

···

On Mon, 24 Jul 2006 08:09:58 +0900, transfire@gmail.com wrote:

Ron Jeffries

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

I'm not sure what the best place for this is; sorry. The following are
my views:
  What we know as 'duck typing' is not really a programming paradigm,
but a set practices as Mr. Black says--merely the "yin" end of the
type-checking continuum. I first learned about it, although of course
not by that name, from studying C++ templates, where also the
prevailing wisdom is that you shouldn't assume anything more about your
library's client's code than is absolutely necessary. The 'duck
typing' moniker that marks it as a novelty is most useful against the
background of static languages, where type-checking helps prevent
runtime errors. For Ruby, where *every* error is runtime, duck typing
is the raw form of its behavior, and should be recognized as quickly as
possible, because it isn't always good. At its utmost, duck typing is
the total absence of validation. You are saying that nothing about
your client's program is worth trying to predict, that 'if it works, it
works,' and if it doesn't, he'll know because it just blew up.

No. That's not duck typing, that is shoddy programming.

You may have a rescue clause right after your doubtful code,
or somewhere else upwards in your call stack. Or it might be
guaranteed by application semantics (as opposed to static typeing)
that your object can handle the messages sent to it.

My take on duck typing:
- allows sending messages to objects without *prior* validations.
- breaks up dependencies on a strict class hierarchy by allowing to send
  any message to any object.

Neither of them requires that a program may blow up.

  Hmm. I see where type-checking came from. As far as Ruby best
practices go, I think 'duck typing' just means using respond_to?() more
than kind_of?() and include?(). If you really wanted to, dumping class
use entirely and turning Ruby into a prototype-based language wouldn't
be too hard: you'd use Object::new() only, define only singleton
methods, and extend objects with clone(); and if you wanted to
delegate, you'd keep an array of references of "parent" objects,
Perl-style.

Sometimes it might be better to use #responds_to? early, and many
people will still consider this duck typing. It may be less "pure"
than handling NoMethodError, but it might be just the right tool
depending on your situation.

Even #kind_of? can have its merit in certain situations. I wouldn't
call code using it to rely on duck typing though, but that's not a bad
thing per se.

Prototype based languages are tangential to this, and need not be
drawn into this discussion here.

  Personally, I feel that Ruby needs more, rather than less, type
safety, to balance its natural inclination otherwise and because no
amount of 'duck typing' disaffirms that erroneous behavior is best
caught as soon as possible. But I don't think anyone would advocate a
return to rigid inheritance checking, which realization the deprecation
of type() notably indicates.

By your argument, exceptions are bad too, because they catch errors
"late". And IMHO exception handling was one of the better points when
going from C to C++. Think of duck typing as yet another technique not
to litter your code with error checking, but still do it
somewhere/sometime. You do handle C++ exceptions too, do you, if not
neccessarily right next to throwing them?

I repeat: duck typing is not to produce bombing out code, but a new*
way to handle dynamic and flexible type validation "late", with the
objective to ease development and produce clean code.

* actually not. But many people coming from C++ or Java just don't know
prior OOP languages.

-Jürgen

···

On Tue, Jul 25, 2006 at 01:05:11PM +0900, Dumaiu wrote:

--
The box said it requires Windows 95 or better so I installed Linux

Jake McArthur wrote:

I much prefer its (less mature) derivative, Io. Everything is a message to something else, and everything is a prototype. Very simple, very powerful (even, dare I say, more powerful than Ruby, albeit a bit less pretty).

- Jake McArthur

Actual, real programming languages with compilers or interpreters, a code base, applications and vibrant communities are for wimps! Give me an academic abstract language like the Pi-Calculus any day!

:slight_smile:

Now that I think of it, Lisp was once an academic abstract language ... some bozo had to spoil it by writing an interpreter for the IBM 704.

Speaking of languages, isn't FORTRAN 50 years old this year?

Robert Dober wrote:
<snip>
>> and hence any hash-like object.
>
> Yeah great, you see that is what troubles me, it is completely cool to
talk
> about hash-like object, but what is a hash-like object? Which messages
> must
> a hash-like object respond to? All of Hash, I suppose, thus a subclass,
or
> only some, then we can talk about protocols again, but the failure to be
> able to define the protocol just worries me.
That's the whole point. Duck-typing means that your class only needs to
define the methods (of Hash, in this case) that the called method
(transform here) needs, *not* the whole Hash class, *without* having to
specify a protocol. If you want to specify a protocol, there's one
example of how to do it here:

Ruby Monitor-Functions - Or Meta-Meta-Programming in Ruby

Well I have read that, kind of, it is a little bit heavy, too heavy I am
afraid.
I still do not get the point, are you saying I am right (let dogs life) or
are you saying I am wrong (let only ducks life).
Mixins are another nice way to think about it

class Dog
     include Duck
... # no this is *not* the Perl6 Thingy Jabbawalky operator :wink:
end

d = Puppet
d.implements? Duck ==> true

but maybe this is here already, gotta check.
Thx for your considerations
I repeat nevertheless
Ducks are great, unless they kill Dogs :wink:

Cheers
Robert

Again very important: The failure to be able, not to have to, I am 100%
for
> the enabeling approach, but who enables constraints and protocol
checking?
See above. Second time I've used that link in this thread :slight_smile:

I will not blame you, yet :wink:

···

On 7/24/06, Alex Young <alex@blackkettle.org> wrote:

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

--

Alex

You piqued my curiosity with that. But "lo" is really hard to google for. Do you have any reference links?
-Mat

···

On Jul 23, 2006, at 10:59 PM, Jake McArthur wrote:

I much prefer its (less mature) derivative, Io. Everything is a message to something else, and everything is a prototype. Very simple, very powerful (even, dare I say, more powerful than Ruby, albeit a bit less pretty).

- Jake McArthur

Daniel DeLorme wrote:

> I also like it because I don't think that there's anything especially
> fundamental about classes. With predicate classes, all you're really
> saying is that "if I've got something that can do x and y, then I know
> that I can equally validly think of it as something that can do z".

The concept really piqued my interest, and since ruby gives us such nice
metaprogramming abilities, why not do it?

module DuckTyping
   @@quacks = Hash.new{ |h,k| h[k] = {} }

[snip cool code]

ducktype :quack do
   def quack_loudly
     quack.upcase
   end
end

class Duck
   def quack
     "quack!"
   end
end

class Dog
   def bark
     "woof!"
   end
end

Duck.new.quack_loudly #=> "QUACK!"
Dog.new.quack_loudly #=> NoMethodError

nifty?

Nicely done! Code worthy of experimentation. A lot of excellent
comments in this thread too.

I wonder then, if we take up John Carter's notion on duck as mixin,
then Enumerable can be defined as:

  ducktype :each do
    def collect
      each{ |e| yield(e) }
    end
    ...
  end

Although clearly the distinction between a mixin and a ducktype is the
ducktypes global influence. Quite powerful! Yet, I do imagine that with
this is place someone would call for selector namepsaces to reign in
the abundant flocks :wink: Onefurther step would have to be taken, at the
very least. a means of constraining them to specific scopes. Perhaps
that's a simple as limiting them the module space they are defined in?

In any case very interesting. I really wonder just how far one can take
this shift in paradigm?

T.

···

benjohn@fysh.org wrote:

Hi --

I also like it because I don't think that there's anything especially
fundamental about classes. With predicate classes, all you're really
saying is that "if I've got something that can do x and y, then I know
that I can equally validly think of it as something that can do z".

The concept really piqued my interest, and since ruby gives us such nice
metaprogramming abilities, why not do it?

module DuckTyping
@@quacks = Hash.new{ |h,k| h[k] = {} }

[...]

Duck.new.quack_loudly #=> "QUACK!"
Dog.new.quack_loudly #=> NoMethodError

I guess you'd have to think of a new name to refer to what has in the
past been called "duck typing" :slight_smile:

David

···

On Tue, 25 Jul 2006, Daniel DeLorme wrote:

benjohn@fysh.org wrote:

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
Ruby for Rails => RUBY FOR RAILS (reviewed on
                                     Slashdot, 7/12/2006!)
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
dblack@wobblini.net => me

Daniel DeLorme wrote:

···

benjohn@fysh.org wrote:

I also like it because I don't think that there's anything especially
fundamental about classes. With predicate classes, all you're really
saying is that "if I've got something that can do x and y, then I know
that I can equally validly think of it as something that can do z".

The concept really piqued my interest, and since ruby gives us such nice
metaprogramming abilities, why not do it?

module DuckTyping
  @@quacks = Hash.new{ |h,k| h[k] = {} }

  def ducktype(*reqs, &block)
    o = Object
    before = o.methods
    o.class_eval(&block)
    after = o.methods

    for methodname in (after - before)
      @@quacks[methodname.to_sym][reqs] = o.instance_method(methodname.to_sym)
      o.send(:remove_method, methodname.to_sym)
    end
  end

  def ducktype_method(methodname)
    @@quacks[methodname.to_sym].each do |reqs, m|
      if reqs.all?{ |r| self.respond_to?(r) }
        return m
      end
    end
    return nil
  end

  def method_missing(methodname, *args, &block)
    if m = ducktype_method(methodname)
      m.bind(self).call(*args, &block)
    else
      super
    end
  end
end
Object.module_eval{ include DuckTyping }

ducktype :quack do
  def quack_loudly
    quack.upcase
  end
end

class Duck
  def quack
    "quack!"
  end
end

class Dog
  def bark
    "woof!"
  end
end

Duck.new.quack_loudly #=> "QUACK!"
Dog.new.quack_loudly #=> NoMethodError

nifty?

Isn't this stuff used i Aspect Oriented Programming as well? I only know what I've read in the RCR, so I'm not sure.

Cheers,
Daniel