On 21Mar2020 12:15, Stephen J. Turnbull <turnbull.stephen...@u.tsukuba.ac.jp> 
wrote:
Steven D'Aprano writes:
> So each loop will need its own context manager, meaning its own
> class. The *actual* invariant will be buried far away, in a CM
> class, rather than right there next to the loop.

I see no reason why that will be true for many invariants.  The
context manager class would be simple, in principle: __entry__,
__exit__, and invariants.  The expression in the with statement would
be a constructor.

> Worse: the condition will likely need to be written as a string, or a
> lambda, in order to delay evaluation.

Or a local def.  This is correct, as far as I know.  I would expect
the example from Wikipedia
(https://en.wikipedia.org/wiki/Loop_invariant#Informal_example)
translated to Python would be written in the "condition as string"
implementation as

def max(n, a):

   m = a[0]

   # m equals the maximum value in a[0...0]
   i = 1
   while (i != n) {
       with Invariants('m == max(a[0:i])'):
[... and hacks with globals, locals ...]

Twio things:

1:
Might I point out to everyone the icontract PyPI module (maybe I've missing this in the discussion?), which does all this kind of thing for functions (programming by contract, thus the function level focus).

The important point here is that it uses lambda to express the assertions:

   @require(lambda foo: foo > 1)
   def func(foo):
       ...

There's a post condition decorator, and invariants etc. It does funky function signature inspection to match up the lambda parameter names to the function paraemeter names. very cool.

2:
Anyway, a salient point here is that you can write _arbitrary_ invariants as context managers using closures to get the locals/globals stuff (icontract isn't doing this, but it is heavy on the lambdas). For example, maybe:

   from ... import invariant_cm

   def max(n, a):
       m = a[0]
       # m equals the maximum value in a[0...0]
       i = 1
       while (i != n) {
           with invariant_cm(lambda: m == max(a[0:i])):

where invariant_cm came out of your library for checking before and after the suite. The closure gets you the locals/globals directly without cumbersomeness.

Cheers,
Cameron Simpson <c...@cskk.id.au>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/K5A6SMIU6QCGQIAADTR2SQHKO5YX47LN/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to