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
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.
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
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.
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?
> >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!
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’
===============================================================================
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.
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!
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’
===============================================================================
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.
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.
> >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