Optional param modifier

classic Classic list List threaded Threaded
43 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: Optional param modifier

Marco van de Voort-2

Op 2019-04-13 om 09:47 schreef Sven Barth via fpc-pascal:

>
>     I think the same as when I read the suggestion for an inout
>     variant of
>     VAR. Move this out of the language syntax, and make it directives or
>     attribute like syntax (like we will need to get anyway for const ref).
>
>
> Im definitely for new syntaxes (or the attribute one) than a
> directive. A directive can be anywhere and I'd need to go looking for
> it if I want to know whether it is set or not. Some syntax extension
> would be right at the declaration.
>
Such "inventions" are usually for specific APIs, and then the directive
can be set global. Make it a new language syntax, and it turns up
everywhere, also where it was not intended for.

> So, yeah, we'll probably compromise towards the attribute syntax...
>
That's a second. Note that the stuff where this is borrowed from (like
Windows headers [size_is are also attributes.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

class contracts [[was: Re: Optional param modifier]]

Martin Frb
In reply to this post by Free Pascal - General mailing list
On 15/04/2019 09:41, Sven Barth via fpc-pascal wrote:

> Am 14.04.2019 um 23:48 schrieb Martin Frb:
>> type
>>   TFoo= class
>>      function DoTheFooThing(Foo1, Foo2: TFoo): Tbar;
>>         requires
>>            assigned(Foo1) or assigned(Foo2): 'Need at least 1 foo,
>> for the connection';
>>         guarantees // better than ensure
>>            assigned(result);
>>            result.KnowsMyFoo = true: 'Connection exists';  // the
>> =true is redundant
>>     procedure DoTheBar;
>>   end;
>>
>> It is to be noted, that requires and guarantees contain conditions
>> (expressions), not pascal code. So technically it is ok, that they
>> are in the interface and not implementation.
>> If I want something in the implementation, I can use normal "assert"
>> (which by the way, have often great documenting value)
> The problem is that both "require" and "ensure" can check for fields
> as well (think of a setter for example or something that changes the
> state). Thus you could use a field name that the compiler does not yet
> know. So you would need to order your methods in a order dictated by
> the compiler due to the method's implementation instead of an order of
> your own choosing.
>
> And yes, that would also be a problem with "class invariants", though
> there it's more clear if we say that only identifiers can be used that
> have been declared before as it's the same with properties and their
> setters/getters.

Also to be ask if properties can have contract conditions. Especially
thinking of indexed properties, where the index is a constant. Several
properties using the same getter/setter (with diff index) may have
different conditions for the contract.

Yes accessing fields is valid. Though easily leads to confusion what
should and what should not be in the contract. (Yet that is not to be
enforced...)
I saw an example, where the "ensure" of a setter checked that the field
was set. That may be valid, but it also may have been something for a
normal assert. Depends on the intend.
The ensure (again I prefer guarantees) is a contract. (between the
class/method and someone else).
So if the check for the field is an internal detail, it should be a
normal assert.  (the getter result, could be part of the contract then /
that is different)

Only a normal assert is not quite the same. Contracts are checked too,
if an inherited overwritten method is called. Assert are not (not if
there is no call to inherited).
So a contract post condition could be used to make sure that any
overwritten setter method will have changed the field. In that case the
partner in the contract is the inherited class. And the post condition
is less of a guarantee, but more a hidden requirement to the contract
partner.

Anyway about the field order.... (and there could be circular
requires/guarantees)
It would be an option to specify the contract details deferred

type
   TFoo= class
      function DoTheFooThing(Foo1, Foo2: TFoo): Tbar;
      procedure DoTheBar;
// need full declaration, could be overloaded // may skip param names?,
just types should be ok
      requirements for DoTheFooThing(Foo1, Foo2: TFoo): Tbar;
            assigned(Foo1) or assigned(Foo2): 'Need at least 1 foo, for
the connection';
      guarantees for DoTheFooThing(TFoo, TFoo): Tbar;
            assigned(result);
            result.KnowsMyFoo = true: 'Connection exists';  // the =true
is redundant
   end;

Bit awkward because you need the full signature....
The compiler could allow both the "requires" right after the method, and
the deferred "requirement for"

Alternative (but I do like that even less) named forward requirements
type
   TFoo= class
      function DoTheFooThing(Foo1, Foo2: TFoo): Tbar; requires
'WhatTheFooWants';
      procedure DoTheBar;
      requirements for WhatTheFooWants;
            assigned(Foo1) or assigned(Foo2): 'Need at least 1 foo, for
the connection';
   end;

That way, 2 methods could refer to the same requirements block.
Then it could even be possible to refer to several blocks....
      function DoTheFooThing(Foo1, Foo2: TFoo): Tbar; requires
'WhatTheFooWants', 'TheFooSpecials';

But this will make it hard to read. Especially in the reverse, if you
are in a named requirement block, it is not easy to find all methods
that are affected by it.

Anyway just throwing in some ideas and possibilities.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: class contracts [[was: Re: Optional param modifier]]

Martin Frb
In reply to this post by Free Pascal - General mailing list
On 15/04/2019 09:41, Sven Barth via fpc-pascal wrote:
> Am 14.04.2019 um 23:48 schrieb Martin Frb:
>> As for "documentation". I disagree with the way it is done in oxygen.
>> But I am not sure I have any good alternative.
>> For me a class contract (require/ensure) is part of the interface.

Putting them in the implementation as oxygen does may also cause a
technical issue.
As pointed out, for a class the contract also affects inherited methods.


Unit A
interface
   TFoo= class
     procedure DoFoo(a:TSome); virtual;
  end;
implementation
uses B;
   procedure DoFoo(a:TSome);
   requires
     whatever



Unit B;
interface
uses A; // AFAIK can only read the interface, the implementation has a
circular "uses B"
   TFooSpecial= class(TFoo)
     procedure DoFoo(a:TSome); override; // needs to know implementation
details from unit A
  end;


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
123