"stereotyping" (was: Re: Strong Typing (Re: Managing metadata about attribute types) )

This is a wonderful idea. Let me restate it to make sure I
understand it. Just as you can do the following:

class Person
def greet(other_person)
other_person.to do
say “hello”
end
end
end

class Person
def some_other_method
end
end

…(I’ve defined class Person somewhere, but I can always open up the
class again and define something else in it): it would be
wonderful if you can either inline it or make it external in
a similar fashion. […]
I think the ability to do this would make the whole idea a lot more
palatable to a lot of us.

I’ve been thinking about DbC stuff for some time and something in Matz Ruby
2 talk last Saturday sparked an idea along these lines …

class Person
def greet(other_person)
marry(other_person)
end
end

Then specify the contract in a separate file …

class Person
def greet:pre(other_person)
assert ! self.married?
assert ! other_person.married?
end

 def greet:post(other_person)
   assert other_person.married?
   assert self.married?
   assert_equal self, other_person.spouse
   assert_equal other_person, self.spouse
 end

end

An aside: Unfortunately, the post method doesn’t have access to the result
returned from the function. In this case it doesn’t matter, but many post
conditions assert something interesting about the result. I guess I would
have to use a wrap method for that.

···


– Jim Weirich / Compuware
– FWP Capture Services
– Phone: 859-386-8855

How would this work:

def greet(other_person)
if (shake_hand(other_person) == not_clammy) then
marry(other_person)
end
end

It seems that you could only pre-assert that objects going in had a certain
range of values that fit the requirement. The above example wouldn’t work
because it depends on the result of a method call. Would it be logical to
have some checks for a method done in one place, but other checks done
somewhere else? Or would pre-assertions just be considered part of the
method calling contract? it sort of feels like code logic is spread out,
making the human brain work harder to bring it all back into one place
conceptually.

Sean O'Dell
···

On Friday 21 November 2003 11:06 am, Weirich, James wrote:

This is a wonderful idea. Let me restate it to make sure I
understand it. Just as you can do the following:

class Person
def greet(other_person)
other_person.to do
say “hello”
end
end
end

class Person
def some_other_method
end
end

…(I’ve defined class Person somewhere, but I can always open up the
class again and define something else in it): it would be
wonderful if you can either inline it or make it external in
a similar fashion. […]
I think the ability to do this would make the whole idea a lot more
palatable to a lot of us.

I’ve been thinking about DbC stuff for some time and something in Matz Ruby
2 talk last Saturday sparked an idea along these lines …

class Person
def greet(other_person)
marry(other_person)
end
end

Then specify the contract in a separate file …

class Person
def greet:pre(other_person)
assert ! self.married?
assert ! other_person.married?
end

 def greet:post(other_person)
   assert other_person.married?
   assert self.married?
   assert_equal self, other_person.spouse
   assert_equal other_person, self.spouse
 end

end

An aside: Unfortunately, the post method doesn’t have access to the result
returned from the function. In this case it doesn’t matter, but many post
conditions assert something interesting about the result. I guess I would
have to use a wrap method for that.

I’ve been thinking about DbC stuff for some time and something in Matz Ruby

2 talk last Saturday sparked an idea along these lines …

···

On Sat, 22 Nov 2003, Weirich, James wrote:

class Person

def greet(other_person)

marry(other_person)

end

end

Then specify the contract in a separate file …

class Person

def greet:pre(other_person)

assert ! self.married?

assert ! other_person.married?

end

def greet:post(other_person)

assert other_person.married?

assert self.married?

assert_equal self, other_person.spouse

assert_equal other_person, self.spouse

end

end

Very cool, Jim. It makes me wonder what other “paradigms” might be
available without language modifications. There are, of course, some
limitations to this as you point out, but this simple wrapping adds a lot
of flexibility.

A question for Matz (and Sean, for that matter): I’ve heard Sean say that
you could turn off his stuff in production (maybe it was the old
proprosal…can’t remember). How would you feel in general about
implementing a system that actually slows things down, but with the idea
that you wouldn’t use it in production?

We don’t stress out too much about making debuggers that will allow our
code to run at full speed. And, from what I’ve heard from the proponents
of interface checking, the desire is to help people–not computers.

So, why worry too much about speed? You could potentially implement
something using pre/wrap/post (or some sugary-syntax derivative), and so
what if it has to use respond_to? and slow things down? You just remove
it before you actually put the code into use.

Thoughts?

Hi,

I’ve been thinking about DbC stuff for some time and something in Matz Ruby
2 talk last Saturday sparked an idea along these lines …

class Person
def greet(other_person)
marry(other_person)
end
end

Then specify the contract in a separate file …

class Person
def greet:pre(other_person)
assert ! self.married?
assert ! other_person.married?
end

def greet:post(other_person)
  assert other_person.married?
  assert self.married?
  assert_equal self, other_person.spouse
  assert_equal other_person, self.spouse
end

end

I’d be second to Chad. Cool.

An aside: Unfortunately, the post method doesn’t have access to the result
returned from the function. In this case it doesn’t matter, but many post
conditions assert something interesting about the result. I guess I would
have to use a wrap method for that.

The only reason the result is not available from post method is we
don’t have neat syntax construct. Any proposal?

						matz.
···

In message “Re: “stereotyping” (was: Re: Strong Typing (Re: Managing metadata about attribute types) )” on 03/11/22, “Weirich, James” James.Weirich@FMR.COM writes:

Lisp has (call-next-method &rest args) used in method combination…
I’m not sure how things have been proposed (I only saw the slide),
but:

def foo:pre(a,b)
call_next unless (a > b)
end

def foo(a, b)
return “OK” if (a < 15)
call_next(a+b)
end

def foo:post(x)
:
end

def foo:wrap(a,b)
# blah blah
res = call_next(b, a) # Might get “OK”? or whatever :post returns…
# blah blah
end

Again, I’m not sure how you want everything to flow exactly. With
‘call_next’, the ability to call it or not is both an advantage and a
disadvantage.

···

On Sat, 22 Nov 2003 08:37:03 +0900 matz@ruby-lang.org (Yukihiro Matsumoto) wrote:

An aside: Unfortunately, the post method doesn’t have access to the result
returned from the function. In this case it doesn’t matter, but many post
conditions assert something interesting about the result. I guess I would
have to use a wrap method for that.

The only reason the result is not available from post method is we
don’t have neat syntax construct. Any proposal?

  					matz.


Ryan Pavlik rpav@mephle.com

“Now if you’ll excuse me, I’ve got to single-handedly
save a film genre.” - 8BT

> >Then specify the contract in a separate file ... > > > > class Person > > def greet:pre(other_person) > > assert ! self.married? > > assert ! other_person.married? > > end > > > > def greet:post(other_person) > > assert other_person.married? > > assert self.married? > > assert_equal self, other_person.spouse > > assert_equal other_person, self.spouse > > end > > end > > I'd be second to Chad. Cool. > > >An aside: Unfortunately, the post method doesn't have access to the result > >returned from the function. In this case it doesn't matter, but many post > >conditions assert something interesting about the result. I guess I would > >have to use a wrap method for that. > > The only reason the result is _not_ available from post method is we > don't have neat syntax construct. Any proposal?

class Person
def greet:post other_person #=> result
assert other_person.married?
assert self.married?
assert_equal self, other_person.spouse
assert_equal other_person, self.spouse
end
end

  • ‘#=>’ is it’s own token, therefore no confusion with hash or comment

-a

···

On Sat, 22 Nov 2003, Yukihiro Matsumoto wrote:

ATTN: please update your address books with address below!

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================

Yukihiro Matsumoto wrote:

An aside: Unfortunately, the post method doesn’t have access to the result
returned from the function. In this case it doesn’t matter, but many post
conditions assert something interesting about the result. I guess I would
have to use a wrap method for that.

The only reason the result is not available from post method is we
don’t have neat syntax construct. Any proposal?

  					matz.

My first impulse is to say: Just as super is used within “wrap”,
let it be used within “post”.

The difference would be that in the latter, it would not be a
true method call, only a reference to a captured return value.

Hal

what is required of it? would a special keyword variable be enough?

def greet:post(other_person)
   assert result
   assert other_person.married?
   assert self.married?
   assert_equal self, other_person.spouse
   assert_equal other_person, self.spouse
 end

Would yield be needed in these? If no, then you could use yeild, and result of
function is passed to :post as block.

def greet:post(other_person)
   assert yield
   assert other_person.married?
   assert self.married?
   assert_equal self, other_person.spouse
   assert_equal other_person, self.spouse
 end

Or is there something I am missing?

···

On Saturday 22 November 2003 12:37 am, Yukihiro Matsumoto wrote:

The only reason the result is not available from post method is we
don’t have neat syntax construct. Any proposal?

i remeber some talk of ‘def’ returning values. this leads nicely into setting
the atrributes for a method via a ‘Method’ object:

class Method
# beautiful thing that matz will write
end

class Person
greet_method =
def greet
# …
end

greet_method.pre = lambda{|args, block|...}
#greet_method.pre = :name_of_greet_pre_checker 
#greet_method.pre = another Method object 

greet_method.post = lambda{|result, args, block|...}
#greet_method.post = :name_of_greet_post_checker 
#greet_method.post = another Method object 

end

if this existed one could do (in person_if.rb)

class Person
greet_method = method(:greet)

greet_method.pre =
  def greet_pre; end
greet_method.post =
  def greet_post; end
  ...

end

something that objectified methods and gave them :pre and :post methods would
lead to all sorts of possibilities

… just another idea …

-a

···

On Sat, 22 Nov 2003, Yukihiro Matsumoto wrote:

I’ve been thinking about DbC stuff for some time and something in Matz Ruby
2 talk last Saturday sparked an idea along these lines …

class Person
def greet(other_person)
marry(other_person)
end
end

Then specify the contract in a separate file …

class Person
def greet:pre(other_person)
assert ! self.married?
assert ! other_person.married?
end

def greet:post(other_person)
  assert other_person.married?
  assert self.married?
  assert_equal self, other_person.spouse
  assert_equal other_person, self.spouse
end

end

I’d be second to Chad. Cool.

An aside: Unfortunately, the post method doesn’t have access to the result
returned from the function. In this case it doesn’t matter, but many post
conditions assert something interesting about the result. I guess I would
have to use a wrap method for that.

The only reason the result is not available from post method is we
don’t have neat syntax construct. Any proposal?

  					matz.

ATTN: please update your address books with address below!

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================

Yukihiro Matsumoto wrote:

The only reason the result is not available from post
method is we don’t have neat syntax construct. Any proposal?

Ruby’s default argument mechanism makes it impossible to add
the main return'' value as an extra argument of a post method, so we need to offer the access to the main return’’ value via a
method or a variable automatically provided for every post method.

Since super'' is freely available we could use it (super with no arguments allowed) - of course this is old school keyword overloading’’ which
I don’t like too much, so I probably would opt for another keyword
like main:result'', main_result’‘, post:result'' or post_result’’
(we could use the same keyword to provide access to the ``main return’’
value in a wrap method).

One way or the other, I really really want to have this feature even
at the cost of ugly syntax or keyword overloading. Any chance we
got to play with this in 1.9? I am also wandering about your planning on
the interaction of blocks with the pre,wrap,post mechanism.

/Christoph

matz@ruby-lang.org (Yukihiro Matsumoto) writes:

The only reason the result is not available from post method is we
don’t have neat syntax construct. Any proposal?

Seems to me that overloading ‘super’ again, as others have proposed,
is just too much overloading for my personal taste. Assuming you’re
not planning on getting rid of $?, that would be a good place to put
it, I think. If post method wants to do other things that would reset
$?, then post method should save it off first.

Just a thought,

-=Eric

···


Come to think of it, there are already a million monkeys on a million
typewriters, and Usenet is NOTHING like Shakespeare.
– Blair Houghton.

That would break a lot of code that uses it as a means to annotate an
expression.

If we are introducing a new multichar token, why not → ?

martin

···

Ara.T.Howard ahoward@ngdc.noaa.gov wrote:

On Sat, 22 Nov 2003, Yukihiro Matsumoto wrote:

> >Then specify the contract in a separate file ... > > > > class Person > > def greet:pre(other_person) > > assert ! self.married? > > assert ! other_person.married? > > end > > > > def greet:post(other_person) > > assert other_person.married? > > assert self.married? > > assert_equal self, other_person.spouse > > assert_equal other_person, self.spouse > > end > > end > > I'd be second to Chad. Cool. > > >An aside: Unfortunately, the post method doesn't have access to the result > >returned from the function. In this case it doesn't matter, but many post > >conditions assert something interesting about the result. I guess I would > >have to use a wrap method for that. > > The only reason the result is _not_ available from post method is we > don't have neat syntax construct. Any proposal?

class Person
def greet:post other_person #=> result
assert other_person.married?
assert self.married?
assert_equal self, other_person.spouse
assert_equal other_person, self.spouse
end
end

  • ‘#=>’ is it’s own token, therefore no confusion with hash or comment

Lisp has (call-next-method &rest args) used in method combination...

In CLOS the type of the method determine where call-next-method can be
called. For standard method, it's allowed in primary methods and around
methods. For generic functions using define-method-combination,
call-next-method is allowed only in around method (if I'm right, there is
a long time that I've not used CLOS ...)

The super in :wrap can be seen as the equivalent of call-next-method

Guy Decoux