Typed Parameters

Dear group

there was a recent thread about "Boolean" and it braught me to my favorit
thing I would love to have in Ruby2.

*typed parameters*

My code is completely filled with things like this:

def never_saw_a_better_method( clever, smart, stupid )
            assert_type clever, String
           assert_type smart, Hash
          assert_type stuoid, Boolean
....
def cool( clever : String, smart : Hash, stupid : Boolean )

and of course
def x(y) would be equivalent to def(x : Object )

There is no other than practical reason to that, I found that this kind of
type assertion finds the most devious bugs in my code.

Thaughts?

Robert

···

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

- Albert Einstein

Dear group

there was a recent thread about "Boolean" and it braught me to my
favorit thing I would love to have in Ruby2.

*typed parameters*

This might happen, but it's unlikely to work the way you have
suggested. I personally hope it doesn't happen, as it will make
Ruby a little less "smart."

My code is completely filled with things like this:

def never_saw_a_better_method( clever, smart, stupid )
            assert_type clever, String
           assert_type smart, Hash
          assert_type stuoid, Boolean
....
def cool( clever : String, smart : Hash, stupid : Boolean )

and of course
def x(y) would be equivalent to def(x : Object )

There is no other than practical reason to that, I found that this
kind of type assertion finds the most devious bugs in my code.

It's not actually that practical, and such things end up making your
code very much like C++ and Java.

Ruby is smarter than that. Ruby can do more than that.

Think in terms of what your object's required capabilities are instead
of pretending that a class indicator is sufficient for that.

-austin

···

On 4/1/06, Robert Dober <robert.dober@gmail.com> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Howabout what I do..

def never_saw_a_better_method( clever, smart, stupid )
   clever.static_type_check String
   smart.quacks_like :each_pair
   stupid.poymorphic_type_check SomeBaseClass
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 symbol.
   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
   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
   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
   end

end

if $0 == __FILE__ then
   require 'test/unit'

   class TC_Utilities < Test::Unit::TestCase

     def test_utilities
       assert_raise( DuckTypingException) { nil.quacks_like( :call)}
       assert_raise( DuckTypingException) { 1.quacks_like( :+, :call)}
       1.quacks_like( :+, :-, :*)

       assert_raise( StaticTypeException) { nil.static_type_check( String)}

       assert_raise( PolymorphicTypeException) {"foo".polymorphic_type_check( Array)}

       begin
         2.static_type_check( String)
       rescue TypeCheckException => details
         puts details
       end
       begin
         2.polymorphic_type_check( String)
       rescue TypeCheckException => details
         puts details
       end
     end

   end

end

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.

···

On Sun, 2 Apr 2006, Robert Dober wrote:

Dear group

there was a recent thread about "Boolean" and it braught me to my favorit
thing I would love to have in Ruby2.

*typed parameters*

My code is completely filled with things like this:

def never_saw_a_better_method( clever, smart, stupid )
           assert_type clever, String
          assert_type smart, Hash
         assert_type stuoid, Boolean
....
def cool( clever : String, smart : Hash, stupid : Boolean )

and of course
def x(y) would be equivalent to def(x : Object )

<blockquote>
It's not actually that practical, and such things end up making your
code very much like C++ and Java.

Ruby is smarter than that. Ruby can do more than that.

Think in terms of what your object's required capabilities are instead
of pretending that a class indicator is sufficient for that.
</blockquote>

While I understand you pointr Austin --obviously where talking Duck
Typing here. But I think it is interesting to condier that this is some
respect antithetical to OOP in general --I mean the reciever _is_ a
specific type. And that reacieve detemine the functionality of the
method call. It is sort of as if you were progamming in a more
traditional functional language and _had_ to specifiy the type of the
first argument, but never the remaining.

  foofunc( FooClass foo, clever, smart, stupid )

instead of

  foo.foofunc( clever, smart, stupid )

So why shouldn't any of the other participating objects have a
selective effect too?

T.

Austin as I have the highes admiration to your contribution to the
community, these are claims without any evidence.
Would you care to provide some?
I'd really appreciate.

Robert

···

On 4/2/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/1/06, Robert Dober <robert.dober@gmail.com> wrote:
> Dear group
>
> there was a recent thread about "Boolean" and it braught me to my
> favorit thing I would love to have in Ruby2.
>
> *typed parameters*

This might happen, but it's unlikely to work the way you have
suggested. I personally hope it doesn't happen, as it will make
Ruby a little less "smart."

> My code is completely filled with things like this:
>
> def never_saw_a_better_method( clever, smart, stupid )
> assert_type clever, String
> assert_type smart, Hash
> assert_type stuoid, Boolean
> ....
> def cool( clever : String, smart : Hash, stupid : Boolean )
>
> and of course
> def x(y) would be equivalent to def(x : Object )
>
> There is no other than practical reason to that, I found that this
> kind of type assertion finds the most devious bugs in my code.

It's not actually that practical, and such things end up making your
code very much like C++ and Java.

Ruby is smarter than that. Ruby can do more than that.

Think in terms of what your object's required capabilities are instead
of pretending that a class indicator is sufficient for that.

-austin
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

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

- Albert Einstein

Hi --

<blockquote>
It's not actually that practical, and such things end up making your
code very much like C++ and Java.

Ruby is smarter than that. Ruby can do more than that.

Think in terms of what your object's required capabilities are instead
of pretending that a class indicator is sufficient for that.
</blockquote>

While I understand you pointr Austin --obviously where talking Duck
Typing here. But I think it is interesting to condier that this is some
respect antithetical to OOP in general --I mean the reciever _is_ a
specific type. And that reacieve detemine the functionality of the
method call. It is sort of as if you were progamming in a more
traditional functional language and _had_ to specifiy the type of the
first argument, but never the remaining.

foofunc( FooClass foo, clever, smart, stupid )

instead of

foo.foofunc( clever, smart, stupid )

It's actually more like this:

   foofunc(object_that_responds_to_foofunc, etc.)

The fact that an object handles a message does not imply its class.
(I'm transliterating 'type' to 'class' as that seems to be what the
thread is actually about [as it usually is :-].)

So why shouldn't any of the other participating objects have a
selective effect too?

Because there's no applicable general notion of "a selective effect."
Each of these things is a different part of a system.

David

···

On Sun, 2 Apr 2006, Trans wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

Trans ha scritto:

It is sort of as if you were progamming in a more
traditional functional language and _had_ to specifiy the type of the
first argument, but never the remaining.

  foofunc( FooClass foo, clever, smart, stupid )

instead of

  foo.foofunc( clever, smart, stupid )

So why shouldn't any of the other participating objects have a
selective effect too?

<noise type="useless">
I agree, let's stop this antidemocratic self-proclaimed dictatorship of, well, self.
(and recall that our uncle Common Lisp had dynamic typing and multiple dispatch for decades withouth becoming Java :slight_smile:
</noise>

Well, I think you should allowed to put a selective effect on the
remaining arguments, but it should at least allow you to be a little
smarter than simply checking one single Type. I'd like to see you
able to check against multiple types as well as methods and
combinations thereof, like

def foo(arg1 : (Array and :custom_array_method) or Hash or :special_method)

Then at least it's simply a syntactic convenience for writing
respond_to? and kind_of? calls. And, logically, you should be able to
assign these parameter checks to a variabe so you can reduce the
duplication of them, although I don't have a clue as to what a good
syntax for that would be... Maybe something like:

type_check = TypeCheck.new do |var|
  case var
  when Array
    return true if var.respond_to? :custom_array_method
  when Hash
    return Hash
  else
    return true if var.respond_to? :special_method
  end
  return false
end

And, of course, you can do any checking you want in the block. You
could then do this:

def foo(arg1 : type_check)
def bar(arg1, arg2 : type_check)

···

On 4/1/06, Trans <transfire@gmail.com> wrote:

<blockquote>
It's not actually that practical, and such things end up making your
code very much like C++ and Java.

Ruby is smarter than that. Ruby can do more than that.

Think in terms of what your object's required capabilities are instead
of pretending that a class indicator is sufficient for that.
</blockquote>

While I understand you pointr Austin --obviously where talking Duck
Typing here. But I think it is interesting to condier that this is some
respect antithetical to OOP in general --I mean the reciever _is_ a
specific type. And that reacieve detemine the functionality of the
method call. It is sort of as if you were progamming in a more
traditional functional language and _had_ to specifiy the type of the
first argument, but never the remaining.

  foofunc( FooClass foo, clever, smart, stupid )

instead of

  foo.foofunc( clever, smart, stupid )

So why shouldn't any of the other participating objects have a
selective effect too?

T.

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:
http://odeo.com/sendmeamessage/DanNugent

Actually... now that I'm looking about it, that's kinda dumb, we might
as well just add pre, post, and around calls so we can more cleanly
seperate the Type and condition checks from the actual method.

···

On 4/1/06, Daniel Nugent <nugend@gmail.com> wrote:

Well, I think you should allowed to put a selective effect on the
remaining arguments, but it should at least allow you to be a little
smarter than simply checking one single Type. I'd like to see you
able to check against multiple types as well as methods and
combinations thereof, like

def foo(arg1 : (Array and :custom_array_method) or Hash or :special_method)

Then at least it's simply a syntactic convenience for writing
respond_to? and kind_of? calls. And, logically, you should be able to
assign these parameter checks to a variabe so you can reduce the
duplication of them, although I don't have a clue as to what a good
syntax for that would be... Maybe something like:

type_check = TypeCheck.new do |var|
  case var
  when Array
    return true if var.respond_to? :custom_array_method
  when Hash
    return Hash
  else
    return true if var.respond_to? :special_method
  end
  return false
end

And, of course, you can do any checking you want in the block. You
could then do this:

def foo(arg1 : type_check)
def bar(arg1, arg2 : type_check)

On 4/1/06, Trans <transfire@gmail.com> wrote:
> <blockquote>
> It's not actually that practical, and such things end up making your
> code very much like C++ and Java.
>
> Ruby is smarter than that. Ruby can do more than that.
>
> Think in terms of what your object's required capabilities are instead
> of pretending that a class indicator is sufficient for that.
> </blockquote>
>
> While I understand you pointr Austin --obviously where talking Duck
> Typing here. But I think it is interesting to condier that this is some
> respect antithetical to OOP in general --I mean the reciever _is_ a
> specific type. And that reacieve detemine the functionality of the
> method call. It is sort of as if you were progamming in a more
> traditional functional language and _had_ to specifiy the type of the
> first argument, but never the remaining.
>
> foofunc( FooClass foo, clever, smart, stupid )
>
> instead of
>
> foo.foofunc( clever, smart, stupid )
>
> So why shouldn't any of the other participating objects have a
> selective effect too?
>
> T.
>
>
>

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:
W77 🏀 The Best Site for Providing Big Wins in a Fruit Spin Game

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:

dblack@wobblini.net wrote:

Hi --

> <blockquote>
> It's not actually that practical, and such things end up making your
> code very much like C++ and Java.
>
> Ruby is smarter than that. Ruby can do more than that.
>
> Think in terms of what your object's required capabilities are instead
> of pretending that a class indicator is sufficient for that.
> </blockquote>
>
> While I understand you pointr Austin --obviously where talking Duck
> Typing here. But I think it is interesting to condier that this is some
> respect antithetical to OOP in general --I mean the reciever _is_ a
> specific type. And that reacieve detemine the functionality of the
> method call. It is sort of as if you were progamming in a more
> traditional functional language and _had_ to specifiy the type of the
> first argument, but never the remaining.
>
> foofunc( FooClass foo, clever, smart, stupid )
>
> instead of
>
> foo.foofunc( clever, smart, stupid )

It's actually more like this:

   foofunc(object_that_responds_to_foofunc, etc.)

The fact that an object handles a message does not imply its class.
(I'm transliterating 'type' to 'class' as that seems to be what the
thread is actually about [as it usually is :-].)

But the class of that object dictates the functionality of that
message. That's my point --it's class based. A double dispath makes
this very clear:

  class String
    def from( obj )
      # the parameter is type String no matter what
      obj.to( self )
    end
  end

We can even do some fancy dispatching to achieve type parameters:

  class String
    def cool( *args )
      args.shift.cool_string( self, *args )
    end
  end

  class Hash
    def cool_string( str, *args )
      args.shift.cool_string_hash( str, self )
    end
  end

  class Boolean
    def cool_string_hash( str, hsh )
      p str.class, hsh.class, self.class
    end
  end

  def cool( clever, smart, stupid )
    clever.cool( smart, stupid )
  end

  cool( "a string", { :a=>'hash' }, Boolean.new )

produces

  String
  Hash
  Boolean

but

  cool( 1, 2, 3 ) # => NoMethodError

T.

···

On Sun, 2 Apr 2006, Trans wrote:

I quite agree, showes my how helpless I braught this up. :frowning:
Should have named the thread "Easier ways to enforce contracts".
Is that not strange that we think types immediately and than are afraid of
ancient Computer Science History.

Now there is another point.

My programs often pass objects of an unexpected "contract, behavior, type,
mixin interface" you name it.
I would like a modern language to help me, the *stupid* programmer to be
more *effective*
Ruby claims that.

So let me suggest the following syntax

def foo (bar, foobar) is a shortcut to
def foo( bar, foobar : Object) which is a shortcut to
def foo( bar, foobar : { |para| Object === para } ) so we can put any
constraint in there.

I still think that is a good thing for readability and maintenance and
*nobody* would be forced to use it.
Furthermore we are not forced to use the block inside the formal parameter
list, it would just give us the opportunity.

I really fail to see why this is inhibiting the language.
Such programs fail explicitly and early, which is better (I claim) than
maybe failing later or just not behaving as expected.

Robert

···

On 4/2/06, Daniel Nugent <nugend@gmail.com> wrote:

Well, I think you should allowed to put a selective effect on the
remaining arguments, but it should at least allow you to be a little
smarter than simply checking one single Type. I'd like to see you
able to check against multiple types as well as methods and
combinations thereof, like

def foo(arg1 : (Array and :custom_array_method) or Hash or
:special_method)

Then at least it's simply a syntactic convenience for writing
respond_to? and kind_of? calls. And, logically, you should be able to
assign these parameter checks to a variabe so you can reduce the
duplication of them, although I don't have a clue as to what a good
syntax for that would be... Maybe something like:

type_check = TypeCheck.new do |var|
  case var
  when Array
    return true if var.respond_to? :custom_array_method
  when Hash
    return Hash
  else
    return true if var.respond_to? :special_method
  end
  return false
end

And, of course, you can do any checking you want in the block. You
could then do this:

def foo(arg1 : type_check)
def bar(arg1, arg2 : type_check)

On 4/1/06, Trans <transfire@gmail.com> wrote:
> <blockquote>
> It's not actually that practical, and such things end up making your
> code very much like C++ and Java.
>
> Ruby is smarter than that. Ruby can do more than that.
>
> Think in terms of what your object's required capabilities are instead
> of pretending that a class indicator is sufficient for that.
> </blockquote>
>
> While I understand you pointr Austin --obviously where talking Duck
> Typing here. But I think it is interesting to condier that this is some
> respect antithetical to OOP in general --I mean the reciever _is_ a
> specific type. And that reacieve detemine the functionality of the
> method call. It is sort of as if you were progamming in a more
> traditional functional language and _had_ to specifiy the type of the
> first argument, but never the remaining.
>
> foofunc( FooClass foo, clever, smart, stupid )
>
> instead of
>
> foo.foofunc( clever, smart, stupid )
>
> So why shouldn't any of the other participating objects have a
> selective effect too?
>
> T.
>
>
>

--

-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:
W77 🏀 The Best Site for Providing Big Wins in a Fruit Spin Game

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

- Albert Einstein

Maybe the code for that could look something like this:

def foo(arg1, arg2)
  BLAHBLAHBLAH STUFF GOES HERE
end.pre do |*args|
  SOME MORE STUFF
end.post do |*result|
  A LITTLE MORE
end.around do|*args, &method|
  SOME
  method.call(transformed_args)
  STUFF
end

And then you could dynamically add and remove the pre and post
conditions or whatever.

···

On 4/1/06, Daniel Nugent <nugend@gmail.com> wrote:

Actually... now that I'm looking about it, that's kinda dumb, we might
as well just add pre, post, and around calls so we can more cleanly
seperate the Type and condition checks from the actual method.

On 4/1/06, Daniel Nugent <nugend@gmail.com> wrote:
> Well, I think you should allowed to put a selective effect on the
> remaining arguments, but it should at least allow you to be a little
> smarter than simply checking one single Type. I'd like to see you
> able to check against multiple types as well as methods and
> combinations thereof, like
>
> def foo(arg1 : (Array and :custom_array_method) or Hash or :special_method)
>
> Then at least it's simply a syntactic convenience for writing
> respond_to? and kind_of? calls. And, logically, you should be able to
> assign these parameter checks to a variabe so you can reduce the
> duplication of them, although I don't have a clue as to what a good
> syntax for that would be... Maybe something like:
>
> type_check = TypeCheck.new do |var|
> case var
> when Array
> return true if var.respond_to? :custom_array_method
> when Hash
> return Hash
> else
> return true if var.respond_to? :special_method
> end
> return false
> end
>
> And, of course, you can do any checking you want in the block. You
> could then do this:
>
> def foo(arg1 : type_check)
> def bar(arg1, arg2 : type_check)
>
> On 4/1/06, Trans <transfire@gmail.com> wrote:
> > <blockquote>
> > It's not actually that practical, and such things end up making your
> > code very much like C++ and Java.
> >
> > Ruby is smarter than that. Ruby can do more than that.
> >
> > Think in terms of what your object's required capabilities are instead
> > of pretending that a class indicator is sufficient for that.
> > </blockquote>
> >
> > While I understand you pointr Austin --obviously where talking Duck
> > Typing here. But I think it is interesting to condier that this is some
> > respect antithetical to OOP in general --I mean the reciever _is_ a
> > specific type. And that reacieve detemine the functionality of the
> > method call. It is sort of as if you were progamming in a more
> > traditional functional language and _had_ to specifiy the type of the
> > first argument, but never the remaining.
> >
> > foofunc( FooClass foo, clever, smart, stupid )
> >
> > instead of
> >
> > foo.foofunc( clever, smart, stupid )
> >
> > So why shouldn't any of the other participating objects have a
> > selective effect too?
> >
> > T.
> >
> >
> >
>
>
> --
> -Dan Nugent
>
> Don't Feel Like Typing? Send me a voicemail:
> W77 🏀 The Best Site for Providing Big Wins in a Fruit Spin Game
>

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:
W77 🏀 The Best Site for Providing Big Wins in a Fruit Spin Game

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:

Daniel Nugent wrote:

Actually... now that I'm looking about it, that's kinda dumb, we might
as well just add pre, post, and around calls so we can more cleanly
seperate the Type and condition checks from the actual method.

No, it's not so dumb actually. A system like the one you propose could
be used for multi-dispatch --mere method wraps could not, they'd just
be a more formal way of doing what we already must do using case
statments.

I actually wrote a system much like teh one you propose called
LightType, it was based on the Euphoria language's type system. Hmm...
at the time I didn't hink of using multi-dispatch with it. Since I
recently wrote a working overload method maybe I'll revist the
possibility.

T.

Hi --

···

On Sun, 2 Apr 2006, Trans wrote:

dblack@wobblini.net wrote:

Hi --

On Sun, 2 Apr 2006, Trans wrote:

<blockquote>
It's not actually that practical, and such things end up making your
code very much like C++ and Java.

Ruby is smarter than that. Ruby can do more than that.

Think in terms of what your object's required capabilities are instead
of pretending that a class indicator is sufficient for that.
</blockquote>

While I understand you pointr Austin --obviously where talking Duck
Typing here. But I think it is interesting to condier that this is some
respect antithetical to OOP in general --I mean the reciever _is_ a
specific type. And that reacieve detemine the functionality of the
method call. It is sort of as if you were progamming in a more
traditional functional language and _had_ to specifiy the type of the
first argument, but never the remaining.

foofunc( FooClass foo, clever, smart, stupid )

instead of

foo.foofunc( clever, smart, stupid )

It's actually more like this:

   foofunc(object_that_responds_to_foofunc, etc.)

The fact that an object handles a message does not imply its class.
(I'm transliterating 'type' to 'class' as that seems to be what the
thread is actually about [as it usually is :-].)

But the class of that object dictates the functionality of that
message. That's my point --it's class based. A double dispath makes
this very clear:

No: the definition of the method dictates the functionality of the
method. That can vary from one instance to another, even within a
class. It often doesn't; but because it *can*, one can view the case
where two instances of a class behave the same way as a special case
of the case where they don't.

David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

Well, I think you should allowed to put a selective effect on the
remaining arguments, but it should at least allow you to be a little
smarter than simply checking one single Type. I'd like to see you
able to check against multiple types as well as methods and
combinations thereof, like

def foo(arg1 : (Array and :custom_array_method) or Hash or
:special_method)

Then at least it's simply a syntactic convenience for writing
respond_to? and kind_of? calls. And, logically, you should be able
to assign these parameter checks to a variabe so you can reduce the
duplication of them, although I don't have a clue as to what a good
syntax for that would be... Maybe something like:

type_check = TypeCheck.new do |var|
  case var
  when Array
    return true if var.respond_to? :custom_array_method
  when Hash
    return Hash
  else
    return true if var.respond_to? :special_method
  end
  return false
end

And, of course, you can do any checking you want in the block. You
could then do this:

def foo(arg1 : type_check)
def bar(arg1, arg2 : type_check)

I quite agree, showes my how helpless I braught this up. :frowning: Should
have named the thread "Easier ways to enforce contracts". Is that not
strange that we think types immediately and than are afraid of ancient
Computer Science History.

In Ruby, at least, inheritance is not a guarantee of a contract (even on
objects derived from core classes). It's far better to think in terms of
what an object must *do* in your method, rather than to try to consider
what they *are* in your method. An example might help.

Transaction::Simple has a debug mechanism. It expects an object that can
respond to #<< for output (and I believe *checks* for it). By default,
that means that I support String, Array, IO (and most, if not all,
descendants), and StringIO. I explicitly wanted it this way, whereas if
I had placed a class check (and make no mistake: most people are
familiar with statically typed languages and the addition of this will
make people think of Ruby in terms of static typing), I would have
prevented the use of all but the class(es) that I explicitly specified.

Unless you have a *damn* good reason to restrict a method to a
particular class, you shouldn't be doing any sort of checking at all
that way. Checking on method presence (e.g., #respond_to?) is more
useful (but only partially so; you should check the #arity of a method),
but even that fails if the person forgets to implement #respond_to? when
they've implemented #method_missing. It's also an extra run-time check
that, well, Ruby already does for you.

Make no mistake: I'm not afraid of static typing. I just think that it's
useless in the context of real software development. I've been
developing software for ... a long time. Professionally a little less
than that. :wink: I really *cannot* think of a time when I found that static
typing did anything except get in my way.

My programs often pass objects of an unexpected "contract, behavior,
type, mixin interface" you name it. I would like a modern language to
help me, the *stupid* programmer to be more *effective* Ruby claims
that.

It's called "unit tests." If your programs are often passing objects
that don't behave the way you want those objects to behave, then it's a
bug that you should be ensuring doesn't come out of the caller; in Ruby
it's often far more efficient to ensure that the caller doesn't screw up
instead of the callee doing checks ... that Ruby already does. This is
one reason I'm so consistently opposed to the Eater Nil that is
periodically proposed: it changes the behaviour to silently fail instead
of noisily fail if I get something I'm not supposed to (usually a nil;
in the stuff that I've developed, you won't typically get a Real Object
that doesn't work).

So let me suggest the following syntax

def foo (bar, foobar) is a shortcut to
def foo( bar, foobar : Object) which is a shortcut to
def foo( bar, foobar : { |para| Object === para } ) so we can put any
constraint in there.

I still think that is a good thing for readability and maintenance and
*nobody* would be forced to use it. Furthermore we are not forced to
use the block inside the formal parameter list, it would just give us
the opportunity.

It's exceedingly ugly. It's also no better, in implementation terms,
than placing the contract enforcement as lines of code at the top of the
method. Except that the latter is clearer, explicit, and infinitely more
maintainable than writing a miniprogram in the parameter list. (And can
easily be extracted to a unit test where that sort of thing probably
belongs in most Ruby code.)

Don't get me wrong: there are times when specifying a type is necessary.
Those types when you're dealing with pure Ruby are vanishingly small.
I'm looking at implementing some metacode for PDF::Core that includes
class specification (because the PDF specification has a defined number
of object classes). If I'm interacting with SOAP, it is useful to
specify the types/classes that I'm interacting with.

(I would also suggest that if you're going to allow a block for this
sort of thing, you need to actually allow for inter-parameter validation
as well, e.g., if bar is String then foobar must be Fixnum; if bar is
Fixnum, then foobar must be String. Of course, that gets into more
complex validation, which really does underscore my point that this
behaviour belongs in the method itself. Maybe we can have precondition
and postcondition sections of methods, but putting all this in the
parameter list is ugly and nonsensical.)

I really fail to see why this is inhibiting the language. Such
programs fail explicitly and early, which is better (I claim) than
maybe failing later or just not behaving as expected.

Ah. That's where you're wrong: such programs would not fail any earlier
than they do now. The singular "advantage" to statically typed languages
is that they fail during the compile stage if there's a mismatch. Your
method still won't fail until it is called.

-austin

···

On 4/2/06, Robert Dober <robert.dober@gmail.com> wrote:

On 4/2/06, Daniel Nugent <nugend@gmail.com> wrote:

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Hrm... I see, however, effective multi-dispatch would still be
possible with only around calls. Simply make the public method a
dummy:

def public_dummy(*args);end.around do |*args|
  SOME_ARGUMENT_CONDITION CODE
  when CONDITION 1
    real_method_1
  when CONDITION 2
    real_method_2
  else
    real_method_general
  end
end

And, I would say that this is perfectly acceptable because the number
of times you actually NEED multi-methods in Ruby is going to be pretty
small.

···

On 4/1/06, Trans <transfire@gmail.com> wrote:

Daniel Nugent wrote:
> Actually... now that I'm looking about it, that's kinda dumb, we might
> as well just add pre, post, and around calls so we can more cleanly
> seperate the Type and condition checks from the actual method.

No, it's not so dumb actually. A system like the one you propose could
be used for multi-dispatch --mere method wraps could not, they'd just
be a more formal way of doing what we already must do using case
statments.

I actually wrote a system much like teh one you propose called
LightType, it was based on the Euphoria language's type system. Hmm...
at the time I didn't hink of using multi-dispatch with it. Since I
recently wrote a working overload method maybe I'll revist the
possibility.

T.

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:

>> Well, I think you should allowed to put a selective effect on the
>> remaining arguments, but it should at least allow you to be a little
>> smarter than simply checking one single Type. I'd like to see you
>> able to check against multiple types as well as methods and
>> combinations thereof, like
>>
>> def foo(arg1 : (Array and :custom_array_method) or Hash or
>> :special_method)
>>
>> Then at least it's simply a syntactic convenience for writing
>> respond_to? and kind_of? calls. And, logically, you should be able
>> to assign these parameter checks to a variabe so you can reduce the
>> duplication of them, although I don't have a clue as to what a good
>> syntax for that would be... Maybe something like:
>>
>> type_check = TypeCheck.new do |var|
>> case var
>> when Array
>> return true if var.respond_to? :custom_array_method
>> when Hash
>> return Hash
>> else
>> return true if var.respond_to? :special_method
>> end
>> return false
>> end
>>
>> And, of course, you can do any checking you want in the block. You
>> could then do this:
>>
>> def foo(arg1 : type_check)
>> def bar(arg1, arg2 : type_check)

> I quite agree, showes my how helpless I braught this up. :frowning: Should
> have named the thread "Easier ways to enforce contracts". Is that not
> strange that we think types immediately and than are afraid of ancient
> Computer Science History.

In Ruby, at least, inheritance is not a guarantee of a contract (even on
objects derived from core classes).

That is a very delicate point too, I strongly feel that a developper should
*know* what kind of protocol an object is implementing and should be able to
enforce this at a given point.
By extending core classes (and I love to do it BTW) she is taking great
risks.
If you do not agree, that means to me that you are probably a very very
talented designer, but do you not know error prone people like me?

It's far better to think in terms of

what an object must *do* in your method, rather than to try to consider
what they *are* in your method. An example might help.

Transaction::Simple has a debug mechanism. It expects an object that can
respond to #<< for output (and I believe *checks* for it). By default,
that means that I support String, Array, IO (and most, if not all,
descendants), and StringIO. I explicitly wanted it this way, whereas if
I had placed a class check (and make no mistake: most people are
familiar with statically typed languages and the addition of this will
make people think of Ruby in terms of static typing),

might be and the way I presented it, for sure, real big mistake of mine.

I would have

prevented the use of all but the class(es) that I explicitly specified.

So you would not, why should you? There is no static typing, there is only
the possibility of *early* renforcement of contract.
It might be a bad idea anyway, but I did not reach you. This is completely
clear from your very elaborate answer, which I appreciate.
Look at it like this when we ask to check for certain conditions at certain
points by means of assertions we have normally good reason to do so,
right???
I belive that the moment when a message is sent is often the ideal moment to
reinforce such constraints.
def foo(x : {|para| %r{Robert is a real egghead} =~ x})
I can of course write that on my own in the next line, but it would just be
against my laziness

Maybe it is a feeling that I need help for my shortcomings as a programmer.
I thaught "contract enforcing mechanisms" might allow for an easier way to
program defensively.
But I might be caught in too old paradigms, I really feel that you feel this
way and I will take it quite seriously.

Unless you have a *damn* good reason to restrict a method to a

particular class, you shouldn't be doing any sort of checking at all
that way. Checking on method presence (e.g., #respond_to?) is more
useful (but only partially so; you should check the #arity of a method),
but even that fails if the person forgets to implement #respond_to? when
they've implemented #method_missing. It's also an extra run-time check
that, well, Ruby already does for you.

Meta programming might ruin it, singleton methods might ruin it, we should
use only final classes and methods as in Java :wink:
Now you see I understand this, your reaction, it might be a very sound one.

Make no mistake: I'm not afraid of static typing. I just think that it's

useless in the context of real software development.

Agreed

I've been

developing software for ... a long time. Professionally a little less
than that. :wink: I really *cannot* think of a time when I found that static
typing did anything except get in my way.

And you never used assertions neither as you stated above?

My programs often pass objects of an unexpected "contract, behavior,
> type, mixin interface" you name it. I would like a modern language to
> help me, the *stupid* programmer to be more *effective* Ruby claims
> that.

It's called "unit tests." If your programs are often passing objects
that don't behave the way you want those objects to behave, then it's a
bug that you should be ensuring doesn't come out of the caller; in Ruby
it's often far more efficient to ensure that the caller doesn't screw up
instead of the callee doing checks ... that Ruby already does. This is
one reason I'm so consistently opposed to the Eater Nil that is
periodically proposed: it changes the behaviour to silently fail instead
of noisily fail if I get something I'm not supposed to (usually a nil;
in the stuff that I've developed, you won't typically get a Real Object
that doesn't work).

I take this point at 100%, I might be biased by bad design methods.

So let me suggest the following syntax
>
> def foo (bar, foobar) is a shortcut to
> def foo( bar, foobar : Object) which is a shortcut to
> def foo( bar, foobar : { |para| Object === para } ) so we can put any
> constraint in there.

> I still think that is a good thing for readability and maintenance and
> *nobody* would be forced to use it. Furthermore we are not forced to
> use the block inside the formal parameter list, it would just give us
> the opportunity.

It's exceedingly ugly. It's also no better, in implementation terms,
than placing the contract enforcement as lines of code at the top of the
method. Except that the latter is clearer, explicit, and infinitely more
maintainable than writing a miniprogram in the parameter list. (And can
easily be extracted to a unit test where that sort of thing probably
belongs in most Ruby code.)

Well I can live with this statement, I was quite aggressive too :wink:

Don't get me wrong: there are times when specifying a type is necessary.

Those types when you're dealing with pure Ruby are vanishingly small.
I'm looking at implementing some metacode for PDF::Core that includes
class specification (because the PDF specification has a defined number
of object classes). If I'm interacting with SOAP, it is useful to
specify the types/classes that I'm interacting with.

(I would also suggest that if you're going to allow a block for this
sort of thing, you need to actually allow for inter-parameter validation
as well, e.g., if bar is String then foobar must be Fixnum; if bar is
Fixnum, then foobar must be String. Of course, that gets into more
complex validation, which really does underscore my point that this
behaviour belongs in the method itself. Maybe we can have precondition
and postcondition sections of methods, but putting all this in the
parameter list is ugly and nonsensical.)

Well no, that was not intended , please remember that I *never* wanted any
obligation to check.
I wanted a tool, and probably it is not useful, you quite convinced me.

I really fail to see why this is inhibiting the language. Such
> programs fail explicitly and early, which is better (I claim) than
> maybe failing later or just not behaving as expected.

Ah. That's where you're wrong: such programs would not fail any earlier
than they do now. The singular "advantage" to statically typed languages
is that they fail during the compile stage if there's a mismatch. Your
method still won't fail until it is called.

That was intened like this, it would fail when called and not maybe three
stack levels later, but as you said already, I can enforce the contract
myself on crucial points.

-austin

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Thanks a lot for your precious time taken.

Robert

···

On 4/2/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/2/06, Robert Dober <robert.dober@gmail.com> wrote:
> On 4/2/06, Daniel Nugent <nugend@gmail.com> wrote:

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

- Albert Einstein

If I remember correctly from _Object Oriented Software Engineering_,
Betrand Meyer specifically talks about how when pre-conditions fail, it
is the *caller* that has violated the contract. When a program is written
correctly (i.e., without bugs) pre-condition testing is completely superfluous
at run-time. I think the Eiffel compilers even have a switch to turn-off
run-time pre-condition testing.

I'd rather see the support for pre-conditions and testing within the
context of the development environment rather than burdening the run-time
environment. The use of annotations along with smart text editors and
test-case generators might be useful.

Gary Wright

···

On Apr 2, 2006, at 9:29 AM, Austin Ziegler wrote:

On 4/2/06, Robert Dober <robert.dober@gmail.com> wrote:

My programs often pass objects of an unexpected "contract, behavior,
type, mixin interface" you name it. I would like a modern language to
help me, the *stupid* programmer to be more *effective* Ruby claims
that.

It's called "unit tests." If your programs are often passing objects
that don't behave the way you want those objects to behave, then it's a
bug that you should be ensuring doesn't come out of the caller; in Ruby
it's often far more efficient to ensure that the caller doesn't screw up
instead of the callee doing checks ...

[David]
No: the definition of the method dictates the functionality of the
method. That can vary from one instance to another, even within a
class. It often doesn't; but because it *can*, one can view the case
where two instances of a class behave the same way as a special case of
the case where they don't.
[/David]

A fair point althouhg not exactly true. When you define a singleton
method you are quite literally giving an object a new Class, the
original of which becomes the superclass of the new one. One assumes of
course, as we all do and must, that a subclass essentially obeys the
same contract as it's anscestor. Not that it has to of course, but in
general we must in order to gain from the whole OOP methodology.

A String and an Integer, for instance, are very different things. So
when I specify a parameter should be an an Integer, say, I mean that it
should be quite like one of those things, so much so that it should be
a sublcass of it or have a coercability for becoming so, otherwise
don't waste time trying. Just b/c some other object might repsond to
all the same methods I end up using doesn't mean much --poeple just
don't think that way. I've creted my method to deal with Integer's
that's what I designed it to do. You want to send it a Watchamacallit?
Why? You really think it's going to work? Do you know enough about the
method I wrote to think that using it with Watchamcallit's will be all
that beneficial? If a Watchamacallit isn't Integery enough to be a
subclass of one or be coerced into one, what makes you think it SHOULD
work? What if you change Watchamacallit later on? What if my mehtod
changes later on? Integer's not likely to change that's what I'm
depending on. This Integer contract may not be perfect, but it relative
dependency is intrumental to the construction of my software. There are
no gaurantee's whatsoever for Watchamacallits.

I think duck typing is great and all, but it's one of those things that
plays better in theory than it actually does in practice.

T.

Daniel Nugent ha scritto:

And, I would say that this is perfectly acceptable because the number
of times you actually NEED multi-methods in Ruby is going to be pretty
small.

care to elaborate?

I don't think you're saying that we can't do things withouth multimethods, but just in case, a cpu with only SUBTRACT_AND_BRANCH_IF_NEGATIVE is perfectly fine to do everything, but this does not make it pleasant.