Duck typing problem

Hello,

Suppose I have a class named Roelof.

Now I want to use ducktyping to test the class.

So I thought I could do :

def test(obj)
obj.responds_to? (method)
end

but how do I do this when someone uses the test defenition like this

test(Roelof.new)

Roelof

On 2/06/2014, at 5:20 pm, Roelof W. [email protected] wrote:

end

but how do I do this when someone uses the test defenition like this

test(Roelof.new)

Exactly the same. Roelof.new returns an object taht will be passed into
your test method.

Note though that asking an object if it responds to a method isn’t duck
typing. Just call the method.

Henry

Henry M. schreef op 2-6-2014 11:59:

def test(obj)
Henry

Thanks.

Can anyone then give me a hint how to solve this by duck typing ?
I have read many pages about it but I still confuses me.

Roelof

On Monday 02 June 2014 13:24:43, Roelof W. [email protected] wrote:

Can anyone then give me a hint how to solve this by duck typing ?
I have read many pages about it but I still confuses me.

With “traditional” object-oriented programming, a class is also a data
type.
That meant: different class, different data type. If classes have the
same
ancestor or implement the same interface, they can be casted to that
base
class or interface. Basically, the common denominator. Whenever the
method you
want to call is defined in that base class/interface, you can call it,
not
matter what actual class you have.

Now, introduce duck typing. Duck typing has the popular slogan “If it
walks
like a duck, and quacks like a duck, I’ll happily treat it as a duck.”
That
means that there is no need for common base classes or interfaces any
more. If
classes A and B share the same method signature, you can call it on both
classes, no matter what they otherwise do.

Consider, for example, two classes: A PDF writer and a network socket.
Suppose
they both have the method “write(something)” defined. Now, the two
classes do
not share anything else. They have no common ancestor and implement no
common
interface. In fact, they perform two completely different tasks!

Somewhere in your program, you want to serialize a text. You call
“writer_object.write(my_text)”. But there are different code paths that
lead
to this certain point, and in one case, you may end up with a PDF writer
object stored in the variable “writer_object”, and in anthoer case, it
may be
the socket.

In ruby, this works. The results are different, of course, but it works.
The
vast advantage is that you can decide on your program’s behaviour
somewhere in
your code, but have the very same method writing the text.

For example, there could be a user interface where the user could select
“Send
Text via E-Mail” or “Print Text to PDF”. Based on that selection, your
code
would instanciate either the Socket class or the PDF writer. However,
the
other part of your code that is responsible for serializing it does not
have
to know about this choice, it just happily uses the “write” method.

A small code example of Duck Typing in action could look like this:

—%<—
[1] pry(main)> class A
[1] pry(main)* def quack()
[1] pry(main)* puts “Quaaa!”
[1] pry(main)* end
[1] pry(main)* end
=> nil
[2] pry(main)> class B
[2] pry(main)* def quack()
[2] pry(main)* puts “Quack! Quack!”
[2] pry(main)* end
[2] pry(main)* end
=> nil
[3] pry(main)> def do_quack(a_class)
[3] pry(main)* a_class.quack()
[3] pry(main)* end
=> nil
[4] pry(main)> do_quack(A.new)
Quaaa!
=> nil
[5] pry(main)> do_quack(B.new)
Quack! Quack!
=> nil
—>%—

As you can see, the “do_quack” method does not care whether its an
instance of
class A or class B it gets passed, it just calls the “quack” method. And
in
fact, it yields different results each time.

HTH.

  --- Eric

On Monday 02 June 2014 19:15:44, Roelof W. [email protected] wrote:

But what I try is this.

Suppose you have the class A and you would check if it’s a duck.

Basically, you don’t. It’s the whole sense of duck typing: You do not
longer
check, directly or indirectly, whether an object is of a certain class
or
implements a certain interface. You just call obj.method().

I think you can do class A.responds_to(:quack) and if that’s true you
know its a duck.

Again: You don’t need to know. If it walks and quacks, for all what it’s
worth, you can just assume it’s a duck. It could be Cthulhu, but as long
as He
walks and quacks, you just treat Him like a duck instead of going
completely
insane.

  --- Eric

Eric MSP Veith schreef op 2-6-2014 14:32:

Now, introduce duck typing. Duck typing has the popular slogan “If it walks
Somewhere in your program, you want to serialize a text. You call
Text via E-Mail” or “Print Text to PDF”. Based on that selection, your code
[1] pry(main)* end
[3] pry(main)* end
class A or class B it gets passed, it just calls the “quack” method. And in
fact, it yields different results each time.

HTH.

  --- Eric

Oke, I understand this,

But what I try is this.

Suppose you have the class A and you would check if it’s a duck.
I think you can do class A.responds_to(:quack) and if that’s true you
know its a duck.

Roelof

Eric MSP Veith schreef op 2-6-2014 19:55:
On Monday 02 June 2014 19:15:44, Roelof W. <[email protected]> wrote:
But what I try is this.

Suppose you have the class A and you would check if it’s a duck.




Basically, you don’t. It’s the whole sense of duck typing: You do not
longer
check, directly or indirectly, whether an object is of a certain class
or
implements a certain interface. You just call obj.method().
I think you can do class A.responds_to(:quack) and 
if that's true you
know its a duck.
Again: You don't need to know. If it walks and quacks, for all what it's
worth, you can just assume it's a duck. It could be Cthulhu, but as long 
as He
walks and quacks, you just treat Him like a duck instead of going 
completely
insane.
  --- Eric</pre>
</blockquote>
<br>
Oke, <br>
<br>
Then I think I misunderstood the exercise. <br>
<br>
The exercise is : <br>
<br>
<p>You probably know, that in Javascript (and also Ruby) there is no
  concept of interfaces. There is only a concept of inheritance, but
  you can't assume that a certain method or property exists, just
  because it exists in the parent prototype / class. We want to find
  out, whether a given object fulfils the requirements to implement
  the "SantaClausable" <em>interface</em>. We need to implement a
  method which checks for this <em>interface</em>.</p>
<h2>Rules</h2>
<p>The SantaClausable interface is implemented, if all of the
  following methods are defined on an object:</p>
<ul>
  <li><code>sayHoHoHo()</code> / <code>say_ho_ho_ho</code></li>
  <li><code>distributeGifts()</code> / 

distribute_gifts

  • goDownTheChimney() /
    go_down_the_chimney


  • Example


    var santa = {
    sayHoHoHo: function() {
    console.log(‘Ho Ho Ho!’) },
    distributeGifts: function() {
    console.log(‘Gifts for all!’); },
    goDownTheChimney: function() {
    console.log(whoosh); }
    };

    var notSanta = {
    sayHoHoHo: function() {
    console.log(‘Oink Oink!’) }
    // no distributeGifts() and no
    goDownTheChimney()

    };

    isSantaClausable(santa); // must return
    TRUE

    isSantaClausable(notSanta); // must return
    FALSE


    santa =
    sayHoHoHo: ->
    console.log “Ho Ho Ho!”

    distributeGifts: ->
    console.log “Gifts for all!”

    goDownTheChimney: ->
    console.log whoosh

    notSanta = sayHoHoHo: ->
    console.log “Oink Oink!”
    # no distributeGifts() and no
    goDownTheChimney()

    isSantaClausable santa # must return TRUE
    isSantaClausable notSanta # must return
    FALSE


    class SantaClaus
    def say_ho_ho_ho
    # Ho Ho Ho!
    end
    <span class="function"><span class="keyword">def</span> <span 
    

    class=“title”>distribute_gifts
    # Gifts for all!
    end

    <span class="function"><span class="keyword">def</span> <span 
    

    class=“title”>go_down_the_chimney
    # Whoosh!
    end
    end

    class NotSantaClaus
    def say_ho_ho_ho
    end
    end

    is_santa_clausable(SantaClaus.new) # must return TRUE
    is_santa_clausable(NotSantaClaus.new)
    # must return

    and the begin function looks like this :

    def is_santa_clausable(obj)
    #TODO
    end

    Roelof



    On Monday, June 02, 2014 02:32:28 PM Eric MSP Veith wrote:

    Now, introduce duck typing. Duck typing has the popular slogan “If it walks
    like a duck, and quacks like a duck, I’ll happily treat it as a duck.” That
    means that there is no need for common base classes or interfaces any more.
    If classes A and B share the same method signature, you can call it on both
    classes, no matter what they otherwise do.

    Excellent answer. You helped me also a lot to understand this. :slight_smile:

    Regards,
    Arup R.

    Debugging is twice as hard as writing the code in the first place.
    Therefore,
    if you write the code as cleverly as possible, you are, by definition,
    not
    smart enough to debug it.

    –Brian Kernighan

    Making a habit of checking type is indeed not the way to Ruby
    Zen, but it is occasionally useful to write code that can take a
    duck or a zebra.

    Imagine a method that will take either a Color object, or a
    string or symbol with the color name:

     def scribble(color)
       color = Color.lookup(color) unless color.is_a?(Color)
       ...
     end
    

    I imagine it is for purposes such as this that the tutorial
    is teaching how to tell whether you’ve got a duck.

    On 06/02/2014 12:14 PM, Eric MSP Veith wrote:

    So, sure you can check whether a class would respond to a set of
    methods, like
    you did with .respond_to? or by examinating the arrays returned by
    .methods or
    .instance_methods.

    Still, that seems to be alot like forcing a Java/C++ pattern on Ruby.
    Perhaps
    somebody else can comment on this, but my guess would be that this is
    not the
    way to Ruby Zen?

    On Mon, Jun 2, 2014 at 12:55 PM, Eric MSP Veith
    [email protected]
    wrote

    Again: You don’t need to know. If it walks and quacks, for all what it’s
    worth, you can just assume it’s a duck. It could be Cthulhu, but as long
    as He
    walks and quacks, you just treat Him like a duck instead of going
    completely
    insane.

    Finally! A defence against the elder gods. Ia! Ia!

    On Monday 02 June 2014 20:15:00, Roelof W. [email protected] wrote:

    Then I think I misunderstood the exercise.

    Hm, naw, I guess I misunderstood what you’re trying to archieve.

    Of course you can check explicitly whether some object “implements an
    interface”, although something like an interface doesn’t explicitly
    exist in
    the Ruby world.

    So, sure you can check whether a class would respond to a set of
    methods, like
    you did with .respond_to? or by examinating the arrays returned by
    .methods or
    .instance_methods.

    Still, that seems to be alot like forcing a Java/C++ pattern on Ruby.
    Perhaps
    somebody else can comment on this, but my guess would be that this is
    not the
    way to Ruby Zen?

    HTH.

      --- Eric

    On 3 June 2014 06:17, Wayne C. [email protected] wrote:

    end
    

    I imagine it is for purposes such as this that the tutorial
    is teaching how to tell whether you’ve got a duck.

    ​A more Ruby way might be to have Color.lookup(color) be perfectly happy
    to
    accept a Color object. Then you’d have:

    def scribble color
    color = Color.lookup color​

    end

    ​For comparison, see Kernel#Integer and friends.​

    I don’t know where this exercise is from, but from this example it seems
    to
    me that it’s teaching terrible object design habits for dynamic
    languages.
    With extremely rare exceptions (e.g. Ruby’s internal conditional checks
    for
    implicit conversion methods like #to_int), a program should have no need
    to
    do this kind of “interface checking”. If you want to write Java code
    write
    it in Java and let the language take care of interface checks for you.

    This is a good explanation of duck typing. If you are still having
    trouble
    with it you might consider picking up a copy of: "Practical
    Object-Oriented Design in Ruby??? By: Sandi Metz

    Very good book easy to follow and excellent chapter on duck typing among
    other handy features of object oriented design.

    On Monday 02 June 2014 13:24:43, Roelof W. [email protected] wrote:

    Can anyone then give me a hint how to solve this by duck typing ?
    I have read many pages about it but I still confuses me.

    With “traditional” object-oriented programming, a class is also a data
    type. That meant: different class, different data type. If classes have
    the
    same ancestor or implement the same interface, they can be casted to
    that
    base class or interface. Basically, the common denominator. Whenever the
    method you want to call is defined in that base class/interface, you can
    call it, not matter what actual class you have.

    Now, introduce duck typing. Duck typing has the popular slogan “If it
    walks
    like a duck, and quacks like a duck, I’ll happily treat it as a duck.”
    That
    means that there is no need for common base classes or interfaces any
    more.
    If classes A and B share the same method signature, you can call it on
    both
    classes, no matter what they otherwise do.

    Consider, for example, two classes: A PDF writer and a network socket.
    Suppose they both have the method “write(something)” defined. Now, the
    two
    classes do not share anything else. They have no common ancestor and
    implement no common interface. In fact, they perform two completely
    different tasks!

    Somewhere in your program, you want to serialize a text. You call
    “writer_object.write(my_text)”. But there are different code paths that
    lead to this certain point, and in one case, you may end up with a PDF
    writer object stored in the variable “writer_object”, and in anthoer
    case,
    it may be the socket.

    In ruby, this works. The results are different, of course, but it works.
    The vast advantage is that you can decide on your program’s behaviour
    somewhere in your code, but have the very same method writing the text.

    For example, there could be a user interface where the user could select
    “Send Text via E-Mail” or “Print Text to PDF”. Based on that selection,
    your code would instanciate either the Socket class or the PDF writer.
    However, the other part of your code that is responsible for serializing
    it
    does not have to know about this choice, it just happily uses the
    “write”
    method.

    A small code example of Duck Typing in action could look like this:

    —%<—
    [1] pry(main)> class A
    [1] pry(main)* def quack()
    [1] pry(main)* puts “Quaaa!”
    [1] pry(main)* end [1] pry(main)* end => nil
    [2] pry(main)> class B
    [2] pry(main)* def quack()
    [2] pry(main)* puts “Quack! Quack!”
    [2] pry(main)* end [2] pry(main)* end => nil
    [3] pry(main)> def do_quack(a_class)
    [3] pry(main)* a_class.quack()
    [3] pry(main)* end => nil
    [4] pry(main)> do_quack(A.new)
    Quaaa!
    => nil
    [5] pry(main)> do_quack(B.new)
    Quack! Quack!
    => nil
    —>%—

    As you can see, the “do_quack” method does not care whether its an
    instance
    of class A or class B it gets passed, it just calls the “quack” method.
    And
    in fact, it yields different results each time.

    HTH.

      --- Eric

    On 3 June 2014 15:13, Roelof W. [email protected] wrote:

    ​For comparison, see Kernel#Integer and friends.​

    That’s not valid Ruby code, I don’t know what you’re trying to represent
    there. But this is what I was thinking:

    class Color
    @@names = {
    black: Color.new(0,0,0),
    white: Color.new(255,255,255),
    }
    def Color.lookup c
    case c
    when Color
    c
    when Symbol, String
    if @@names[c.to_sym]
    @@names[c.to_sym]
    else
    raise ArgumentError, “Not a color nane”
    end
    else
    raise ArgumentError, “can’t convert #{c.class.name} into Color”
    end
    end
    end

    def scribble color
    color = Color.lookup color

    end

    This is the opposite of duck-typing, it’s effectively doing type
    casting.
    If you call Color.lookup with a Color object, you get it back
    unmodified.
    If you call it with no parameters, you get a generic Ruby
    “ArgumentError:
    wrong number of arguments (0 for 1)” error.

    Matthew K. schreef op 3-6-2014 2:10:
    On 3 June 2014 06:17, Wayne C. <[email protected]> wrote:
    Making a habit of checking type is indeed not the way to Ruby
    Zen, but it is occasionally useful to write code that can take a
    duck _or_ a zebra.

    Imagine a method that will take either a Color object, or a
    string or symbol with the color name:

    ?? ?? def scribble(color)
    ?? ?? ?? color = Color.lookup(color) unless color.is_a?(Color)
    ?? ?? ?? ...
    ?? ?? end

    I imagine it is for purposes such as this that the tutorial
    is teaching how to tell whether you've got a duck.


    ???A more Ruby way might be to have Color.lookup(color) be perfectly happy to accept a Color object. Then you'd have:

    ?? def scribble color
    ?? ?? color = Color.lookup color???
    ?? ?? ...
    ?? end

    ???For comparison, see Kernel#Integer and friends.???

    --

    thanks,
    But what if someone does this

    def scribble color.new
    ???????? color = Color.lookup ???
    ???????? ....
    end

    Matthew K. schreef op 3-6-2014 7:44:
    On 3 June 2014 15:13, Roelof W. <[email protected]> wrote:
    Matthew K. schreef op 3-6-2014 2:10:
    ??? A more Ruby way might be to have Color.lookup(color) be perfectly happy to accept a Color object. Then you'd have:

    ?? def scribble color
    ?? ?? color = Color.lookup color???
    ?? ?? ...
    ?? end

    ??? For comparison, see Kernel#Integer and friends.???

    thanks,
    But what if someone does this

    def scribble color.new
    ???????? color = Color.lookup ???
    ???????? ....
    end


    That's not valid Ruby code, I don't know what you're trying to represent there. But this is what I was thinking:

    ?? class Color
    ?? ?? @@names = {
    ?? ?? ?? black: Color.new(0,0,0),
    ?? ?? ?? white: Color.new(255,255,255),
    ?? ?? }
    ?? ?? def Color.lookup c
    ?? ?? ?? case c
    ?? ?? ?? when Color
    ?? ?? ?? ?? c
    ?? ?? ?? when Symbol, String
    ?? ?? ?? ?? if @@names[c.to_sym]
    ?? ?? ?? ?? ?? @@names[c.to_sym]
    ?? ?? ?? ?? else
    ?? ?? ?? ?? ?? raise ArgumentError, "Not a color nane"
    ?? ?? ?? ?? end
    ?? ?? ?? else
    ?? ?? ?? ?? raise ArgumentError, "can't convert #{c.class.name} into Color"
    ?? ?? ?? end
    ?? ?? end
    ?? end

    ?? def scribble color
    ?? ?? color = Color.lookup color
    ?? ?? ...
    ?? end

    This is the opposite of duck-typing, it's effectively doing type casting. If you call Color.lookup with a Color object, you get it back unmodified. If you call it with no parameters, you get a generic Ruby "ArgumentError: wrong number of arguments (0 for 1)" error.
    ???
    --

    Then Im confused by this test-case :

    Test.assert_equals is_santa_clausable(SantaClaus.new), true

    Roelof

    On 3 June 2014 15:57, Arup R. [email protected] wrote:

    @@names.fetch(c.to_sym, ArgumentError.new(“Not a color nane”))

    ​Not quite, since #fetch doesn’t​ raise the default. But you could use
    either of the following:

    @@names.fetch(c.to_sym) {|k| raise ArgumentError, "Not a color name" 
    

    }
    @@names[c.to_sym] or raise ArgumentError, “Not a color name”

    ​I wrote it my way first because, originally, I was going to start with
    if c =~ /#.../, so the name lookup was the second if-statement, and it
    seemed
    more natural to write it that way.​

    On 3 June 2014 16:01, Roelof W. [email protected] wrote:

     color = Color.lookup color​
     color = Color.lookup ???
    
       white: Color.new(255,255,255),
         end
    

    Then Im confused by this test-case :

    Test.assert_equals is_santa_clausable(SantaClaus.new), true

    Roelof

    ​Don’t confuse the function definition and the thing that calls the
    function. If you had my definition above, you could then call:

    scribble Color.new(...)
    scribble :black
    scribble 'white'
    scribble Color.lookup('black')
    

    but not:

    scribble 42​
    scribble Array.new
    

    etc.​

    if @@names[c.to_sym]
    @@names[c.to_sym]
    else
    raise ArgumentError, “Not a color nane”
    end

    The above can be written also -

    @@names.fetch(c.to_sym,ArgumentError.new(“Not a color nane”))

    This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

    | Privacy Policy | Terms of Service | Remote Ruby Jobs