[Python-ideas] Simplicity of C (was why is design-by-contracts not widely)

Chris Angelico rosuav at gmail.com
Sun Sep 30 00:50:28 EDT 2018


On Sun, Sep 30, 2018 at 2:27 PM Steven D'Aprano <steve at pearwood.info> wrote:
>
> On Sun, Sep 30, 2018 at 12:17:25PM +1000, Chris Angelico wrote:
> > On Sun, Sep 30, 2018 at 11:54 AM Steven D'Aprano <steve at pearwood.info> wrote:
> > > This discussion is for those of us who would like to include DbC in our
> > > projects but don't like existing solutions. C++ being designed with a
> > > shovel is not relevant.
> > >
> > > (Except in the sense that we should always be careful about piling on
> > > feature upon feature into Python.)
> >
> > And as such, I do not want to see dedicated syntax for no purpose
> > other than contracts.
>
> That's a reasonable objection, except that contracts are a BIG purpose.

I think that's a matter of debate, but sure, let's accept that
contracts are big.

> Would you object to dedicated syntax for object oriented programming?
> (Classes and methods.) I hope not. Imagine if OOP in Python was limited
> to an API like this:

TBH I don't think contracts are nearly as big a tool as classes are.

> MyClass = type(name="MyClass", parent=object)
> MyClass.add_method(__init__=lambda self, arg: setattr(self, "arg", arg))
> MyClass.add_method(__str__=lambda self: "MyClass(%r)" % (self.arg,))
> MyClass.add_method(spam=lambda self, x, y: (self.arg + x)/y)
> MyClass.add_method(eggs=lambda self, x, y: self.arg*x - y)
> MyClass.add_member(cheese='Cheddar')
> MyClass.add_member(aardvark=None)

Actually, that's not far from the way JavaScript's class hierarchy
was, up until ES2015. Which suggests that a class keyword is a
convenience, but not actually essential.

> I know that adding syntax is a big step, and should be considered a last
> resort for when a library or even a built-in won't work. But adding
> contracts isn't a small benefit. Its not a magic bullet, nobody says
> that, but I would say that contracts as a feature is *much* bigger and
> more important than (say) docstrings, and we have dedicated syntax for
> docstrings.

Hmm, what we really have is just string literals, plus a bit of magic
that says "if the first thing in a function/class is a string literal,
we save it". But sure.

> > What I'm interested in is (a) whether something
> > can and should be added to the stdlib, and (b) whether some specific
> > (and probably small) aspect of it could benefit from language support.
> > As a parallel example, consider type hints. The language has ZERO
> > support for special syntax for a language of types.
>
> That's a weird use of the word "ZERO" :-)
>
>     def spam(x: int) -> float:
>         y: int
>
> I count three special syntax forms for a language of types:
>
> - parameter type hints;
> - return type hints;
> - variable type hints.
>
> (Yes, I'm aware that *technically* we can put anything we like in the
> hints, they don't have to be used as type hints, but Guido has made it
> clear that such uses are definitely of second-rate importance and only
> grudgingly supported.)

That's exactly my point though. The syntax is for "attach this thing
to that function". There is no syntax for a language of types, a type
algebra syntax. We don't have a syntax that says "tuple containing
int, two strings, and float". The syntactic support is the very
smallest it can be - and, as you say, it's not actually restricted to
type hints at all. If I'm reading the dates correctly, annotations
were completely non-specific from 2006 (PEP 3107) until 2014 (PEP
484).

So what is the smallest piece of syntactic support that would enable
decent DbC? And "none at all" is a valid response, although I think in
this case it's incorrect.

> > What you have is
> > simple, straight-forward names like "List", and the normal behaviours
> > that we already can do such as subscripting. There is language
> > support, however, for attaching expressions to functions and their
> > arguments.
>
> Your point is taken that there is no separate syntax for referring to
> the types *themselves*, but then there's no need for such. int is int,
> whether you refer to the class "int" or the static type "int".

The static type "int" is one of the simplest possible type
declarations. There are much more complicated options.

> > At the moment, I'm seeing decorator-based contracts as a clunky
> > version of unit tests.
>
> Contracts are not unit tests.
>
> Contracts and unit tests are complementary, and overlap somewhat, but
> they are the same. Unit tests only test the canned values you write in
> you tests. Contracts test real data you pass to your application.
>

And yet all the examples I've seen have just been poor substitutes for
unit tests. Can we get some examples that actually do a better job of
selling contracts?

ChrisA


More information about the Python-ideas mailing list