Hi Yasuo,
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:
For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}
It would require only one new reserved word "ensure".
The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions (zero
cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectations
For inherited methods, only the self <input-assert-expression> should be
checked, and all parent <output-asser-expression>. This is borrowed from D
but not necessary to be repeated exactly.
I think we shouldn't introduce "invariant" constraints for classes now. May
be later.
Implementation is going to generate code for input constraint after all
RECV opcodes and before code for function body, and code for output
constraint before RETURN opcode (may be reusing implementation of
"finally").
See:
http://dlang.org/contracts.html
http://jan.newmarch.name/java/contracts/paper-long.html
Thanks. Dmitry.
Am 05.02.2015 12:14 schrieb "Dmitry Stogov" dmitry@zend.com:
For php it may look like the following:
function foo()
require(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
How would one access the function return value in the
output-assert-expression?
And what about side effects in these expressions? Could they be suppressed
/ made into errors somehow?
best regards
Patrick
Am 05.02.2015 12:14 schrieb "Dmitry Stogov" dmitry@zend.com:
For php it may look like the following:
function foo()
require(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
How would one access the function return value in the
output-assert-expression?
good point. we may use a reserved name. e.g. $result.or $return_value
And what about side effects in these expressions? Could they be suppressed
/ made into errors somehow?
I afraid, we won't be able catch possible side effects of assert
expressions.
For now, we may just relay on user, in the same way as with assert()
now.
Thanks. Dmitry.
best regards
Patrick
Hi Dimitry
-----Ursprüngliche Nachricht-----
Von: Dmitry Stogov [mailto:dmitry@zend.com]
Gesendet: Donnerstag, 5. Februar 2015 12:14
An: Yasuo Ohgaki; PHP Internals
Betreff: [PHP-DEV] Design by ContractHi Yasuo,
Following our conversation, I tried to imagine how DbC should look like in PHP from user perspective. Finally, I was
influenced by the semantic proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions (zero cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectationsFor inherited methods, only the self <input-assert-expression> should be checked, and all parent <output-asser- expression>. This is borrowed from D but not necessary to be repeated exactly.
I think we shouldn't introduce "invariant" constraints for classes now. May be later.
Implementation is going to generate code for input constraint after all RECV opcodes and before code for function body,
and code for output constraint before RETURN opcode (may be reusing implementation of "finally").See:
http://dlang.org/contracts.html
http://jan.newmarch.name/java/contracts/paper-long.htmlThanks. Dmitry.
I am not sure if this new syntactic sugar really improves readability. What is the difference between the above and having something like?
function foo($x, $y){
if(validateFoo($x, $y)){}
//do something
$result = 'some value';
if(postValidateFoo($result){
return $ result;
}
}
Actually putting everything in one function seems even worse from a single responsibility point of view. But I suppose I am missing something essential here.
Cheers,
Robert
Hi Robert,
This is about "declarative" vs "imperative" programming.
Also constraints may be enabled for debugging and completely disabled for
production.
I'm not the inventor of this approach, I just started to think about it
myself :)
You opinion makes sense as well. PHP doesn't have to support all the
possible features.
Thanks. Dmitry.
Hi Dimitry
-----Ursprüngliche Nachricht-----
Von: Dmitry Stogov [mailto:dmitry@zend.com]
Gesendet: Donnerstag, 5. Februar 2015 12:14
An: Yasuo Ohgaki; PHP Internals
Betreff: [PHP-DEV] Design by ContractHi Yasuo,
Following our conversation, I tried to imagine how DbC should look like
in PHP from user perspective. Finally, I was
influenced by the semantic proposed in D, and syntax proposed for Java.
So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions
(zero cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectationsFor inherited methods, only the self <input-assert-expression> should be
checked, and all parent <output-asser- expression>. This is borrowed from D but not necessary to be repeated
exactly.I think we shouldn't introduce "invariant" constraints for classes now.
May be later.Implementation is going to generate code for input constraint after all
RECV opcodes and before code for function body,
and code for output constraint before RETURN opcode (may be reusing
implementation of "finally").See:
http://dlang.org/contracts.html
http://jan.newmarch.name/java/contracts/paper-long.htmlThanks. Dmitry.
I am not sure if this new syntactic sugar really improves readability.
What is the difference between the above and having something like?function foo($x, $y){
if(validateFoo($x, $y)){}//do something
$result = 'some value';if(postValidateFoo($result){
return $ result;
}
}Actually putting everything in one function seems even worse from a single
responsibility point of view. But I suppose I am missing something
essential here.Cheers,
Robert
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:
function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}
This way, no new reserved words are needed at all, and the programmer can give
a name to the "variable that holds the result" locally to avoid clashes with
anything else in the function.
I'm a bit undecided whether returning true/false there to give the verdict,
would be the best way. Maybe better would be another use for declare, without
a block, to declare that the pre/postcondition failed - giving a nice place to
put a suitable message, too. And again without introducing any extra keywords:
function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}
best regards
Patrick
Hello, internals!
From my point of view, contracts should not affect execution of source code
in production env, or can be enabled partially. I have implemented DbC
paradigm on top of the AOP layer, so each contract can be defined via
annotation and looks pretty nice, for example :
use PhpDeal\Annotation as Contract;
/**
-
Simple trade account class
-
@Contract\Invariant("$this->balance > 0")
*/
class Account implements AccountContract
{/**
- Current balance
- @var float
*/
protected $balance = 0.0;
/**
- Deposits fixed amount of money to the account
- @param float $amount
- @Contract\Verify("$amount>0 && is_numeric($amount)")
- @Contract\Ensure("$this->balance == $__old->balance+$amount")
*/
public function deposit($amount)
{
$this->balance += $amount;
}
/**
- Returns current balance
- @Contract\Ensure("$__result == $this->balance")
- @return float
*/
public function getBalance()
{
return $this->balance;
}
}
All contracts (verify|ensure) are enforced only when DbC is enabled and
doesn't have an impact on execution for production mode. Moreover, all
annotations are parsed only once, decorators are generated too, so overhead
is minimal even for debug mode. Engine takes care to insert appropriate
before/around checks via an aspect
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php
Here is a simple snippet of pointcut definition and advice body:
/**
* Verifies pre-condition contract for the method
*
* @param MethodInvocation $invocation
* @Before("@annotation(PhpDeal\Annotation\Verify)")
*
* @throws ContractViolation
*/
public function preConditionContract(MethodInvocation $invocation)
{
$object = $invocation->getThis();
$args = $this->getMethodArguments($invocation);
$scope = $invocation->getMethod()->getDeclaringClass()->name;
foreach ($invocation->getMethod()->getAnnotations() as $annotation) {
if (!$annotation instanceof Contract\Verify) {
continue;
}
if (!$this->isContractSatisfied($object, $scope, $args,
$annotation)) {
throw new ContractViolation($invocation, $annotation->value);
};
}
}
2015-02-05 15:13 GMT+03:00 Patrick Schaaf php@bof.de:
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}This way, no new reserved words are needed at all, and the programmer can
give
a name to the "variable that holds the result" locally to avoid clashes
with
anything else in the function.I'm a bit undecided whether returning true/false there to give the verdict,
would be the best way. Maybe better would be another use for declare,
without
a block, to declare that the pre/postcondition failed - giving a nice
place to
put a suitable message, too. And again without introducing any extra
keywords:function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}best regards
Patrick
So, is it possible to use annotations for defining such metadata on
engine-level? This will be a good way to do this and to define custom
handlers via AST hooks, that can be able to patch method definition node
with concrete opcodes.
2015-02-05 15:24 GMT+03:00 Alexander Lisachenko lisachenko.it@gmail.com:
Hello, internals!
From my point of view, contracts should not affect execution of source
code in production env, or can be enabled partially. I have implemented DbC
paradigm on top of the AOP layer, so each contract can be defined via
annotation and looks pretty nice, for example :use PhpDeal\Annotation as Contract;
/**
Simple trade account class
@Contract\Invariant("$this->balance > 0")
*/
class Account implements AccountContract
{/**
- Current balance
- @var float
*/
protected $balance = 0.0;/**
- Deposits fixed amount of money to the account
- @param float $amount
- @Contract\Verify("$amount>0 && is_numeric($amount)")
- @Contract\Ensure("$this->balance == $__old->balance+$amount")
*/
public function deposit($amount)
{
$this->balance += $amount;
}/**
- Returns current balance
- @Contract\Ensure("$__result == $this->balance")
- @return float
*/
public function getBalance()
{
return $this->balance;
}
}All contracts (verify|ensure) are enforced only when DbC is enabled and
doesn't have an impact on execution for production mode. Moreover, all
annotations are parsed only once, decorators are generated too, so overhead
is minimal even for debug mode. Engine takes care to insert appropriate
before/around checks via an aspect
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.phpHere is a simple snippet of pointcut definition and advice body:
/** * Verifies pre-condition contract for the method * * @param MethodInvocation $invocation * @Before("@annotation(PhpDeal\Annotation\Verify)") * * @throws ContractViolation */ public function preConditionContract(MethodInvocation $invocation) { $object = $invocation->getThis(); $args = $this->getMethodArguments($invocation); $scope = $invocation->getMethod()->getDeclaringClass()->name; foreach ($invocation->getMethod()->getAnnotations() as $annotation) { if (!$annotation instanceof Contract\Verify) { continue; } if (!$this->isContractSatisfied($object, $scope, $args, $annotation)) { throw new ContractViolation($invocation, $annotation->value); }; } }
2015-02-05 15:13 GMT+03:00 Patrick Schaaf php@bof.de:
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}This way, no new reserved words are needed at all, and the programmer can
give
a name to the "variable that holds the result" locally to avoid clashes
with
anything else in the function.I'm a bit undecided whether returning true/false there to give the
verdict,
would be the best way. Maybe better would be another use for declare,
without
a block, to declare that the pre/postcondition failed - giving a nice
place to
put a suitable message, too. And again without introducing any extra
keywords:function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}best regards
Patrick
For now, we don't have any mechanism for annotations or attributes except
for doc-comments.
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 3:27 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:
So, is it possible to use annotations for defining such metadata on
engine-level? This will be a good way to do this and to define custom
handlers via AST hooks, that can be able to patch method definition node
with concrete opcodes.2015-02-05 15:24 GMT+03:00 Alexander Lisachenko lisachenko.it@gmail.com:
Hello, internals!
From my point of view, contracts should not affect execution of source
code in production env, or can be enabled partially. I have implemented DbC
paradigm on top of the AOP layer, so each contract can be defined via
annotation and looks pretty nice, for example :use PhpDeal\Annotation as Contract;
/**
Simple trade account class
@Contract\Invariant("$this->balance > 0")
*/
class Account implements AccountContract
{/**
- Current balance
- @var float
*/
protected $balance = 0.0;/**
- Deposits fixed amount of money to the account
- @param float $amount
- @Contract\Verify("$amount>0 && is_numeric($amount)")
- @Contract\Ensure("$this->balance == $__old->balance+$amount")
*/
public function deposit($amount)
{
$this->balance += $amount;
}/**
- Returns current balance
- @Contract\Ensure("$__result == $this->balance")
- @return float
*/
public function getBalance()
{
return $this->balance;
}
}All contracts (verify|ensure) are enforced only when DbC is enabled and
doesn't have an impact on execution for production mode. Moreover, all
annotations are parsed only once, decorators are generated too, so overhead
is minimal even for debug mode. Engine takes care to insert appropriate
before/around checks via an aspect
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.phpHere is a simple snippet of pointcut definition and advice body:
/** * Verifies pre-condition contract for the method * * @param MethodInvocation $invocation * @Before("@annotation(PhpDeal\Annotation\Verify)") * * @throws ContractViolation */ public function preConditionContract(MethodInvocation $invocation) { $object = $invocation->getThis(); $args = $this->getMethodArguments($invocation); $scope = $invocation->getMethod()->getDeclaringClass()->name; foreach ($invocation->getMethod()->getAnnotations() as $annotation) { if (!$annotation instanceof Contract\Verify) { continue; } if (!$this->isContractSatisfied($object, $scope, $args, $annotation)) { throw new ContractViolation($invocation, $annotation->value); }; } }
2015-02-05 15:13 GMT+03:00 Patrick Schaaf php@bof.de:
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}This way, no new reserved words are needed at all, and the programmer
can give
a name to the "variable that holds the result" locally to avoid clashes
with
anything else in the function.I'm a bit undecided whether returning true/false there to give the
verdict,
would be the best way. Maybe better would be another use for declare,
without
a block, to declare that the pre/postcondition failed - giving a nice
place to
put a suitable message, too. And again without introducing any extra
keywords:function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}best regards
Patrick
Hi Alexander,
Defining contracts through doc-comments is also possible, but this way is
not native.
On the other hand, if you already have this implemented, we may just reuse
it.
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 3:24 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:
Hello, internals!
From my point of view, contracts should not affect execution of source
code in production env, or can be enabled partially. I have implemented DbC
paradigm on top of the AOP layer, so each contract can be defined via
annotation and looks pretty nice, for example :use PhpDeal\Annotation as Contract;
/**
Simple trade account class
@Contract\Invariant("$this->balance > 0")
*/
class Account implements AccountContract
{/**
- Current balance
- @var float
*/
protected $balance = 0.0;/**
- Deposits fixed amount of money to the account
- @param float $amount
- @Contract\Verify("$amount>0 && is_numeric($amount)")
- @Contract\Ensure("$this->balance == $__old->balance+$amount")
*/
public function deposit($amount)
{
$this->balance += $amount;
}/**
- Returns current balance
- @Contract\Ensure("$__result == $this->balance")
- @return float
*/
public function getBalance()
{
return $this->balance;
}
}All contracts (verify|ensure) are enforced only when DbC is enabled and
doesn't have an impact on execution for production mode. Moreover, all
annotations are parsed only once, decorators are generated too, so overhead
is minimal even for debug mode. Engine takes care to insert appropriate
before/around checks via an aspect
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.phpHere is a simple snippet of pointcut definition and advice body:
/** * Verifies pre-condition contract for the method * * @param MethodInvocation $invocation * @Before("@annotation(PhpDeal\Annotation\Verify)") * * @throws ContractViolation */ public function preConditionContract(MethodInvocation $invocation) { $object = $invocation->getThis(); $args = $this->getMethodArguments($invocation); $scope = $invocation->getMethod()->getDeclaringClass()->name; foreach ($invocation->getMethod()->getAnnotations() as $annotation) { if (!$annotation instanceof Contract\Verify) { continue; } if (!$this->isContractSatisfied($object, $scope, $args, $annotation)) { throw new ContractViolation($invocation, $annotation->value); }; } }
2015-02-05 15:13 GMT+03:00 Patrick Schaaf php@bof.de:
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}This way, no new reserved words are needed at all, and the programmer can
give
a name to the "variable that holds the result" locally to avoid clashes
with
anything else in the function.I'm a bit undecided whether returning true/false there to give the
verdict,
would be the best way. Maybe better would be another use for declare,
without
a block, to declare that the pre/postcondition failed - giving a nice
place to
put a suitable message, too. And again without introducing any extra
keywords:function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}best regards
Patrick
2015-02-05 15:32 GMT+03:00 Dmitry Stogov dmitry@zend.com:
Hi Alexander,
Defining contracts through doc-comments is also possible, but this way is
not native.
On the other hand, if you already have this implemented, we may just reuse
it.
Thanks, Dmitry! This would be a really nice feature on engine-level.
Ideally, for PHP7-8, I would like to see a hook system from compile-level
to userland, to define a language extension. This feature is highly
required for custom DSLs and much more. DbC technique can be also
implemented as parse-time weaver. E.g. we define a parser-extension:
register_parser_extension(ContractExtension::class);
this class will receive an AST of PHP file and check interesting nodes.
This node can be annotation or something else:
[Contract::Invariant => $this->value > 0]
class Test {
public $value = 100;
public function foo($newValue) {
$this->value = $newValue;
}
}
and parser extension change the compiled source code by inserting this
check into methods:
[Contract::Invariant => $this->value > 0]
class Test {
public $value = 100;
public function foo($newValue) {
$this->value = $newValue;
assert($this->value > 0); // Inserted by parser extension (via
opcodes)
}
}
Is it possible to do this?
At this moment, I don't have any plans related to implementation of
hook-able compiler.
However the first step was already done, introducing "zend_ast_process"
callback.
In general it's should be possible to provide PHP API to manipulate with
AST and write compiler extensions in PHP.
Looks promising.. :)
Anyway, If you are interested - start working on it.
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 3:42 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:
2015-02-05 15:32 GMT+03:00 Dmitry Stogov dmitry@zend.com:
Hi Alexander,
Defining contracts through doc-comments is also possible, but this way is
not native.
On the other hand, if you already have this implemented, we may just
reuse it.Thanks, Dmitry! This would be a really nice feature on engine-level.
Ideally, for PHP7-8, I would like to see a hook system from compile-level
to userland, to define a language extension. This feature is highly
required for custom DSLs and much more. DbC technique can be also
implemented as parse-time weaver. E.g. we define a parser-extension:register_parser_extension(ContractExtension::class);
this class will receive an AST of PHP file and check interesting nodes.
This node can be annotation or something else:[Contract::Invariant => $this->value > 0]
class Test {
public $value = 100;
public function foo($newValue) {
$this->value = $newValue;
}
}and parser extension change the compiled source code by inserting this
check into methods:[Contract::Invariant => $this->value > 0]
class Test {
public $value = 100;
public function foo($newValue) {
$this->value = $newValue;
assert($this->value > 0); // Inserted by parser extension (via
opcodes)
}
}Is it possible to do this?
2015-02-05 16:07 GMT+03:00 Dmitry Stogov dmitry@zend.com:
In general it's should be possible to provide PHP API to manipulate with
AST and write compiler extensions in PHP.
Looks promising.. :)
Anyway, If you are interested - start working on it.
Actually, it's almost done by Nikita Popov: https://github.com/nikic/php-ast.
Missing part is to put this extension into PHP core, create an interface
for hooks and then give PHP hooks a control during parsing of source code.
So maybe just make a vote to include this API into core? This will give a
lot of food for thoughts and implementations of AOP, DbC, SQL-like native
syntax and much more. From PHP Core developers it will be only the
implementation, all other things can be easily extended by userland
developers.
php-ast is not almost the same, but it may be extended.
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 4:34 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:
2015-02-05 16:07 GMT+03:00 Dmitry Stogov dmitry@zend.com:
In general it's should be possible to provide PHP API to manipulate with
AST and write compiler extensions in PHP.
Looks promising.. :)
Anyway, If you are interested - start working on it.Actually, it's almost done by Nikita Popov:
https://github.com/nikic/php-ast. Missing part is to put this extension
into PHP core, create an interface for hooks and then give PHP hooks a
control during parsing of source code.So maybe just make a vote to include this API into core? This will give a
lot of food for thoughts and implementations of AOP, DbC, SQL-like native
syntax and much more. From PHP Core developers it will be only the
implementation, all other things can be easily extended by userland
developers.
this way we would able to use in constraints any statements.
The require/ensure syntax was limited to expressions (to limit users in
making side effects).
May be we may reuse delare() a bit differently.
function foo() {
declare(pre=<input-constraint>)
declare(post=<output-constraint>)
{
}
However. I like require/ensure more.
Thanks. Dmitry.
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}This way, no new reserved words are needed at all, and the programmer can
give
a name to the "variable that holds the result" locally to avoid clashes
with
anything else in the function.I'm a bit undecided whether returning true/false there to give the verdict,
would be the best way. Maybe better would be another use for declare,
without
a block, to declare that the pre/postcondition failed - giving a nice
place to
put a suitable message, too. And again without introducing any extra
keywords:function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}best regards
Patrick
Hi Patrick,
On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:function foo() {
declare(pre) {
if (whatever...) return false;
// arbitrary PHP code
}
declare(post=$resultvar) {
if ($resultvar == XXX) return true;
return false;
}
}This way, no new reserved words are needed at all, and the programmer can
give
a name to the "variable that holds the result" locally to avoid clashes
with
anything else in the function.I'm a bit undecided whether returning true/false there to give the verdict,
would be the best way. Maybe better would be another use for declare,
without
a block, to declare that the pre/postcondition failed - giving a nice
place to
put a suitable message, too. And again without introducing any extra
keywords:function foo() {
declare(post=$resultvar) {
if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
}
}
The idea of "declare(post=$resultvar)" seems interesting, even though
post=$resulvar
looks wired.
$resultvar is L value, but it's located as R value.
There may be better syntax.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Dmitry,
De : Dmitry Stogov [mailto:dmitry@zend.com]
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:
Please have a look at https://wiki.php.net/rfc/dbc, just the beginning, up to 'Pre-conditions'. It contains 2 examples. This is not D syntax, while functionally similar, because I want to preserve BC and provide built-in checks on phpdoc declared types.
Cheers
François
Yeah, this may work.
The only problem, that it looks not native and defines additional language
for constraints.
I don't talk it's wrong. Both approaches may make sense, but of course, we
have to select one.
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 4:19 PM, François Laupretre francois@tekwire.net
wrote:
Hi Dmitry,
De : Dmitry Stogov [mailto:dmitry@zend.com]
Following our conversation, I tried to imagine how DbC should look like
in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:Please have a look at https://wiki.php.net/rfc/dbc, just the beginning,
up to 'Pre-conditions'. It contains 2 examples. This is not D syntax, while
functionally similar, because I want to preserve BC and provide built-in
checks on phpdoc declared types.Cheers
François
De : Dmitry Stogov [mailto:dmitry@zend.com]
Yeah, this may work.
The only problem, that it looks not native and defines additional language for constraints.
I don't talk it's wrong. Both approaches may make sense, but of course, we have to select one.
Yes, it makes phpdoc more tied to the engine but is it a problem ?
I think BC is essential here. If people need to write PHP7-specific code, we'll loose them.
And remember : we already have tons of code with documented argument/return types ready for DbC checks.
François
De : Dmitry Stogov [mailto:dmitry@zend.com]
Yeah, this may work.
The only problem, that it looks not native and defines additional
language for constraints.
I don't talk it's wrong. Both approaches may make sense, but of course,
we have to select one.Yes, it makes phpdoc more tied to the engine but is it a problem ?
And here I have to jump in and say: don't.
And remind about one of the exact purposes of annotations.
Hi all,
De : Dmitry Stogov [mailto:dmitry@zend.com]
Yeah, this may work.
The only problem, that it looks not native and defines additional
language for constraints.
I don't talk it's wrong. Both approaches may make sense, but of
course, we have to select one.Yes, it makes phpdoc more tied to the engine but is it a problem ?
And here I have to jump in and say: don't.
And remind about one of the exact purposes of annotations.
We don't have to integrate DbC into phpdoc. phpdoc may have integration of
new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as document.
There are too many possibility for DbC syntax.
We are better to choose something in common among languages.
All of us understand why DbC is good for weakly typed PHP especially, don't
we?
Let's concentrate we have clean syntax for DbC.
Dmitry's idea is good enough. IMHO. But if you have better one, it should
be written on
this thread now and discuss.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo Ohgaki
We don't have to integrate DbC into phpdoc. phpdoc may have integration of new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as document.There are too many possibility for DbC syntax.
We are better to choose something in common among languages.
No. The more I detail the concept, the more I read alternative proposals, the more I consider extending phpdoc is the best solution. As I explain in the RFC, both concepts are closely related, and that's the only solution I've seen so far that preserves BC. I could add that it proposes a solution to issues not even detected nor discussed in alternative proposals, like the syntax for return value, separate check for arguments returned by ref, built-in type checks, etc. Before we choose an alternative syntax, I think we should have good reasons, not 'Hey, that's how it's done in D !'. If there's a good reason to copy D or Eiffel syntax, let's adopt it, but I haven't read any good reason so far. And D is not so widely used so there's no user habit. We can copy the concept without copying the syntax.
I think we're going too fast here. Before giving up and switching to another syntax, can you give me a little time to present what I have in mind. I started writing it yesterday evening and it will be ready tomorrow morning (UTC). Then, we can make a decision.
Cheers
François
Hi Francois,
On Fri, Feb 6, 2015 at 1:11 AM, François Laupretre francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiWe don't have to integrate DbC into phpdoc. phpdoc may have integration
of new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as
document.There are too many possibility for DbC syntax.
We are better to choose something in common among languages.No. The more I detail the concept, the more I read alternative proposals,
the more I consider extending phpdoc is the best solution. As I explain in
the RFC, both concepts are closely related, and that's the only solution
I've seen so far that preserves BC. I could add that it proposes a solution
to issues not even detected nor discussed in alternative proposals, like
the syntax for return value, separate check for arguments returned by ref,
built-in type checks, etc. Before we choose an alternative syntax, I think
we should have good reasons, not 'Hey, that's how it's done in D !'. If
there's a good reason to copy D or Eiffel syntax, let's adopt it, but I
haven't read any good reason so far. And D is not so widely used so there's
no user habit. We can copy the concept without copying the syntax.I think we're going too fast here. Before giving up and switching to
another syntax, can you give me a little time to present what I have in
mind. I started writing it yesterday evening and it will be ready tomorrow
morning (UTC). Then, we can make a decision.
I didn't notice you have updated the RFC sorry. Sure, I'll read it and
respond.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Francois,
On Fri, Feb 6, 2015 at 1:11 AM, François Laupretre francois@tekwire.net
wrote:De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiWe don't have to integrate DbC into phpdoc. phpdoc may have integration
of new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as
document.There are too many possibility for DbC syntax.
We are better to choose something in common among languages.No. The more I detail the concept, the more I read alternative proposals,
the more I consider extending phpdoc is the best solution. As I explain in
the RFC, both concepts are closely related, and that's the only solution
I've seen so far that preserves BC. I could add that it proposes a solution
to issues not even detected nor discussed in alternative proposals, like
the syntax for return value, separate check for arguments returned by ref,
built-in type checks, etc. Before we choose an alternative syntax, I think
we should have good reasons, not 'Hey, that's how it's done in D !'. If
there's a good reason to copy D or Eiffel syntax, let's adopt it, but I
haven't read any good reason so far. And D is not so widely used so there's
no user habit. We can copy the concept without copying the syntax.I think we're going too fast here. Before giving up and switching to
another syntax, can you give me a little time to present what I have in
mind. I started writing it yesterday evening and it will be ready
tomorrow morning (UTC). Then, we can make a decision.I didn't notice you have updated the RFC sorry. Sure, I'll read it and
respond.
Thank you for your time. It's based on annotation approach. This kind of
implementation requires a lot of work...
I have more simpler approach in my mind based on current PHP language
not to invent new language. I'll use syntax something similar to Dmitry
proposed.
Let me explain my original thought.
Since we have reserved __functionname(), __some_functioname() should not
have
BC issues.
function foo($param)
require ( // Compiled as __require_foo($param)
// Any PHP code is allowed and works just like PHP function.
// Abuse is possible. Users have freedom shoot their own foot.
assert('is_string($param');
if (strlen($param) > 100) {
echo "String is more than 100\n";
return FALSE; // return value is ignored.
}
)
ensure ( // Compiled as __ensure_foo($__return_value)
// Same as require. Any PHP code
assert('is_int($__return_value)'); // $__return_value is the return value
assert($__return_value > 0);
)
invariant ( // Check conditions always true. It may be __invariant_foo()
// Question is should this have foo() scope?
// Same as require/ensure. Any PHP code.
// invariant() exists not to repeat require()/ensure()
)
// Function body
{
// BODY
}
Zend engine has 2 execute()
- execute() - Just execute foo()
- execute_dev() - Call functions as follows
__require_foo($param)
__invariant()
foo()
__invariant()
__ensure_foo($__return_value)
With this approach, parser and compiler needs little modification and
execute_dev() can handle additional functions while execute() only
executes foo(). execute_dev() is simple because it just calls plain PHP
functions if they exists.
Is there is syntax error or assertion error. Error messages look like
PHP Warning: assert()
: asdfasdf failed in __require_foo() on line 2
This is simple yet useful/easy to use/powerful/flexible/fast.
Any checks can be done with PHP syntax. I think assert()
should be used
usually, though.
I thought to use require{} rather than require() because {} seemed
natural for function.
This is my thought. It's almost D.
I don't know about AST much, so AST may be better/easier than having
2 execute().
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Is there is syntax error or assertion error. Error messages look like
I mean
If there is syntax error...
--
Yasuo Ohgaki
yohgaki@ohgaki.net
__invariant()
Oops
__invariant_before_foo()
__invariant_after_foo()
There are other bad english. I should spend more time to check. Sorry.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
If we allow any statements in require/ensure, then we should use {} instead
of()
function foo($a, $b)
reuire {
...
}
ensure($ret) {
...
}
{
}
my idea was to restrict constraint code to expression.
in this case () would be enough.
it should be possible to use few constraint expressions.
we may also add error messages like in assert()
.
function add($a, $b)
require(is_numeric($a) && $a >= 0, "some error message")
require(is_numerc($b) && $b >= 0, "another error message")
ensure($ret >= 0, "yet another error message)
{
return $a + $b;
}
both proposals may work, of course.
I don't think we should chose "right" approach right now.
It's better to collect few possible solutions e.g. statements, expressions,
doc-comments, attributes...
then describe their pros and cons to select the best one
Thanks. Dmitry.
Thanks. Dmitry.
Hi Francois,
On Fri, Feb 6, 2015 at 1:11 AM, François Laupretre francois@tekwire.net
wrote:De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiWe don't have to integrate DbC into phpdoc. phpdoc may have
integration of new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as
document.There are too many possibility for DbC syntax.
We are better to choose something in common among languages.No. The more I detail the concept, the more I read alternative
proposals, the more I consider extending phpdoc is the best solution. As I
explain in the RFC, both concepts are closely related, and that's the only
solution I've seen so far that preserves BC. I could add that it proposes a
solution to issues not even detected nor discussed in alternative
proposals, like the syntax for return value, separate check for arguments
returned by ref, built-in type checks, etc. Before we choose an alternative
syntax, I think we should have good reasons, not 'Hey, that's how it's done
in D !'. If there's a good reason to copy D or Eiffel syntax, let's adopt
it, but I haven't read any good reason so far. And D is not so widely used
so there's no user habit. We can copy the concept without copying the
syntax.I think we're going too fast here. Before giving up and switching to
another syntax, can you give me a little time to present what I have in
mind. I started writing it yesterday evening and it will be ready
tomorrow morning (UTC). Then, we can make a decision.I didn't notice you have updated the RFC sorry. Sure, I'll read it and
respond.Thank you for your time. It's based on annotation approach. This kind of
implementation requires a lot of work...I have more simpler approach in my mind based on current PHP language
not to invent new language. I'll use syntax something similar to Dmitry
proposed.Let me explain my original thought.
Since we have reserved __functionname(), __some_functioname() should not
have
BC issues.function foo($param)
require ( // Compiled as __require_foo($param)
// Any PHP code is allowed and works just like PHP function.
// Abuse is possible. Users have freedom shoot their own foot.
assert('is_string($param');
if (strlen($param) > 100) {
echo "String is more than 100\n";
return FALSE; // return value is ignored.
}
)
ensure ( // Compiled as __ensure_foo($__return_value)
// Same as require. Any PHP code
assert('is_int($__return_value)'); // $__return_value is the return value
assert($__return_value > 0);
)
invariant ( // Check conditions always true. It may be __invariant_foo()
// Question is should this have foo() scope?
// Same as require/ensure. Any PHP code.
// invariant() exists not to repeat require()/ensure()
)
// Function body
{
// BODY
}Zend engine has 2 execute()
- execute() - Just execute foo()
- execute_dev() - Call functions as follows
__require_foo($param)
__invariant()
foo()
__invariant()
__ensure_foo($__return_value)With this approach, parser and compiler needs little modification and
execute_dev() can handle additional functions while execute() only
executes foo(). execute_dev() is simple because it just calls plain PHP
functions if they exists.Is there is syntax error or assertion error. Error messages look like
PHP Warning:
assert()
: asdfasdf failed in __require_foo() on line 2This is simple yet useful/easy to use/powerful/flexible/fast.
Any checks can be done with PHP syntax. I thinkassert()
should be used
usually, though.I thought to use require{} rather than require() because {} seemed
natural for function.This is my thought. It's almost D.
I don't know about AST much, so AST may be better/easier than having
2 execute().Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Dmitry,
I don't think we should chose "right" approach right now.
It's better to collect few possible solutions e.g. statements,
expressions, doc-comments, attributes...
then describe their pros and cons to select the best one
I agree.
ensure($ret) {}
is better than my original thought.
I don't object to restrict pre/post conditions to expressions.
require(is_numeric($a) && $a >= 0, "some error message")
require(is_numerc($b) && $b >= 0, "another error message")
this requires less lines and meaning is clear. For parsers other than PHP
require {
assert(is_numeric($a) && $a >= 0, "some error message")
assert(is_numerc($b) && $b >= 0, "another error message")
}
may be a little easy to parse. Even if it is, it's marginal.
Allowing any PHP syntax would require other parsers complex parsing.
Those who would like to get pre/post conditions, it's time to think how
it looks like including reflection. Restricting pre/post conditions to
assert expressions may yield clean result. AST would be handy.
Reflection is not too important, since pre/post conditions are for
development. It may be okay to reflect existence of pre/post conditions.
These conditions does not exists in production anyway. I'm not sure it's
worth to support reflection. Rather than reflection, user space AST browser
could be more useful.
IMHO, E_WARNING
is good enough.
If anyone would like to 'throw' exceptions, it's time to think, too.
These are my random thoughts.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Dmitry,
I don't think we should chose "right" approach right now.
It's better to collect few possible solutions e.g. statements,
expressions, doc-comments, attributes...
then describe their pros and cons to select the best oneI agree.
ensure($ret) {}
is better than my original thought.
I don't object to restrict pre/post conditions to expressions.require(is_numeric($a) && $a >= 0, "some error message")
require(is_numerc($b) && $b >= 0, "another error message")this requires less lines and meaning is clear. For parsers other than PHP
require {
assert(is_numeric($a) && $a >= 0, "some error message")
assert(is_numerc($b) && $b >= 0, "another error message")
}may be a little easy to parse. Even if it is, it's marginal.
Allowing any PHP syntax would require other parsers complex parsing.
Those who would like to get pre/post conditions, it's time to think how
it looks like including reflection. Restricting pre/post conditions to
assert expressions may yield clean result. AST would be handy.
I think it should not be a big problem extending parser to support
require/ensure syntax.
AST is going to be really helpful :)
Compilation is not going to be trivial but it's solvable.
Reflection is not too important, since pre/post conditions are for
development. It may be okay to reflect existence of pre/post conditions.
These conditions does not exists in production anyway. I'm not sure it's
worth to support reflection. Rather than reflection, user space AST browser
could be more useful.IMHO,
E_WARNING
is good enough.
If anyone would like to 'throw' exceptions, it's time to think, too.
We may relay on assert()
behavior. Depending on some setting it may emit
error or throw exception.
Thanks. Dmtiry.
These are my random thoughts.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo Ohgaki
Thank you for your time. It's based on annotation approach. This kind of
implementation requires a lot of work...
I have an idea of a way to do it with limited work. Most important, everything would be in an extension and would require no change in the PHP engine.
I have more simpler approach in my mind based on current PHP language
not to invent new language. I'll use syntax something similar to Dmitry proposed.Let me explain my original thought.
Since we have reserved __functionname(), __some_functioname() should not have
BC issues.
I understand your proposal but I repeat the same from the beginning : once modified, your code cannot run in PHP 5 anymore (especially if you use 'require'). The (huge) BC break is there, not in the fact that we use a hidden reserved function name.
Additionnally :
-
that's a detail but I find that 'require' and 'ensure' are less intuitive that 'in' and 'out'.
-
invariants are for classes, not functions. Which syntax would you use ?
-
I insist on the importance of checking 'smart' built-in phpdoc types because, unfortunately, in PHP, most is_xxx() functions don't do what the user would intuitively expect. Starting with is_int('123') returning false, while '123' is a correct int argument value. The RFC will include a table of 'restricted' type juggling explaining the rules to match phpdoc types with zval type/value.
Cheers
François
This is just a brainstorming, and we are not going to provide a working
solution tomorrow :)
You have enough time :)
I don't like phpdoc approach because we have to define, parse and compile
new syntax for constraints.
Would constraint be able to call other functions? include external php
files? etc?
For me it's an overhead. We may reuse PHP syntax.
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 7:11 PM, François Laupretre francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiWe don't have to integrate DbC into phpdoc. phpdoc may have integration
of new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as
document.There are too many possibility for DbC syntax.
We are better to choose something in common among languages.No. The more I detail the concept, the more I read alternative proposals,
the more I consider extending phpdoc is the best solution. As I explain in
the RFC, both concepts are closely related, and that's the only solution
I've seen so far that preserves BC. I could add that it proposes a solution
to issues not even detected nor discussed in alternative proposals, like
the syntax for return value, separate check for arguments returned by ref,
built-in type checks, etc. Before we choose an alternative syntax, I think
we should have good reasons, not 'Hey, that's how it's done in D !'. If
there's a good reason to copy D or Eiffel syntax, let's adopt it, but I
haven't read any good reason so far. And D is not so widely used so there's
no user habit. We can copy the concept without copying the syntax.I think we're going too fast here. Before giving up and switching to
another syntax, can you give me a little time to present what I have in
mind. I started writing it yesterday evening and it will be ready tomorrow
morning (UTC). Then, we can make a decision.Cheers
François
De : Dmitry Stogov [mailto:dmitry@zend.com]
I don't like phpdoc approach because we have to define, parse and compile new syntax for constraints.
Would constraint be able to call other functions? include external php files? etc?
There are 2 sort of constraints :
-
declared types with a specific, while very intuitive, syntax (support for every current type found in phpdoc will be provided). These types will be sent as plain strings along with the corresponding zval argument to an internal validator function. This is a valuable addition compared to the DbC basic conditions. I gave the example of
str_replace()
whose search argument would have a type like 'string|array(string)'. Do you think that, if we implement such a check in PHP in an in{} block, it will be as readable ? I don't think so. OK, it is an addition to what other languages implement but, if we implement something easier and more readable, the concept is still valid. -
and assertions. An assertion line just contains a PHP expression to evaluate. No new syntax here, expression can do
anything, like calling an external validator function. The condition would be executed in the function scope, so it would have access to anything accessible from the function body. Exactly the same as what we would do with in/out{} blocks.
In my opinion, as I previously explained, constraints shouldn't be parsed by the PHP engine, but by a pre-processor which would run before any other action takes place. This pre-processor would insert some PHP code where it is needed. Then, the script would be compiled but the engine doesn't have to be concerned.
Cheers
François
This is just a brainstorming, and we are not going to provide a working
solution tomorrow :)
You have enough time :)I don't like phpdoc approach because we have to define, parse and compile
new syntax for constraints.
Would constraint be able to call other functions? include external php
files? etc?
For me it's an overhead. We may reuse PHP syntax.
Last time we discussed annotation a syntax reusing PHP short syntax
for array came up. To keep it as simple as possible and let the
application deals with the contents. It sounds like a good compromise
and flexible enough.
A possible key point is also the ability to use them while using the
same source for both 5.x and 7.x. Not sure it is technically possible
but this is something to keep in mind.
Just a thought: may be we can reuse part of PHP syntax and ask standard PHP
parser to do the work and provide AST.
<<requre(PHP_EXPRESSION)>>
<<weight(PHP_NUMBER)>>
I don't know if it's possible to implement...
Thanks. Dmitry.
This is just a brainstorming, and we are not going to provide a working
solution tomorrow :)
You have enough time :)I don't like phpdoc approach because we have to define, parse and compile
new syntax for constraints.
Would constraint be able to call other functions? include external php
files? etc?
For me it's an overhead. We may reuse PHP syntax.Last time we discussed annotation a syntax reusing PHP short syntax
for array came up. To keep it as simple as possible and let the
application deals with the contents. It sounds like a good compromise
and flexible enough.A possible key point is also the ability to use them while using the
same source for both 5.x and 7.x. Not sure it is technically possible
but this is something to keep in mind.
De : Pierre Joye [mailto:pierre.php@gmail.com]
Yes, it makes phpdoc more tied to the engine but is it a problem ?
And here I have to jump in and say: don't.
And remind about one of the exact purposes of annotations.
Sorry, I am not sure I understand.
If you're talking about the link between the engine and phpdoc comments, I agree. It is not a job for the PHP engine. It is a job for a script pre-processor, contained in an extension, and called BEFORE the file starts to be parsed by the engine, not after the AST is generated. It is very easy to pre-process PHP scripts and insert PHP code for DbC checks, while doing the same using an AST and generated opcodes looks much harder to me.
As I told Alexander, in my opinion, phpdoc blocks already provide a lot of useful DbC information. My objective is to extend the syntax to support more complex directives, which are still legitimate phpdoc information. I see both concepts as closely related. One is generating documentation, one is generating runtime checks, but both use the same information.
About annotations, I don't know much about it, as I was naively thinking that phpdoc '@' directives were annotations, but I understand I was probably wrong. The only concern I have about introducing a new annotation syntax is BC break.
Cheers
François
phpdoc is annotation as well, but to split it into specific attributes we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.
http://docs.hhvm.com/manual/en/hack.attributes.php
Thanks. Dmitry.
On Thu, Feb 5, 2015 at 6:40 PM, François Laupretre francois@tekwire.net
wrote:
De : Pierre Joye [mailto:pierre.php@gmail.com]
Yes, it makes phpdoc more tied to the engine but is it a problem ?
And here I have to jump in and say: don't.
And remind about one of the exact purposes of annotations.Sorry, I am not sure I understand.
If you're talking about the link between the engine and phpdoc comments, I
agree. It is not a job for the PHP engine. It is a job for a script
pre-processor, contained in an extension, and called BEFORE the file starts
to be parsed by the engine, not after the AST is generated. It is very easy
to pre-process PHP scripts and insert PHP code for DbC checks, while doing
the same using an AST and generated opcodes looks much harder to me.As I told Alexander, in my opinion, phpdoc blocks already provide a lot of
useful DbC information. My objective is to extend the syntax to support
more complex directives, which are still legitimate phpdoc information. I
see both concepts as closely related. One is generating documentation, one
is generating runtime checks, but both use the same information.About annotations, I don't know much about it, as I was naively thinking
that phpdoc '@' directives were annotations, but I understand I was
probably wrong. The only concern I have about introducing a new annotation
syntax is BC break.Cheers
François
phpdoc is annotation as well, but to split it into specific attributes we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.
Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.
--
Pierre
@pierrejoye | http://www.libgd.org
Hi all,
I already said before and I'm happy to say it again...
Whenever you feel ready to get true, complete Annotations into core, just
tell me and I'll be ready to work on previously suggested Annotations in
sync with current internals.
Cheers,
phpdoc is annotation as well, but to split it into specific attributes we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.--
Pierre@pierrejoye | http://www.libgd.org
--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
On Fri, Feb 6, 2015 at 11:08 AM, guilhermeblanco@gmail.com
guilhermeblanco@gmail.com wrote:
Hi all,
I already said before and I'm happy to say it again...
Whenever you feel ready to get true, complete Annotations into core, just
tell me and I'll be ready to work on previously suggested Annotations in
sync with current internals.
We are, with the simplified syntax we discussed last time (have to dig
the archive)
Cheers,
phpdoc is annotation as well, but to split it into specific attributes
we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.--
Pierre@pierrejoye | http://www.libgd.org
--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
--
Pierre
@pierrejoye | http://www.libgd.org
Hi Pierre,
Sorry, but you don't. Proposing a simple syntax is the same as not
proposing it.
We can do whatever syntax is proposed, but we need to discuss on how to
handle inheritance, overriding, etc.
None ever discussed that. 2010's patch handled all that nicely. I do
remember however Dmitry had a suggestion to optimize the overall storage of
annotation values, but it got lost in time. I somehow remember he wanted to
store a cached version of reflection class into the class entry and expose
as Class::CLASS or something... I saw this written in another place too...
it got slightly changed over time and we now have it return only its FQCN.
[]s,
On Fri, Feb 6, 2015 at 11:08 AM, guilhermeblanco@gmail.com
guilhermeblanco@gmail.com wrote:Hi all,
I already said before and I'm happy to say it again...
Whenever you feel ready to get true, complete Annotations into core, just
tell me and I'll be ready to work on previously suggested Annotations in
sync with current internals.We are, with the simplified syntax we discussed last time (have to dig
the archive)Cheers,
On Thu, Feb 5, 2015 at 11:00 PM, Pierre Joye pierre.php@gmail.com
wrote:phpdoc is annotation as well, but to split it into specific attributes
we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.--
Pierre@pierrejoye | http://www.libgd.org
--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada--
Pierre@pierrejoye | http://www.libgd.org
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
On Fri, Feb 6, 2015 at 11:14 AM, guilhermeblanco@gmail.com
guilhermeblanco@gmail.com wrote:
Hi Pierre,
Sorry, but you don't. Proposing a simple syntax is the same as not proposing
it.
We can do whatever syntax is proposed, but we need to discuss on how to
handle inheritance, overriding, etc.
None ever discussed that. 2010's patch handled all that nicely. I do
remember however Dmitry had a suggestion to optimize the overall storage of
annotation values, but it got lost in time. I somehow remember he wanted to
store a cached version of reflection class into the class entry and expose
as Class::CLASS or something... I saw this written in another place too...
it got slightly changed over time and we now have it return only its FQCN.
Benjamin proposed it and I think it is a good compromise, it can then
evolve if necessary or desired.
Hi,
do you have a link to old proposal and/or implementation?
Thanks. Dmitry.
On Fri, Feb 6, 2015 at 7:08 AM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Hi all,
I already said before and I'm happy to say it again...
Whenever you feel ready to get true, complete Annotations into core, just
tell me and I'll be ready to work on previously suggested Annotations in
sync with current internals.Cheers,
phpdoc is annotation as well, but to split it into specific attributes
we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.--
Pierre@pierrejoye | http://www.libgd.org
--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
phpdoc is annotation as well, but to split it into specific attributes we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.http://docs.hhvm.com/manual/en/hack.attributes.php
Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.
Exact. Annotations !== comments. Because PHP has no annotation system,
we used to use comments for this purpose, but it's a workaround.
De : Ivan Enderlin @ Hoa [mailto:ivan.enderlin@hoa-project.net]
Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.
Exact. Annotations !== comments. Because PHP has no annotation system,
we used to use comments for this purpose, but it's a workaround.
It seems this discussion about DbC cannot remain on the DbC subject itself. Some claim we shouldn't add DbC because it would require a 'new language' (I don't see where...). Now, the discussion is about annotations, which are another subject as we don't need this to implement DbC. Well, annotations would be nice, but I won't wait for annotations to propose DbC !
What we need is to make an extension able to get control from the engine in 3 locations :
-
when a script file is read, before any parsing takes place. The file won't be modified but the extension will use that to read and internalize the constraints associated with the different script elements.
-
When a method or function is called, after arguments are received, and before the function body is executed. There, we will execute the pre-conditions.
-
Just after function return, but still in the function scope. There we will execute post-conditions.
Class conditions (invariants) are added to pre/post-conditions when appropriate.
Maybe this is already possible from a Zend extension, I don't know. But, even some of these hooks don't exist yet, they shouldn't be that hard to implement.
François
annotations might be useful for DbC, but I doubt if they are more readable.
<<reguire(is_numeric($a) && $a > 0)>>
<<reguire(is_numeric($b) && $b > 0)>>
<<ensure($ret > 0)>>
function foo ($a, $b) {
return $a + $b;
}
Also, to use them, we will have to develop them first (not a trivial task
as well), but may be this is a right road.
Thanks. Dmitry.
phpdoc is annotation as well, but to split it into specific attributes we
have to write specialized parsers.
Other languages support annotation or attributes that may be used more
easily.Exactly, phpdoc is used as annotation (or comments with some similar
syntax) but is definitively not aimed to be annotations.--
Pierre@pierrejoye | http://www.libgd.org
Hi Internal :-),
I just would like to point out some stuff.
tl;dr: Contracts can be used to validate code (Design-by-Contract) or
generate test data to validate code (Contract-based Testing). There are
plenty of contract languages in the wild, each one addresses a specific
problem (object, structured type, temporal logic, scenario etc.). If we
try to develop a contract language, IT WILL FAIL, I guarantee it.
The solution is to give tools to developers to ease the use of
contracts, for example with Aspect Oriented Programming.
There is a whole research PhD thesis about Contract-based Testing in
PHP, which includes Design-by-Contract, automatic generation of complex
test data and automatic generation of test suites:
https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf.
Unfortunately, the thesis is in French but research articles are in
English. You can found them here
(http://hoa-project.net/En/Literature.html#Research):
- Praspel: A Specification Language for Contract-Driven Testing in
PHP (article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf,
keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf), - Grammar-Based Testing using Realistic Domains in PHP (article:
http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote:
http://keynote.hoa-project.net/Amost12/EDGB12.pdf), - A Constraint Solver for PHP Arrays (article:
http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote:
http://keynote.hoa-project.net/Cstva13/EGB13.pdf).
Concepts behind contracts are twofold:
- Design-by-Contract (DbC), validate code at compile time or at
runtime (in the case of PHP, it will be at runtime), - Contract-based Testing (CbT), generate test data based on
contracts. Preconditions are used to generate inputs, and postconditions
validate outputs. Invariants must hold before and after the execution of
the SUT (System Under Test, here methods and functions).
So there are two goals with contracts. We can only address validation
(DbC) or both (DbC and CbT).
From my own experience and study in this field (I am a PhD in the test
domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because
the language used to express contracts (even if we use PHP) will be too
much poor or too much inappropriate for test data validation or test
data generation (resp. DbC or CbT).
The articles listed above, in addition to the PhD thesis, present
Praspel, a specification language for PHP, based on contracts. Praspel
is used to validate and generate (test) data and test suites. This
language is inspired from JML (Java Modeling Language) and ACSL (ANSI/C
Specification Language) while addressing PHP features (weakly type for
instance). But there is a lot more languages in the wild.
Inventing another language will lead to a fail at a particular time,
believe me. Each contract language has a specificity: Handling
structured data, handling events, handling scenario (see Dwyer patterns
for temporal linear logic) etc. We CANNOT address all these needs.
However, there is a hope :-). DbC and CbT can be easily implemented with
an Aspect Oriented Programming (AOP) paradigm. Before each “method
execution”, we interpret or execute the invariants and the preconditions
expressed in the contract, the method runs and after “method execution”,
we interpret or execute the invariants and the postconditions expressed
in the contract. No need to have a specific implementation in PHP's core
for contracts.
Moreover, we can enable or disable AOP in development or production
environment, which ensures performances.
Thoughts?
Hi Yasuo,
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions (zero
cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectationsFor inherited methods, only the self <input-assert-expression> should be
checked, and all parent <output-asser-expression>. This is borrowed from D
but not necessary to be repeated exactly.I think we shouldn't introduce "invariant" constraints for classes now. May
be later.Implementation is going to generate code for input constraint after all
RECV opcodes and before code for function body, and code for output
constraint before RETURN opcode (may be reusing implementation of
"finally").See:
http://dlang.org/contracts.html
http://jan.newmarch.name/java/contracts/paper-long.htmlThanks. Dmitry.
Hi Ivan,
On Thu, Feb 5, 2015 at 11:25 PM, Ivan Enderlin @ Hoa <
ivan.enderlin@hoa-project.net> wrote:
I just would like to point out some stuff.
tl;dr: Contracts can be used to validate code (Design-by-Contract) or
generate test data to validate code (Contract-based Testing). There are
plenty of contract languages in the wild, each one addresses a specific
problem (object, structured type, temporal logic, scenario etc.). If we try
to develop a contract language, IT WILL FAIL, I guarantee it. The
solution is to give tools to developers to ease the use of contracts, for
example with Aspect Oriented Programming.There is a whole research PhD thesis about Contract-based Testing in PHP,
which includes Design-by-Contract, automatic generation of complex test
data and automatic generation of test suites:
https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf.
Unfortunately, the thesis is in French but research articles are in
English. You can found them here (http://hoa-project.net/En/
Literature.html#Research):
- Praspel: A Specification Language for Contract-Driven Testing in PHP
(article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf,
keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf),- Grammar-Based Testing using Realistic Domains in PHP (article:
http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote:
http://keynote.hoa-project.net/Amost12/EDGB12.pdf),- A Constraint Solver for PHP Arrays (article:
http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote:
http://keynote.hoa-project.net/Cstva13/EGB13.pdf).Concepts behind contracts are twofold:
- Design-by-Contract (DbC), validate code at compile time or at runtime
(in the case of PHP, it will be at runtime),- Contract-based Testing (CbT), generate test data based on contracts.
Preconditions are used to generate inputs, and postconditions validate
outputs. Invariants must hold before and after the execution of the SUT
(System Under Test, here methods and functions).So there are two goals with contracts. We can only address validation
(DbC) or both (DbC and CbT).From my own experience and study in this field (I am a PhD in the test
domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because
the language used to express contracts (even if we use PHP) will be too
much poor or too much inappropriate for test data validation or test data
generation (resp. DbC or CbT).The articles listed above, in addition to the PhD thesis, present Praspel,
a specification language for PHP, based on contracts. Praspel is used to
validate and generate (test) data and test suites. This language is
inspired from JML (Java Modeling Language) and ACSL (ANSI/C Specification
Language) while addressing PHP features (weakly type for instance). But
there is a lot more languages in the wild.
Inventing another language will lead to a fail at a particular time,
believe me. Each contract language has a specificity: Handling structured
data, handling events, handling scenario (see Dwyer patterns for temporal
linear logic) etc. We CANNOT address all these needs.However, there is a hope :-). DbC and CbT can be easily implemented with
an Aspect Oriented Programming (AOP) paradigm. Before each “method
execution”, we interpret or execute the invariants and the preconditions
expressed in the contract, the method runs and after “method execution”, we
interpret or execute the invariants and the postconditions expressed in the
contract. No need to have a specific implementation in PHP's core for
contracts.
Moreover, we can enable or disable AOP in development or production
environment, which ensures performances.
It sounds you are looking for way beyond what we discuss.
If there are contracts, program correctness may be proven by contracts, but
this kind of validation is not in scope.
If you think D like DbC support in language is wrong, could you list the
reason why it is?
Thank you.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Ivan,
Hi Yasuo :-),
On Thu, Feb 5, 2015 at 11:25 PM, Ivan Enderlin @ Hoa
<ivan.enderlin@hoa-project.net mailto:ivan.enderlin@hoa-project.net>
wrote:I just would like to point out some stuff. tl;dr: Contracts can be used to validate code (Design-by-Contract) or generate test data to validate code (Contract-based Testing). There are plenty of contract languages in the wild, each one addresses a specific problem (object, structured type, temporal logic, scenario etc.). If we try to develop a contract language, **IT WILL FAIL**, I guarantee it. The solution is to give tools to developers to ease the use of contracts, for example with Aspect Oriented Programming. There is a whole research PhD thesis about Contract-based Testing in PHP, which includes Design-by-Contract, automatic generation of complex test data and automatic generation of test suites: https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf. Unfortunately, the thesis is in French but research articles are in English. You can found them here (http://hoa-project.net/En/Literature.html#Research): * Praspel: A Specification Language for Contract-Driven Testing in PHP (article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf, keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf), * Grammar-Based Testing using Realistic Domains in PHP (article: http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote: http://keynote.hoa-project.net/Amost12/EDGB12.pdf), * A Constraint Solver for PHP Arrays (article: http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote: http://keynote.hoa-project.net/Cstva13/EGB13.pdf). Concepts behind contracts are twofold: 1. Design-by-Contract (DbC), validate code at compile time or at runtime (in the case of PHP, it will be at runtime), 2. Contract-based Testing (CbT), generate test data based on contracts. Preconditions are used to generate inputs, and postconditions validate outputs. Invariants must hold before and after the execution of the SUT (System Under Test, here methods and functions). So there are two goals with contracts. We can only address validation (DbC) or both (DbC and CbT). From my own experience and study in this field (I am a PhD in the test domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because the language used to express contracts (even if we use PHP) will be too much poor or too much inappropriate for test data validation or test data generation (resp. DbC or CbT). The articles listed above, in addition to the PhD thesis, present Praspel, a specification language for PHP, based on contracts. Praspel is used to validate and generate (test) data and test suites. This language is inspired from JML (Java Modeling Language) and ACSL (ANSI/C Specification Language) while addressing PHP features (weakly type for instance). But there is a lot more languages in the wild. Inventing another language will lead to a fail at a particular time, believe me. Each contract language has a specificity: Handling structured data, handling events, handling scenario (see Dwyer patterns for temporal linear logic) etc. We CANNOT address all these needs. However, there is a hope :-). DbC and CbT can be easily implemented with an Aspect Oriented Programming (AOP) paradigm. Before each “method execution”, we interpret or execute the invariants and the preconditions expressed in the contract, the method runs and after “method execution”, we interpret or execute the invariants and the postconditions expressed in the contract. No need to have a specific implementation in PHP's core for contracts. Moreover, we can enable or disable AOP in development or production environment, which ensures performances.
It sounds you are looking for way beyond what we discuss.
If there are contracts, program correctness may be proven by
contracts, but
this kind of validation is not in scope.
Proven? I don't dare to speak about proof here. If you would like to
execute pre-, postconditions and invariants at runtime, you need a super
language to define behaviors efficiently… and the problem is: What
behaviors? Only the data type? The order of execution of methods? The
time of execution of methods? A lot of constraints might be expressed in
contracts.
There are a lot of researches in this field. PHP has a great opportunity
to not close the doors by forcing a language. I suggest you to offer an
API to hook on the runtime and “control” it, like AOP does. It will open
the doors to so many interesting contributions!
If you think D like DbC support in language is wrong, could you list
the reason why it is?
I don't understand the question :-).
Cheers!
Hi Ivan,
On Fri, Feb 6, 2015 at 4:44 PM, Ivan Enderlin @ Hoa <
ivan.enderlin@hoa-project.net> wrote:
On Thu, Feb 5, 2015 at 11:25 PM, Ivan Enderlin @ Hoa <
ivan.enderlin@hoa-project.net> wrote:I just would like to point out some stuff.
tl;dr: Contracts can be used to validate code (Design-by-Contract) or
generate test data to validate code (Contract-based Testing). There are
plenty of contract languages in the wild, each one addresses a specific
problem (object, structured type, temporal logic, scenario etc.). If we try
to develop a contract language, IT WILL FAIL, I guarantee it. The
solution is to give tools to developers to ease the use of contracts, for
example with Aspect Oriented Programming.There is a whole research PhD thesis about Contract-based Testing in PHP,
which includes Design-by-Contract, automatic generation of complex test
data and automatic generation of test suites:
https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf.
Unfortunately, the thesis is in French but research articles are in
English. You can found them here (
http://hoa-project.net/En/Literature.html#Research):
- Praspel: A Specification Language for Contract-Driven Testing in PHP
(article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf,
keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf),- Grammar-Based Testing using Realistic Domains in PHP (article:
http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote:
http://keynote.hoa-project.net/Amost12/EDGB12.pdf),- A Constraint Solver for PHP Arrays (article:
http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote:
http://keynote.hoa-project.net/Cstva13/EGB13.pdf).Concepts behind contracts are twofold:
- Design-by-Contract (DbC), validate code at compile time or at
runtime (in the case of PHP, it will be at runtime),- Contract-based Testing (CbT), generate test data based on contracts.
Preconditions are used to generate inputs, and postconditions validate
outputs. Invariants must hold before and after the execution of the SUT
(System Under Test, here methods and functions).So there are two goals with contracts. We can only address validation
(DbC) or both (DbC and CbT).From my own experience and study in this field (I am a PhD in the test
domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because
the language used to express contracts (even if we use PHP) will be too
much poor or too much inappropriate for test data validation or test data
generation (resp. DbC or CbT).The articles listed above, in addition to the PhD thesis, present
Praspel, a specification language for PHP, based on contracts. Praspel is
used to validate and generate (test) data and test suites. This language is
inspired from JML (Java Modeling Language) and ACSL (ANSI/C Specification
Language) while addressing PHP features (weakly type for instance). But
there is a lot more languages in the wild.
Inventing another language will lead to a fail at a particular time,
believe me. Each contract language has a specificity: Handling structured
data, handling events, handling scenario (see Dwyer patterns for temporal
linear logic) etc. We CANNOT address all these needs.However, there is a hope :-). DbC and CbT can be easily implemented with
an Aspect Oriented Programming (AOP) paradigm. Before each “method
execution”, we interpret or execute the invariants and the preconditions
expressed in the contract, the method runs and after “method execution”, we
interpret or execute the invariants and the postconditions expressed in the
contract. No need to have a specific implementation in PHP's core for
contracts.
Moreover, we can enable or disable AOP in development or production
environment, which ensures performances.It sounds you are looking for way beyond what we discuss.
If there are contracts, program correctness may be proven by contracts, but
this kind of validation is not in scope.Proven? I don't dare to speak about proof here. If you would like to
execute pre-, postconditions and invariants at runtime, you need a super
language to define behaviors efficiently… and the problem is: What
behaviors? Only the data type? The order of execution of methods? The time
of execution of methods? A lot of constraints might be expressed in
contracts.
I suppose so. Your research is to prove program correctness mechanically,
right?
It's tough theme.
There are a lot of researches in this field. PHP has a great opportunity to
not close the doors by forcing a language. I suggest you to offer an API to
hook on the runtime and “control” it, like AOP does. It will open the doors
to so many interesting contributions!
Your request may be implemented. We may have any valid PHP code in pre/post
blocks and they works like hook.
Pre/post are only evaluated dev mode. There is zero performance penalty in
production system.
I've posted how it could be done. Please comment if you find any issues.
If you think D like DbC support in language is wrong, could you list the
reason why it is?I don't understand the question :-).
Do you think of any negative impact on PHP if we implement D like
in{}/out{} which allow any PHP syntax?
Thank you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Yasuo,
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo Ohgaki
Do you think of any negative impact on PHP if we implement D like
in{}/out{} which allow any PHP syntax?
Can you please give your opinion about the BC break a D-like syntax would introduce ? It is important because, if the community accepts such a BC break for PHP 7, I stop working on my proposal based on phpdoc comments.
IMO, it is essential to offer DbC option without making the 'DbC-enabled' code unable to run on PHP 5, but that's just my opinion.
Cheers
François
Hi Francois,
On Fri, Feb 6, 2015 at 6:55 PM, François Laupretre francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
Ohgaki
Do you think of any negative impact on PHP if we implement D like
in{}/out{} which allow any PHP syntax?Can you please give your opinion about the BC break a D-like syntax would
introduce ? It is important because, if the community accepts such a BC
break for PHP 7, I stop working on my proposal based on phpdoc comments.
IMO, it is essential to offer DbC option without making the 'DbC-enabled'
code unable to run on PHP 5, but that's just my opinion.
I can understand motivation to write script runs in older release.
It's nice, I agree.
Personally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.
Therefore, I prefer PHP syntax based one. If it could be written as
normal PHP code, it would be great.
I prefer my proposal of course. However, I don't care much about
where it should be written. I only care we have clean/fast/native/easy
DbC support in PHP 7.
I thought you are going to write PHP syntax borrowed one.
For most users, PHP syntax is better. IMHO.
Since Dmitry offered something based on annotation, could
you work based on PHP syntax? and show us your concept on
this thread?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Francois,
I can understand motivation to write script runs in older release.
It's nice, I agree.Personally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.
Therefore, I prefer PHP syntax based one. If it could be written as
normal PHP code, it would be great.I prefer my proposal of course. However, I don't care much about
where it should be written. I only care we have clean/fast/native/easy
DbC support in PHP 7.I thought you are going to write PHP syntax borrowed one.
For most users, PHP syntax is better. IMHO.
Since Dmitry offered something based on annotation, could
you work based on PHP syntax? and show us your concept on
this thread?
I believe native DbC support in PHP 7 attracts users including
many new users. And I also believe D like syntax attracts more users.
I think Facebook folks will like it. I heard they liked D.
http://www.drdobbs.com/mobile/facebook-adopts-d-language/240162694
What I believe is not important to you. I could be wrong. I appreciate
your proposal anyway. Even if my original thought is not accepted,
I'm grateful to have it.
What important is sort out ideas, make a consensus!
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo Ohgaki
Personally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.
That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You probably didn't live the PHP 4/5 migration but I guess we won't have more than 30 % of production servers under PHP 7 in 2018, just due to the delays of distros, hosting companies, and others.
Now, suppose you're distributing a library or a framework, like Symfony, Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can use it but this implies splitting your code to two independent branches and maintain them in parallel until you have no PHP 5 customer anymore.". What do you think you'll do (or won't do) ?
@Pierre,@Dmitry : you have a better vision than mine on the migration process. What's your opinion on forcing software developers to maintain two separate branches ?
Once again, the conditions in @assert lines ARE PHP code. There's no new syntax. There is no real difference between writing 'assert(<condition>)' and '@assert <condition>', especially if the require/ensure blocks should contain 'assert' statements only.
What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
You probably didn't live the PHP 4/5 migration
Now, this seems to become a habit.
--
Regards,
Mike
Hi Dmitry,
Last time we discussed was this one: https://wiki.php.net/rfc/annotations
The ideal one was the version before:
https://wiki.php.net/rfc/annotations?rev=1300089833
To have this in core, we need to step back and re-evaluate how we could
achieve 80% minimum. My original proposal was trying 95%, too much.
We could get 80% by having a simpler implementation, something like this:
<[ new Foo() ]>
class Bar
{
}
And all it would be required is 2 new methods as part of Reflection classes.
The example could be translated into this:
$bar = new \ReflectionClass('Bar');
$bar->setMetadata([ new Foo() ]);
var_dump($bar->getMetadata());
array(1) {
[0] => object(Foo)
}
Does that sound reasonable? It would allow us to achieve "nested
annotations".
However, it would not achieve a bunch of other things, like named
parameters (you couldn't only do one or two as a constructor params...
Foo(null, null, 'value') would be seen everywhere).
We forget about inheritance, so metadata wouldn't be propagated to
inherited classes, methods or properties.
Also, if we implement in important Reflection structures, that would
incredibly improve its power, such as: ReflectionClass, ReflectionProperty,
ReflectionMethod, ReflectionParameter and ReflectionFunction.
I think this is more reasonable than my original proposal, addresses 80% of
use cases and still help all projects around.
Named parameters would be my next battle then... =D
[]s,
On Fri, Feb 6, 2015 at 9:17 AM, François Laupretre francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have more
than 30 % of production servers under PHP 7 in 2018, just due to the delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.". What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to maintain two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no new
syntax. There is no real difference between writing 'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
in my opinion, RFC looks reasonable.
can you remember main arguments against it.
why it was declined?
For PHP7, it may be possible to change RFC to accept any PHP expression as
annotation value.
Then this expression may be captured as AST or evaluated to constant.
Thanks. Dmitry.
On Fri, Feb 6, 2015 at 5:35 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Hi Dmitry,
Last time we discussed was this one: https://wiki.php.net/rfc/annotations
The ideal one was the version before:
https://wiki.php.net/rfc/annotations?rev=1300089833To have this in core, we need to step back and re-evaluate how we could
achieve 80% minimum. My original proposal was trying 95%, too much.
We could get 80% by having a simpler implementation, something like this:<[ new Foo() ]>
class Bar
{
}And all it would be required is 2 new methods as part of Reflection
classes.
The example could be translated into this:$bar = new \ReflectionClass('Bar');
$bar->setMetadata([ new Foo() ]);var_dump($bar->getMetadata());
array(1) {
[0] => object(Foo)
}Does that sound reasonable? It would allow us to achieve "nested
annotations".
However, it would not achieve a bunch of other things, like named
parameters (you couldn't only do one or two as a constructor params...
Foo(null, null, 'value') would be seen everywhere).
We forget about inheritance, so metadata wouldn't be propagated to
inherited classes, methods or properties.
Also, if we implement in important Reflection structures, that would
incredibly improve its power, such as: ReflectionClass, ReflectionProperty,
ReflectionMethod, ReflectionParameter and ReflectionFunction.I think this is more reasonable than my original proposal, addresses 80%
of use cases and still help all projects around.
Named parameters would be my next battle then... =D[]s,
On Fri, Feb 6, 2015 at 9:17 AM, François Laupretre francois@tekwire.net
wrote:De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have more
than 30 % of production servers under PHP 7 in 2018, just due to the delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.". What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to maintain two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no new
syntax. There is no real difference between writing 'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
I see your point, and, of course, it makes sense, but it also means that no
new PHP7 features might not be used in these frameworks and libraries for a
long time. Should we stop add new features in major releases?
As I said, according to DbC, I'm not sure if it should be defined on
language level. Doc comments or annotations with external tools might be
good enough.
Thanks. Dmitry.
On Fri, Feb 6, 2015 at 5:17 PM, François Laupretre francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have more
than 30 % of production servers under PHP 7 in 2018, just due to the delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.". What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to maintain two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no new
syntax. There is no real difference between writing 'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
Dmitry,
Doc comments are terrible. I really want you to spend some time looking at
what we had to do inside of Doctrine Annotations to make it work. We have
to token_get_all()
the file to be processed and track for "use"s to allow
importing inside of doc blocks. We also had to build a top-down recursive
parser to make it work... don't you think it's too much? As one of the
library maintainers, I do, by heart.
We have until Mar 15 to work on something and propose. I can work on it
without any problems, but as an enthusiast of PHP, it's very frustrating
that I spend time to make PHP better and none even care to review PRs or
simply ignore messages on php-internals. If anyone compromise to review,
I'd do my best to get it ready yesterday if it was possible!
Thanks,
I see your point, and, of course, it makes sense, but it also means that no
new PHP7 features might not be used in these frameworks and libraries for a
long time. Should we stop add new features in major releases?As I said, according to DbC, I'm not sure if it should be defined on
language level. Doc comments or annotations with external tools might be
good enough.Thanks. Dmitry.
On Fri, Feb 6, 2015 at 5:17 PM, François Laupretre francois@tekwire.net
wrote:De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have more
than 30 % of production servers under PHP 7 in 2018, just due to the
delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can
use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.".
What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to maintain
two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no new
syntax. There is no real difference between writing 'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
Hi Dmitry,
Actually the RFC was approved by 1 or 2 votes more than needed, but the
overall response from core maintainers was that it was overly complex,
adding features the language did not support until that point (named
parameters, short array syntax as examples), it was broken with the
proposed opcache merge (was not a trivial fix IIRC) and memory expensive.
I think a simpler approach could work now as I suggested in previous
messages. It does not add new features besides annotations itself.
We'd still have to discuss about the memory usage and where the metadata
class instances should be placed.
[]s,
On Fri, Feb 6, 2015 at 10:12 AM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Dmitry,
Doc comments are terrible. I really want you to spend some time looking at
what we had to do inside of Doctrine Annotations to make it work. We have
totoken_get_all()
the file to be processed and track for "use"s to allow
importing inside of doc blocks. We also had to build a top-down recursive
parser to make it work... don't you think it's too much? As one of the
library maintainers, I do, by heart.We have until Mar 15 to work on something and propose. I can work on it
without any problems, but as an enthusiast of PHP, it's very frustrating
that I spend time to make PHP better and none even care to review PRs or
simply ignore messages on php-internals. If anyone compromise to review,
I'd do my best to get it ready yesterday if it was possible!Thanks,
I see your point, and, of course, it makes sense, but it also means that
no
new PHP7 features might not be used in these frameworks and libraries for
a
long time. Should we stop add new features in major releases?As I said, according to DbC, I'm not sure if it should be defined on
language level. Doc comments or annotations with external tools might be
good enough.Thanks. Dmitry.
On Fri, Feb 6, 2015 at 5:17 PM, François Laupretre francois@tekwire.net
wrote:De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have
more
than 30 % of production servers under PHP 7 in 2018, just due to the
delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can
use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.".
What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to maintain
two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no new
syntax. There is no real difference between writing
'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks
should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
I think the original proposal is more consistent then the simple one.
Most probably, it just came not in right time.
In case @internals really like annotations and we came to consensus how it
should look like, I may take care about efficient implementation.
Thanks. Dmitry.
On Fri, Feb 6, 2015 at 6:19 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Hi Dmitry,
Actually the RFC was approved by 1 or 2 votes more than needed, but the
overall response from core maintainers was that it was overly complex,
adding features the language did not support until that point (named
parameters, short array syntax as examples), it was broken with the
proposed opcache merge (was not a trivial fix IIRC) and memory expensive.I think a simpler approach could work now as I suggested in previous
messages. It does not add new features besides annotations itself.
We'd still have to discuss about the memory usage and where the metadata
class instances should be placed.[]s,
On Fri, Feb 6, 2015 at 10:12 AM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:Dmitry,
Doc comments are terrible. I really want you to spend some time looking
at what we had to do inside of Doctrine Annotations to make it work. We
have totoken_get_all()
the file to be processed and track for "use"s to
allow importing inside of doc blocks. We also had to build a top-down
recursive parser to make it work... don't you think it's too much? As one
of the library maintainers, I do, by heart.We have until Mar 15 to work on something and propose. I can work on it
without any problems, but as an enthusiast of PHP, it's very frustrating
that I spend time to make PHP better and none even care to review PRs or
simply ignore messages on php-internals. If anyone compromise to review,
I'd do my best to get it ready yesterday if it was possible!Thanks,
I see your point, and, of course, it makes sense, but it also means that
no
new PHP7 features might not be used in these frameworks and libraries
for a
long time. Should we stop add new features in major releases?As I said, according to DbC, I'm not sure if it should be defined on
language level. Doc comments or annotations with external tools might be
good enough.Thanks. Dmitry.
On Fri, Feb 6, 2015 at 5:17 PM, François Laupretre <francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de
Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have
more
than 30 % of production servers under PHP 7 in 2018, just due to the
delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like
Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You
can use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.".
What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to
maintain two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no
new
syntax. There is no real difference between writing
'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks
should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
On Fri, Feb 6, 2015 at 6:12 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Dmitry,
Doc comments are terrible. I really want you to spend some time looking at
what we had to do inside of Doctrine Annotations to make it work. We have
totoken_get_all()
the file to be processed and track for "use"s to allow
importing inside of doc blocks. We also had to build a top-down recursive
parser to make it work... don't you think it's too much? As one of the
library maintainers, I do, by heart.
On the other hand you have a working solution.
You won't be able to use annotations for PHP5 projects anyway.
Except, if we put them into comments or doc-comments.
/*[Attribute(Value)]/
We have until Mar 15 to work on something and propose. I can work on it
without any problems, but as an enthusiast of PHP, it's very frustrating
that I spend time to make PHP better and none even care to review PRs or
simply ignore messages on php-internals. If anyone compromise to review,
I'd do my best to get it ready yesterday if it was possible!
Unfortunately, this is live. Everyone here has their own job to do and
their own interest in php project.
Of course, nobody can guarantee, that finally annotations will be accepted.
Thanks. Dmitry.
Thanks,
I see your point, and, of course, it makes sense, but it also means that
no
new PHP7 features might not be used in these frameworks and libraries for
a
long time. Should we stop add new features in major releases?As I said, according to DbC, I'm not sure if it should be defined on
language level. Doc comments or annotations with external tools might be
good enough.Thanks. Dmitry.
On Fri, Feb 6, 2015 at 5:17 PM, François Laupretre francois@tekwire.net
wrote:De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiPersonally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You
probably didn't live the PHP 4/5 migration but I guess we won't have
more
than 30 % of production servers under PHP 7 in 2018, just due to the
delays
of distros, hosting companies, and others.Now, suppose you're distributing a library or a framework, like Symfony,
Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can
use
it but this implies splitting your code to two independent branches and
maintain them in parallel until you have no PHP 5 customer anymore.".
What
do you think you'll do (or won't do) ?@Pierre,@Dmitry : you have a better vision than mine on the migration
process. What's your opinion on forcing software developers to maintain
two
separate branches ?Once again, the conditions in @assert lines ARE PHP code. There's no new
syntax. There is no real difference between writing
'assert(<condition>)'
and '@assert <condition>', especially if the require/ensure blocks
should
contain 'assert' statements only.What I believe is not important to you. I could be wrong.
It is important. As I may be wrong too.
Cheers
François
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
On the other hand you have a working solution.
You won't be able to use annotations for PHP5 projects anyway.
Except, if we put them into comments or doc-comments./*[Attribute(Value)]/
Why not /*@ Attribute Value / or /@ Attribute(Value) */? No []
required and @ looks more familiar with docblock annotations in use.
Hi Dmitry,
So, can we start drafting out some things?
Simple questions would help everybody to get this moving forward.
I'll compile a simple list of questions to answer that would drive the
direction on how it would be implemented.
Please ignore the formatting on HOW they are defined. Tokens can change.
Here it is:
1- Doc comments vs. outside?
2- Keep object instance creation the same? IE: @Foo vs new Foo()
3- Is constructor the only way to inject parameters?
4- What if we have optional arguments, like: @Foo("bar", null, null, "woo")?
Suppose that you wanna fix the optional arguments by declaring names (like
this: @Foo("bar", test="woo")), doesn't it collide with PHP interests of
not supporting parametrized arguments? How would parameter skipping
proposal address this in a nicer way?
5- How would you deal with inheritance? Should a method inherit the same
annotations from parent or not?
Should we add ability to flag to inherit or not? What about overrides?
Would they be allowed? Is there a vague idea on how this concept could be
achieved?
6- Would you be possible to change annotations value at runtime?
7- Would we validate annotation arguments at all? Consider as array?
Properties of objects?
8- In case we take the approach of properties of objects... how would we
flag that a given class can/cannot be used as annotation: another
annotation, interface, any other idea?
9- Would we and/or wow would we flag that a given class could be used only
in a class and not in a method?
10- How would it be the syntax to declare a new annotation?
I think we have a good start now... =)
[]s,
On Fri, Feb 6, 2015 at 12:53 PM, Dennis Birkholz dennis@birkholz.biz
wrote:
On the other hand you have a working solution.
You won't be able to use annotations for PHP5 projects anyway.
Except, if we put them into comments or doc-comments./*[Attribute(Value)]/
Why not /*@ Attribute Value / or /@ Attribute(Value) */? No []
required and @ looks more familiar with docblock annotations in use.--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
I may give my opinion, but it's going to be only mine.
May be it's better to write all these question in RFC and make everyone to
expose their opinion.
It shouldn't be a final voting, just a survey that would help us make a
decisions, where to go.
don't dive into implementation details, use cases, syntax and behavior are
more important.
Thanks. Dmitry.
On Fri, Feb 6, 2015 at 9:21 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Hi Dmitry,
So, can we start drafting out some things?
Simple questions would help everybody to get this moving forward.
I'll compile a simple list of questions to answer that would drive the
direction on how it would be implemented.
Please ignore the formatting on HOW they are defined. Tokens can change.
Here it is:1- Doc comments vs. outside?
2- Keep object instance creation the same? IE: @Foo vs new Foo()
3- Is constructor the only way to inject parameters?
4- What if we have optional arguments, like: @Foo("bar", null, null,
"woo")?
Suppose that you wanna fix the optional arguments by declaring names (like
this: @Foo("bar", test="woo")), doesn't it collide with PHP interests of
not supporting parametrized arguments? How would parameter skipping
proposal address this in a nicer way?5- How would you deal with inheritance? Should a method inherit the same
annotations from parent or not?
Should we add ability to flag to inherit or not? What about overrides?
Would they be allowed? Is there a vague idea on how this concept could be
achieved?6- Would you be possible to change annotations value at runtime?
7- Would we validate annotation arguments at all? Consider as array?
Properties of objects?8- In case we take the approach of properties of objects... how would we
flag that a given class can/cannot be used as annotation: another
annotation, interface, any other idea?9- Would we and/or wow would we flag that a given class could be used only
in a class and not in a method?10- How would it be the syntax to declare a new annotation?
I think we have a good start now... =)
[]s,
On Fri, Feb 6, 2015 at 12:53 PM, Dennis Birkholz dennis@birkholz.biz
wrote:On the other hand you have a working solution.
You won't be able to use annotations for PHP5 projects anyway.
Except, if we put them into comments or doc-comments./*[Attribute(Value)]/
Why not /*@ Attribute Value / or /@ Attribute(Value) */? No []
required and @ looks more familiar with docblock annotations in use.--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
Hi,
De : guilhermeblanco@gmail.com [mailto:guilhermeblanco@gmail.com]
Envoyé : vendredi 6 février 2015 19:22
À : Dennis Birkholz
Cc : PHP internals
Objet : Re: [PHP-DEV] Design by ContractHi Dmitry,
So, can we start drafting out some things?
Simple questions would help everybody to get this moving forward.
I'll compile a simple list of questions to answer that would drive the
direction on how it would be implemented.
Please ignore the formatting on HOW they are defined. Tokens can change.
Here it is:...
Could you please write it in an RFC or revive a previous one, so that we can clearly see what you're proposing. And please start a new thread to discuss this. I understand that DbC is a good use case for annotations but this is not the same subject.
Maybe annotations will be approved as a pre-requisite for DbC, but it is not the only possible solution, and getting a consensus on annotations AND DbC for March 15 seems improbable.
Cheers
François
Hi Dmitri,
Yes, unfortunately, PHP features not compatible with the PHP 5 interpreter will be harder to adopt for most developers, even if they are not technically BC breaks.
I agree with your POV, as I now think that it shouldn't be included in the core, provided we have the needed hooks. I explain the hooks we need in the draft RFC. Can you tell me if it seems possible to you ?
François
De : Dmitry Stogov [mailto:dmitry@zend.com]
I see your point, and, of course, it makes sense, but it also means that no new PHP7 features might not be used in these >frameworks and libraries for a long time. Should we stop add new features in major releases?
As I said, according to DbC, I'm not sure if it should be defined on language level. Doc comments or annotations with external >tools might be good enough.
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo Ohgaki
Personally, backward compatibility is not too important.
PHP5 is dead by PHP 7.2 release... This is the reason why.
It's only 3 years later, only 2 years later after PHP 7.0 release.That's where we disagree, as I think it's most important.
Thinking that PHP 5 is dead in 3 years is extremely naïve IMO. You probably didn't live the PHP 4/5 migration but I guess we won't have more than 30 % of production servers under PHP 7 in 2018, just due to the delays of distros, hosting companies, and others.
Now, suppose you're distributing a library or a framework, like Symfony, Doctrine, etc. Someone tells you : "Here's the new DbC feature. You can use it but this implies splitting your code to two independent branches and maintain them in parallel until you have no PHP 5 customer anymore.". What do you think you'll do (or won't do) ?
@Pierre,@Dmitry : you have a better vision than mine on the migration process. What's your opinion on forcing software developers to maintain two separate branches ?
From a SemVer point of view, two branches are the worst thing we could
do. The same applies to extensions btw.
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
this is not going to be a BC break, this is going to be a Forward
Compatibility break, that won't allow PHP code that use this feature work
on PHP5.
Scalar type hints and attributes are also going to introduce such breaks.
On the other hand if we keep constraints in phpdoc, PHP core shouldn't care
about it at all, and DbC is going to be a goal for separate project (like
phpDocumentor). Alexander, already have AOP based implementation.
In this moment, I don't have strong opinion, if we really need support for
DbC in PHP language (like in D).
Thanks. Dmitry.
Thanks. Dmitry.
On Fri, Feb 6, 2015 at 12:55 PM, François Laupretre francois@tekwire.net
wrote:
Hi Yasuo,
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
Ohgaki
Do you think of any negative impact on PHP if we implement D like
in{}/out{} which allow any PHP syntax?Can you please give your opinion about the BC break a D-like syntax would
introduce ? It is important because, if the community accepts such a BC
break for PHP 7, I stop working on my proposal based on phpdoc comments.IMO, it is essential to offer DbC option without making the 'DbC-enabled'
code unable to run on PHP 5, but that's just my opinion.Cheers
François
Hi Ivan,
Hi Yasuo :-),
On Fri, Feb 6, 2015 at 4:44 PM, Ivan Enderlin @ Hoa
<ivan.enderlin@hoa-project.net mailto:ivan.enderlin@hoa-project.net>
wrote:On Thu, Feb 5, 2015 at 11:25 PM, Ivan Enderlin @ Hoa <ivan.enderlin@hoa-project.net <mailto:ivan.enderlin@hoa-project.net>> wrote: I just would like to point out some stuff. tl;dr: Contracts can be used to validate code (Design-by-Contract) or generate test data to validate code (Contract-based Testing). There are plenty of contract languages in the wild, each one addresses a specific problem (object, structured type, temporal logic, scenario etc.). If we try to develop a contract language, **IT WILL FAIL**, I guarantee it. The solution is to give tools to developers to ease the use of contracts, for example with Aspect Oriented Programming. There is a whole research PhD thesis about Contract-based Testing in PHP, which includes Design-by-Contract, automatic generation of complex test data and automatic generation of test suites: https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf. Unfortunately, the thesis is in French but research articles are in English. You can found them here (http://hoa-project.net/En/Literature.html#Research): * Praspel: A Specification Language for Contract-Driven Testing in PHP (article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf, keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf), * Grammar-Based Testing using Realistic Domains in PHP (article: http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote: http://keynote.hoa-project.net/Amost12/EDGB12.pdf), * A Constraint Solver for PHP Arrays (article: http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote: http://keynote.hoa-project.net/Cstva13/EGB13.pdf). Concepts behind contracts are twofold: 1. Design-by-Contract (DbC), validate code at compile time or at runtime (in the case of PHP, it will be at runtime), 2. Contract-based Testing (CbT), generate test data based on contracts. Preconditions are used to generate inputs, and postconditions validate outputs. Invariants must hold before and after the execution of the SUT (System Under Test, here methods and functions). So there are two goals with contracts. We can only address validation (DbC) or both (DbC and CbT). From my own experience and study in this field (I am a PhD in the test domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because the language used to express contracts (even if we use PHP) will be too much poor or too much inappropriate for test data validation or test data generation (resp. DbC or CbT). The articles listed above, in addition to the PhD thesis, present Praspel, a specification language for PHP, based on contracts. Praspel is used to validate and generate (test) data and test suites. This language is inspired from JML (Java Modeling Language) and ACSL (ANSI/C Specification Language) while addressing PHP features (weakly type for instance). But there is a lot more languages in the wild. Inventing another language will lead to a fail at a particular time, believe me. Each contract language has a specificity: Handling structured data, handling events, handling scenario (see Dwyer patterns for temporal linear logic) etc. We CANNOT address all these needs. However, there is a hope :-). DbC and CbT can be easily implemented with an Aspect Oriented Programming (AOP) paradigm. Before each “method execution”, we interpret or execute the invariants and the preconditions expressed in the contract, the method runs and after “method execution”, we interpret or execute the invariants and the postconditions expressed in the contract. No need to have a specific implementation in PHP's core for contracts. Moreover, we can enable or disable AOP in development or production environment, which ensures performances. It sounds you are looking for way beyond what we discuss. If there are contracts, program correctness may be proven by contracts, but this kind of validation is not in scope.
Proven? I don't dare to speak about proof here. If you would like to execute pre-, postconditions and invariants at runtime, you need a super language to define behaviors efficiently… and the problem is: What behaviors? Only the data type? The order of execution of methods? The time of execution of methods? A lot of constraints might be expressed in contracts.
I suppose so. Your research is to prove program correctness
mechanically, right?
It's tough theme.
Not to prove, to test. Proof kind be seen as an exhaustive testing process.
There are a lot of researches in this field. PHP has a great opportunity to not close the doors by forcing a language. I suggest you to offer an API to hook on the runtime and “control” it, like AOP does. It will open the doors to so many interesting contributions!
Your request may be implemented. We may have any valid PHP code in
pre/post blocks and they works like hook.
Pre/post are only evaluated dev mode. There is zero performance
penalty in production system.
I've posted how it could be done. Please comment if you find any issues.
My main issue is that PHP is not appopriated to specify or describe
behaviors of different nature without being verbose. Using PHP here
would turn the code difficult to read and debug IMHO. When we use
contracts, it's rarely to express simple behaviors…
If you think D like DbC support in language is wrong, could you list the reason why it is?
I don't understand the question :-).
Do you think of any negative impact on PHP if we implement D like
in{}/out{} which allow any PHP syntax?
See my comments above :-).
There are a lot of researches in this field. PHP has a great opportunity to
not close the doors by forcing a language. I suggest you to offer an API to
hook on the runtime and “control” it, like AOP does. It will open the doors
to so many interesting contributions!
Hello,
after reading this discussion, this seems like the best way to handle DbC.
Regards
Pavel Kouril
Can you suggest what exactly should be done?
Thanks. Dmitry.
There are a lot of researches in this field. PHP has a great opportunity
to
not close the doors by forcing a language. I suggest you to offer an API
to
hook on the runtime and “control” it, like AOP does. It will open the
doors
to so many interesting contributions!Hello,
after reading this discussion, this seems like the best way to handle DbC.
Regards
Pavel Kouril
Hi Dmitry,
Thank you for your time!
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
require(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Less reserved word is better.
The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions (zero
cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectationsFor inherited methods, only the self <input-assert-expression> should be
checked, and all parent <output-asser-expression>. This is borrowed from D
but not necessary to be repeated exactly.I think we shouldn't introduce "invariant" constraints for classes now.
May be later.Implementation is going to generate code for input constraint after all
RECV opcodes and before code for function body, and code for output
constraint before RETURN opcode (may be reusing implementation of
"finally").
It seems fine to me overall.
I have a few questions, but I think it's better to handle discussion as I
promised.
I'll ask later!
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
--001a11c20e52da1ee0050e556679
Content-Type: text/plain; charset=UTF-8Hi Yasuo,
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions (zero
cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectations
I really like the idea. D allows complete blocks that then use assert. Might
be worht investigating why they went for a block rather than one expression.
For inherited methods, only the self <input-assert-expression> should be
checked, and all parent <output-asser-expression>. This is borrowed from D
but not necessary to be repeated exactly.I think we shouldn't introduce "invariant" constraints for classes now. May
be later.
I believe invariant is one of the strongest contract ideas as it goes well with
proper encapsluation and immutability like structures.
Hi Dimitry, Francois and Guilherme,
Hi Yasuo,
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Should I add D like version to the RFC? I don't care much about syntax as
long as
we have DbC.
Like Guilherme suggested, make some decisions first?
1- Doc comments vs. outside?
2- Keep object instance creation the same? IE: @Foo vs new Foo()
3- Is constructor the only way to inject parameters?
4- What if we have optional arguments, like: @Foo("bar", null, null, "woo")?
Suppose that you wanna fix the optional arguments by declaring names (like
this: @Foo("bar", test="woo")), doesn't it collide with PHP interests of
not supporting parametrized arguments? How would parameter skipping
proposal address this in a nicer way?
5- How would you deal with inheritance? Should a method inherit the same
annotations from parent or not?
Should we add ability to flag to inherit or not? What about overrides?
Would they be allowed? Is there a vague idea on how this concept could be
achieved?
6- Would you be possible to change annotations value at runtime?
7- Would we validate annotation arguments at all? Consider as array?
Properties of objects?
8- In case we take the approach of properties of objects... how would we
flag that a given class can/cannot be used as annotation: another
annotation, interface, any other idea?
9- Would we and/or wow would we flag that a given class could be used only
in a class and not in a method?
10- How would it be the syntax to declare a new annotation?
Since people's preferences are diverse. It might be a good idea having
pre-vote
for designs, then we may have final vote with single design.
We need some consensuses even for pre-vote.
What do you think?
Guilherme, is this the RFC you've mentioned?
Whenever you feel ready to get true, complete Annotations into core
https://wiki.php.net/rfc/annotations
Just making sure.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Guilherme and Francois,
Could you give your ideas for these?
Thank you.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Dimitry, Francois and Guilherme,
Hi Yasuo,
Following our conversation, I tried to imagine how DbC should look like
in PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}It would require only one new reserved word "ensure".
Should I add D like version to the RFC? I don't care much about syntax as
long as
we have DbC.Like Guilherme suggested, make some decisions first?
1- Doc comments vs. outside?
2- Keep object instance creation the same? IE: @Foo vs new Foo()
3- Is constructor the only way to inject parameters?
4- What if we have optional arguments, like: @Foo("bar", null, null,
"woo")?
Suppose that you wanna fix the optional arguments by declaring names (like
this: @Foo("bar", test="woo")), doesn't it collide with PHP interests of
not supporting parametrized arguments? How would parameter skipping
proposal address this in a nicer way?5- How would you deal with inheritance? Should a method inherit the same
annotations from parent or not?
Should we add ability to flag to inherit or not? What about overrides?
Would they be allowed? Is there a vague idea on how this concept could be
achieved?6- Would you be possible to change annotations value at runtime?
7- Would we validate annotation arguments at all? Consider as array?
Properties of objects?8- In case we take the approach of properties of objects... how would we
flag that a given class can/cannot be used as annotation: another
annotation, interface, any other idea?9- Would we and/or wow would we flag that a given class could be used only
in a class and not in a method?10- How would it be the syntax to declare a new annotation?
Since people's preferences are diverse. It might be a good idea having
pre-vote
for designs, then we may have final vote with single design.We need some consensuses even for pre-vote.
What do you think?
Guilherme, is this the RFC you've mentioned?
Whenever you feel ready to get true, complete Annotations into core
https://wiki.php.net/rfc/annotations
Just making sure.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo Ohgaki
Since people's preferences are diverse. It might be a good idea having pre-vote
for designs, then we may have final vote with single design.We need some consensuses even for pre-vote.
What do you think?
What I think is that I have written a 600-line RFC, that you refuse to comment because you still hope you can impose a D-like syntax by another way. I don't agree on a pre-vote on design and, then, care about details, because that's just an artefact to get an agreement on D-like syntax before people can read and understand my proposal, and without exploring the implications of your design.
Here is a fair way to proceed: I have written an RFC, trying to explore honestly every aspects of the design I'm proposing. Now, either you agree, or you write yours with the same goal in mind. Then, we may choose. That's the rule. Saying 'I don't like that' without proposing an alternative is not the right way. I won't help you get an a-priori approval, just to say thereafter that, whatever problem we find, we must stick with this design because it was pre-approved. If you write an RFC and people approve it, that's OK.
Anyway, as I think DbC can be implemented without any change in the core, I'll probably implement it by myself as a zend extension. So, you can do what you want in PHP 7.
Regards
François
Hi Francois,
On Mon, Feb 9, 2015 at 12:43 AM, François Laupretre francois@tekwire.net
wrote:
De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo
OhgakiSince people's preferences are diverse. It might be a good idea having
pre-vote
for designs, then we may have final vote with single design.We need some consensuses even for pre-vote.
What do you think?
What I think is that I have written a 600-line RFC, that you refuse to
comment because you still hope you can impose a D-like syntax by another
way. I don't agree on a pre-vote on design and, then, care about details,
because that's just an artefact to get an agreement on D-like syntax before
people can read and understand my proposal, and without exploring the
implications of your design.Here is a fair way to proceed: I have written an RFC, trying to explore
honestly every aspects of the design I'm proposing. Now, either you agree,
or you write yours with the same goal in mind. Then, we may choose. That's
the rule. Saying 'I don't like that' without proposing an alternative is
not the right way. I won't help you get an a-priori approval, just to say
thereafter that, whatever problem we find, we must stick with this design
because it was pre-approved. If you write an RFC and people approve it,
that's OK.Anyway, as I think DbC can be implemented without any change in the core,
I'll probably implement it by myself as a zend extension. So, you can do
what you want in PHP 7.
I agree. I can also implement basic DbC feature as zend extension. It
will be ugly without parser modification, but the change wouldn't be too
hard.
I'm sure Dmitry would do much better job than me :)
You would like me to write D like version. No problem at all.
If majority/consensus is annotation approach, I don't insist to have
D like proposal. If you would like to choose by vote anyway, I'll
write/add
RFC with Dmitry's idea in mind.
Dmitry, what is your opinion now?
It's not mandatory, but I still prefer to have D like syntax because users
can code contracts just like PHP code and get all kinds of syntax errors/etc
as PHP. Would you like to have D like syntax as vote option or choose with
one of
annotation/D like before vote? (It seems annotation is more popular)
D like design has advantage that internal functions/classes may have
contracts
just like user space. This may help to get better performance also. User
would
get consistent/similar contract errors from internal classes/functions. (I
can imagine
number of people against raising E_WARNING
from classes, though)
Guiherme, you have comprehensive annotation implementation.
Could you give us your idea's about DbC and annotation?
Is your idea the same as Francois's?
We don't have much time. I hope we have consensus before deadline.
Thank you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi!
Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}
Why not do it simpler?
function foo() {
// require
assert(<input-assert-expression>);
...
// ensure
assert(<output-assert-expression>);
}
I'm oversimplifying a bit, but in general, why we need more places to
have code in the function than the actual code of the function? It would
be harder to parse, to read, to maintain, to debug, to profile, etc. and
I'm not sure what exactly it provides that can't be done by plain
regular code inside the function.
If we're concerned about the costs of assert, we could make special
provision in the compiler for zero-cost asserts. It doesn't require
moving code out of the function.
Stas Malyshev
smalyshev@gmail.com
Hi Stas,
On Mon, Feb 9, 2015 at 8:11 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Following our conversation, I tried to imagine how DbC should look like
in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}Why not do it simpler?
function foo() {
// require
assert(<input-assert-expression>);
...
// ensure
assert(<output-assert-expression>);
}I'm oversimplifying a bit, but in general, why we need more places to
have code in the function than the actual code of the function? It would
be harder to parse, to read, to maintain, to debug, to profile, etc. and
I'm not sure what exactly it provides that can't be done by plain
regular code inside the function.If we're concerned about the costs of assert, we could make special
provision in the compiler for zero-cost asserts. It doesn't require
moving code out of the function.
Interesting idea. I like it.
The only draw back I can see now is that this may make post/pre condition
retrieving
harder for automatic documentation. We may think of solution for this.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Yasuo,
Design by Contract could be used at the top of Annotation if (and only if)
it also had support for Interceptors. Since it could potentially be a
nightmare for PHP, I don't think it's time to propose something at the top
of another thing that is still far from being reality.
It would follow somehow a similar approach of what Symfony validators do:
http://symfony.com/doc/current/book/validation.html but it would be called
at possible 3 times: pre-execution, in-execution (using around and bound to
an external class) and post-execution.
However, I keep myself asking if this is a good idea. It obviously brings a
certain level of AOP to PHP, but I'd rather take a simplistic approach such
as the one suggested by Stas but with a few adjustments.
His approach is more inline to C and C++, but I like a more customizable
Java style assertion support
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html
Example:
function foo($name) {
assert $name !== '': "Name must not be an empty value";
}
This would be similar to this:
function foo($name) {
if ($name === null) {
throw new AssertionError("Name must not be an empty value");
}
}
Basically, new grammar to be supported would be something like this:
assert_statement:
T_ASSERT expr ':' expr ';'
;
Where the first expr is a boolean expression and the second expr must
return a value (cannot be null).
This would be a good start for PHP, even though Java does not recommend to
use this for argument's method check (
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage),
but I consider that since PHP is not a strict language, we do not have the
same privileges by automating this check form arguments itself.
That is my personal suggestion for DbC, which does not fully align with
what it was proposed, but since you asked... here it is.
[]s,
Hi Stas,
On Mon, Feb 9, 2015 at 8:11 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:Following our conversation, I tried to imagine how DbC should look like
in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}Why not do it simpler?
function foo() {
// require
assert(<input-assert-expression>);
...
// ensure
assert(<output-assert-expression>);
}I'm oversimplifying a bit, but in general, why we need more places to
have code in the function than the actual code of the function? It would
be harder to parse, to read, to maintain, to debug, to profile, etc. and
I'm not sure what exactly it provides that can't be done by plain
regular code inside the function.If we're concerned about the costs of assert, we could make special
provision in the compiler for zero-cost asserts. It doesn't require
moving code out of the function.Interesting idea. I like it.
The only draw back I can see now is that this may make post/pre condition
retrieving
harder for automatic documentation. We may think of solution for this.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
Hi Guilherme,
On Mon, Feb 9, 2015 at 11:58 AM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Design by Contract could be used at the top of Annotation if (and only if)
it also had support for Interceptors. Since it could potentially be a
nightmare for PHP, I don't think it's time to propose something at the top
of another thing that is still far from being reality.
It would follow somehow a similar approach of what Symfony validators do:
http://symfony.com/doc/current/book/validation.html but it would be
called at possible 3 times: pre-execution, in-execution (using around and
bound to an external class) and post-execution.
However, I keep myself asking if this is a good idea. It obviously brings
a certain level of AOP to PHP, but I'd rather take a simplistic approach
such as the one suggested by Stas but with a few adjustments.
His approach is more inline to C and C++, but I like a more customizable
Java style assertion support
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html
Example:function foo($name) {
assert $name !== '': "Name must not be an empty value";
}This would be similar to this:
function foo($name) {
if ($name === null) {
throw new AssertionError("Name must not be an empty value");
}
}Basically, new grammar to be supported would be something like this:
assert_statement:
T_ASSERT expr ':' expr ';'
;Where the first expr is a boolean expression and the second expr must
return a value (cannot be null).This would be a good start for PHP, even though Java does not recommend to
use this for argument's method check (
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage),
but I consider that since PHP is not a strict language, we do not have the
same privileges by automating this check form arguments itself.That is my personal suggestion for DbC, which does not fully align with
what it was proposed, but since you asked... here it is.
Thank you.
Since assert is going to have zero performance penalty, Stas proposal would
work.
We have to think of how invariants should be.
Joe, could you add "Proposal" section to the RFC.
https://wiki.php.net/rfc/expectations
Currently, it does not have "Proposal" section and it's harder to
understand what the
RFC is. Then, could you start vote? New assert is valuable regardless of
DbC.
The RFC will encourage users to use assert()
, my little concern with Stas's
proposal
is misuse/abuse of assert()
. Stas's proposal is simplest, but I'm not sure
if we should go
for it or not.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Yasuo,
Class invariants could be done as this example:
class Foo {
private function isValidState() {
// Checks class's state and returns boolean
}
public function doSomething($args) {
// Some complex operation over Foo instance using $args
// then...
assert $this->isValidState(): $this; // it would call
Foo::__toString() for AssertionError message
}
}
Another example of pre and post conditions:
function foo($number) {
// pre-condition
assert is_numeric($number): '...';
// Some expensive operation creating $value as response
// post-condition
assert someCheckWith($value): '...';
return $value;
}
A good explanation about use-cases can be found here
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#class-invariants
[]s,
Hi Guilherme,
On Mon, Feb 9, 2015 at 11:58 AM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:Design by Contract could be used at the top of Annotation if (and only
if) it also had support for Interceptors. Since it could potentially be a
nightmare for PHP, I don't think it's time to propose something at the top
of another thing that is still far from being reality.
It would follow somehow a similar approach of what Symfony validators do:
http://symfony.com/doc/current/book/validation.html but it would be
called at possible 3 times: pre-execution, in-execution (using around and
bound to an external class) and post-execution.
However, I keep myself asking if this is a good idea. It obviously brings
a certain level of AOP to PHP, but I'd rather take a simplistic approach
such as the one suggested by Stas but with a few adjustments.
His approach is more inline to C and C++, but I like a more customizable
Java style assertion support
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html
Example:function foo($name) {
assert $name !== '': "Name must not be an empty value";
}This would be similar to this:
function foo($name) {
if ($name === null) {
throw new AssertionError("Name must not be an empty value");
}
}Basically, new grammar to be supported would be something like this:
assert_statement:
T_ASSERT expr ':' expr ';'
;Where the first expr is a boolean expression and the second expr must
return a value (cannot be null).This would be a good start for PHP, even though Java does not recommend
to use this for argument's method check (
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage),
but I consider that since PHP is not a strict language, we do not have the
same privileges by automating this check form arguments itself.That is my personal suggestion for DbC, which does not fully align with
what it was proposed, but since you asked... here it is.Thank you.
Since assert is going to have zero performance penalty, Stas proposal
would work.
We have to think of how invariants should be.Joe, could you add "Proposal" section to the RFC.
https://wiki.php.net/rfc/expectations
Currently, it does not have "Proposal" section and it's harder to
understand what the
RFC is. Then, could you start vote? New assert is valuable regardless of
DbC.The RFC will encourage users to use
assert()
, my little concern with
Stas's proposal
is misuse/abuse ofassert()
. Stas's proposal is simplest, but I'm not sure
if we should go
for it or not.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
Hi Guilherme,
On Mon, Feb 9, 2015 at 1:44 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Class invariants could be done as this example:
class Foo {
private function isValidState() {
// Checks class's state and returns boolean
}public function doSomething($args) { // Some complex operation over Foo instance using $args // then... assert $this->isValidState(): $this; // it would call
Foo::__toString() for AssertionError message
}
}Another example of pre and post conditions:
function foo($number) {
// pre-condition
assert is_numeric($number): '...';// Some expensive operation creating $value as response // post-condition assert someCheckWith($value): '...'; return $value;
}
A good explanation about use-cases can be found here
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#class-invariants
Thank you for the info.
I had this syntax in mind.
class Foo {
__invariant() {
// Ignored for production.
// Check class state, every method calls invoke this method
before/after except
// __construct()/__wakeup()/__set_state() - after only
// __destruct() - before only
}
}
// Framework developer shouldn't use this. Leave this function for app
developers.
function __invariant() {
// Ignored for production.
// Invariant conditions of functions invoked for every function calls
// to check app state. e.g. global vars,etc
}
__invariant() has similar issue as __autoload(), we may be better to
provide generic registration
method.
Just my initial thought for discussion.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
I'll try to answer to all the emails at once.
Personally, I like the D approach more, but doc-comment proposal has its
advantages as well.
The problem that doc-comment solution is external to PHP core.
In my opinion, it should be implemented as a separate preprocessor that
reads doc-comments and generates PHP code with asserts().
I don't see how this may be implemented in PHP core itself, and I most
probably won't be evolved in development of other project.
Something similar was already implemented...
Alexander, could you please send link to implentation/dicumentation and
explain how it works (in few words).
Yasuo, I think you should describe the D proposal as well. I'm not sure if
it should be done in the same RFC (it's already big) or a new one.
Any solution would require zero-cost assert (or similar concept)
implemented in php core.
Thanks. Dmitry.
Hi Guilherme,
On Mon, Feb 9, 2015 at 1:44 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:Class invariants could be done as this example:
class Foo {
private function isValidState() {
// Checks class's state and returns boolean
}public function doSomething($args) { // Some complex operation over Foo instance using $args // then... assert $this->isValidState(): $this; // it would call
Foo::__toString() for AssertionError message
}
}Another example of pre and post conditions:
function foo($number) {
// pre-condition
assert is_numeric($number): '...';// Some expensive operation creating $value as response // post-condition assert someCheckWith($value): '...'; return $value;
}
A good explanation about use-cases can be found here
http://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#class-invariantsThank you for the info.
I had this syntax in mind.
class Foo {
__invariant() {
// Ignored for production.
// Check class state, every method calls invoke this method
before/after except
// __construct()/__wakeup()/__set_state() - after only
// __destruct() - before only
}
}// Framework developer shouldn't use this. Leave this function for app
developers.
function __invariant() {
// Ignored for production.
// Invariant conditions of functions invoked for every function calls
// to check app state. e.g. global vars,etc
}__invariant() has similar issue as __autoload(), we may be better to
provide generic registration
method.Just my initial thought for discussion.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
It's nothing wrong here. It's just a concept that cares about constraints
definition more.
So, DbC with asserts spread among the code is like OOP without classes.
Thanks. Dmitry.
On Mon, Feb 9, 2015 at 2:11 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
Following our conversation, I tried to imagine how DbC should look like
in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}Why not do it simpler?
function foo() {
// require
assert(<input-assert-expression>);
...
// ensure
assert(<output-assert-expression>);
}I'm oversimplifying a bit, but in general, why we need more places to
have code in the function than the actual code of the function? It would
be harder to parse, to read, to maintain, to debug, to profile, etc. and
I'm not sure what exactly it provides that can't be done by plain
regular code inside the function.If we're concerned about the costs of assert, we could make special
provision in the compiler for zero-cost asserts. It doesn't require
moving code out of the function.Stas Malyshev
smalyshev@gmail.com
Morning internals,
I really liked the original idea Dmitry had, with the D-ish syntax.
We could use require and return like:
function foo()
require(input-expr)
return(output-expr) {
/* ... */
}
to avoid adding more keywords.
I'd really appreciate seeing this as an option in the RFC.
Cheers
Joe
It's nothing wrong here. It's just a concept that cares about constraints
definition more.So, DbC with asserts spread among the code is like OOP without classes.
Thanks. Dmitry.
On Mon, Feb 9, 2015 at 2:11 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
Following our conversation, I tried to imagine how DbC should look like
in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}Why not do it simpler?
function foo() {
// require
assert(<input-assert-expression>);
...
// ensure
assert(<output-assert-expression>);
}I'm oversimplifying a bit, but in general, why we need more places to
have code in the function than the actual code of the function? It would
be harder to parse, to read, to maintain, to debug, to profile, etc. and
I'm not sure what exactly it provides that can't be done by plain
regular code inside the function.If we're concerned about the costs of assert, we could make special
provision in the compiler for zero-cost asserts. It doesn't require
moving code out of the function.Stas Malyshev
smalyshev@gmail.com
Usage of "return" is a good idea.
The more heads the better result :)
Thanks. Dmitry.
Morning internals,
I really liked the original idea Dmitry had, with the D-ish syntax.
We could use require and return like:
function foo() require(input-expr) return(output-expr) { /* ... */ } to avoid adding more keywords. I'd really appreciate seeing this as an option in the RFC.
Cheers
JoeIt's nothing wrong here. It's just a concept that cares about constraints
definition more.So, DbC with asserts spread among the code is like OOP without classes.
Thanks. Dmitry.
On Mon, Feb 9, 2015 at 2:11 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
Following our conversation, I tried to imagine how DbC should look
like
in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:For php it may look like the following:
function foo()
requre(<input-assert-expression>)
ensure(<output-assert-expression>)
{
...
}Why not do it simpler?
function foo() {
// require
assert(<input-assert-expression>);
...
// ensure
assert(<output-assert-expression>);
}I'm oversimplifying a bit, but in general, why we need more places to
have code in the function than the actual code of the function? It would
be harder to parse, to read, to maintain, to debug, to profile, etc. and
I'm not sure what exactly it provides that can't be done by plain
regular code inside the function.If we're concerned about the costs of assert, we could make special
provision in the compiler for zero-cost asserts. It doesn't require
moving code out of the function.Stas Malyshev
smalyshev@gmail.com
Hi Dmitry and Joe,
Usage of "return" is a good idea.
The more heads the better result :)
Less additional reserved word :)
So I'll use "require" and "return" for D like RFC.
We haven't talk much about invariants. I'll write my idea.
Current RFC is large enough already, I'll prepare new one.
We may decide what to do with 2 RFCs.
We have choices for with block or without block. I prefer with block
version, since
assert expression could be messy. With block, IDE may do it's jobs. i.e.
Hide blocks.
==============================================
Function/Method
[With block]
function foo()
require {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
return {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
{
// body
}
OR
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
// function body
}
Currently, following code wouldn't work (PHP 7.0.0-dev)
assert(function() {return FALSE;}, 'AAAAA');
For block version, which do you prefer, allow any PHP syntax or assert
only?
People may use anonymous function to do fancy jobs anyway if it's
supported.
No block version only accepts EXPR obviously, but anonymous function may
be used with this as well.
==============================================
Class invariants
[With block]
class Foo {
__invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
}
OR
[Without block]
class Foo {
__construct() {
invariant(assert-expr, 'msg'); // Only allow in __construct()? Allowing
invariant.
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
}
}
==============================================
Global invariant
I'm not sure if we should have
function __invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
OR
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
to assert global vars, whole app state, etc. It may be useful for unit
tests as well as app development.
I'll start working after I get comment from you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
HI Dmitry,
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');// function body
}
OOPS. Without block cannot work ;)
I should have notice while I'm writing.
I'll go with "with block". If you find any other issues, please let me know.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Morning Yasuo,
Can you explain what invariant is for ?
I prefer a list of contracts with a single expression, over blocks of
expressions in one contract.
An IDE can just as easy generate a block of code or set of contracts,
so it's really just a matter of how complex it makes the implementation if
you allow any block of code in the contract. I think it does make it
unnecessarily complicated to implement, I can be wrong.
If there is going to be two rfc's, I will vote no on the annotations
based one, I'd rather no time was wasted on even writing it; Before you
convince anyone that DBC is a good idea you have to convince them
annotations is a good idea, many have tried and failed.
Cheers
Joe
Hi Dmitry and Joe,
Usage of "return" is a good idea.
The more heads the better result :)Less additional reserved word :)
So I'll use "require" and "return" for D like RFC.
We haven't talk much about invariants. I'll write my idea.Current RFC is large enough already, I'll prepare new one.
We may decide what to do with 2 RFCs.We have choices for with block or without block. I prefer with block
version, since
assert expression could be messy. With block, IDE may do it's jobs. i.e.
Hide blocks.==============================================
Function/Method[With block]
function foo()
require {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
return {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
{
// body
}OR
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');// function body
}Currently, following code wouldn't work (PHP 7.0.0-dev)
assert(function() {return FALSE;}, 'AAAAA');
For block version, which do you prefer, allow any PHP syntax or assert
only?
People may use anonymous function to do fancy jobs anyway if it's
supported.No block version only accepts EXPR obviously, but anonymous function may
be used with this as well.==============================================
Class invariants[With block]
class Foo {
__invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
}OR
[Without block]
class Foo {
__construct() {
invariant(assert-expr, 'msg'); // Only allow in __construct()?
Allowing invariant.
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
}
}==============================================
Global invariantI'm not sure if we should have
function __invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}OR
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}to assert global vars, whole app state, etc. It may be useful for unit
tests as well as app development.I'll start working after I get comment from you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
invariant is for classes only. It should be called before and/or after each
method to check object consistency.
syntax with expressions may work if we put constraints before the function
body .
function foo($a int): int
require(expr1)
require(expr2, msg)
return(expr3)
{
}
Yasuo, I would suggest to describe both syntax options.
Thanks. Dmitry.
Morning Yasuo,
Can you explain what invariant is for ? I prefer a list of contracts with a single expression, over blocks of
expressions in one contract.
An IDE can just as easy generate a block of code or set of contracts,
so it's really just a matter of how complex it makes the implementation if
you allow any block of code in the contract. I think it does make it
unnecessarily complicated to implement, I can be wrong.If there is going to be two rfc's, I will vote no on the annotations
based one, I'd rather no time was wasted on even writing it; Before you
convince anyone that DBC is a good idea you have to convince them
annotations is a good idea, many have tried and failed.Cheers
JoeHi Dmitry and Joe,
Usage of "return" is a good idea.
The more heads the better result :)Less additional reserved word :)
So I'll use "require" and "return" for D like RFC.
We haven't talk much about invariants. I'll write my idea.Current RFC is large enough already, I'll prepare new one.
We may decide what to do with 2 RFCs.We have choices for with block or without block. I prefer with block
version, since
assert expression could be messy. With block, IDE may do it's jobs. i.e.
Hide blocks.==============================================
Function/Method[With block]
function foo()
require {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
return {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
{
// body
}OR
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');// function body
}Currently, following code wouldn't work (PHP 7.0.0-dev)
assert(function() {return FALSE;}, 'AAAAA');
For block version, which do you prefer, allow any PHP syntax or assert
only?
People may use anonymous function to do fancy jobs anyway if it's
supported.No block version only accepts EXPR obviously, but anonymous function may
be used with this as well.==============================================
Class invariants[With block]
class Foo {
__invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
}OR
[Without block]
class Foo {
__construct() {
invariant(assert-expr, 'msg'); // Only allow in __construct()?
Allowing invariant.
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
}
}==============================================
Global invariantI'm not sure if we should have
function __invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}OR
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}to assert global vars, whole app state, etc. It may be useful for unit
tests as well as app development.I'll start working after I get comment from you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {
public function method($param) : return
require(input-expr),
return(output-expr) {
}
}
To avoid invariant keyword maybe.
Cheers
Joe
invariant is for classes only. It should be called before and/or after
each method to check object consistency.syntax with expressions may work if we put constraints before the function
body .function foo($a int): int
require(expr1)
require(expr2, msg)
return(expr3)
{
}Yasuo, I would suggest to describe both syntax options.
Thanks. Dmitry.
Morning Yasuo,
Can you explain what invariant is for ? I prefer a list of contracts with a single expression, over blocks of
expressions in one contract.
An IDE can just as easy generate a block of code or set of contracts,
so it's really just a matter of how complex it makes the implementation if
you allow any block of code in the contract. I think it does make it
unnecessarily complicated to implement, I can be wrong.If there is going to be two rfc's, I will vote no on the annotations
based one, I'd rather no time was wasted on even writing it; Before you
convince anyone that DBC is a good idea you have to convince them
annotations is a good idea, many have tried and failed.Cheers
JoeHi Dmitry and Joe,
Usage of "return" is a good idea.
The more heads the better result :)Less additional reserved word :)
So I'll use "require" and "return" for D like RFC.
We haven't talk much about invariants. I'll write my idea.Current RFC is large enough already, I'll prepare new one.
We may decide what to do with 2 RFCs.We have choices for with block or without block. I prefer with block
version, since
assert expression could be messy. With block, IDE may do it's jobs. i.e.
Hide blocks.==============================================
Function/Method[With block]
function foo()
require {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
return {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
{
// body
}OR
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');// function body
}Currently, following code wouldn't work (PHP 7.0.0-dev)
assert(function() {return FALSE;}, 'AAAAA');
For block version, which do you prefer, allow any PHP syntax or assert
only?
People may use anonymous function to do fancy jobs anyway if it's
supported.No block version only accepts EXPR obviously, but anonymous function may
be used with this as well.==============================================
Class invariants[With block]
class Foo {
__invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
}OR
[Without block]
class Foo {
__construct() {
invariant(assert-expr, 'msg'); // Only allow in __construct()?
Allowing invariant.
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
}
}==============================================
Global invariantI'm not sure if we should have
function __invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}OR
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}to assert global vars, whole app state, etc. It may be useful for unit
tests as well as app development.I'll start working after I get comment from you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
yes. this may work.
probably better to put it after extends and implements.
Dmitry.
Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
Cheers
Joeinvariant is for classes only. It should be called before and/or after
each method to check object consistency.syntax with expressions may work if we put constraints before the
function body .function foo($a int): int
require(expr1)
require(expr2, msg)
return(expr3)
{
}Yasuo, I would suggest to describe both syntax options.
Thanks. Dmitry.
On Mon, Feb 9, 2015 at 1:46 PM, Joe Watkins pthreads@pthreads.org
wrote:Morning Yasuo,
Can you explain what invariant is for ? I prefer a list of contracts with a single expression, over blocks
of expressions in one contract.
An IDE can just as easy generate a block of code or set of
contracts, so it's really just a matter of how complex it makes the
implementation if you allow any block of code in the contract. I think it
does make it unnecessarily complicated to implement, I can be wrong.If there is going to be two rfc's, I will vote no on the annotations
based one, I'd rather no time was wasted on even writing it; Before you
convince anyone that DBC is a good idea you have to convince them
annotations is a good idea, many have tried and failed.Cheers
JoeOn Mon, Feb 9, 2015 at 10:34 AM, Yasuo Ohgaki yohgaki@ohgaki.net
wrote:Hi Dmitry and Joe,
Usage of "return" is a good idea.
The more heads the better result :)Less additional reserved word :)
So I'll use "require" and "return" for D like RFC.
We haven't talk much about invariants. I'll write my idea.Current RFC is large enough already, I'll prepare new one.
We may decide what to do with 2 RFCs.We have choices for with block or without block. I prefer with block
version, since
assert expression could be messy. With block, IDE may do it's jobs.
i.e. Hide blocks.==============================================
Function/Method[With block]
function foo()
require {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
return {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
{
// body
}OR
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');// function body
}Currently, following code wouldn't work (PHP 7.0.0-dev)
assert(function() {return FALSE;}, 'AAAAA');
For block version, which do you prefer, allow any PHP syntax or assert
only?
People may use anonymous function to do fancy jobs anyway if it's
supported.No block version only accepts EXPR obviously, but anonymous function
may
be used with this as well.==============================================
Class invariants[With block]
class Foo {
__invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
}OR
[Without block]
class Foo {
__construct() {
invariant(assert-expr, 'msg'); // Only allow in __construct()?
Allowing invariant.
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
}
}==============================================
Global invariantI'm not sure if we should have
function __invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}OR
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}to assert global vars, whole app state, etc. It may be useful for unit
tests as well as app development.I'll start working after I get comment from you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Yeah, after ....
yes. this may work.
probably better to put it after extends and implements.Dmitry.
Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
Cheers
Joeinvariant is for classes only. It should be called before and/or after
each method to check object consistency.syntax with expressions may work if we put constraints before the
function body .function foo($a int): int
require(expr1)
require(expr2, msg)
return(expr3)
{
}Yasuo, I would suggest to describe both syntax options.
Thanks. Dmitry.
On Mon, Feb 9, 2015 at 1:46 PM, Joe Watkins pthreads@pthreads.org
wrote:Morning Yasuo,
Can you explain what invariant is for ? I prefer a list of contracts with a single expression, over blocks
of expressions in one contract.
An IDE can just as easy generate a block of code or set of
contracts, so it's really just a matter of how complex it makes the
implementation if you allow any block of code in the contract. I think it
does make it unnecessarily complicated to implement, I can be wrong.If there is going to be two rfc's, I will vote no on the annotations
based one, I'd rather no time was wasted on even writing it; Before you
convince anyone that DBC is a good idea you have to convince them
annotations is a good idea, many have tried and failed.Cheers
JoeOn Mon, Feb 9, 2015 at 10:34 AM, Yasuo Ohgaki yohgaki@ohgaki.net
wrote:Hi Dmitry and Joe,
Usage of "return" is a good idea.
The more heads the better result :)Less additional reserved word :)
So I'll use "require" and "return" for D like RFC.
We haven't talk much about invariants. I'll write my idea.Current RFC is large enough already, I'll prepare new one.
We may decide what to do with 2 RFCs.We have choices for with block or without block. I prefer with block
version, since
assert expression could be messy. With block, IDE may do it's jobs.
i.e. Hide blocks.==============================================
Function/Method[With block]
function foo()
require {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
return {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
{
// body
}OR
[Without block]
function foo() {
require(assert-expr, 'msg');
require(assert-expr, 'msg');
require(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');
return(assert-expr, 'msg');// function body
}Currently, following code wouldn't work (PHP 7.0.0-dev)
assert(function() {return FALSE;}, 'AAAAA');
For block version, which do you prefer, allow any PHP syntax or assert
only?
People may use anonymous function to do fancy jobs anyway if it's
supported.No block version only accepts EXPR obviously, but anonymous function
may
be used with this as well.==============================================
Class invariants[With block]
class Foo {
__invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}
}OR
[Without block]
class Foo {
__construct() {
invariant(assert-expr, 'msg'); // Only allow in __construct()?
Allowing invariant.
invariant(assert-expr, 'msg');
invariant(assert-expr, 'msg');
}
}==============================================
Global invariantI'm not sure if we should have
function __invariants() {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}OR
invariant {
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
assert(assert-expr, 'msg');
}to assert global vars, whole app state, etc. It may be useful for unit
tests as well as app development.I'll start working after I get comment from you.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Dmitry and Joe,
yes. this may work.
probably better to put it after extends and implements.Dmitry.
Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
This would work.
If users have adopted DbC in some way, 'invariant' may be used already.
I see two issues.
Interface works, but most classes are class without interfaces. Then users
have to repeat
require()/return() many times to check class state or have to use interface
for DbC.
Since compiler does not know a method() is for DbC invariant, it will be
compiled and exists
in production execution.
Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons) - if interface is not used, user has to repeat invariant conditions over
and over (cons) - requires to define method that should not exist in production (cons)
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.
On place closure call like javascript is not supported in PHP, but function
works with assert.
<?php
function foo() { return FALSE; }
assert(foo());
?>
PHP Warning: assert()
: Assertion failed in - on line 3
This wouldn't be changed for require()/return()/invariant()?
We need a switch to change development/production. I'll use "dbc=On/Off"
for now.
If you have any better idea, please let me know. (dbc will be INI_SYSTEM)
For CLI, there will be no command line switch for dbc. It executes script
production mode by
default. If user needs development mode
php -d dbc=1 script.php
should be used.
And finally, are we going to allow custom assertion error message? e.g.
require($a > 0, 'Parameter $a must be positive number');
Since this contract is definition like "implements"/"extends", we may not
allow
custom error message. I'll write the RFC not to allow custom error messages
unless
you dislike it.
I think we have enough consensus/information to start writing the RFC.
If I have any concern, I'll ask here.
Regards,
P.S. If anyone finds issues with DbC as class definition, please let me
know.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons)- if interface is not used, user has to repeat invariant conditions over
and over (cons)- requires to define method that should not exist in production (cons)
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.
It might be be better to use special method. No keyword, use only reserved
method name __func().
I'll write what I think that are better for PHP in the RFC.
We may discuss anything here to complete the RFC.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production (cons)
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.It might be be better to use special method. No keyword, use only reserved
method name __func().
I'll write what I think that are better for PHP in the RFC.
We may discuss anything here to complete the RFC.
The RFC draft is ready.
https://wiki.php.net/rfc/dbc2
I think we might be better to use
return($ret) {
assert($ret > 0);
}
as the syntax. It doesn't look like definition, but code though.
We may introduce $> or like as return value, but it looks like PERL.
It's not for me, but PHP stands for People Hate Perl for some.
Any comments, corrections, improvements are appreciated.
If anyone could fix bad English, it would be great!
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Morning,
A good start ... ish ...
Please steer clear of using the assert API, and in so doing avoid BC
concerns with the current assert API.
Please avoid adding a magic method and use the suggested syntax for
invariant.
class Some {
require(invariant-expr);
/* ... */
}
like that is best I think ...
You need to explain how invariants are going to be inherited and executed
in detail.
Keep statements such as
With proper use of DbC concept, it is known programs to be more robust,
secure and faster
Out of the RFC, since that cannot possibly be true and is just going to
cause people to argue about that point when it's extremely unimportant.
Cheers
Joe
Hi all,
Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production (cons)
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.It might be be better to use special method. No keyword, use only
reserved method name __func().
I'll write what I think that are better for PHP in the RFC.
We may discuss anything here to complete the RFC.The RFC draft is ready.
https://wiki.php.net/rfc/dbc2I think we might be better to use
return($ret) {
assert($ret > 0);
}as the syntax. It doesn't look like definition, but code though.
We may introduce $> or like as return value, but it looks like PERL.
It's not for me, but PHP stands for People Hate Perl for some.Any comments, corrections, improvements are appreciated.
If anyone could fix bad English, it would be great!Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Joe,
You need to explain how invariants are going to be inherited and executed
in detail.
OK. Thank you. This wouldn't change even if syntax changes.
Keep statements such as
With proper use of DbC concept, it is known programs to be more
robust, secure and fasterOut of the RFC, since that cannot possibly be true and is just going to
cause people to argue about that point when it's extremely unimportant.
Good point.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Joe's idea was to use Interface for invariant condition grouping.
It wasn't, it was to use "require" at the class declaration, using it in
the class body is better still ...
Cheers
Joe
Hi Joe,
On Tue, Feb 10, 2015 at 3:16 PM, Joe Watkins pthreads@pthreads.org
wrote:You need to explain how invariants are going to be inherited and executed
in detail.OK. Thank you. This wouldn't change even if syntax changes.
Keep statements such as
With proper use of DbC concept, it is known programs to be more
robust, secure and fasterOut of the RFC, since that cannot possibly be true and is just going to
cause people to argue about that point when it's extremely unimportant.Good point.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi!
Please steer clear of using the assert API, and in so doing avoid BC
concerns with the current assert API.
The operator can be called something other than "assert", I'm sure the
thesaurus has a lot of possibilities.
Please avoid adding a magic method and use the suggested syntax for
invariant.class Some {
require(invariant-expr);
I think reusing syntax for existing operator in completely unrelated
context is a big mistake. Having code outside of functions is probably
not the best idea too.
--
Stas Malyshev
smalyshev@gmail.com
I think reusing syntax for existing operator in completely unrelated
context is a big mistake.
I keep hearing that, I agree, but adding keywords presents it's own
problems.
The keywords can always be changed, maybe they can be a voting option even.
Cheers
Joe
On Wed, Feb 11, 2015 at 6:56 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
Please steer clear of using the assert API, and in so doing avoid BC
concerns with the current assert API.The operator can be called something other than "assert", I'm sure the
thesaurus has a lot of possibilities.Please avoid adding a magic method and use the suggested syntax for
invariant.class Some {
require(invariant-expr);I think reusing syntax for existing operator in completely unrelated
context is a big mistake. Having code outside of functions is probably
not the best idea too.--
Stas Malyshev
smalyshev@gmail.com
I still don't see what's wrong with just putting the code
at the beginning of the function and whenever you want to check it
That makes inheritance of contracts awkward/impossible/impractical:
class Some {
public function method() {
assertOrWhatever($expr);
}
}
class Other extends Some {
public function method() {
}
}
The implementation of Other::method cannot inherit or otherwise make use of
the contracts made by Some.
Putting invariants in the class scope and pre/post conditions in the
function prototype makes inheritance relatively easy.
This seems to answer all your questions.
Cheers
Joe
I think reusing syntax for existing operator in completely unrelated
context is a big mistake.I keep hearing that, I agree, but adding keywords presents it's own
problems.The keywords can always be changed, maybe they can be a voting option even.
Cheers
JoeOn Wed, Feb 11, 2015 at 6:56 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
Please steer clear of using the assert API, and in so doing avoid BC
concerns with the current assert API.The operator can be called something other than "assert", I'm sure the
thesaurus has a lot of possibilities.Please avoid adding a magic method and use the suggested syntax for
invariant.class Some {
require(invariant-expr);I think reusing syntax for existing operator in completely unrelated
context is a big mistake. Having code outside of functions is probably
not the best idea too.--
Stas Malyshev
smalyshev@gmail.com
Hi Stas,
I agree, it may look weird at first, but if you familiar with concept it
looks more or less natural. It's implemented in D, Effiel, it was a
proposal for Java, etc
Anyway, we will have at least 3 competing proposals.
- contracts in doc-commetns https://wiki.php.net/rfc/dbc
/**
- @requires ($a >= 0)
*/
function foo($a) {
}
- contracts as part of the language https://wiki.php.net/rfc/dbc2
function foo($a)
require($a >= 0)
{
}
- contracts in annotations
<<requires($a >= 0)>>
function foo($a) {
}
The fact that we are working on (2) now, doesn't mean we will select it as
a final solution. (3) is an interesting option as well.
Thanks. Dmitry.
On Wed, Feb 11, 2015 at 9:56 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
Please steer clear of using the assert API, and in so doing avoid BC
concerns with the current assert API.The operator can be called something other than "assert", I'm sure the
thesaurus has a lot of possibilities.Please avoid adding a magic method and use the suggested syntax for
invariant.class Some {
require(invariant-expr);I think reusing syntax for existing operator in completely unrelated
context is a big mistake. Having code outside of functions is probably
not the best idea too.--
Stas Malyshev
smalyshev@gmail.com
Hi!
- contracts in doc-commetns https://wiki.php.net/rfc/dbc
/**
- @requires ($a >= 0)
*/
function foo($a) {
}
We've spent several years rejecting annotations because no information
can be in comments, not even a little bit, not even a tiny. Now we'd
have full-blown running code in comments? How would this code be
debugged/profiled/interpreted by tools? Writing PHP parser is not easy
right now, but this would turn it into nightmare (what if you have a
comment inside @requires? etc.)
- contracts as part of the language https://wiki.php.net/rfc/dbc2
function foo($a)
require($a >= 0)
{
}
This is a step better but still we have the similar issues with
readability, to which reuse of 'require' is added.
- contracts in annotations
<<requires($a >= 0)>>
function foo($a) {
}
That one actually looks better to me, but: I'm not sure how annotation
syntax is supposed to support expressions or closures, yet more - how it
is supposed to share the scope with the function. I.e., if you define
annotation class/method/function/data structure/whatever it is, what it
is supposed to receive? Is it some special form of annotation for this
purpose only (meh)?
Oh, and <<>> syntax is ugly ;)
--
Stas Malyshev
smalyshev@gmail.com
Hi!
function foo($a)
require($a >= 0)
{
}This is a step better but still we have the similar issues with
readability, to which reuse of 'require' is added.
Just a thought - what about something like __pre/__post? We own __*, so
no BC problems.
OTOH, don't our new parsing improvements allow us to handle syntax like
this without introducing a keyword that would be forbidden as
class/function name? The context is pretty unambiguous here.
Stas Malyshev
smalyshev@gmail.com
Just a thought - what about something like __pre/__post? We own __*, so
no BC problems.
I'm not married to the words being used, at all.
I think this is a good idea, we would need __pre, __post , and __invariant,
or some combination of three.
Any objection to using __ prefixed names, and any other suggestion for
them, or just use the above ?
Cheers
Joe
On Wed, Feb 11, 2015 at 8:09 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
function foo($a)
require($a >= 0)
{
}This is a step better but still we have the similar issues with
readability, to which reuse of 'require' is added.Just a thought - what about something like __pre/__post? We own __*, so
no BC problems.
OTOH, don't our new parsing improvements allow us to handle syntax like
this without introducing a keyword that would be forbidden as
class/function name? The context is pretty unambiguous here.Stas Malyshev
smalyshev@gmail.com
OTOH, don't our new parsing improvements allow us to handle syntax like
this without introducing a keyword that would be forbidden as
class/function name
Not that I am aware of, the AST stuff didn't touch the parser like that, it
has the same limitations it had before AFAIK.
Cheers
Joe
Just a thought - what about something like __pre/__post? We own __*, so
no BC problems.I'm not married to the words being used, at all.
I think this is a good idea, we would need __pre, __post , and
__invariant, or some combination of three.Any objection to using __ prefixed names, and any other suggestion for
them, or just use the above ?Cheers
JoeOn Wed, Feb 11, 2015 at 8:09 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
function foo($a)
require($a >= 0)
{
}This is a step better but still we have the similar issues with
readability, to which reuse of 'require' is added.Just a thought - what about something like __pre/__post? We own __*, so
no BC problems.
OTOH, don't our new parsing improvements allow us to handle syntax like
this without introducing a keyword that would be forbidden as
class/function name? The context is pretty unambiguous here.Stas Malyshev
smalyshev@gmail.com
Hi Joe,
Just a thought - what about something like __pre/__post? We own __*, so
no BC problems.I'm not married to the words being used, at all.
I think this is a good idea, we would need __pre, __post , and
__invariant, or some combination of three.Any objection to using __ prefixed names, and any other suggestion for
them, or just use the above ?
It's very close to my original idea, but I like current definition like
syntax.
No objection from me...
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
We've spent several years rejecting annotations because no information
can be in comments, not even a little bit, not even a tiny.
I find that a strange comment, since I've been using annotation in PHP
from day one. The phpdoc material helped me get started all those years
ago since every third party library had it as part of their coding style
from PHP4 days.
All of the current demands ... and I think they are demands! ... stamp
on past history and load even more work on everybody to have to support
all these new features. Even if dbc is wrapped in comment blocks to hide
it it's potential presence in third party parts of a project means that
all tools have to be modified and my use of phpdoc is further eroded.
I see all these comments about 'D' and 'Effiel' and my ONLY thought is
... Then bloody use that! ... Even the people demanding strict typing!
DbC does not have to modify the core code to be usable by those wanting
it. In the same way that phpdoc has never needed that. BUT a means of
expanding the /* / wrapper to include extra types over the /* tag may
be appropriate, then people can use their own preferred annotation
system, and other tools can simply 'switch off' where appropriate. While
I don't feel 'compiling' is the right way forward for PHP projects, the
'min' processing of files as applied to just about every other scripting
element does make sense as a half way house to opcode caching.
( and some help with actually fixing php7 in code would be appreciated! )
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Hi Lester,
All of the current demands ... and I think they are demands! ... stamp
on past history and load even more work on everybody to have to support
all these new features. Even if dbc is wrapped in comment blocks to hide
it it's potential presence in third party parts of a project means that
all tools have to be modified and my use of phpdoc is further eroded.
The proposal to embed DbC conditions in phpdoc is just defining new '@' keywords. That's the implicit way such a basic annotation system works : tools ignore the lines they don't understand. I ran phpDocumentor on DbC-commented script files, and it still produces the same documentation. It's supposed to be the same with everyone extending phpdoc syntax.
So, I don't understand why you should modify any of your tools.
Cheers
François
All of the current demands ... and I think they are demands! ... stamp
on past history and load even more work on everybody to have to support
all these new features. Even if dbc is wrapped in comment blocks to hide
it it's potential presence in third party parts of a project means that
all tools have to be modified and my use of phpdoc is further eroded.
The proposal to embed DbC conditions in phpdoc is just defining new '@' keywords. That's the implicit way such a basic annotation system works : tools ignore the lines they don't understand. I ran phpDocumentor on DbC-commented script files, and it still produces the same documentation. It's supposed to be the same with everyone extending phpdoc syntax.So, I don't understand why you should modify any of your tools.
While phpDocumentor can ignore elements it does not understand, that
information would be useful to maintain, so some modification of it's
parsing would be appropriate. But I was referring more to the other
proposals for adding essentially the same information, and how that
might be hidden in non-docblock comment packets.
But currently some tools are lagging behind even current changes in PHP
and phpDocumentor does not get everything right already. I can't get a
clean set of documents currently with either the original version or the
Mk2 version of phpDocumentor on code that has produced clean documents
in the past. Just another area that needs time spending to work out what
now need updating which does not affect the working code.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
On Wed, Feb 11, 2015 at 10:58 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
- contracts in doc-commetns https://wiki.php.net/rfc/dbc
/**
- @requires ($a >= 0)
*/
function foo($a) {
}We've spent several years rejecting annotations because no information
can be in comments, not even a little bit, not even a tiny. Now we'd
have full-blown running code in comments? How would this code be
debugged/profiled/interpreted by tools? Writing PHP parser is not easy
right now, but this would turn it into nightmare (what if you have a
comment inside @requires? etc.)
I don't see how this can be implemented in PHP core as well.
This approach is for external tools.
- contracts as part of the language https://wiki.php.net/rfc/dbc2
function foo($a)
require($a >= 0)
{
}This is a step better but still we have the similar issues with
readability, to which reuse of 'require' is added.
- contracts in annotations
<<requires($a >= 0)>>
function foo($a) {
}That one actually looks better to me, but: I'm not sure how annotation
syntax is supposed to support expressions or closures,
keep AST.
yet more - how it
is supposed to share the scope with the function. I.e., if you define
annotation class/method/function/data structure/whatever it is, what it
is supposed to receive?
We may have AST transformation pass that would convert these annotations
into assert()
and insert them into AST of the function.
Is it some special form of annotation for this
purpose only (meh)?
yes. some special attributes. requires/ensures/invariant
Oh, and <<>> syntax is ugly ;)
It's from HHVM. I don't like it as well, please, propose the better one.
Thanks. Dmitry.
--
Stas Malyshev
smalyshev@gmail.com
2015-02-11 13:25 GMT+02:00 Dmitry Stogov dmitry@zend.com:
yes. some special attributes. requires/ensures/invariant
Oh, and <<>> syntax is ugly ;)
It's from HHVM. I don't like it as well, please, propose the better one.
I like syntax, like a switch:
function add(int $a, int $b) : int
case $a > 0:
case $b > 0:
return($ret, $ret > 0, "something wrong")
{
return $a + $b;
}
Hi!
That one actually looks better to me, but: I'm not sure how annotation syntax is supposed to support expressions or closures,
keep AST.
So we'd have a zval type that is the raw AST? Would it also be available
to user functions or internal functions/classes? It's an intriguing
concept but I'm not sure we appreciate all the consequences of it -
adding new type is a rather big change as everything should support it.
Or did you mean something else?
Is it some special form of annotation for this purpose only (meh)?
yes. some special attributes. requires/ensures/invariant
Ah, so <<require()>> annotation would work different than any other type
of annotation? Then I don't see any use for it to use annotation syntax
(whatever it would be) - same syntax should mean same or at least
similar function. Maybe I am still missing what you meant.
Oh, and <<>> syntax is *ugly* ;)
It's from HHVM. I don't like it as well, please, propose the better one.
Pretty much every other one is better:
Java and the followers, Python: @foo
C#: [foo]
--
Stas Malyshev
smalyshev@gmail.com
Hi,
On Wed, Feb 11, 2015 at 10:05 PM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
That one actually looks better to me, but: I'm not sure how
annotation
syntax is supposed to support expressions or closures,
keep AST.
So we'd have a zval type that is the raw AST? Would it also be available
to user functions or internal functions/classes? It's an intriguing
concept but I'm not sure we appreciate all the consequences of it -
adding new type is a rather big change as everything should support it.
Or did you mean something else?
This is just an initial idea, and some research is required.
I don't propose to add new ZVAL type. AST may be just stored internally and
accesses through extended Reflection API.
This API may provide some classes to represent AST nodes.
Is it some special form of annotation for this purpose only (meh)?
yes. some special attributes. requires/ensures/invariant
Ah, so <<require()>> annotation would work different than any other type
of annotation? Then I don't see any use for it to use annotation syntax
(whatever it would be) - same syntax should mean same or at least
similar function. Maybe I am still missing what you meant.
I don't understand you as well. It should be clear, that annotation should
allow declaration of any attributes, and some of them may be used for
different purposes. some for DbC.
Oh, and <<>> syntax is *ugly* ;)
It's from HHVM. I don't like it as well, please, propose the better one.
Pretty much every other one is better:
Java and the followers, Python: @foo
C#: [foo]
[foo] is already a legal syntax in PHP - array with constant foo.
Thanks. Dmitry.
--
Stas Malyshev
smalyshev@gmail.com
Hi all,
We have discussed most of issues for https://wiki.php.net/rfc/dbc2
==Missing parts of the RFC for me==
-
Advantage over annotation:
Written as code, executed as code. ("Written as document, available
as document" would be
annotation advantage) -
Advantage over
assert()
only solution:
Part of DbC can be done byassert()
only, but it reduces readability.
Post condition can be
located anywhere in function. It makes difficult to distinguish if
assert()
is contract or internal
error. Invariant helps to reduce number ofassert()
a lot. In short,
contract and internal logic
assertion is different assertion.
DbC encourage proper class design. It's taken from Eiffel site.
https://www.eiffel.com/values/design-by-contract/introduction/
"These observations shed light on the true significance of
inheritance: not just a reuse,
subtyping and classification mechanism, but a way to ensure
compatible semantics by
other means. They also provide useful guidance as to how to use
inheritance properly."DbC encourages proper secure design. Since DbC removes all assertion
from production
code, users must ensure app input/output validity when it accepts
input and write outputs.
http://cwe.mitre.org/top25/#Mitigations
https://www.owasp.org/images/0/08/OWASP_SCP_Quick_Reference_Guide_v2.pdf
DbC also encourages proper defense in depth, since users must think
"where is the
best place for defense in depth?" with DbC.
These helps users to adopt desirable secure and efficient
application architecture. This
cannot be accomplished only by assert()
.
-
Recursion
Since DbC evaluate contracts automatically, certain code may lead to
infinite recursion.
Most obvious is calling itself. e.g.
myMethod() {
require(MyMethod());
}
We don't need protections for bad code. -
Clearness:
Interface/trait support. I suppose it is. Am I correct?
Normal function support may not be obvious for people didn't involve
discussion.
Global invariant (main function invariant). This is not supported. -
Future scope:
Internal module class/interface support. e.g. SessionHandlerInterface
Someone may insist immutable over invariant. Immutable and invariant
is not the
same for me. It may be better to state "immutables" as stricter
constraint.
Joe, could you add some them? You do better job than me :) I don't mind
whichever
you pick. These are not mandatory.
==Ideas for open issues==
- Contracts inheritance rules
Invariant should be implicit like D and Eiffel and evaluated always under
DbC mode.
For method calls, overridden method should not evaluate parents contract on
entry.
It should be evaluated when parent method is called.
D had restriction to call public methods from invaliant. Calling public
method from
invariant might be better to be restricted. It might be OK to allow user to
shoot
their own foot since user can do that with protected/private method anyway.
- Consider introduction of static require() as class invariant for static
methods
I probably don't understand the idea correctly. Could you give some
explanations?
- Need to discuss syntax
There were many ideas for possible syntaxes, I prefer current simple syntax.
Syntax is not my priority. I don't mind require{assert();},
return{assert();}, etc.
Since "error message" can be added and any expression is allowed, writing
contracts
as code may be better. We are better to avoid new keyword whenever it's
possible.
- How to manage votes for 2 RFCs
Both RFCs are large enough. How about make vote only RFC
https://wiki.php.net/rfc/dbc_vote
- Explain what is DbC.
- Choose "Introduce Native DbC for PHP - Yes or No"
- For people voted for Yes, "Annotation or Code" refer
links to https://wiki.php.net/rfc/dbc, https://wiki.php.net/rfc/dbc2 - Choose "Annotation or Code"
==Annotation DbC Implementation==
Dmitry, I guess it wouldn't be too hard for you to implement this RFC. How
about annotation
version? Can it be implemented with reasonable amount of efforts?
Thank you all those who are contributed discussion!
I hope you choose to have DbC support. DbC helps to achieve "strict/precise
development"
and "maximum performance in production" at the same time.
Regards,
P.S. It takes time to get used to new syntax. We may be better try to
expose new syntax
as much as possible. i.e. Put new syntax in mails whenever possible.
Native DbC support syntax:
class Child {
require($this->age < 18); // Invariant (Class state condition)
public function someMethod($input)
require(somethingAbout($input)) // Precondition
return($ret, somethingReturn($ret)) // Postcondition
{
/* Great! We are certain that caller satisfy precondition, return
appropriate return value and have proper class state! */
}
}
--
Yasuo Ohgaki
yohgaki@ohgaki.net
> myMethod() {
> require(MyMethod());
> }
>
My hand is not used to new syntax yet. This should be.
myMethod()
require(myMethid())
{
/* */
}
==========
Native DbC support syntax:
class Child {
require($this->age < 18); // Invariant (Class state condition)
public function someMethod($input)
require(somethingAbout($input)) // Precondition
return($ret, somethingReturn($ret)) // Postcondition
{
/* Great! We are certain that caller satisfy precondition, return
appropriate return value and have proper class state! */
}
}
--
Yasuo Ohgaki
yohgaki@ohgaki.net
"Stanislav Malyshev" wrote in message news:54DAFD32.3000005@gmail.com...
Hi!
Please steer clear of using the assert API, and in so doing avoid BC
concerns with the current assert API.The operator can be called something other than "assert", I'm sure the
thesaurus has a lot of possibilities.
How about "pre_assert" and "post_assert"? As Dbc is supposed to be about
defining preconditions and postconditions the use of the word "pre" and
"post" would seem appropriate.
--
Tony Marston
The RFC draft is ready.
https://wiki.php.net/rfc/dbc2
These contracts are evaluated development time only. Therefore, there is no performance penalty with DbC.
Sorry but that makes no sense to me at all. If this is something only to
use with an IDE then why does it have to have anything that is visible
at 'run time'? This seems to be going down the track of "we will be
compiling this eventually" and that is just not what PHP IS about.
These are more hints, but assume that at runtime what they define is not
relevant?
ALL of this discussion on type hinting how ever it is handled is simply
sidestepping the major plus on PHP with associative arrays. I see no
point expanding every database record read to 'magic access functions'
for multiple variables and it IS the scalar values stored in these
arrays that needs the 'hint/constraint' control.
I am getting even more confused about just what all the different
factions are trying to achieve. Yes I know I can totally ignore all of
it, but with my current tools losing traction because of all the 'better
ways of working' what in my opinion IS the best way to allow different
factions to add their own pet style is drowning simple clean solutions
such as docblock.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Hello, internals!
DbC is good thing, but the way you want to do this via language changes is
really awful. Why do you want to add more custom features into the
language, instead of providing an API to extend it in a more natural way by
framework developers?
Many existing implementation of DbC is just kind of bytecode compilers and
IDE tools. Main idea of DbC is to help developer with writing a better code
without errors. But then, during compiling (production mode) all checks
will be removed.
Am I one who think that this code is looking weird?
public function destroy($id)
require(strlen <http://www.php.net/strlen>($id) > 10)
return(is_bool <http://www.php.net/is_bool>($>))
{
@unlink <http://www.php.net/unlink>($this->path . $id);
}
This part of code is breaks block structure of function, adding custom
part of code, which is not related to the function logic itself.
Instead of doing this weird syntax only for personal fun, just think
about more general usages of parser and assertions.
As you know, I'm working with aspect-oriented programming in PHP and
have a library for that. And it wasn't easy to implement it, because
there is no API for that from PHP. This techniques can be also used
for DbC as well.
So, my suggestion is to drop current rfc and start more general one,
called "PHP Language Extension API", which will include an API for
defining metadata and API for opcode manipulation. Compare previous
example with another one with plain metadata:
[Require => strlen <http://www.php.net/strlen>($id) > 10)]
[Return => is_bool <http://www.php.net/is_bool>($__result))
public function destroy($id)
{
@unlink <http://www.php.net/unlink>($this->path . $id);
}
This code then will be parsed and PHP hooks that were registered by
register_parser_extension() will be called and extension will
produce a valid opcodes for that for method destroy(), by modifying AST-node.
This way is much elegant and can be reused later for many features,
like Design By Contracts, native SQL support syntax in PHP (LINQ),
Aspect-Oriented Programming, hooks and much more.
Just stop to create custom features in the engine itself and give this
work for framework and PHP-extension developers.
2015-02-10 13:32 GMT+03:00 Lester Caine lester@lsces.co.uk:
The RFC draft is ready.
https://wiki.php.net/rfc/dbc2These contracts are evaluated development time only. Therefore, there is
no performance penalty with DbC.Sorry but that makes no sense to me at all. If this is something only to
use with an IDE then why does it have to have anything that is visible
at 'run time'? This seems to be going down the track of "we will be
compiling this eventually" and that is just not what PHP IS about.
These are more hints, but assume that at runtime what they define is not
relevant?ALL of this discussion on type hinting how ever it is handled is simply
sidestepping the major plus on PHP with associative arrays. I see no
point expanding every database record read to 'magic access functions'
for multiple variables and it IS the scalar values stored in these
arrays that needs the 'hint/constraint' control.I am getting even more confused about just what all the different
factions are trying to achieve. Yes I know I can totally ignore all of
it, but with my current tools losing traction because of all the 'better
ways of working' what in my opinion IS the best way to allow different
factions to add their own pet style is drowning simple clean solutions
such as docblock.--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Am 10.02.2015 12:45 schrieb "Alexander Lisachenko" <lisachenko.it@gmail.com
:
DbC is good thing, but the way you want to do this via language changes is
really awful. Why do you want to add more custom features into the
language, instead of providing an API to extend it in a more natural way
by
framework developers?
Ahem. Any open ended API-for-frameworks will A) force me to pick a
framework and bend to the way it wants these things to look, and B) result
in fragmentation and incompatibilities for any two pieces of code/library
developed with different such frameworks in mind. That will be a total mess.
Having it in the language means I can just use it. Unit tests can just use
it, especially the PHP tests themselves. And if and where frameworks think
they need to mess with it, they can surely be given some Reflection API to
have a go at it.
best regards
Patrick
2015-02-10 14:56 GMT+03:00 Patrick Schaaf bof@bof.de:
Ahem. Any open ended API-for-frameworks will A) force me to pick a
framework and bend to the way it wants these things to look, and B) result
in fragmentation and incompatibilities for any two pieces of code/library
developed with different such frameworks in mind. That will be a total mess.
It's another task for another people, typically for standartization group,
like PSR, JSR, PEP, etc. Framework developers should rely on interfaces and
should provide interfaces. For Java world this works (some ideas here
http://java.dzone.com/articles/jsr-305-and-design-contract)
If put all the things into the PHP core, it will become much bigger, more
slower and hard to maintain. Later posts describes EOL for some extensions
and SAPIs, but this place will not be clean, because another custom feature
XXX is landed on free space.
I would like to see a language with good extension API. For now, it's
almost impossible to extend a parser, even from extension level (however,
PHP7 will have a hook for that, thanks God).
2015-02-10 15:10 GMT+03:00 Alexander Lisachenko lisachenko.it@gmail.com:
I would like to see a language with good extension API. For now, it's
almost impossible to extend a parser, even from extension level (however,
PHP7 will have a hook for that, thanks God).
To understand how it can be implemented, just read about Checker Framework
(Java) http://types.cs.washington.edu/checker-framework/
...The Checker Framework enhances Java’s type system to make it more
powerful and useful. This lets software developers detect and prevent
errors in their Java programs. The Checker Framework includes compiler
plug-ins ("checkers") that find bugs or verify their absence. It also
permits you to write your own compiler plug-ins...
This is built on top of reflection+annotation+parser extension.
Why not to implement this for PHP? From my point of view, this is just an
additional feature, that can be used by limited number of developers.
On Tue, Feb 10, 2015 at 2:44 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:
> Hello, internals!
>
> DbC is good thing, but the way you want to do this via language changes is
> really awful. Why do you want to add more custom features into the
> language, instead of providing an API to extend it in a more natural way by
> framework developers?
>
>
First of all, I know that you have something working, so your opinion and
suggestions are important for us.
I already told that currently we are in a brainstorming phase
We already have two drafts:
https://wiki.php.net/rfc/dbc (doc-comment based)
https://wiki.php.net/rfc/dbc2 (inspired by D language)
both have their pros and cons.
> Many existing implementation of DbC is just kind of bytecode compilers and
> IDE tools. Main idea of DbC is to help developer with writing a better code
> without errors. But then, during compiling (production mode) all checks
> will be removed.
>
this should be implemented with zero-cost assert proposed long time ago
https://wiki.php.net/rfc/expectations
>
> Am I one who think that this code is looking weird?
>
> public function destroy($id)
> require(strlen($id) > 10)
> return(is_bool($>))
> {
> @unlink($this->path . $id);
> }
>
>
For me it's quite readable.
>
> This part of code is breaks block structure of function, adding custom
> part of code, which is not related to the function logic itself.
>
> Instead of doing this weird syntax only for personal fun, just think
> about more general usages of parser and assertions.
> As you know, I'm working with aspect-oriented programming in PHP and
> have a library for that. And it wasn't easy to implement it, because
> there is no API for that from PHP. This techniques can be also used
> for DbC as well.
>
So, my suggestion is to drop current rfc and start more general one,
> called "PHP Language Extension API", which will include an API for
> defining metadata and API for opcode manipulation. Compare previous
> example with another one with plain metadata:
>
> [Require => strlen($id) > 10)]
> [Return => is_bool($__result))
> public function destroy($id)
> {
> @unlink($this->path . $id);
> }
>
for me it's less readable, but this is a general solution that may be
reused for other features. So, it's interesting.
>
> This code then will be parsed and PHP hooks that were registered by
> register_parser_extension() will be called and extension will
> produce a valid opcodes for that for method destroy(), by modifying
> AST-node.
>
I thought about this way, and you are welcome to start composing another
RFC. it makes sense and has its advantages.
Unfortunately, it relays on many unavailable features that has to be
designed as well (annotations, AST manipulation, opcode manipulation), but
may be this is a right road.
> This way is much elegant and can be reused later for many features,
> like Design By Contracts, native SQL support syntax in PHP (LINQ),
> Aspect-Oriented Programming, hooks and much more.
>
> Just stop to create custom features in the engine itself and give this
> work for framework and PHP-extension developers.
>
D and Effiel approach may work as well, but if you like another (annotation
based) approach - be involved into development.
At first we'll need 3-rd RFC that defines all the things that must be
implemented.
I may help, with RFC, design and implementation.
Thanks. Dmitry.
>
>
>
> 2015-02-10 13:32 GMT+03:00 Lester Caine
>
> >
> > > The RFC draft is ready.
> > > https://wiki.php.net/rfc/dbc2
> >
> > > These contracts are evaluated development time only. Therefore, there
> is
> > no performance penalty with DbC.
> >
> > Sorry but that makes no sense to me at all. If this is something only to
> > use with an IDE then why does it have to have anything that is visible
> > at 'run time'? This seems to be going down the track of "we will be
> > compiling this eventually" and that is just not what PHP *IS* about.
> > These are more hints, but assume that at runtime what they define is not
> > relevant?
> >
> > ALL of this discussion on type hinting how ever it is handled is simply
> > sidestepping the major plus on PHP with associative arrays. I see no
> > point expanding every database record read to 'magic access functions'
> > for multiple variables and it *IS* the scalar values stored in these
> > arrays that needs the 'hint/constraint' control.
> >
> > I am getting even more confused about just what all the different
> > factions are trying to achieve. Yes I know I can totally ignore all of
> > it, but with my current tools losing traction because of all the 'better
> > ways of working' what in my opinion IS the best way to allow different
> > factions to add their own pet style is drowning simple clean solutions
> > such as docblock.
> >
> > --
> > Lester Caine - G8HFL
> > -----------------------------
> > Contact - http://lsces.co.uk/wiki/?page=contact
> > L.S.Caine Electronic Services - http://lsces.co.uk
> > EnquirySolve - http://enquirysolve.com/
> > Model Engineers Digital Workshop - http://medw.co.uk
> > Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
2015-02-10 15:20 GMT+03:00 Dmitry Stogov dmitry@zend.com:
I thought about this way, and you are welcome to start composing another
RFC. it makes sense and has its advantages.
Unfortunately, it relays on many unavailable features that has to be
designed as well (annotations, AST manipulation, opcode manipulation), but
may be this is a right road.
Thanks, Dmitry! Your position is clearly highlight my vision, it's not so
easy, but maybe it will bring us much more profit at the end.
2015-02-10 15:20 GMT+03:00 Dmitry Stogov dmitry@zend.com:
D and Effiel approach may work as well, but if you like another
(annotation based) approach - be involved into development.
At first we'll need 3-rd RFC that defines all the things that must be
implemented.
I may help, with RFC, design and implementation.
Thanks, your help is really appreciated ) I'l try to start another one RFC
about this API, let's have a look what can be done.
On Tue, Feb 10, 2015 at 1:30 PM, Alexander Lisachenko
lisachenko.it@gmail.com wrote:
2015-02-10 15:20 GMT+03:00 Dmitry Stogov dmitry@zend.com:
I thought about this way, and you are welcome to start composing another
RFC. it makes sense and has its advantages.
Unfortunately, it relays on many unavailable features that has to be
designed as well (annotations, AST manipulation, opcode manipulation), but
may be this is a right road.Thanks, Dmitry! Your position is clearly highlight my vision, it's not so
easy, but maybe it will bring us much more profit at the end.2015-02-10 15:20 GMT+03:00 Dmitry Stogov dmitry@zend.com:
D and Effiel approach may work as well, but if you like another
(annotation based) approach - be involved into development.
At first we'll need 3-rd RFC that defines all the things that must be
implemented.
I may help, with RFC, design and implementation.Thanks, your help is really appreciated ) I'l try to start another one RFC
about this API, let's have a look what can be done.
Hello,
maybe you could try to consult your ideas with Ivan Enderlin. He
mentioned in previous emails (for instance
http://news.php.net/php.internals/82245) that he would prefer some
AOP/hook-based approach to DbC as well, so it may be compatible with
your mindset.
Regards
Pavel Kouril
2015-02-10 15:35 GMT+03:00 Pavel Kouřil pajousek@gmail.com:
Hello,
maybe you could try to consult your ideas with Ivan Enderlin. He
mentioned in previous emails (for instance
http://news.php.net/php.internals/82245) that he would prefer some
AOP/hook-based approach to DbC as well, so it may be compatible with
your mindset.
Yes, I know about Praspel, it's quite a good implementation, but for
specific case. My implementation of DbC is built on top of AOP and can be
described with only one (!) aspect and few annotations. If you are
interested in it, you could look across wiki
https://github.com/lisachenko/php-deal/wiki or even open an aspect class
itself
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php
to see an advices that will be triggered as custom hooks before/after or
around original method invocations.
I think, that AOP-based solution is pretty nice: it's only for development
mode. Annotations are not parsed for production mode and looks like a good
documentation, this can be improved later with BDD (Gherkin) to define a
contracts in human-readable format.
@Contract\Verify("Given $amount is positive")
@Contract\Ensure("Result is changed from $old to $old+$amount")
So, it can be a good idea to discuss this topic with Ivan Enderlin. Maybe
he can help me with RFC too.
Hi!
Hello, internals!
DbC is good thing, but the way you want to do this via language changes is
really awful. Why do you want to add more custom features into the
Agreed here. I still don't see what's wrong with just putting the code
at the beginning of the function and whenever you want to check it. Why
this need to change the language syntax? OK, you don't like assert
because it's limited or performance-costly or whatever. We can fix that.
Why we need weird syntax that places function code in three different
places, reuses existing syntax constructs for things that have nothing
to do with their original use and look like Perl YAPH signature? I
understand implementing fashionable concepts is fun, but must they come
with weird syntax? Why can't we keep it simple?
--
Stas Malyshev
smalyshev@gmail.com
it's possible to achieve the same validation just with assert()
spread over
the code.
It's nothing wrong with this, but this is not DbC.
The question, if we need DbC at all, is still open.
Thanks. Dmitry.
On Wed, Feb 11, 2015 at 10:05 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
Hello, internals!
DbC is good thing, but the way you want to do this via language changes
is
really awful. Why do you want to add more custom features into theAgreed here. I still don't see what's wrong with just putting the code
at the beginning of the function and whenever you want to check it. Why
this need to change the language syntax? OK, you don't like assert
because it's limited or performance-costly or whatever. We can fix that.
Why we need weird syntax that places function code in three different
places, reuses existing syntax constructs for things that have nothing
to do with their original use and look like Perl YAPH signature? I
understand implementing fashionable concepts is fun, but must they come
with weird syntax? Why can't we keep it simple?--
Stas Malyshev
smalyshev@gmail.com
Hi Dmitry and Joe,
yes. this may work.
probably better to put it after extends and implements.Dmitry.
On Mon, Feb 9, 2015 at 2:19 PM, Joe Watkins pthreads@pthreads.org
wrote:Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
This would work.
If users have adopted DbC in some way, 'invariant' may be used already.I see two issues.
Interface works, but most classes are class without interfaces. Then
users have to repeat
require()/return() many times to check class state or have to use
interface for DbC.
In D classes may have "invariant" constraints. We may use "require" keyword
for it. The constraints ineritance rules and order of calls to constrains
must be the same s in D.
class Foo {
private $sum = 0;
require($this->sum >= 0); // invariant constraint will be called before
and after every method
function add($n) {
$this->sum += $n;
}
}
Since compiler does not know a method() is for DbC invariant, it will be
compiled and exists
in production execution.Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production (cons)
I didn't understand you idea.
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.On place closure call like javascript is not supported in PHP, but
function works with assert.<?php
function foo() { return FALSE; }
assert(foo());
?>
PHP Warning:assert()
: Assertion failed in - on line 3This wouldn't be changed for require()/return()/invariant()?
We need a switch to change development/production. I'll use "dbc=On/Off"
for now.
If you have any better idea, please let me know. (dbc will be INI_SYSTEM)
Check the "expectations" RFC. I think, it's going to be 3 state switch,
zero-cost disable, run-time disable, run-time enable. So, it may be
INI_ALL, but it won't be possible to switch from/to zero-cost at run-time.
For CLI, there will be no command line switch for dbc. It executes script
production mode by
default. If user needs development modephp -d dbc=1 script.php
should be used.
And finally, are we going to allow custom assertion error message? e.g.
require($a > 0, 'Parameter $a must be positive number');
I think, it may be useful.
Since this contract is definition like "implements"/"extends", we may not
allow
custom error message. I'll write the RFC not to allow custom error
messages unless
you dislike it.I think we have enough consensus/information to start writing the RFC.
If I have any concern, I'll ask here.
Ok, go forward :)
Thanks. Dmitry.
Regards,
P.S. If anyone finds issues with DbC as class definition, please let me
know.--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Dmitry,
Hi Dmitry and Joe,
yes. this may work.
probably better to put it after extends and implements.Dmitry.
On Mon, Feb 9, 2015 at 2:19 PM, Joe Watkins pthreads@pthreads.org
wrote:Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
This would work.
If users have adopted DbC in some way, 'invariant' may be used already.I see two issues.
Interface works, but most classes are class without interfaces. Then
users have to repeat
require()/return() many times to check class state or have to use
interface for DbC.In D classes may have "invariant" constraints. We may use "require"
keyword for it. The constraints ineritance rules and order of calls to
constrains must be the same s in D.class Foo {
private $sum = 0;
require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}
OK. I'll update the RFC.
Since compiler does not know a method() is for DbC invariant, it will be
compiled and exists
in production execution.Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production (cons)
I didn't understand you idea.
Joe's idea was to use Interface for invariant condition grouping.
If we use your idea, issue is solved.
class Foo {
private $sum = 0; require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}
Ok.
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.On place closure call like javascript is not supported in PHP, but
function works with assert.<?php
function foo() { return FALSE; }
assert(foo());
?>
PHP Warning:assert()
: Assertion failed in - on line 3This wouldn't be changed for require()/return()/invariant()?
We need a switch to change development/production. I'll use "dbc=On/Off"
for now.
If you have any better idea, please let me know. (dbc will be INI_SYSTEM)Check the "expectations" RFC. I think, it's going to be 3 state switch,
zero-cost disable, run-time disable, run-time enable. So, it may be
INI_ALL, but it won't be possible to switch from/to zero-cost at run-time.
Ok.
For CLI, there will be no command line switch for dbc. It executes
script production mode by
default. If user needs development modephp -d dbc=1 script.php
should be used.
And finally, are we going to allow custom assertion error message? e.g.
require($a > 0, 'Parameter $a must be positive number');
I think, it may be useful.
Ok. I'll use it.
Since this contract is definition like "implements"/"extends", we may
not allow
custom error message. I'll write the RFC not to allow custom error
messages unless
you dislike it.I think we have enough consensus/information to start writing the RFC.
If I have any concern, I'll ask here.Ok, go forward :)
Updated wiki page.
https://wiki.php.net/rfc/dbc2
If you would like to change something, please let me know.
I don't think finished draft at all and I don't mind going back and forth.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
can I make some minor correction?
Thanks. Dmitry.
Hi Dmitry,
Hi Dmitry and Joe,
yes. this may work.
probably better to put it after extends and implements.Dmitry.
On Mon, Feb 9, 2015 at 2:19 PM, Joe Watkins pthreads@pthreads.org
wrote:Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
This would work.
If users have adopted DbC in some way, 'invariant' may be used already.I see two issues.
Interface works, but most classes are class without interfaces. Then
users have to repeat
require()/return() many times to check class state or have to use
interface for DbC.In D classes may have "invariant" constraints. We may use "require"
keyword for it. The constraints ineritance rules and order of calls to
constrains must be the same s in D.class Foo {
private $sum = 0;
require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}OK. I'll update the RFC.
Since compiler does not know a method() is for DbC invariant, it will
be compiled and exists
in production execution.Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require interface
(cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production (cons)
I didn't understand you idea.
Joe's idea was to use Interface for invariant condition grouping.
If we use your idea, issue is solved.class Foo {
private $sum = 0; require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}Ok.
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.On place closure call like javascript is not supported in PHP, but
function works with assert.<?php
function foo() { return FALSE; }
assert(foo());
?>
PHP Warning:assert()
: Assertion failed in - on line 3This wouldn't be changed for require()/return()/invariant()?
We need a switch to change development/production. I'll use
"dbc=On/Off" for now.
If you have any better idea, please let me know. (dbc will be
INI_SYSTEM)Check the "expectations" RFC. I think, it's going to be 3 state switch,
zero-cost disable, run-time disable, run-time enable. So, it may be
INI_ALL, but it won't be possible to switch from/to zero-cost at run-time.Ok.
For CLI, there will be no command line switch for dbc. It executes
script production mode by
default. If user needs development modephp -d dbc=1 script.php
should be used.
And finally, are we going to allow custom assertion error message? e.g.
require($a > 0, 'Parameter $a must be positive number');
I think, it may be useful.
Ok. I'll use it.
Since this contract is definition like "implements"/"extends", we may
not allow
custom error message. I'll write the RFC not to allow custom error
messages unless
you dislike it.I think we have enough consensus/information to start writing the RFC.
If I have any concern, I'll ask here.Ok, go forward :)
Updated wiki page.
https://wiki.php.net/rfc/dbc2If you would like to change something, please let me know.
I don't think finished draft at all and I don't mind going back and forth.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
I'm not sure we can always enforce invariant contracts ...
Evaluating invariant expressions on entry and exit is not enough, since a
property can be changed without the use of a method.
Can or should, we do anything about that ?
This should also be covered in the RFC, I think.
Cheers
Joe
Hi,
can I make some minor correction?
Thanks. Dmitry.
Hi Dmitry,
Hi Dmitry and Joe,
yes. this may work.
probably better to put it after extends and implements.Dmitry.
On Mon, Feb 9, 2015 at 2:19 PM, Joe Watkins pthreads@pthreads.org
wrote:Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
This would work.
If users have adopted DbC in some way, 'invariant' may be used already.I see two issues.
Interface works, but most classes are class without interfaces. Then
users have to repeat
require()/return() many times to check class state or have to use
interface for DbC.In D classes may have "invariant" constraints. We may use "require"
keyword for it. The constraints ineritance rules and order of calls to
constrains must be the same s in D.class Foo {
private $sum = 0;
require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}OK. I'll update the RFC.
Since compiler does not know a method() is for DbC invariant, it will
be compiled and exists
in production execution.Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require
interface (cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production
(cons)I didn't understand you idea.
Joe's idea was to use Interface for invariant condition grouping.
If we use your idea, issue is solved.class Foo {
private $sum = 0; require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}Ok.
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.On place closure call like javascript is not supported in PHP, but
function works with assert.<?php
function foo() { return FALSE; }
assert(foo());
?>
PHP Warning:assert()
: Assertion failed in - on line 3This wouldn't be changed for require()/return()/invariant()?
We need a switch to change development/production. I'll use
"dbc=On/Off" for now.
If you have any better idea, please let me know. (dbc will be
INI_SYSTEM)Check the "expectations" RFC. I think, it's going to be 3 state switch,
zero-cost disable, run-time disable, run-time enable. So, it may be
INI_ALL, but it won't be possible to switch from/to zero-cost at run-time.Ok.
For CLI, there will be no command line switch for dbc. It executes
script production mode by
default. If user needs development modephp -d dbc=1 script.php
should be used.
And finally, are we going to allow custom assertion error message? e.g.
require($a > 0, 'Parameter $a must be positive number');
I think, it may be useful.
Ok. I'll use it.
Since this contract is definition like "implements"/"extends", we may
not allow
custom error message. I'll write the RFC not to allow custom error
messages unless
you dislike it.I think we have enough consensus/information to start writing the RFC.
If I have any concern, I'll ask here.Ok, go forward :)
Updated wiki page.
https://wiki.php.net/rfc/dbc2If you would like to change something, please let me know.
I don't think finished draft at all and I don't mind going back and forth.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
good point, but I think we can do nothing about that.
Anyway, it should be reflected in RFC.
Dmitry.
I'm not sure we can always enforce invariant contracts ...
Evaluating invariant expressions on entry and exit is not enough, since a
property can be changed without the use of a method.Can or should, we do anything about that ?
This should also be covered in the RFC, I think.
Cheers
JoeHi,
can I make some minor correction?
Thanks. Dmitry.
Hi Dmitry,
Hi Dmitry and Joe,
On Mon, Feb 9, 2015 at 8:27 PM, Dmitry Stogov dmitry@zend.com
wrote:yes. this may work.
probably better to put it after extends and implements.Dmitry.
On Mon, Feb 9, 2015 at 2:19 PM, Joe Watkins pthreads@pthreads.org
wrote:Could this be described as a requirement of the class ?
class Mine
require(invariant-expr)
extends Something
implements Someface {public function method($param) : return require(input-expr), return(output-expr) { }
}
To avoid invariant keyword maybe.
This would work.
If users have adopted DbC in some way, 'invariant' may be used
already.I see two issues.
Interface works, but most classes are class without interfaces. Then
users have to repeat
require()/return() many times to check class state or have to use
interface for DbC.In D classes may have "invariant" constraints. We may use "require"
keyword for it. The constraints ineritance rules and order of calls to
constrains must be the same s in D.class Foo {
private $sum = 0;
require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}OK. I'll update the RFC.
Since compiler does not know a method() is for DbC invariant, it will
be compiled and exists
in production execution.Use of interface:
- no additional keyword (pros)
- requires interface for DbC, most classes does not require
interface (cons)- if interface is not used, user has to repeat invariant conditions
over and over (cons)- requires to define method that should not exist in production
(cons)I didn't understand you idea.
Joe's idea was to use Interface for invariant condition grouping.
If we use your idea, issue is solved.class Foo {
private $sum = 0; require($this->sum >= 0); // invariant constraint will be called
before and after every method
function add($n) {
$this->sum += $n;
}
}Ok.
New keyword:
- does not require interface for efficient definition (pros).
- new keyword (cons)
It seems we are better to choose proper keyword for 'invariant'.
'invariant' is not common, so 'invariant'
may be good enough choice. Does anyone use 'invariant' as
function/method/class/constant names?
If there is better name, suggestion is appreciated.On place closure call like javascript is not supported in PHP, but
function works with assert.<?php
function foo() { return FALSE; }
assert(foo());
?>
PHP Warning:assert()
: Assertion failed in - on line 3This wouldn't be changed for require()/return()/invariant()?
We need a switch to change development/production. I'll use
"dbc=On/Off" for now.
If you have any better idea, please let me know. (dbc will be
INI_SYSTEM)Check the "expectations" RFC. I think, it's going to be 3 state switch,
zero-cost disable, run-time disable, run-time enable. So, it may be
INI_ALL, but it won't be possible to switch from/to zero-cost at run-time.Ok.
For CLI, there will be no command line switch for dbc. It executes
script production mode by
default. If user needs development modephp -d dbc=1 script.php
should be used.
And finally, are we going to allow custom assertion error message?
e.g.require($a > 0, 'Parameter $a must be positive number');
I think, it may be useful.
Ok. I'll use it.
Since this contract is definition like "implements"/"extends", we may
not allow
custom error message. I'll write the RFC not to allow custom error
messages unless
you dislike it.I think we have enough consensus/information to start writing the RFC.
If I have any concern, I'll ask here.Ok, go forward :)
Updated wiki page.
https://wiki.php.net/rfc/dbc2If you would like to change something, please let me know.
I don't think finished draft at all and I don't mind going back and
forth.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Joe,
I'm not sure we can always enforce invariant contracts ...
Evaluating invariant expressions on entry and exit is not enough, since a
property can be changed without the use of a method.Can or should, we do anything about that ?
This should also be covered in the RFC, I think.
One reason I would like to use __invariant() is to allow overriding parents.
I think we should have way for it, but I don't have good idea now.
I'm still thinking.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
One reason I would like to use __invariant() is to allow overriding
parents.
Well, another approach would be optionally named contracts:
class Some {
require contractName (invariant-expr);
/* ... */
}
This would also improve default error messages as a by-product.
Cheers
Joe
Hi Joe,
On Tue, Feb 10, 2015 at 3:59 PM, Joe Watkins pthreads@pthreads.org
wrote:I'm not sure we can always enforce invariant contracts ...
Evaluating invariant expressions on entry and exit is not enough, since a
property can be changed without the use of a method.Can or should, we do anything about that ?
This should also be covered in the RFC, I think.
One reason I would like to use __invariant() is to allow overriding
parents.
I think we should have way for it, but I don't have good idea now.
I'm still thinking.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Am 10.02.2015 08:08 schrieb "Yasuo Ohgaki" yohgaki@ohgaki.net:
One reason I would like to use __invariant() is to allow overriding
parents.
I think we should have way for it, but I don't have good idea now.
I'm still thinking.
Hmm, Idea... Imagine the require keyword, in the context of classes, as an
alternative to the function keyword. One could write any of these:
class foo {
require (expr); // like anonymous function. nonoverridable
static require (expr); // same for nonmethod calls
// named form
require something (expr); // overrides
static require otherthing (expr); // overrides
}
This way selective overriding would be possible for individual conditions.
The namespace for these invariant expression names could / should be wholly
separate from the method namespace itself.
best regards
Patrick
Hi
can I make some minor correction?
Sure. I'm done now.
I would not touch at least few hours.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Am 10.02.2015 07:25 schrieb "Yasuo Ohgaki" yohgaki@ohgaki.net:
First of all, thanks for your effort so far.
Some questions, after reading the RFC, with no particular order:
-
Regarding invariants: those will be called for method calls on objects.
What about static class methods? Could we have static class invariants
(static require(.....))? Would these be called for both static and
nonstatic method calls (nonstatic method calls can change static class
state, too) -
the pre- and postconditions could be useful for ordinary, non-OO
functions, too, to check parameters, return, and global state invariants -
I think that method preconditions are not sufficient. Pretty often,
public methods first sanitize and validate their input parameters, and
rightly so. In these cases, it would be useful to have the checking, in the
same general framework, at an arbitrary point in the function body. In
other words, assert (with an expression as the first argument, instead of a
string....). -
regarding the error message second argument to the condition
definitions, it would be useful to have these not only as plain
(extrapolated) strings, but as full expressions-that-evaluate-to-string.
That would permit hooking to arbitrary private logging and log formatting
methods. -
and a bit off-topic, it would be useful to be able to declare (sic)
whole methods to be nonproduction only: Methods that will only be used in
pre/post/invariant condition expresions (or error formatters a la my point
best regards
Patrick
Am 10.02.2015 07:25 schrieb "Yasuo Ohgaki" yohgaki@ohgaki.net:
First of all, thanks for your effort so far.
Some questions, after reading the RFC, with no particular order:
- Regarding invariants: those will be called for method calls on objects.
What about static class methods? Could we have static class invariants
(static require(.....))? Would these be called for both static and
nonstatic method calls (nonstatic method calls can change static class
state, too)
yeah, "static require()" may be a good addition. However, I don't like to
invite a bicycle, we are going to borrow most related semantic from D.
- the pre- and postconditions could be useful for ordinary, non-OO
functions, too, to check parameters, return, and global state invariants
any function will able to use contracts.
- I think that method preconditions are not sufficient. Pretty often,
public methods first sanitize and validate their input parameters, and
rightly so. In these cases, it would be useful to have the checking, in the
same general framework, at an arbitrary point in the function body. In
other words, assert (with an expression as the first argument, instead of a
string....).
assert()
will work as well. Actually, all these addition require/return
syntax is going to be just a syntax sugar that will finally call assert()
s
in proper order.
- regarding the error message second argument to the condition
definitions, it would be useful to have these not only as plain
(extrapolated) strings, but as full expressions-that-evaluate-to-string.
That would permit hooking to arbitrary private logging and log formatting
methods.
I don't think we will implement this. It may be proposed later as a DbC
extension.
- and a bit off-topic, it would be useful to be able to declare (sic)
whole methods to be nonproduction only: Methods that will only be used in
pre/post/invariant condition expresions (or error formatters a la my point
this is also not directly related as well.
Sorry, but we should define realistic target to be able to provide a
working solution.
We can't think about all possible and indirectly related features at once.
Thanks. Dmitry.
best regards
Patrick
Hi Dmitry,
- regarding the error message second argument to the condition
definitions, it would be useful to have these not only as plain
(extrapolated) strings, but as full expressions-that-evaluate-to-string.
That would permit hooking to arbitrary private logging and log formatting
methods.I don't think we will implement this. It may be proposed later as a DbC
extension.
I thought it works just like assert()
, but no problem for me.
- and a bit off-topic, it would be useful to be able to declare (sic)
whole methods to be nonproduction only: Methods that will only be used in
pre/post/invariant condition expresions (or error formatters a la my point
this is also not directly related as well.
Sorry, but we should define realistic target to be able to provide a
working solution.
We can't think about all possible and indirectly related features at once.
I agree.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Actually I'm not sure it's at all sane to try to override contracts, I'd
actually avoid that completely, so no need to name contracts and no need
for magic __invariant.
Cheers
Joe
Hi Dmitry,
- regarding the error message second argument to the condition
definitions, it would be useful to have these not only as plain
(extrapolated) strings, but as full expressions-that-evaluate-to-string.
That would permit hooking to arbitrary private logging and log
formatting
methods.I don't think we will implement this. It may be proposed later as a DbC
extension.I thought it works just like
assert()
, but no problem for me.
- and a bit off-topic, it would be useful to be able to declare (sic)
whole methods to be nonproduction only: Methods that will only be used
in
pre/post/invariant condition expresions (or error formatters a la my
point
this is also not directly related as well.
Sorry, but we should define realistic target to be able to provide a
working solution.
We can't think about all possible and indirectly related features at
once.I agree.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Joe,
Actually I'm not sure it's at all sane to try to override contracts, I'd
actually avoid that completely, so no need to name contracts and no need
for magic __invariant.
For example,
class Animal {
protected $legs;
require($legs >= 0);
}
class Snake extends Animal {
// Snake is fine, no leg
}
class Human extends Animal {
// 2 legs. $this->leg === 2
}
Overriding makes sense for many cases.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Example code never works, I can just say that's a bad abstraction,
vertebrate and invertebrate are distinct and abstraction should reflect
that.
Why should we provide a way to change contracts is the question ?
It doesn't seem to make sense to do that, a derived class should be able to
define additional contracts, but not change the contracts of it's parent.
Cheers
Joe
Hi Joe,
On Tue, Feb 10, 2015 at 4:31 PM, Joe Watkins pthreads@pthreads.org
wrote:Actually I'm not sure it's at all sane to try to override contracts, I'd
actually avoid that completely, so no need to name contracts and no need
for magic __invariant.For example,
class Animal {
protected $legs;
require($legs >= 0);
}class Snake extends Animal {
// Snake is fine, no leg
}class Human extends Animal {
// 2 legs. $this->leg === 2
}Overriding makes sense for many cases.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
completely agree. contracts must be permanent.
Thanks. Dmitry.
Example code never works, I can just say that's a bad abstraction,
vertebrate and invertebrate are distinct and abstraction should reflect
that.Why should we provide a way to change contracts is the question ?
It doesn't seem to make sense to do that, a derived class should be able
to define additional contracts, but not change the contracts of it's parent.Cheers
JoeHi Joe,
On Tue, Feb 10, 2015 at 4:31 PM, Joe Watkins pthreads@pthreads.org
wrote:Actually I'm not sure it's at all sane to try to override contracts, I'd
actually avoid that completely, so no need to name contracts and no need
for magic __invariant.For example,
class Animal {
protected $legs;
require($legs >= 0);
}class Snake extends Animal {
// Snake is fine, no leg
}class Human extends Animal {
// 2 legs. $this->leg === 2
}Overriding makes sense for many cases.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Joe,
It doesn't seem to make sense to do that, a derived class should be able
to define additional contracts, but not change the contracts of it's parent.
I forgot that invariants in D and Eiffel implicitly inherits parent's
invariants.
So classes that causes problems have design bug.
Please go ahead editing the file. I wouldn't have time until next morning.
There will be hours. I'll wait as long as it takes.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Patrick,
Am 10.02.2015 07:25 schrieb "Yasuo Ohgaki" yohgaki@ohgaki.net:
First of all, thanks for your effort so far.
Some questions, after reading the RFC, with no particular order:
- Regarding invariants: those will be called for method calls on objects.
What about static class methods? Could we have static class invariants
(static require(.....))? Would these be called for both static and
nonstatic method calls (nonstatic method calls can change static class
state, too)
Static calls should not use $this->var, so invariant condition is ignored.
It should be in the RFC.
- the pre- and postconditions could be useful for ordinary, non-OO
functions, too, to check parameters, return, and global state invariants
I proposed __invariant() function, but some would not like to have it.
Since you've requested, we may consider again.
Rre/postconditions (require/return) can be used for non-OO functions.
It should be in the RFC. I'll add it in the RFC later.
- I think that method preconditions are not sufficient. Pretty often,
public methods first sanitize and validate their input parameters, and
rightly so. In these cases, it would be useful to have the checking, in the
same general framework, at an arbitrary point in the function body. In
other words, assert (with an expression as the first argument, instead of a
string....).
I might misunderstand you. Anyway,
assert( $var > 0 )
is allowed. So you can write usual PHP code. Even we can
assert( foo() ) // The same applies to require()/return()
is allowed. However, PHP does not allow in place closure call currently. We
cannot do
assert(function() { return $a > 0;} )
It's just ignored. This is the same as current assert()
.
- regarding the error message second argument to the condition
definitions, it would be useful to have these not only as plain
(extrapolated) strings, but as full expressions-that-evaluate-to-string.
That would permit hooking to arbitrary private logging and log formatting
methods.
assert( $var > 0, '$var must be positive')
is allowed.
This should be in the RFC. require()/return() works just like assert()
.
- and a bit off-topic, it would be useful to be able to declare (sic)
whole methods to be nonproduction only: Methods that will only be used in
pre/post/invariant condition expresions (or error formatters a la my point
Do you mean enable DbC partially? Like
declare(dbc=1);
At the top of script?
I think it would not happen, but others may think it should.
Anyone?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Am 10.02.2015 08:25 schrieb "Yasuo Ohgaki" yohgaki@ohgaki.net:
- and a bit off-topic, it would be useful to be able to declare (sic)
whole methods to be nonproduction only: Methods that will only be used in
pre/post/invariant condition expresions (or error formatters a la my point
Do you mean enable DbC partially? Like
declare(dbc=1);
At the top of script?
Nono. i shouldn't have said declare, sorry.
What I meant is this (using a made-up keyword "dbconly" just for
exposition):
class foo {
function normalmethod($arg)
require($this->just_for_dbc_check($arg))
{ .... }
dbconly function just_for_dbc_check($arg) {
... whatever validation code ...
return false;
}
}
And then when DbC is inactive (production) metho just_for_dbc_check would
not be compiled at all / invisible.
I now realize that I'm asking for a way to have arbitrary PHP code for
checking, through a backdoor :)
But this would permit some nice consolidation of more complex checks,
ones that maybe would be shared by several methods with repetition of the
expressions in the case we cannot do this.
Just thinking out loud, I fully agree with Dmitry's comment of keeping it
simple and manageable at the moment, and this is something that could be
added later at any time.
best regards
Patrick
Hi Yasuo,
Le Tue, 10 Feb 2015 07:25:00 +0100, Yasuo Ohgaki yohgaki@ohgaki.net a
écrit:
Updated wiki page.
https://wiki.php.net/rfc/dbc2
While I agree this RFC is going in the right direction, I don't like the
use of "require" and "return".
They are already used for something completely different, I think it will
make the code more difficult to understand (for beginners) and parse (for
external programs). IDE will have some difficulties too. I've discussed
about it with some PHP developers who work with me, and they all agree.
If it was me, I would use "pre" and "post", "in" and "out" or "requires"
and "ensures". I understand that creating more keywords isn't something
pleasant, but it would make the code more readable and logical.
Regards,
Benoit.
Hi Dmitry,
De : Dmitry Stogov [mailto:dmitry@zend.com]
Envoyé : lundi 9 février 2015 12:05
À : Joe Watkins
Cc : Yasuo Ohgaki; Stanislav Malyshev; PHP Internals
Objet : Re: [PHP-DEV] Design by Contractinvariant is for classes only. It should be called before and/or after each
method to check object consistency.syntax with expressions may work if we put constraints before the function
body .function foo($a int): int
require(expr1)
require(expr2, msg)
return(expr3)
{
}
I understand you're defining an implementation based on assertions only, despite the fact that 'require' and 'return' are very ambiguous choices IMO.
Did you take into account that, in many cases, this would revert to strict type checking, due to the way is_xxx() functions are working ?
If someone writes 'function tan($op) / require (is_float($op));' will he expect tan(1) to be rejected ? (we're back to Rasmus' complaint).
The same with is_int()
and others, they're all based on zval types. Only is_numeric()
is smarter and allows specifying a 'number' in the PHP way. Unfortunately, these functions are wrong as they don't fit with the way people are used to consider types in PHP. So, no easy way to say you can accept 1 or 1.0, let alone "1".
That's why my proposal features assertions AND 'smart' argument types. Actually, types are more important than assertions because that's what people will use first. Primary use for assertions will be checking conditions between args. The same for properties and return type. Actually, I would say that most phpdoc-annotated code already contains most DbC constraints it needs. We just need to formalize and use them.
As others already said here, be it for type checking or DbC, we need a mechanism to interpret types the 'PHP' way, something between PHP permissive type juggling and strict zval-based typing. That's what I tried to define.
I understand the prevention against inserting PHP code in doc comments and, if I was designing the language from scratch, I wouldn't use such a design. But, considering every aspects of the problem, I still think it's the best compromise to add the feature.
Regards
François
On Mon, Feb 9, 2015 at 3:57 PM, François Laupretre francois@tekwire.net
wrote:
Hi Dmitry,
De : Dmitry Stogov [mailto:dmitry@zend.com]
Envoyé : lundi 9 février 2015 12:05
À : Joe Watkins
Cc : Yasuo Ohgaki; Stanislav Malyshev; PHP Internals
Objet : Re: [PHP-DEV] Design by Contractinvariant is for classes only. It should be called before and/or after
each
method to check object consistency.syntax with expressions may work if we put constraints before the
function
body .function foo($a int): int
require(expr1)
require(expr2, msg)
return(expr3)
{
}I understand you're defining an implementation based on assertions only,
despite the fact that 'require' and 'return' are very ambiguous choices IMO.Did you take into account that, in many cases, this would revert to strict
type checking, due to the way is_xxx() functions are working ?If someone writes 'function tan($op) / require (is_float($op));' will he
expect tan(1) to be rejected ? (we're back to Rasmus' complaint).
You'll get exactly what you write in constraint, no any predefined
semantic, no need to learn predefined rules.
The same with
is_int()
and others, they're all based on zval types. Only
is_numeric()
is smarter and allows specifying a 'number' in the PHP way.
Unfortunately, these functions are wrong as they don't fit with the way
people are used to consider types in PHP. So, no easy way to say you can
accept 1 or 1.0, let alone "1".That's why my proposal features assertions AND 'smart' argument types.
Actually, types are more important than assertions because that's what
people will use first. Primary use for assertions will be checking
conditions between args. The same for properties and return type. Actually,
I would say that most phpdoc-annotated code already contains most DbC
constraints it needs. We just need to formalize and use them.
I think, people will use type hinting first (in a way they'll be
implemented in PHP-7).
Thanks. Dmitry.
As others already said here, be it for type checking or DbC, we need a
mechanism to interpret types the 'PHP' way, something between PHP
permissive type juggling and strict zval-based typing. That's what I tried
to define.
I understand the prevention against inserting PHP code in doc comments
and, if I was designing the language from scratch, I wouldn't use such a
design. But, considering every aspects of the problem, I still think it's
the best compromise to add the feature.Regards
François