Worth an RCR? static_type_check, polymorphic_type_check, quacks_like

Is there another library like this? I would love it if it were just
standard methods on Object.

I find this very useful and ‘require’ it into all code I write. Just
helps me mop up those problems that static type checking would have
found for me…

Heres a typical usage, create an object and initialize it with
stuff. Only much later when you invoke the methods on the object do
you find you initialized it with the wrong stuff.

Got the parameter order wrong or something. But then the bug isn’t on
the backtrace. So put when you initialize your instance variables you
can type check’em like so…

eg.
class MyObject
def initialize( _name, _drawable, _theme)
@name = _name.static_type_check String
@drawable = _drawable.polymorphic_type_check Drawable
@theme = _theme.quacks_like :border_color, :fill_colour
end

end

Abstract base class for all the type check exceptions

class TypeCheckException < Exception
end

This exception is thrown in event of a method being invoked with an

object of the wrong duck type.

class DuckTypingException < TypeCheckException
end

This exception is thrown in event of a method being invoked with a

parameter of of the wrong static type.

class StaticTypeException < TypeCheckException
end

This exception is thrown in event of a method being invoked with a

parameter of of the wrong polymorphic type.

class PolymorphicTypeException < TypeCheckException
end

class Object
# Raise a DuckTypingException unless the object responds to all
these symbols.
def quacks_like( *symbols)
symbols.each do |symbol|
raise DuckTypingException, “Duck typing error, expected this
object to respond to :#{symbol}, but found class
#{self.class}\n\t\t#{symbol.inspect}” unless
respond_to? symbol
end
self
end

def static_type_check_boolean
   raise StaticTypeException, "Static type check error, expected 

object to be a boolean, found ‘#{self.class}’
\t\t#{self.inspect}" unless
(self.class == TrueClass) ||
(self.class == FalseClass) ||
(self.class == NilClass)
self
end

def static_type_check( klass)
   raise StaticTypeException, "Static type check error, expected 

object to be exactly class ‘#{klass}’, found
‘#{self.class}’\n\t\t#{self.inspect}" unless
self.class == klass
self
end

def static_type_check_each( klass)
   each do |object|
      object.static_type_check klass
   end
   self
end

def polymorphic_type_check_each( klass)
   each do |object|
      object.polymorphic_type_check klass
   end
   self
end

def polymorphic_type_check( klass)
   raise PolymorphicTypeException, "Polymorphic type check error, 

expected object to be a kind of ‘#{klass}’, found
‘#{self.class}’\n\t\t#{self.inspect}" unless
self.kind_of? klass
self
end

end

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand

On Dec 5, 5:48 pm, John C. [email protected] wrote:

end

object of the wrong duck type.

class PolymorphicTypeException < TypeCheckException
end
def static_type_check( klass)
end
self.kind_of? klass
self
end

end

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand

Ola B. released something similar last year [1]. It didn’t go over
very well (though I liked it and have used it a couple times). YMMV.

Regards,
Jordan

[1] http://rubyforge.org/projects/ducktator/

On Dec 5, 6:48 pm, John C. [email protected] wrote:

end
Special methods? Just do:

def initialize( _name, _drawable, _theme)
  raise ArgumentError unless _name.instance_of?(String)
  raise ArgumentError unless _drawable.kind_of?(Drawable)
  raise ArgumentError unless [:border_color, :fill_color].all?{|m|

_theme.respond_to?(m)}
@name, @drawable, @theme = _name, _drawable, _theme
end

Besides, with exception to the 2nd (done for the right reason) this is
all generally considered a bad practice. If you want to do it for
debugging purposes that’s cool --wrap the the check in an ‘if $DEBUG’.
But the idea behind duck-typing is to NOT do these types of checks.
Just let it ride, so we can drop whatever we want into your method –
if our object is “adapted” right then it can work regardless.

Note: I used to think the last made sense. But I’ve learned over time
that it actually is worse --you’re assuming those methods dictate some
type of behavior, but those methods might not do what you think they
do. Use of respond_to? should be generally avoided.

T.

John C. wrote:

Is there another library like this? I would love it if it were just
standard methods on Object.

My Chattr gem does stuff like this for attributes and for arrays.

gem install chattr.

Clifford H…

On Dec 5, 7:08 pm, Trans [email protected] wrote:

def initialize( _name, _drawable, _theme)
raise ArgumentError unless [:border_color, :fill_color].all?{|m|

Note: I used to think the last made sense. But I’ve learned over time
that it actually is worse --you’re assuming those methods dictate some
type of behavior, but those methods might not do what you think they
do. Use of respond_to? should be generally avoided.

T.

Heh. I used to think the opposite about respond_to?, but for a while
I’ve been thinking about it as not asking for a promise of behavior,
but for a promise that it’s safe to act like we have a promise of
behavior. Just like when we use “begin…rescue NoMethodError”, we’re
not saying “now I’ve ensured X object will behave well”, we’re saying
“now I can safely pretend like object X implements some interface” The
only difference at all that I see between asking respond_to? and
using a “begin…rescue NoMethodError” clause, is that one asks for
permission and the other asks for forgiveness (i.e., the only
difference is the point in time at which they occur). That said, there
are problems with method signature validation by respond_to?, as many
people have pointed out before, e.g., method_missing dispatching with
variable arity. So, while I would agree that it may not often be a
good idea, pragmatically, I disagree with the idea that it
necessarily promotes a wrong way of thinking about programming (or
at least programming in ruby).

Regards,
Jordan

2007/12/6, MonkeeSage [email protected]:

found for me…
class MyObject
raise ArgumentError unless _drawable.kind_of?(Drawable)
if our object is “adapted” right then it can work regardless.
but for a promise that it’s safe to act like we have a promise of
good idea, pragmatically, I disagree with the idea that it
necessarily promotes a wrong way of thinking about programming (or
at least programming in ruby).

Some more random thoughts about respond_to?

  1. the point in time may be crucial, i.e. when checking on
    initialization the object might actually not yet respond to the method
    but logic otherwise guarantees that it does when the method is
    actually invoked.

  2. point in time is not the only difference as you have pointed out
    (method_missing).

  3. the net effect is the same, i.e. if you check with respond_to? you
    will have to raise an exception - you will get an exception as well
    when you simply call the method.

For the me disadvantages of respond_to? and type checks by far
outweigh the benefits (assumed increase in robustness or faster bug
finding).

Kind regards

robert

Robert K. wrote:

  1. point in time is not the only difference as you have pointed out
    (method_missing).

While I mostly agree with what you say: if somebody defines
method_missing, he should update respond_to? accordingly. Anything else
I’d consider a bug.

Regards
Stefan

Hi –

On Thu, 6 Dec 2007, John C. wrote:

Is there another library like this? I would love it if it were just
standard methods on Object.

I find this very useful and ‘require’ it into all code I write. Just
helps me mop up those problems that static type checking would have
found for me…

Keep in mind, though, that static type checking isn’t just some safety
net that Matz forgot to include in Ruby. The objects are dynamic. You
can’t statically check dynamic objects. You can examine their
class/module ancestry, but that only tells you their class/module
ancestry.

def initialize( _name, _drawable, _theme)

Abstract base class for all the type check exceptions

class TypeCheckException < Exception
end

This exception is thrown in event of a method being invoked with an

object of the wrong duck type.

You can just say “type” here. There’s really no such thing as a “duck
type”; “type” already refers to the behaviors of a given object at a
given point in runtime.

class PolymorphicTypeException < TypeCheckException
end

class Object

Raise a DuckTypingException unless the object responds to all these

symbols.

Duck typing isn’t just about whether the object responds to a given
message, though. It’s really not about the object at all; Dave T.,
who introduced the term, describes it as “a way of thinking about
programming in Ruby.” (I think I’ve got that verbatim, or nearly so.)
See also earlier discussions of “hard” and “soft” duck typing, and
Rick DeNatale’s concept of “chicken typing”.

I don’t want to recapitulate the thousands (literally, I believe) of
posts to this and other lists about class/module-checking in Ruby, but
my two biggest problems with it are:

  1. it doesn’t work, because Ruby objects are not constrained by
    their ancestry;
  2. it tends to be the tail wagging the dog, in the sense that it
    leads to (or sometimes comes from) the conviction that having
    objects that don’t behave exactly like freshly-minted objects
    of their class must be bad, when it’s actually engineered
    as a basic principle into the language.

David

Hi –

On Fri, 7 Dec 2007, Stefan R. wrote:

Robert K. wrote:

  1. point in time is not the only difference as you have pointed out
    (method_missing).

While I mostly agree with what you say: if somebody defines
method_missing, he should update respond_to? accordingly. Anything else
I’d consider a bug.

You might want to file a bug report against the standard library:

require ‘ostruct’
=> true

os = OpenStruct.new
=> #

os.respond_to?(:“a=”)
=> false

os.a = 1
=> 1

:slight_smile: I think it all depends on exactly what you’re doing with
method_missing. In general, I tend to see it the other way around:
respond_to? tells you what the object’s current knowledge of its
messages is, while method_missing is specifically a handler for
messages the object does not respond to. In the end, it can be done
either way, and probably should be, in different situations. I
wouldn’t say that either approach is inherently buggy.

David

On Dec 6, 2007 9:22 PM, David A. Black [email protected] wrote:

I’d consider a bug.
=> 1
David
I believe that it is naive to think one could update responds_to?
dynamically when implementing method_missing, just think about the
following implementation:

def method_missing name, *args, &blk
super if random(42) > 20
42
end

would you like respond_to?( :something ) to return :maybe ?

BTW this is not the only reason why respond_to? shall not consider
what method_missing might do or not.

Cheers
Robert
end


Upcoming training by David A. Black/Ruby Power and Light, LLC:
* Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details and 2008 announcements!

http://ruby-smalltalk.blogspot.com/


All truth passes through three stages. First, it is ridiculed. Second,
it is violently opposed. Third, it is accepted as being self-evident.
Schopenhauer (attr.)

On Thu, 6 Dec 2007, David A. Black wrote:

I find this very useful and ‘require’ it into all code I write. Just
helps me mop up those problems that static type checking would have
found for me…

Keep in mind, though, that static type checking isn’t just some safety
net that Matz forgot to include in Ruby. The objects are dynamic. You
can’t statically check dynamic objects. You can examine their
class/module ancestry, but that only tells you their class/module
ancestry.

I don’t want to recapitulate the thousands (literally, I believe) of
posts to this and other lists about class/module-checking in Ruby, but
my two biggest problems with it are:

Yes, yes, yes, I know all the theory, I’ve read the arguments…and
I’m not suggesting that one make every method call have strictly type
parameter checking.

I don’t. I’d say I don’t do parameter type checking in 98% of my
methods.

But believe you me, when I hit a bug where I invoke a method that dies
because there is something screwy in an instance variable and the bug
isn’t on the backtrace…

I say, stuff the theory, slap one of those beauties in the constructor
and find the bug instantly.

And then I leave it there to catch the next time I or someone else is
stupid in the same way.

Of course, occasionally, very very rarely, the theory bites me in the
bum and my program dies when it shouldn’t, no problem because…

a) The cause of death and the exact file name and line number to fix
is right there on the screen in front of me.
b) It happens during development, not production.

However, given the number of bugs I’ve caught whilst waiting for such
events, including ones that would have otherwise made it released
version, no amount of theory will convince me not to use this technique.

Please, I’m not saying, Dynamic Ruby Bad strictly typed languages like
C++ /
Pascal / … is Good.

I’m saying this is a really really simple, clean idiom for rapidly
catching a largish class of bugs fairly hard to track down by other
means.

ie. These methods aren’t about theory, they about a pragmatic
superclean idiom for catching a certain large class of bugs.

ie. Latent defects created by inserting the wrong object into a
variable, but
the defect becomes visible at a point where the defective line is not
on the backtrace.

ie. When you have one of these bugs, reach for these methods.

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand

John C. wrote:

I say, stuff the theory, slap one of those beauties in the constructor
and find the bug instantly.

So use chattr - that’s exactly what I wrote it for.

Clifford H…

On Dec 6, 5:16 am, Robert K. [email protected] wrote:

I find this very useful and ‘require’ it into all code I write. Just

def initialize( _name, _drawable, _theme)

But the idea behind duck-typing is to NOT do these types of checks.
Heh. I used to think the opposite about respond_to?, but for a while
people have pointed out before, e.g., method_missing dispatching with
actually invoked.

  1. point in time is not the only difference as you have pointed out
    (method_missing).

  2. the net effect is the same, i.e. if you check with respond_to? you
    will have to raise an exception - you will get an exception as well
    when you simply call the method.

I can’t think of an actual use case offhand (heh, that probably speaks
for itself), but I’ve used it before in places where the exceptional
case is non-terminal. A contrived example…

class B < Array; private :index; end
b = B.new
unless b.respond_to? :index
p “state 1, use #foo
class B; public :index; end
end
#…
if b.respond_to? :index
p “state 2, use #index
class B; private :index; end
end

For the me disadvantages of respond_to? and type checks by far
outweigh the benefits (assumed increase in robustness or faster bug
finding).

Kind regards

robert


use.inject do |as, often| as.you_can - without end

Regards,
Jordan

On 12/6/07, Robert D. [email protected] wrote:

method_missing. In general, I tend to see it the other way around:
respond_to? tells you what the object’s current knowledge of its
messages is, while method_missing is specifically a handler for
messages the object does not respond to. In the end, it can be done
either way, and probably should be, in different situations. I
wouldn’t say that either approach is inherently buggy.

I believe that it is naive to think one could update responds_to?
dynamically when implementing method_missing, just think about the
following implementation:

def method_missing name, *args, &blk
super if random(42) > 20
42
end

would you like respond_to?( :something ) to return :maybe ?

While this last example might strike some, heck even me, as silly, it
is evidence of how Ruby ‘types’ are dynamic in multiple dimensions.

  • Time
  • Instance by instance, with the ‘class’ held constant.
  • State of the instance, with the ‘class’ held constant.

I came across another interesting example from ActiveRecord, as I was
reading myself to sleep early this AM with “The Ruby Way.”

There’s a method ActiveRecord::Base#save which is used to, surprise,
save/update an AR model instance to the database. This method is
documented as taking no arguments.

BUT

Under some circumstances, you can call the method with an optional
argument as in:

book.save(false)

Which causes the object to be saved bypassing any validation callbacks.

It turns out that the save method will only take the argument if the
model has one or more validations specified. The method signature
changes dynamically.

While I can see these kind of things frustrating, or even angering
chicken typers, the are the very things which make Ruby magical.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Dec 6, 2007 11:32 PM, John C. [email protected] wrote:

I say, stuff the theory, slap one of those beauties in the constructor
and find the bug instantly.

I wrote code to do this 4 years ago. It is a framework that does it
by writing a “typesig” declaration before your method declaration (or
through various other methods of applying them). The type checks
allow a LOT of flexible type declarations, including respond_to
checks, class/module checks, conditional checks depending on previous
type matches, repeated sequence matches against varargs, etc, etc,
etc.

Matching your example, you would declare
class MyObject
typesig :exact, String, Drawable, Type::Respond(:border_color,
:fill_colour)
def initialize( _name, _drawable, _theme)
@name = _name
@drawable = _drawable
@theme = _theme
end
end

Overall, I don’t feel that it gave me that much to use it anyway -
more trouble than it was worth - but in my opinion, it solves the
problem better and if we are going to provide more type checking
support, that’s a better place to start. The form of declaration keep
the type checks normalized and allow us to turn them off for
production if there is a speed penalty (which makes it possible to
have expensive type checks in there), and it keeps the declaration at
the same point as the parameter list, decreasing noise in the code
itself.

The code is available here:
http://people.freebsd.org/~eivind/ruby/types/

I am willing to do more work on it if anybody actually use it, and I
am willing to let somebody else take over maintenance if they prefer.

BTW: If we are going to discuss adding more type checking, I’ll note
that the place where I feel it could primarily be of value is at the
“edge” of library code, where it would function as more formal
documentation of the calling convention than th present variants, with
the added bonus that you know it is sort of correct.

Eivind.

On Dec 7, 7:09 am, Rick DeNatale [email protected] wrote:

method_missing, he should update respond_to? accordingly. Anything else

os.a = 1
dynamically when implementing method_missing, just think about the
is evidence of how Ruby ‘types’ are dynamic in multiple dimensions.
documented as taking no arguments.
It turns out that the save method will only take the argument if the
model has one or more validations specified. The method signature
changes dynamically.

While I can see these kind of things frustrating, or even angering
chicken typers, the are the very things which make Ruby magical.


Rick DeNatale

My blog on Rubyhttp://talklikeaduck.denhaven2.com/

That’s also a great use case for what I was talking about in my last
post. :wink: An #arity < 1 check might be nicely used in such a case to
check whether to call #save with an argument, and if not, do something
else, rather than letting the exception raise, catching it, then doing
something else. Either way works (though catching the exception is
probably less efficient, because an exception object has to be
instantiated and the rescue machinery has to run); but in cases like
that, it makes perfect sense to do “validation” on the object. (Even
if it arities like a chicken right now…it’s still really a duck ;P)

Regards,
Jordan

On 2007-12-07 04:19 +0900 (Fri), Stefan R. wrote:

While I mostly agree with what you say: if somebody defines
method_missing, he should update respond_to? accordingly. Anything
else I’d consider a bug.

Not always, as others have pointed out on this thread. Still, good
point. It would be cool to have a “lint” program for Ruby that could
point out these sorts of things when necessary. Particularly for things
that want to be compared to equality…

cjs

On 12/7/07, MonkeeSage [email protected] wrote:

On Dec 7, 7:09 am, Rick DeNatale [email protected] wrote:

argument as in:
chicken typers, the are the very things which make Ruby magical.
That’s also a great use case for what I was talking about in my last
post. :wink: An #arity < 1 check might be nicely used in such a case to
check whether to call #save with an argument, and if not, do something
else, rather than letting the exception raise, catching it, then doing
something else. Either way works (though catching the exception is
probably less efficient, because an exception object has to be
instantiated and the rescue machinery has to run); but in cases like
that, it makes perfect sense to do “validation” on the object. (Even
if it arities like a chicken right now…it’s still really a duck ;P)

But that kills the duck.

Think about how this is used in ActiveRecord/Rails.

In most cases you want to save and run validations, using save with no
parameter works fine, note that the argument, when it’s supported, has
a default value of true which causes the validations to be run.

In some particular cases, you want to overrule validations because you
know what you are doing. You know that the model has validations, and
you know you want to override them in this case. The best way to
validate this knowledge is with test cases rather than burdening the
production code with unnecessary overhead.

IMHO, chicken typing is for Chicken Littles, who worry too much about
exactly what exception would be raised if the sky actually fell.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

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