Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-27 Thread Fleshgrinder
On 5/27/2016 2:34 PM, Lester Caine wrote:
> Hence the 'in an ideal world'! It is perhaps worth making clear that a
> 'typed property' element IS simply a holder for the pointer to the real
> element while the untyped properties are the element themselves? The
> differentiation of 'scalar' probably comes into play, but does that
> result in untyped scalers having to have the overheads for adding the
> type flags?
> 

Nope, they both work exactly the same way. Typed properties just guard
the properties from assignment of values that are not typed hinted against.

I don't know what you mean with untyped scalars. Every variable always
has a type. It is up to you if you care about it or not.

On 5/27/2016 2:34 PM, Lester Caine wrote:
> And 32bit builds mess things up as well ...
> 

YES!

On 5/27/2016 2:34 PM, Lester Caine wrote:
> With the proviso that $o is not used again ... currently all of my
> object classes have a constructor for a blank object along with a loader
> to 'initialize' the data. Empty objects such as 'father' can be
> populated with data and saved, loaded with an existing record, or wiped
> if incorrect associations existed ... allowing the correct data to be
> added. AJAX allows things to happen within a page which in the past
> would have been complete new page loads without any of the problems of
> 'cached' data?
> 

Sounds like bad design to me where you always need to know when to call
what and when what was called but if it works for you. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-27 Thread Fleshgrinder
On 5/27/2016 11:53 AM, Lester Caine wrote:
> On 27/05/16 10:16, Rowan Collins wrote:
>> My comment was in reaction to Lester expressing surprise at destroying
>> and re-creating objects when new data is fetched. To be clear, I'm
>> talking about this:
>>
>> // Clear old data
>> $this->data = [];
>> // Re-populate from new DB result
>> foreach ( $db_resultset as $row ) {
>>$this->data[] = new SomeModel($row);
>> }
>>
>> The most useful typehints are inside the SomeModel class, not the
>> table-level wrapper. This is true even if they're just dumb structs, and
>> all the behaviour is at the table level, because it presumably has
>> basically one field: array $data.
> 
> Probably the only difference here is that '$row' in my result set is not
> a dumb structure. It has type information, field lengths and potentially
> even value constraints. So my table level wrapper can potentially have
> the same typehints that you are then adding to SomeModel. All the
> properties of SomeModel already exist and if typed properties are
> working correctly in PHP $row can simply be accessed directly. This is
> why in my book all of the debate about 'attributes' and everything else
> is so tied up in the definition of making a simple variable a much more
> flexible generic object.
> 

The type hints belong to SomeModel because you want to insert the data
into SomeModel and not into your repository (Table).

  class Person {
public int $id;
public DateTimeImmutable $created;
public DateTimeImmutable $changed;
public string $name;
public DateTimeImmutable $birth;
public ?DateTimeImmutable $marriage;
public ?DateTimeImmutable $death;
public int $number_of_siblings = 0;
  }

  class SomeModels {
public function findAll() {
  foreach ($db->select('SELECT * FROM `SomeModel`') as $row) {
$some_model = new SomeModel;
$some_model->id = $row['id'];
$some_model->created = new DateTimeImmutable($row['created']);
$some_model->changed = new DateTimeImmutable($row['changed']);
$some_model->name = $row['name'];
$some_model->birth = new DateTimeImmutable($row['birth']);
if (isset($row['marriage'])) {
  $some_model->marriage = new DateTimeImmutable($row['marriage']);
}
if (isset($row['death'])) {
  $some_model->death = new DateTimeImmutable($row['death']);
}
$some_model->number_of_siblings = $row['number_of_siblings'];
yield $some_model;
  }
}
  }

The Person object is however still behaviorless and anemic, throwing
type hints at public properties does not change that fact.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-27 Thread Fleshgrinder
On 5/27/2016 11:41 AM, Lester Caine wrote:
> Now I am confused, but it's probably because I'm looking at a simple
> 
> $f->d = new DateTime( $initial );
> 
> While you are looking at
> 
> If ( isset($initial) )
> then $f->d = new DateTime( $initial );
> else $f->d = null;
> 
> While the original code would have simply been
> 
> $f->d = $initial;
> 
> And in an ideal world, because $d has been typed as DateTime this would
> magically run 'new DateTime($initial)' which is where I am stumbling
> because *I* simply look at '?DateTime $d' as creating a DateTime object
> where in fact $d is a different type of object which will then hold the
> link to the real one. I am still looking for $d to be an object I can do
> all of the checks on that are provided by int or DateTime as appropriate
> ... the object needs to exist before the 'new' in order to know if you
> need the first or second type of $initial code ... or we make typed
> properties only work one way or the other?
> 

PHP does not automagically instantiate the DateTime object for you, this
is still your responsibility. The type hint on the property only
restricts what you are allowed to assign to the property, nothing else.

It is true that PHP will coerce the value automatically if you are in
weak mode but this is only true for scalar values and nothing else. Also
note that you might not want that while working with a database because
PHP might destroy your UNSIGNED BIGINTs without you noticing.

  class O {
public ?DateTime $d;
  }

  if (isset($row['d'])) {
$o->d = new DateTime($row['d']);
  }

No need to assign null since it already is null by default and the
nullable hint will not result in any errors upon accessing it.

PS: The UNSIGNED BIGINT thing is one of the reasons why I want
intersection and union types so that we can do the following:

  class O {
private int|string $id;
  }

And leave it to a more intelligent system to determine whether this can
be safely converted to an int or not (e.g. MySQLi).

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-27 Thread Fleshgrinder
On 5/27/2016 10:35 AM, Tony Marston wrote:
> I disagree completely. In a database system there is no rule that says
> an object can only hold data from a single row otherwise Martin Fowler,
> the author of PoEE, would not have patterns that hold data from several
> rows. When I instantiate one of my table classes it is a valid but empty
> object. There are two actions I can perform - inject data from the
> client via the $_POST array, or tell it to retrieve data from the
> database. This may involve just a single row, or multiple rows. When
> reading from the database it may even result in zero rows.
> 

Yes?!? That is how everybody does it.

On 5/27/2016 10:35 AM, Tony Marston wrote:
> You are trying to change the language to suit the way that you work
> without considering the fact that your way is not the only way and this
> change may not suit the way that others work. As far as I can see this
> proposal not only does not solve a genuine problem, it adds levels of
> complexity that will do nothing but increase the WTF! factor for untold
> numbers of programmers who have been happily using the language for years.
> 

Oh come on, this story again? Please, just keep on using PHP in the way
you like it without making use of these new features. Nothing is
changing and if all your problems are solved, good. And please, please
don't start the PHP 5.2 was so much better discussion now and claiming
that we all are incapable programmers.

We know it by now. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-27 Thread Fleshgrinder
On 5/26/2016 11:40 PM, Rowan Collins wrote:
> On 26/05/2016 21:00, Fleshgrinder wrote:
>> PS: This needs a cast unless some special driver options are active.
>>
>>$me->numSiblings = (int) $db_record['num_siblings'];
> 
> ...or unless strict_types=0, in which case PHP will add an implicit cast
> for you. :)
> 
> Regards,
> 

I need to get used to that nice new feature. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 10:40 PM, Lester Caine wrote:
> I think what is irritating here is that actually both of these can still
> validly be null. It's HAVING to add the ? to every item when actually by
> conventions 'NOT NULL' is the exception. Would ? indicating 'NOT NULL'
> actually be better since it IS only adding that flag which is required
> here to block the use of null?
> 

The use case for the majority is the opposite. Java decided to go for
the /everything can be null/ and people are making jokes about it all
the time.

On 5/26/2016 10:40 PM, Lester Caine wrote:
> BUT DateTime currently will not store 'null' - it returns 'now' instead.
> We end up having to store string or integer values because we can't
> store a null date :(
> 

This is unrelated to typed properties. You can implement your own
DateTime class that has support for your special use case.

On 5/26/2016 10:40 PM, Lester Caine wrote:
> The suggestion I was seeing was that a 'NOT NULL' value had to be
> initialized. I think my problem is perhaps is just what errors are
> created that break the normal flow and what gets returned when checking
> to see IF a value has been initialised.
> 

Nothing breaks your normal flow, you will be able to use isset() and
empty() as you always were.

On 5/26/2016 10:40 PM, Lester Caine wrote:
> $me->numSiblings would actually be null in this case if it has not yet
> been established since the answer may well be '0' but that just explains
> why null is still valid even for an int property. We just have no idea
> if it's null because it's just been created or because the database read
> returned 'null'.
> 

0 !== null and if your database can return null for this field add it to
its definition: `public ?int $num_siblings`

On 5/26/2016 10:40 PM, Lester Caine wrote:
> The alternate 'not null' value is more clear cut in that 'null' can mean
> that it is uninitialized, and one needs to run the initialization code
> for it. I need is_null($me->numSiblings) to work and return true so I
> can select the initialization code, or should there be a new state of
> 'uninit' as well? Then if we want to 'reset' the person object do the
> 'not null' entries get rest to null so they can be re-initialized.
> 'unset' the person does not remove the object simply rewinds it to an
> unset state ... so should unset of these typed properties do that or do
> we actually need an uninit?
> 

Not null would result in the same questions being raised as we are
facing them now.

You can use !isset() instead of is_null(), it does the same thing
without errors being raised.

The concept of reseting objects and reinitializing them is something I
read very often from you. This is against all of OOP. What you are
basically doing is misusing classes as behaviorless anemic containers of
data. Even Smalltalk from the '70s did not encourage this and PHP never
did so either. Just because it is possible does not mean that it is the
proper way. Just make a new instance. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 9:56 PM, Rowan Collins wrote:
> The current proposal (or the one which I am advocating) for that is that
> you would have something like the following:
> 
> class Person {
> public \DateTime $birth;
> public ?\DateTime $marriage;
> public ?\DateTime $death;
> public int $numSiblings;
> }
> 
> Creating an object would leave it in an invalid state:
> 
> $me = new Person;
> // accessing $me->birth or $me->numSiblings is an error in this state,
> because defaulting to NULL would violate their type constraint
> // accessing $me->marriage or $me->death returns NULL (because they
> allow nulls) but raises E_NOTICE
> 
> Now you can initialise the mandatory fields:
> 
> $me->birth = new \DateTime($db_record['birth_date']);
> $me->marriage = new \DateTime($db_record['marriage_date']);
> $me->death = new \DateTime($db_record['death_date']);
> $me->numSiblings = $db_record['num_siblings'];
> // all properties can now be safely accessed
> // $me->marriage and $me->death may still be null, as indicated by the
> "?" in their type spec
> // $me->birth is guaranteed to be a \DateTime object
> 
> Regards,
> 

Nothing to add here. :)

PS: This needs a cast unless some special driver options are active.

  $me->numSiblings = (int) $db_record['num_siblings'];

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 9:10 PM, Lester Caine wrote:
> DateTime is probably a better example to work with than 'int' since it
> already has a long pedigree of problems and clashes where many projects
> had their own interpretation and still use their own version of the
> class. My problem with '\DateTime $d' is that by default it returns
> 'now' rather than an 'empty/null' value in which to put the data from
> the database. I can't create a 'null' version of DateTime so one has to
> have a phantom date simply to ensure you know if it has been initialized
> with your own data later - or continue to use the older user space classes.
> 
> It is handling just how the variable/property is initialized that is the
> whole problem here and there may be very good reasons that the
> initialization is later then the 'construct' be that a DateTime or an
> int ... null is the correct way of indicating that 'as yet we do not
> have the value of type xxx' just as it does for an untyped value, so
> trying to make a special case to block it's use is simply strangling
> normal usage in other cases?
> 

Could you come up with some example code of what you cannot achieve? I
cannot think of a single situation that is valid and not a developer
error which would be impossible with the currently discussed approach.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 7:20 PM, Rowan Collins wrote:
> I think the difference is the emphasis of whose responsibility it is to
> fix it: a TypeError confirms that the error is in the O class for
> exposing an incorrectly typed property; a NullPointerException, as you
> put it, makes it my fault for trusting the class.
> 
> Or to put it a different way, is the error in the first arrow (accessing
> "->d") or the second one (de-referencing "d->").
> 
> 
> At the end of the day, all the type notations being added to PHP are
> just assertions anyway. So the same could be said of this:
> 
> function foo(\DateTime $d) {
>echo $d->format('Y-m-d H:i:s');
> }
> foo(null);
> 
> If this didn't throw an error at "foo(null)", it would throw an error at
> "$d->format".
> 

Yes, they are just assertions and design by contract and you make a very
good point here for an actual error. I am convinced. ;)

However, it should not throw an error for isset() and empty() to allow
more special constructs. As we already have it in place everywhere with
the two.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 7:00 PM, Tom Worster wrote:
> On 5/26/16, 12:48 PM, "Fleshgrinder"  wrote:
>> This would be a valid approach too, yes. I personally would be against
>> it because I do not want to initialize all my properties.
>>
>>  class A {
>>
>>private int $x;
>>
>>public function getX() {
>>  if (empty($this->x)) {
>>$this->x = 42;
>>  }
>>  return $this->x;
>>}
>>
>>  }
>>
>> This would not yield an E_NOTICE because both isset() and empty() never
>> do. This allows the attentive programmers to keep up there coding
>> practices without the necessity to assign meaningless values everywhere.
>>
>>  class A {
>>
>>/** -1 is invalid */
>>public int $x = -1;
>>
>>/** 'INVALID' is invalid but empty string is allowed */
>>public string $s = 'INVALID';
>>
>>/** Null byte is invalid but anything else is valid */
>>public string $welcome_to_the_c_world = '\0';
>>
>>  }
> 
> If you want that kind of thing, you can do it the old PHP way like this
> 
> class A {
> private ?int $x = null;
> ...
> 

Doing that defeats the whole purpose of typed properties in my opinion.
I want to be sure that nobody can assign null to this property and only
allow it to be null until I initialize it myself.

  class A {

private int $x;

private function getX() {
  if (empty($this->x)) {
$this->x = 42;
  }
  return $this->x;
}

public function doSomething() {
  // lots of code ...
  $_ = $__ * $this->x;
  // lots of code ...
}

  }

This would emit an E_NOTICE (and possibly end up in an error due to
null) and the developer of the doSomething() method will notice that she
should call getX() instead.

This would not be the case with private ?int $x. :(

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 6:50 PM, Rowan Collins wrote:
> As I'm sure has already been pointed out (I haven't followed the whole
> thread) this defeats a large advantage of typed properties - I now can't
> read from the property without checking if it's null, so I can't do this:
> 
> class O {
>public \DateTimeImmutable $d;
> }
> echo (new O)->d->format('Y-m-d H:i:s');
> 
> There's no ? on the type def, so I ought to be able to trust the type. A
> TypeError makes more sense here, because it is a programming error for
> it to be in this state.
> 

That is exactly what Stanislav raised too. I really have no idea how we
should prevent this from happening and honestly think we shouldn't. Your
construct will result in a fatal error (also known as
NullPointerException to some, *evil-laughter*) anyways preceded by an
E_NOTICE that tells you that your property is not defined.

I am of course open for ideas but emitting another kind of fatal error
does not really make things better imho.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 6:40 PM, Tom Worster wrote:
> On 5/26/16, 12:30 PM, "Fleshgrinder"  wrote:
> 
>> The problem is a completely different one, how should the following code
>> behave?
>>
>>  class A {
>>
>>public int $x;
>>
>>  }
>>
>>  (new A)->x;
>>
>> The property has no value assigned but it is being accessed. The current
>> PHP behavior is to simply initialize it with null. But this is
>> impossible according to the type definition.
>>
>> There are not many ways to handle this. I think we already had all of
>> them proposed:
>>
>> 0. Fatal error after __construct was called.
>> 1. Fatal error and abort.
>> 2. Initialize with appropriate type.
>> 3. Initialize with null.
> 
> Under another 5th option, the problem you state does not arise. Disallow
> "public int $x;". Under this option you may declare $x with type int and
> an initial value or you may declare $x without type but you may not
> declare $x with type (nullable or not) and undefined initial value.
> 
> Tom
> 

This would be a valid approach too, yes. I personally would be against
it because I do not want to initialize all my properties.

  class A {

private int $x;

public function getX() {
  if (empty($this->x)) {
$this->x = 42;
  }
  return $this->x;
}

  }

This would not yield an E_NOTICE because both isset() and empty() never
do. This allows the attentive programmers to keep up there coding
practices without the necessity to assign meaningless values everywhere.

  class A {

/** -1 is invalid */
public int $x = -1;

/** 'INVALID' is invalid but empty string is allowed */
public string $s = 'INVALID';

/** Null byte is invalid but anything else is valid */
public string $welcome_to_the_c_world = '\0';

  }

Not cool. :(

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
The problem is a completely different one, how should the following code
behave?

  class A {

public int $x;

  }

  (new A)->x;

The property has no value assigned but it is being accessed. The current
PHP behavior is to simply initialize it with null. But this is
impossible according to the type definition.

There are not many ways to handle this. I think we already had all of
them proposed:

0. Fatal error after __construct was called.
1. Fatal error and abort.
2. Initialize with appropriate type.
3. Initialize with null.

Option 0. is out the window because it creates endless edge cases.

Option 1. is extremely brutal and not necessarily what we want (lazy,
anyone?).

Option 2. has a huge problem with objects because it cannot initialize
e.g. a \Fleshgrinder\Custom\SuperClass nor a \DateTime.

Option 3. is the current behavior but silently doing so results in a
type hint violation. Emitting an E_NOTICE at this point is the most
sensible thing that we can do at this point in my opinion. Extending
this logic to all kind of properties is just logical to keep
conditionals in the internals low and have a consistent behavior across
all of the userland functionality. After all, aren't the following
things equal?

  $a;
  echo $a; // null + E_NOTICE

  class O {
public int $x;
  }
  echo (new O)->x; // null + E_NOTICE

One could even argue that an E_NOTICE is required for void routines too.

  function f() {}
  echo f(); // null + E_NOTICE

But that's another story. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 1:57 PM, Rowan Collins wrote:
> I am definitely in favour of this from a language point of view. The
> notice is warning about *initialization*, not *declaration*, so it makes
> sense to warn on "var $foo" and not "var $foo = null".
> 
> The only thing I'm not sure is what the impact would have on the
> internals, which may be why it doesn't already work that way. With a
> simple variable the notice can be easily raised based on the variable
> name not being in the current symbol table; with an object property, the
> name *is* in the relevant table, because it's been *declared* even
> though it hasn't been *initialized*. Thus you need some extra flag to
> track that a declared property exists but has never been written to.
> 
> But it sounds like typed properties require adding some such overhead
> anyway...
> 
> Regards,

Looking at `zend_object_handlers.c` and `zend_std_read_property` there
is the line:

  retval = &EG(uninitialized_zval);

This is what gives us the default null of our properties if I interpret
everything correctly. This is also the place where the undefined
property error comes from.

We need help here from people who know the PHP source better.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 1:41 PM, Lester Caine wrote:
>>   var_dump(property_exists($g, 'x'));  // true
> 
> or array_key_exists('x', $g) in our consistent style but as has been
> pointed out we do not have a simple 'exists' ...
> $g->exists('x') ?
> along with $g->isinit('x')
> 

I like the exists() idea. :) But we might not need it.

On 5/26/2016 1:41 PM, Lester Caine wrote:
>>   var_dump($g->x); // null + E_NOTICE Uninitialized
>>   var_dump(is_null($g->x));// true + E_NOTICE Uninitialized
>>   var_dump($g->x == null); // true + E_NOTICE Uninitialized
>>   var_dump($g->x === null);// true + E_NOTICE Uninitialized
> 
> Unless null IS the required initial value? Why should we have to
> initialize a nullable typed property explicitly?
> 

You don't have to unless null *is* the required initial value.

You are only punished with an E_NOTICE if you try to access a property
that was never initialized with anything. This would be 100% consistent
with old PHP behavior.

  $x;
  var_dump($x); // null + E_NOTICE Undefined

  $y = null;
  var_dump($y); // null

  class O {
public $x;
public $y = null;
  }
  $o = new O;

  var_dump($o->x); // null + E_NOTICE Undefined / Uninitialized

  var_dump($o->y); // null

Only the E_NOTICE for $o->x would be new.

On 5/26/2016 1:41 PM, Lester Caine wrote:
> I'm still stuck in the simple model of things where 'x' is expandable so
> we have the simple generic variable of old (PHP4 days) which now has
> additional attributes such as accessibility (public etc) and a few
> special cases of type filtering but is lacking a tidy way of adding the
> more useful filtering attributes such as constraints and yes typing.
> 
> properties and associative arrays are simply managed list of these
> simple variables so why do we need different functions to access them.
> Within a class isset($x) should mirror isset($this->x) and exists($x)
> makes sense along with other 'object' related functions, but is there no
> way to get back to a lot simpler consistent handling of variables ...
> and a more constructive way to add flexible type constraints.
> 

With this proposal we would not go anywhere else. We would make it more
consistent and allow the typed properties RFC to continue. Unless I
missed something in the discussion or got something wrong again. Please
correct me!

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 12:39 PM, Rowan Collins wrote:
> On 26/05/2016 11:16, Fleshgrinder wrote:
>>   $o = (object) ['x' => null];
>>   var_dump(isset($a->x));  // false
>>   var_dump(property_exists($a, 'x'));  // true
> 
> Apart from a typo in your example (you change from $o to $a), this is
> already the current behaviour, and always has been: https://3v4l.org/NeqGl
> 
> isset() is really very simple: if the thing your accessing would give
> you the value null, it returns false, otherwise it returns true.
> 
> Regards,

Now I feel stupid but I guess I got lost myself. :P

This means it is even simpler, we just have to add the E_NOTICE and be
done with it.

  $g = new class { public $x; };

  var_dump($g->x); // null + E_NOTICE Uninitialized
  var_dump(isset($g->x));  // false
  var_dump(property_exists($g, 'x'));  // true
  var_dump(is_null($g->x));// true + E_NOTICE Uninitialized
  var_dump($g->x == null); // true + E_NOTICE Uninitialized
  var_dump($g->x === null);// true + E_NOTICE Uninitialized

This behavior would be true for all variations:

  class A {

var $x;

public $x;

public int $x;

public ?int $x;

  }

No notice for the following:

  class A {

var $x = null;

public $x = null;

public int $x = 0;

public ?int $x = null;

  }

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
On 5/26/2016 12:03 PM, Rowan Collins wrote:
> Could you summarise what your proposal actually is; I got a bit lost
> with what your long list of examples was trying to show me.
> 

To summarize it: we should change the behavior of isset() to work
exactly the same way as it does for associative array keys if they have
null assigned to them.

Shorter example of current PHP implementation:

  $a = ['x' => null];
  var_dump(isset($a['x']));// false
  var_dump(array_key_exists($a, 'x')); // true

  $o = (object) ['x' => null];
  var_dump(isset($a->x));  // true
  var_dump(property_exists($a, 'x'));  // true

PHP 8

  $o = (object) ['x' => null];
  var_dump(isset($a->x));  // false
  var_dump(property_exists($a, 'x'));  // true

This would actually be more consistent with the isset() behavior
together with associative arrays and it would allow us to handle typed
properties that where not initialized (as illustrated in the longer
example).


On 5/26/2016 12:03 PM, Rowan Collins wrote:
> Can you provide a reference for that? The only thing mentioned in the
> changelog in the manual is this rather rare situation:
> 
> $foo = 'a string';
> isset($foo['some_key']);
> 
> $foo['some_key'] doesn't actually have much of a meaning in that case,
> anyway, and it has nothing to do with initialisation.
>

Just tested it with those ancient versions and you are right that I
interpreted that sentence incorrectly. The behavior of isset() with
array keys that were explicitly set to null never changed.

ref: https://3v4l.org/TS621

However, this does not change my proposal. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
Have a look at my latest message:

http://marc.info/?l=php-internals&m=146424924029857&w=2

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-26 Thread Fleshgrinder
/ false
  var_dump(property_exists($g, 'x'));  // true
  var_dump(is_null($g->x));// true + E_NOTICE Uninitialized
  var_dump($g->x == null); // true + E_NOTICE Uninitialized
  var_dump($g->x === null);// true + E_NOTICE Uninitialized
/* }}} */

The only thing I personally dislike is the fact that there is no
counterpart to isset(). This means that one cannot create a positive
conditional that checks for the opposite case without raising an E_NOTICE.

  class T {

private int $x;

public function getX() {
  if (isset($this-x) === false) {
$this->x = 42;
  }
  return $this->x;
}

  }

However, one could argue that empty() is good enough at this point --
despite the fact that many values are considered empty that might be
valid values in other circumstances -- because we want to know the
uninitialized case here. From the manual:

> The following things are considered to be empty: [...] a variable
> declared, but without a value
>
> --- https://secure.php.net/function.empty

  class T {

private int $x;

public function getX() {
  if (empty($this->x)) {
$this->x = 42;
  }
  return $this->x;
}

  }

I could live with that.

Note that the behavior of isset() and empty() was already once changed
during the 5.4 feature release! I am proposing to change it with a major
version for existing code and only emitting an E_STRICT till then. This
is not even close as brutal as that behavioral change back then but
other than that pretty much the same change. This time it just affects
objects and not associative arrays.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 11:37 PM, Stanislav Malyshev wrote:
> Hi!
> 
>> We already have the differentiation between IS_NULL and IS_UNDEF, why
>> not expose the latter to userland? I mean, JavaScript has it too and
>> people are able to understand it.
> 
> IS_UNDEF is not a PHP type, it is an engine implementation flag. Now,
> adding a new type "undefined" would be a pretty big thing and then you'd
> need to deal with all the implications of it. Including a huge BC break
> of changing the type of all uninitialized variables, and the question of
> "what if I want my parameter to be able to accept undefined values" and
> so on. Huge can of worms, and all of it again just to have a type that
> is exactly like null but not null. While the only reason null exists is
> to do exactly what "undefined" is proposed to do.
> 

Andrea already said that we would not use it for untyped properties,
hence, no BC.

It is not the same as null, very similar, but definitely not the same.
Think of it in DB terms:

  | table |
  | - |
  | id|

  SELECT name FROM table;

That's not null, it's not defined (undefined, unset, ...). In other
words, null is a value and undefined/unset a state.

Whether this proposal should become part of this RFC or not is something
that needs to be discussed.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 11:35 PM, Thomas Bley wrote:
> Following "Type safety is the goal of this RFC, not validating objects.", it 
> would be better to do implicit casting for uninitialized properties (whenever 
> implicit casting is possible) or use null for nullable types:
> 
> class A {
>   public int $x;
>   public ?int $y = null;
>   public int $z = 42;
>   public ?int $u;
>   public ?datetime $v;
>   public datetime $w;
> }
> 
> $a = new A;
> var_dump($a->x); // 0 + notice
> var_dump($a->y); // null
> var_dump($a->z); // 42
> unset($a->z);
> var_dump($a->z); // 0 + notice
> var_dump($a->u); // null + notice
> var_dump($a->v); // null + notice
> var_dump($a->w); // Fatal error, uninitialized...
> 

This was proposed many times but it renders checks whether something was
initialized or not completely useless and is not really a solution to
the problem at hand.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 11:29 PM, Stanislav Malyshev wrote:
> OTOH, we do have precedent for properties that can not be unset -
> namely, static properties can not be unset. They can be nulled-out, of
> course, and they default to null. I have no idea how "static int $x;"
> would work though. The current RFC doesn't implement it, which
> definitely would be weird since people would expect if you can have
> typed object property, you can have typed static property, but that's
> not what the RFC says.
> 

This was also a point that I found to be weird and I am absolutely sure
that this will cast confusion as you are.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 5:49 PM, Andrea Faulds wrote:
> PHP's existing untyped properties are implicitly initialised to null,
> and so yes, we would essentially only be copying our existing behaviour.
> 
> However, I think it is worth asking whether our existing behaviour is
> useful before we preserve it here. From my perspective, it is unhelpful
> that PHP does not warn you about using properties you haven't
> initialised, and this applies to both typed and untyped properties. In
> some cases (like in my linked list example in a previous email), null
> might be a meaningful value and worth distinguishing from a property not
> having being initialised yet.
> 
> We can't change the behaviour of our existing untyped properties (or at
> least, that's beyond the scope of this RFC), but we could choose the
> behaviour we find more useful for our typed properties.
> 

We already have the differentiation between IS_NULL and IS_UNDEF, why
not expose the latter to userland? I mean, JavaScript has it too and
people are able to understand it.

  class A {

public int $x;

public ?int $y = null;

public int $z = 42;

  }

  $a = new A;
  var_dump($a->x); // undefined
  var_dump($a->y); // null
  var_dump($a->z); // 42
  unset($a->z);
  var_dump($a->z); // undefined + error

At least to me this makes sense and there would be no problem with
unset() anymore. Although I truly question the usefulness of its
functionality. Can anyone come up with a real world use case for unset()?

Or maybe not use /undefined/ but /unset/ as a term because it is already
baked in? (Well the constant IS_UNDEF should be renamed to IS_UNSET to
stay consistent in all layers.)

  class A {

public int $x;

public ?int $y = null;

public int $z = 42;

  }

  $a = new A;
  var_dump($a->x);   // unset
  var_dump($a->y);   // null
  var_dump($a->z);   // 42

  // NOT SURE IF THIS SHOULD BE POSSIBLE
  $a->z = (unset) $a->z; // was null (PHP<7.1) would become unset
  var_dump($a->z);   // unset + error

  $a->z = unset;
  var_dump($a->z);   // unset + error

  unset($a->z);
  var_dump($a->z);   // unset + error

Of course this would also requires the introduction of an unset (and
UNSET) constant in userland.

  class A {

private $x;

public function getX() {
  if ($x === unset) {
$this->x = 42;
  }
  return $this->x;
}

  }

I love the difference to null, this makes the code much more expressive.

There would be the following rules:
- Access always results in error.
- Usage as argument results in error.
- Usage as return results in error (could be void but BC).
- ... more errors ...
- Comparison is possible!
- The following existing operations would need to be changed to make use
of unset instead of null (possible BC):
  - unset()
  - (unset) cast
- The following new operations would need to be introduced:
  - is_unset()
- The following existing operations would need to be extended:
  - gettype()
  - settype()

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 10:23 PM, Benoit Schildknecht wrote:
> Le Wed, 25 May 2016 21:40:28 +0200, Fleshgrinder 
> a écrit:
> 
>> and unset simply because the property is not
>> explicitly assigned null by unset, it is being undefined.
> 
> 
> Because null !== undefined. That's why you get an error after an
> unset($this->var), and you don't get one after $this->var = null; .
> "$var = null;" and "unset($var)" are totally different, it has been like
> that for years. If you want to change this behavior, propose an RFC, and
> make it approve. But meanwhile, you'll have to keep this in mind :
> "null" is a value. While "unset" does not affect a value, it deletes the
> variable, it deletes any references of the variable it targets, the
> variable doesn't exist anymore. With unset, the variable is dead. With
> null, it has amnesia. I can't find any better analogy.
> 

Which is exactly what I wrote and think is correct. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 9:13 PM, Niklas Keller wrote:
> 2016-05-25 20:39 GMT+02:00 Fleshgrinder :
> 
>> In my opinion it should simply vanish along with its definition. I mean,
>>
> 
> Usually, yes. But suddenly `private Type $foo` isn't reliable anymore if
> unset is supported for typed properties, because the following would just
> remove all type info / enforcement:
> 
> $backup = $this->foo;
> unset($this->foo);
> $this->foo = $backup;
> 
> Unset can reset it to the default value, but wiping type information is
> probably
> not an option here.
> 
> Regards, Niklas
> 

I had to check because I never tried this once in my life (why would one
need it anyways) ...

  class A {

private $foo = "foo";

function get() {
  return $this->foo;
}

function unset() {
  unset($this->foo);
}

  }

  $a = new A;
  echo $a->get(); // foo
  $a->unset();
  echo $a->get(); // Notice: Undefined property: A::$foo
  $a->foo = "foo";

  // Fatal error: Uncaught Error: Cannot access private property A::$foo

In other words, unset is not really unset already!

QED: Preserving *all* attributes of a property is the only consistent
way. However, preserving its value is not.

I do not think that there is a problem together with the typed
properties, nullability, and unset simply because the property is not
explicitly assigned null by unset, it is being undefined.

I think internally null is actually assigned and it's not IS_UNDEF,
right? However, from a userland perspective it is definitely not defined
anymore and access should (as it does) result in an error (in our case
E_INFO) plus null is being returned but only because undefined does not
exist in PHP userland.

I did not read up on all the history yet but I am on it ...

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-05-25 Thread Fleshgrinder
On 5/25/2016 8:01 PM, Stanislav Malyshev wrote:
> Hi!
> 
>> Why do you say "now"? unset() has done this for a long time, so far as I
>> know.
> 
> True. But I don't see how would it work for typed properties - what
> exactly would happen after unset? Would it be - as it is now - that it
> is as if the property was never defined, or would it be something else?
> 

In my opinion it should simply vanish along with its definition. I mean,
isn't that the definition of unset in general.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Simple Annotations

2016-05-17 Thread Fleshgrinder
On 5/17/2016 7:47 PM, Rasmus Schultz wrote:
> You're not annotating the function - this is just a round-about way of
> annotating the argument.
> 
> You would do that directly, like this:
> 
> function foo(
> << ValidateRange(0, 100) >>
> int $percentage
> ) { ... }
> 

What is this good for?
When is /ValidateRange/ being evaluated?
On every call? How?

I really do not get it, sorry.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Simple Annotations

2016-05-17 Thread Fleshgrinder
#x27;);
  echo $some_annotations[0]->json;
  // data

  $annotations = new AnnotatedFunction('x');
  $some_annotations = $annotations->getAnnotations('someAnnotations');
  // Fatal error: Uncaught JsonParseException in ...

The above is just fine. The annotation library registered the callback
and it knows what kind of errors can happen. The annotation library is
also the one reading the annotations and it can therefore easily handle
those errors and act upon them. Of course in the above case the fatal
error is just fine and it is the developers duty to write unit tests and
take care of writing proper configuration. It is not PHP's duty to
ensure to absolutely no error can happen in any subsystem. (This is
actually ridiculous to think of in the first place.)

On 5/17/2016 11:06 AM, Rasmus Schultz wrote:
> I maintain that the majority use-case is object annotations - and that
> deferring the construction of those objects doesn't solve anything.
> 

Seriously? Every construction is deferred, always, again see the console
example from above.

On 5/17/2016 11:06 AM, Rasmus Schultz wrote:
> You're just deferring or hiding the problem, adding complexity, and
> mental as well as practical debugging effort - but the problem doesn't
> go away.
> 

I am putting a runtime feature to runtime like all runtime features are
at runtime in PHP. The error is hidden during reflection, that is true,
but on purpose! You do not want reflection to error out while you are
performing introspection on a data structure.

The annotation reader however will error out in the moment you try to
access something. This separation of concern makes it actually easier
and is in the vain of good software development too.

I understand what you want to solve. I am just telling you that this is
the wrong approach and others are telling it to you too.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Simple Annotations

2016-05-16 Thread Fleshgrinder
On 5/16/2016 3:05 PM, Rasmus Schultz wrote:
> I'm sorry, but I think that the idea of meta-data that can't error
> somehow, somewhere, at some point, is completely unrealistic.
> 
> And I'd much rather have a simple facility that enables those errors
> to surface quickly.
> 

It should error and it should error exactly at the point when you want
to use it and at no other point. Right now they will error anytime
anyone wants to do anything with any annotation.

I fully understand the urge to directly access objects and I actually
support it and I want them to error out at the point where you try to
instantiate them. However, not when I simply access annotations in
introspection.

According to your logic I have to load the whole dependency chain, even
thought I just want to generate my documentation that might have some
annotations in use. I also need to load all my dependencies even though
I wanted to leave the security dependency out because I wanted to easily
disable the security annotation system locally for development. I even
have to load the whole dependency chain, even though I just want to
introspect the single data structure at hand without invoking anything.

Even worse if I am using a package that has Doctrine annotations but I
use it without them: /fatal error/

Nice? No!

Solutions?

Make the /simple/ annotations /simple/. ;-)

Only allow scalar data to be defined and allow userland to register
themselves for specific annotations. I mentioned this before but somehow
everyone wants something more fancy and I have no karma (even though
requested but ignored) to write my own RFC. That being said, you have
the ability to write an RFC so please just take it. :-)

Some PHP code to illustrate what I was thinking of since I am better
with code than with words. :-P

https://gist.github.com/Fleshgrinder/d26cd4751827b8c10a0dc33da32b48c3

Reflection is the wrong tool for the job to build annotation systems.
Reflection should not be used in production it should be used to
introspect data structures and reason about them or other stuff during
unit tests.

However, reflection should provide the ability to read annotations, it
just does not do anything with them by default and outputs stupid
arrays. You will definitely understand what I mean it you follow the Gist.

I am sure there is room for improvement and that I overlooked something
in my Gist. But I think it is a starting point, some additional notes:

- I do not see any benefit in annotations for parameters.
- I do not see any benefit in annotations for Generators.
- I do not see any benefit for annotations in php-src.

My proposal would include to ban annotations from php-src and make it a
pure userland functionality. This has many advantages:

- No name collisions.
- Clear policy for the future.
- php-src features are never optional.
- php-src does not provide meta-data.

Let me know what you think or if you have questions in regards to the
Gist that are unclear. (Or maybe you found mistakes.)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Simple Annotations

2016-05-16 Thread Fleshgrinder
On 5/13/2016 2:57 PM, Davey Shafik wrote:
> 2) I like the idea of Hacks memoize for example, how do you see those being
> implemented? Or don't you?
> 

I wrote it in the /attribute grammar/ thread and I write it here again.
Stuff like memoize should be implemented as keywords as part of the
language and not via annotations.

  memoized function f() {}

Same goes for deprecated:

  deprecated memoized function f() {}

Or other special effects:

  deprecated inlined memoized function f() {}

These things are not meta-data for userland, they are meta-data for PHP
and should be part of, well, PHP.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Simple Annotations

2016-05-16 Thread Fleshgrinder
On 5/13/2016 2:11 PM, Rasmus Schultz wrote:
> Dear Internals,
> 
> I'm announcing a simplified RFC for annotations:
> 
> https://wiki.php.net/rfc/simple-annotations
> 

-1 again, I am sorry.

The problem is that an annotation by definition is just meta-data. Your
proposal however might result in fatal errors from meta-data:

  $reflector = new ReflectionClass(User::class);
  $reflector->getAnnotations();

  // Fatal error: Uncaught Error: Class 'TableName' not found ...

This is an absolute No-Go for meta-data.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Allow loading extensions by name

2016-05-11 Thread Fleshgrinder
On 5/10/2016 10:07 PM, Lester Caine wrote:
> I would be most surprised to find windows users running php command
> line, but I suppose I am somewhat out of the loop on that side. All my
> windows users run PHP on a web server and have trouble even accessing
> the command line.
> 

I am using Windows and the CLI all day professionally. Yes, people tend
to think like that but it is ancient thinking. Windows is a very capable
operating system and allows you to perform all tasks. Although I have to
admit that PHP tends to be very slow on Windows compared to Linux, that
is a fact.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Allow loading extensions by name

2016-05-10 Thread Fleshgrinder
On 5/10/2016 9:01 PM, Lester Caine wrote:
> The idea has been proposed before, but the addition of php_ for windows
> installs has not been universally applied. Extensions like eAccelerator,
> adodb and other third party extensions that did not form part of the
> windows 'installation' files. Most of these have been killed off by the
> restructuring of the core so it's probably less of a problem now than 5
> years ago!
> 
> Another negative is the fact that most Linux installations do not use
> entries in the php.ini file to enable extensions, preferring to manage
> them via the package manager. THAT particular practice is something I
> already copy back to the windows installs, using individual .ini files
> for each extension, and stripping those extensions and settings from the
> main php.ini.
> 
> This is not simply a matter of adding another load mechanism to the mix,
> so any rfc should perhaps bear in mind all the aspects of 'package
> management' process? Certainly it's not quite as simple as assuming
> windows extensions start php_ and end .dll ...
> 

Handling of the prefix is a no brainer. Just check for php_NAME.dll and
fallback to NAME.dll on Windows otherwise. If both fail error out.

The approach to split ini files does not work on CLI.

UNIX: `php -d extension=foo.so -d zend_extension=bar.so`

WIN: `php -d extension=php_foo.dll -d zend_extension=php_bar.dll`

RFC: `php -d extension=foo -d zend_extension=bar`

Are there really extension on Windows without `.dll` extension? I highly
doubt it and would consider erroring out to be okay. Users can still
specify the exact path if the want to.

  function load_extension($name) {
$extension_dir = ini_get('extension_dir');
$extension_dir = rtrim($extension_dir, DIRECTORY_SEPARATOR);
$extension_dir .= DIRECTORY_SEPARATOR;

if (DIRECTORY_SEPARATOR === '\\') {
  foreach (['php_', ''] as $prefix) {
$path = $extension_dir . $prefix . $name . '.dll';
if (is_file($path)) {
  return do_load_extension($path);
}
}
else {
  $path = $extension_dir . $name . '.so';
  if (is_file($path)) {
return do_load_extension($path);
  }
}

return do_load_extension($name);
  }

Something along these lines should do it (of course in C). :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] [VOTE] PHP Attributes

2016-05-10 Thread Fleshgrinder
On 5/10/2016 8:29 PM, Dmitry Stogov wrote:
> Hi internals,
> 
> I've started voting on "PHP Attributes" RFC.
> 
> https://wiki.php.net/rfc/attributes
> 
> In my opinion, "PHP Attributes" might be a smart tool for PHP extension, but 
> it's not going to be the end of the world, if we decided to live with 
> doc-comments only.
> 

I hope it's going to be negative. The name is misleading and the AST
approach is not really useful in userland. :(

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Allow loading extensions by name

2016-05-10 Thread Fleshgrinder
On 5/10/2016 6:56 PM, Fleshgrinder wrote:
> On 5/10/2016 6:54 PM, Stanislav Malyshev wrote:
>> Hi!
>>
>>>> Please read and comment :
>>>>
>>>> https://wiki.php.net/rfc/load-ext-by-name
>>
>> The RFC says " it is currently impossible to write a single
>> configuration file that will work in both environments" - but even with
>> extension fix, wouldn't it be still impossible since Windows are Unix
>> paths would probably be different?
>>
> 
> Usage of slashes and relative paths works perfectly fine in Windows; or
> do you mean something different?
> 

Just checked it with a simple script on Windows 7 with PHP 7.0.6.
Slashes are no problem but relative paths seem problematic, hence, there
would be the problem regarding `C:/some/path` vs. `/some/path`.

This RFC would still be a big step ahead because we could do something
like the following:

  php -v

PHP 7.0.6 (cli) (built: Apr 28 2016 13:48:13) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

  php -d zend_extension=xdebug -v

PHP 7.0.6 (cli) (built: Apr 28 2016 13:48:13) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans

  php composer install
  php -d zend_extension=xdebug test

This is currently not possible.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Allow loading extensions by name

2016-05-10 Thread Fleshgrinder
On 5/10/2016 6:54 PM, Stanislav Malyshev wrote:
> Hi!
> 
>>> Please read and comment :
>>>
>>> https://wiki.php.net/rfc/load-ext-by-name
> 
> The RFC says " it is currently impossible to write a single
> configuration file that will work in both environments" - but even with
> extension fix, wouldn't it be still impossible since Windows are Unix
> paths would probably be different?
> 

Usage of slashes and relative paths works perfectly fine in Windows; or
do you mean something different?

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC DRAFT] Automatic CSRF Protection

2016-05-10 Thread Fleshgrinder
On 5/10/2016 5:24 AM, Yasuo Ohgaki wrote:
> Hi all,
> 
> It's not nice to work on the same code (i.e. session module) for
> multiple RFCs, but time is limited.
> 
> I would like to hear from ideas/comments before I write patch for this.
> https://wiki.php.net/rfc/automatic_csrf_protection
> 
> Thank you for your comments.
> 
> Regards,
> 
> P.S. Precise session ID management is important, but this one is also
> important. I'll finish and start voting 2 active session RFCs soon. I
> may finish all of them hopefully.
> 

-1 CSRF protection is a very specific need of some parts of a website
and not something that is universally required.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Allow loading extensions by name

2016-05-10 Thread Fleshgrinder
On 5/10/2016 3:22 PM, François Laupretre wrote:
> Please read and comment :
> 
> https://wiki.php.net/rfc/load-ext-by-name
> 

+1 and I am wondering why nobody else ever came to this idea.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-08 Thread Fleshgrinder
author asks /why?/

On 5/3/2016 11:23 PM, Ryan Pallas wrote:
> You didn't address the fact that your "solution" makes it much harder to
> modify the steps in place.
> 
> $ret = getConfig()
>   |> buildApp($$)
>   |> buildRouter($$)
>   |> parseResponse($$);
> 
> Shoot, I forgot to build Dispatcher; Let me add that
> 
> $ret = getConfig()
>   |> buildApp($$)
>   |> buildRouter($$)
> +|> buildDispatcher($$)
>   |> parseResponse($$);
> 
> Such a minimal change. Lets try yours:
> 
> final class ResponseBuilder {
> private $config;
> private $app;
> private $router;
> private $response;
> 
> private function loadConfig() {}
> 
> private function buildApp() {
> $this->app = new App($this->config);
> }
> 
> private function buildRouter() {
> $this->router = new Router($this->app);
> }
> 
> private function parseResponse() {
> $this->response = new Response($this->router);
> }
> 
> public function build() {
>   $this->loadConfig();
>   $this->buildApp();
>   $this->buildRouter();
>   $this->parseResponse();
> 
>   return $this->response;
> }
>   }
> 
> Shoot, I forgot dispatcher; let me add that
> 
> final class ResponseBuilder {
> private $config;
> private $app;
> private $router;
> +  private $dispatcher;
> private $response;
> 
> private function loadConfig() {}
> 
> private function buildApp() {
> $this->app = new App($this->config);
> }
> 
> private function buildRouter() {
> $this->router = new Router($this->app);
> }
> 
> +  private function buildDispatcher() {
> +  $this->dispatcher = new Dispatcher($this->router);
> +  }
> +
> private function parseResponse() {
> -   $this->response = new Response($this->router);
> +  $this->response = new Response($this->dispatcher);
> }
> 
> public function build() {
>   $this->loadConfig();
>   $this->buildApp();
>   $this->buildRouter();
> +$this->buildDispatcher();
>   $this->parseResponse();
> 
>   return $this->response;
> }
>   }
> 
> Whoa that's significantly more changes, and therefore significantly more
> chances to make a typo!
> 

At least the complexity is not completely hidden behind some arbitrary
procedural function call. You assume that the procedural function that
you are introducing already exists and returns the correct thingy that
continues the chain in exactly the order you want it too. Those are a
lot of assumptions considering the fact that the pipe operator is meant
for combining arbitrary libraries.

Sorry, not convinced but a real world example might change that. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal

2016-05-08 Thread Fleshgrinder
On 5/6/2016 8:02 AM, Dmitry Stogov wrote:
> On 05/06/2016 05:06 AM, Jesse Schalken wrote:
>> If you're going to say "do what you want" with regards to annotations,
>> then
>> just let them be a text string. Parsing the annotation as PHP but not
>> evaluating it as PHP seems a very strange and arbitrary half-way
>> point. If
>> the thing consuming the AST is expected to eval() it, then why didn't PHP
>> do that already? If the thing consuming the AST is expected not to eval()
>> it, then it must effectively implement it's own language sharing PHP's
>> syntax but not PHP's semantics. Since it can't possibly attach meaning to
>> all of PHP's syntax, PHP will enforce that the string is valid PHP even
>> though the annotation language will be a very small subset. Not only does
>> that buy you very little in terms of validity checking, but it constrains
>> the annotation language to be a subset of PHP's syntax even when such a
>> constraint may be entirely inappropriate.
>>
>> A true "do what you want" approach, if that is the right approach,
>> would be
>> for the annotation body to be a free text string.
> 
> You talk about a subset of the proposed RFC.
> It proposes an additional question about AST usage.
> 

I think he is talking exactly about the proposed RFC, it is completely
arbitrary and will lead to much confusion and it is not anymore useful
than the current PhpDoc approach that we have in userland. Having an
attribute grammar [1] adds overhead to PHP while parsing our files and
removes only the regular expression stuff that is currently implemented
in the annotation systems of all the software out there; which is at
least offline.

I do not see a single benefit in the current feature proposal.
Especially since one can already run the content of a PhpDoc tag through
the AST thingy and *bam* you have exactly the same thing.

What we need is an annotation system that works for userland and not
this attribute grammar crutch just because it is easier to come up with
and agree upon.

[1] https://en.wikipedia.org/wiki/Attribute_grammar

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-03 Thread Fleshgrinder
On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> I have to disagree, I haven't seen an example of rewriting the original
> example from the RFC in a more expressive AND readable way. Yes, you can
> use lots of intermediate variables, but this makes the code HARDER to read
> QUICKLY which is entirely the point of a syntatic sugar addition like this.
> Syntactic sugar makes a language sweeter, and more palatable. Like cane
> sugar makes your cookies taste good, but doesn't make them more nutritious.
> 

Opinions you know but I am still waiting for that example.

On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> This breaks dependency injection, and makes testing harder.  You now depend
> on an array of data which is accessed internally, and can only minimally
> control it's contents in a testing environment.
> 

Why do you need dependency injection in the most outer point of your
application? This should be tested with your acceptance/integration
tests and nothing else. How many unit tests have you written for your
Symfony app kernel lately?

A rather extreme example of such a /most outer/ but you know how it is
with constructed examples:

http://www.yegor256.com/2014/10/03/di-containers-are-evil.html#the-right-way

On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> Again, how do I dependency inject a config during testing to make sure I
> build the dic correctly? I'm assuming you're using a bunch of temporary
> properties? Also you just made adding a step significantly harder, what if
> from building the app, I need to build another layer build for the router,
> for |> I add ONE line of code, for yours I edit the build function in the
> right location, and change the build router function to load from a
> different property, and build another boilerplate function to build this
> new thing, and add another property to hold this new thing... WHOA that's a
> lot more steps, and a MUCH higher risk of a mistake!
> 

Again, this is the most outer place of everything. I mean, all
frameworks and applications were and are able to solve these issues
easily, nicely, and testable. Just because my /proposed/ solution to an
example that is constructed in the first place is not as nice as those
solutions does not make the examples better. :P

On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> Again, you're solution is to use OOP, but the pipe operator's purpose is to
> make procedural code cleaner. Not one of your solutions maintained a
> procedural interface, and therefore is not an argument against the |>
> operator. The purpose of this operator is syntactic sugar, which "is syntax
> within a programming language that is designed to make things easier to
> read or to express. It makes the language "sweeter" for human use: things
> can be expressed more clearly, more concisely, or in an alternative style 
> *that
> some may prefer*."[1] (emphasis mine). Its not designed to solve a problem
> of how can I do this thing, but how can I write this thing such that my
> team might be able to understand it better.
> 
> Yes, you can rewrite these examples in an entirely different way, but now
> you're not comparing apples to even other fruit (procedural vs OO is not
> the same). The point of this is to take a very common pattern (nesting many
> procedural calls) and make it easier to read and manage later.
> 

  foreach (scandir($arg) as $path) {
if ($path !== '.' && $path !== '..') {
  $ret[] = getFileArg($arg . DIRECTORY_SEPARATOR . $path);
}
  }

What can I say ...

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-03 Thread Fleshgrinder
On 5/3/2016 8:57 PM, Sara Golemon wrote:
> Ooops, missed a negation when I typed it out.
> 
> "Pretending that poorly designed libraries DON'T exist is naîve."
> 

I am not pretending that they do not exist, quite the contrary, I
explicitly stated that they exist and that I fear that this syntactic
sugar yields more of them in the future.

On 5/3/2016 8:57 PM, Sara Golemon wrote:
> As I've said already.  Yes, intermediate variables do address this
> style of coding.  Yes, this proposal is syntactic sugar.
> 
> Intermediate variables also add cognitive overhead of their own in
> cataloging all the various intermediates used in a large function.  By
> removing the explicit intermediate variables and replacing them with
> unnamed temporaries, the code becomes easier to read because there's
> less unnecessary assignments cluttering up the space.
> 

Still waiting for a real life example that illustrates exactly that. All
examples and code I have seen so far is either extremely constructed
(the request-application-response thingy that is now part of the RFC) or
can be trivially rewritten to be super expressive and readable (the
original from the RFC and most in this thread).

  $request = getGlobals()
   |> parseRequest($$)
   |> buildPsr7Request($$);

Ask, don't tell!

  final class RequestBuilder {

public static function fromGlobals() {
  return new static($_GLOBALS);
}

public function buildPsr7Request() {
  $parsed_request = $this->parseRequest();
  return new Psr7Request($parsed_request);
}

  }

  $request = RequestBuilder::fromGlobals()->buildPsr7Request();

  $response = loadConfig()
   |> buildDic($$)
   |> getApp($$)
   |> getRouter($app)
   |> getDispatcher($$, $request)
   |> dispatchBusinessLogic($$, $request, new Response())
   |> renderResponse($$)
   |> buildPsr7Response($$)
   |> emit($$);

Ask, don't tell!

  final class ResponseBuilder {

public static function fromGlobals() {
  return new static($_GLOBALS);
}

public function build() {
  $this->loadConfig();
  $this->buildDic();
  $this->buildApp();
  $this->buildRouter();
  $this->buildDispatcher();
  $this->dispatchBusinessLogic();
  $this->parseResponse();

  return $this->response;
}

  }

  $response = ResponseBuilder::fromGlobals()->build();

The third is exactly the same ...

Now my favorite:

  $ret =
array_merge(
  $ret,
  getFileArg(
array_map(
  function ($x) use ($arg) { return $arg . '/' . $x; },
  array_filter(
scandir($arg),
function ($x) { return $x !== '.' && $x !== '..'); }
  )
)
  )
);

I already rewrote it in another message but once more with the most
relevant parts of my original message:

array_filter with O(n)

array_map with O(n)

array_merge with O(∑ array_i, i != 1) and in our case O(n) where n
equals the total count of elements in $files/$$.

In my universe `getFileArg` (note the absence of a plural form) would
operate on a single path and not on an array of paths:

  foreach (new DirectoryIterator($arg) as $path) {
if ($path->isDot() === false) {
  $ret[] = getFileArg($arg . DIRECTORY_SEPARATOR . $path);
}
  }

Ocramius mentioned that the pipe operator would be super useful in async
libraries and stuff but I am lacking real world examples here that
illustrate how this new operator would make those experimental stuff
benefit from it. Especially benefit besides scalar objects.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-03 Thread Fleshgrinder
On 5/3/2016 8:45 PM, Sara Golemon wrote:
>> The pipe operator is also just a work around for poorly designed
>> libraries in this case and yields more poorly designed libraries.
>>
> Pretending that poorly designed libraries exist is naîve.  PHP is
> dominated by poorly designed software but it manages to work because
> it responds with practicality.
> 
> It's practical to provide a functional version of object method chaining.
> 

I really do not know what you want to tell me with that first sentence.

The solution for the problem is already baked into PHP and usable:
intermediate variables with meaningful names. Yes, this might sometimes
be overly verbose. Yes, this might tempt some people to create
meaningless variable names. All in all no argument that was brought up
so far showed that this kind of operator is really useful to solve
something that cannot be already solved. It is always just about source
code formatting and laziness to write out some variables.

Sorry

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-03 Thread Fleshgrinder
On 5/3/2016 8:12 PM, Sara Golemon wrote:
> The difference with scalar objects is:
> A) We need to agree on what methods these objects are going to have.
> ((And we won't agree))
> 

The nice thing here is that we could start with the things that we agree
on and develop it from there further.

On 5/3/2016 8:12 PM, Sara Golemon wrote:
> We could maybe hedge our bets with a ->invoke(Callable) method that
> pushes the value into an arbitrary closure, but that's just adding
> complexity to... avoid adding complexity... o.O
> 

That would be pure evil.

On 5/3/2016 8:12 PM, Sara Golemon wrote:
> B) It's not just about scalars.
> 
> $foo = SomeLibrary::create(...)
>   |> SomeOtherLibrary::render($$)
>   |> $foo->send($$);
> 
> Scalar objects don't help this case at all, and since the object
> instances are coming from some third-party library, making them
> instantiate extended children instead isn't necessarily a trivial
> thing (arguments about poorly designed libraries aside).
> 
> I like the scalar objects approach as well.  Heck, I wrote one three
> years ago: https://github.com/sgolemon/objectifier but I don't think
> it solves the same problem space as pipe chaining.
> 

The pipe operator is also just a work around for poorly designed
libraries in this case and yields more poorly designed libraries.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-03 Thread Fleshgrinder
On 5/3/2016 4:53 AM, Terry Cullen wrote:
> ​Doesn't Nikic's scalar objects (https://github.com/nikic/scalar_objects)
> more or less achieve the same thing while also cleaning up the std lib?
> 
> $ret = scandir($arg)
> ->filter(function(){})
> ->map(function(){})
> ->merge($someOtherArray);
> 

It is indeed a much better approach. The more I read and think about the
pipe operator the more I am against it.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Annotations VS Attributes

2016-05-01 Thread Fleshgrinder
eal world, we wouldn't use either term if we
> wanted to unambiguously refer to a new feature. At best, the Rust
> example is irrelevant to the discussion; at worst, it weakens the case
> for "annotation" being an unambiguous term, which I thought was part of
> your argument.
> 

I disagree in the context of programming. There are multiple
dictionaries available (and linked in this thread) that define the term
over and over again in the same manner. However, the term attribute
changes its meaning based on context.

On 4/30/2016 11:52 PM, Rowan Collins wrote:
> Absolutely! But all we're deciding is what the language will call the
> overall feature - what page it will be on in the manual, what word will
> be used in the error messages, etc. In some languages, like Java, those
> resources would refer to "Annotations"; in other languages, like C#,
> those resources would refer to "Attributes".
> 
> Both terms have advantages and disadvantages, precedents and
> connotations - and both have potential ambiguities with other uses of
> the normal English words that have been borrowed.  In the end, it really
> is mostly a matter of taste.
> 

Very true but the last sentence is not in my book; maybe in .NET, Perl,
and Hack.

I guess we can summarize:

- .NET world, Perl, and Hack are different than others.
- Rust is complicated and is definitely different than others.
- All others use the term according to most/all dictionaries.

- Richard thinks annotations is the correct term. [1]
- Rowan likes annotations but thinks attributes are equally suited.

I can live with that. Anyone can read our discussion and make up their
mind on their own (and hopefully share it with us).

[1] Unless of course---and I wrote that before---we extend the name of
the new functionality to be more precise:

- Attribute Grammar (what the current proposal effectively is)
- Meta-Attributes
- Custom Attributes
- Annotation Attributes
- Aspects [2]
- ...

[2] https://en.wiktionary.org/wiki/aspect

> In aspect-oriented programming, a feature or component that can be
> applied to parts of a program independent of any inheritance
> hierarchy.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-04-30 Thread Fleshgrinder
On 4/30/2016 5:51 PM, Fleshgrinder wrote:
> $ret = scandir($arg)
>   |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; })
>   |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$)
>   |> getFileArg($$)
>   |> array_merge($ret, $$);

This should actually be formatted as to be fair contender to the
procedural example:

$ret = scandir($arg)
  |> array_filter($$, function ($x) {
return $x !== '.' && $x !== '..';
  })
  }> array_map(function ($x) use ($arg) {
return $arg . '/' . $x;
  }, $$)
  |> getFileArg($$)
  |> array_merge($ret, $$);

Not a big difference now...

$files = scandir($arg);
$files = array_filter($files, function ($x) {
  return $x !== '.' && $x !== '..';
});
$files = array_map(function ($x) use ($arg) {
  return $path . '/' . $x;
}, $files);
$ret = array_merge($ret, getFileArg($files));

...the only thing that bugs me in the procedural code is the fact that
array_filter and array_map take their arguments in different order. :P

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-04-30 Thread Fleshgrinder
On 4/30/2016 5:23 PM, Marco Pivetta wrote:
> This feature has nothing to do with fluent interfaces, nor has their flaws.
> The readability of piped processing for functional code is simply a
> no-brainer here, and doesn't require any API changes in function signatures
> either: it is not "a different way of doing the same thing".
> On Apr 30, 2016 17:05, "Fleshgrinder"  wrote:
> 

This is the example code from the RFC written in a normal procedural way.

$files = scandir($arg);
$files = array_filter($files, function ($x) {
  return $x !== '.' && $x !== '..';
});
$files = array_map(function ($x) use ($arg) {
  return $path . '/' . $x;
}, $files);
$ret = array_merge($ret, getFileArg($files));

This is the example code with the pipe operator.

$ret = scandir($arg)
  |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; })
  |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$)
  |> getFileArg($$)
  |> array_merge($ret, $$);

Definitely looks like "a different way of doing the same thing" to me.
So does the initial super ugly example code of nesting.

Again, I am not really against the proposal nor do I argue against the
fact that it improves readability of certain code constructs. I am just
meh on it because such code can pretty much always be rewritten in a way
that makes it more readable, easier to debug, and even faster. In the
example code we have:

array_filter with O(n)

array_map with O(n)

array_merge with O(∑ array_i, i != 1) and in our case O(n) where n
equals the total count of elements in $files/$$.

In my universe `getFileArg` (note the absence of a plural form) would
operate on a single path and not on an array of paths:

foreach (new DirectoryIterator($arg) as $path) {
  if ($path->isDot() === false) {
$ret[] = getFileArg($arg . DIRECTORY_SEPARATOR . $path);
  }
}

I cannot tell if this construct is really equivalent to the example from
the RFC (because I do not know what $ret contains) but it should do
exactly the same. It is more readable, easier to debug, and much faster.

Now you may argue that the example is simply flawed. Well, maybe, but
functional programming is nice if you have a language that is
functional. The only functional part in PHP are callbacks, everything
else is just plain old procedural + OO and importing more functional
concepts will not change that. However, I am not saying that every
functional concept makes no sense just that the pipes are not very
appealing to me because I only see "a different way of doing the same
thing" with slower code. :P

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Pipe Operator

2016-04-30 Thread Fleshgrinder
On 4/30/2016 8:49 AM, Marco Pivetta wrote:
> I think this is much more readable/clear than any event-driven or
> procedural approach.
> We know exactly what is going on, we will get clear stack traces (this
> could need some fine-tuning of the current PR - I didn't try it out yet)
> and we will be able to introduce intermediate steps with ease. In addition
> to all that, this will ease reactive programming by a lot, as piping is a
> natural fit for streams and all abstractions around streams.
> 
> The syntax is also already effective in F# (you can write very expressive
> and easy to understand code with it) and now also landed in Hack.
> 
> I'd say +10 to this proposal :D
> 

I am with Stanislav on this one or rather meh. It also goes against what
you usually advocate: there should be only one way to achieve things (I
remember your /fluent interface/ example very well). Unless you changed
your mind regarding that. Hence, it is nice syntactic sugar but it does
not allow us to solve problems that we cannot solve already.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-30 Thread Fleshgrinder
On 4/25/2016 10:31 AM, Dmitry Stogov wrote:
> completely disagree.
> Each value in multi-value attribute may have its own meaning. e.g.
> <>
> 

That is a different example but I think that I misinterpreted it anyways.

  <>
  function foo() {}

I thought that the above would result in the following:

  reflect foo => [
test => 1
test => 2
  ]

But I think in reality it results int:

  reflect foo => [
test => [ 1, 2 ]
  ]

In case the latter is true, than everything is fine. :)

On 4/25/2016 10:31 AM, Dmitry Stogov wrote:
> You should try to implement this syntax to understand the problem.
> It leads to parse conflicts.
> 

The inclusion of the semicolon definitely does, yes. Usage of the @
should not but Stanislav already offered to jump in. I am not fit enough
yet with the php-src to take up such a big challenge.

On 4/25/2016 10:31 AM, Dmitry Stogov wrote:
> This RFC is not going to propose coding standards.
> 

Only talking about a standard for internal attributes, userland can and
should do whatever they want. But we need to ensure consistency for
internal attributes and that userland is not going to collide with
internal ones.

Currently the RFC does not include any attributes but many examples that
others might use to deduce a coding standard and later we add internal
attributes and things go south.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: Fwd: [PHP-DEV] [RFC] PHP Attributes

2016-04-30 Thread Fleshgrinder
On 4/28/2016 11:15 PM, Stanislav Malyshev wrote:
> I think we should not try to be Haskell, Scala and Eiffel at the same
> time. DbC is not something most of the users of the language require and
> would ever use, unlike Eiifel where it is major part of what the
> language is. Giving a possibility of implementing it using attributes is
> fine. But bringing yet another conceptual framework into PHP looks like
> overkill to me.
> 

Yes, we should not be copy cats. However, we already have `assert()` and
people are just discovering it, despite being there forever. I am not
proposing the previously mentioned syntax as a real RFC yet, simply
because I do not think that it is the right time to do so. However, I do
believe that DbC does not belong into meta-attributes.

My question remains: why DbC in meta? What could be any advantages?

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Annotations VS Attributes

2016-04-30 Thread Fleshgrinder
he term annotation is wrong
in the Rust example. It is a hint for the compiler that can be added by
the programmer or the compiler. That's pretty much a perfect usage
according to the definition of an annotation.

> Extra information associated with a particular point in a document or
> program. Annotations may be added either by a compiler or by the
> programmer. They are not usually essential to the correct function of
> the program but give hints to improve performance.
>
> --- http://encyclopedia2.thefreedictionary.com/annotation

On 4/28/2016 9:43 PM, Rowan Collins wrote:
> OK, I'm completely lost now. I thought your argument was that the
> feature should under no circumstances be called "attributes", because
> that is too general a term, and that it should instead be called
> "annotations", because that is the only correct term. Then you link to a
> page which demonstrates *annotations* being used as a general term, and
> *attributes* being used for the feature being proposed.
> 

C#/.NET calls them "Data Annotation Attributes" and not "Attributes"
(see above).

Perl does but I am still not sure if it is wrong or right in their
context and included an /if/ in my initial review of their usage of the
word. In case of doubt it's wrong I guess.

Hack definitely uses it wrong.

Also note that the current Attributes proposal is in some way closer to
"Attribute Grammar" [3] than to annotations. I just hope that we can
make an annotation system out of it and not end up with an attribute
grammar system (or would we have to call it /attribution/ system then).

On 4/28/2016 9:43 PM, Rowan Collins wrote:
> Except that the Rust example demonstrates that "annotation" can be used
> just as generically and ambiguously as "attribute". There really is very
> little to choose between the two terms.
> 

> Declarations can be annotated with ‘attributes’ in Rust.
>
> --- https://doc.rust-lang.org/book/attributes.html

That is exactly the definition I gave in the initial message. There is
no annotation system in Rust:

> Currently, you are not allowed to create your own attributes, the
> Rust compiler defines them.
>
> --- https://doc.rust-lang.org/book/attributes.html

I am repeating myself but:

@deprecated function f() {}

We annotated (`@`) the function /f/ with the `deprecated` attribute,
hence, _deprecated_ is now an attribute of function /f/ because we
annotated it.

> Allows use of the #[start] attribute, which changes the entry point
> into a Rust program. This capability, especially the signature for
> the annotated function, is subject to change.
>
> --- https://doc.rust-lang.org/reference.html

The past and current RFCs are not proposing any attributes, they are
proposing a system to annotate data with custom attributes.

[1] http://dataannotationsextensions.org/
[2] https://www.it-visions.de/glossar/alle/454/MetaAttribut.aspx (German)
[3] https://en.wikipedia.org/wiki/Attribute_grammar

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: Fwd: [PHP-DEV] [RFC] PHP Attributes

2016-04-28 Thread Fleshgrinder
Is there a reason why you think that Design by Contract (DbC) should be
implemented via annotations/attributes?

I personally think that such a system should be implemented directly in
the language, like Eiffel has it. I even think that it would be easy to
add it without any BC. It might be a bit more complicated to implement
thought.

  [assert]
  assert.active= 1
  assert.invariant = 1
  assert.require   = 1 ; preconditions
  assert.ensure= 1 ; postconditions

  class PreconditionError extends AssertionError {}
  class PostconditionError extends AssertionError {}

  function hello(string $who): string {
return "Hello {$who}\n";
  }
  require {
# argument must have content
$who !== '';
# argument cannot contain unprintable characters
ctype_print($who);
  }

  hello('');
  // PHP Warning: require(): argument must have content: "$who !== ''"
  // failed in ...

  hello("\0");
  // PHP Warning: require(): argument cannot contain unprintable
  // characters: "ctype_print($who)" failed in ...

  class A {

private DateTimeImmutable $created;
private DateTimeImmutable $changed;

function f() {}
require {}
// Special scope "old" available...
ensure {
  # error message
  $this->x = old::$x - 42;
}

  }
  ensure {
# created cannot be less than changed time
$this->created <= $this->changed;
  }

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Annotations VS Attributes

2016-04-28 Thread Fleshgrinder
 loose sense of "you are annotating the source code". Meanwhile, in the
> menu on the left, we can see a section on "Attributes", which look much
> more like arbitrary metadata of the sort we are discussing right now:
> http://rustbyexample.com/attribute.html
> 

That is why there is an empty line between the pages that are actually
documenting the usage of an annotation functionality and the pages that
are using the term annotation correctly in natural language to describe
something. Again, it is about language and terminology.

Here is the relevant formatting again, note the dots and empty line:

On 4/27/2016 10:11 PM, Fleshgrinder wrote:
> http://ceylon-lang.org/documentation/1.2/tour/annotations/
> http://clojure-doc.org/articles/ecosystem/core_typed/start/annotations.html
> https://www.dartlang.org/effective-dart/style/
> ...
>
> https://rubygems.org/search?utf8=%E2%9C%93&query=annotation
> http://rustbyexample.com/scope/lifetime/explicit.html
> https://www.google.de/search?q=javascript+annotation
> ...
> 

On 4/28/2016 8:02 PM, Rowan Collins wrote:
> I think a survey of what different languages call their metadata
> features would be interesting, but so far, I'm not seeing a clear bias
> in favour of one or the other.
> 
> Like I say, I personally prefer the term "annotations", but I'm not
> going to discount the evidence that major languages like C#/.net, Perl,
> and Rust have chosen the name "attributes" instead.
> 
> Regards,

Me neither, I am saying that the term is too generic and that we should
use the term annotation in order to make it unique, easily
understandable, non-ambiguous in terms of natural language and not in
terms of what others use or do.

[1] https://en.wikipedia.org/wiki/Attribute_%28computing%29

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Annotations VS Attributes

2016-04-28 Thread Fleshgrinder
On 4/27/2016 11:36 PM, Lester Caine wrote:
> To add to your list ...
> https://www.phpdoc.org/docs/latest/guides/docblocks.html
> 
> The glossary entry is rather bare, but I would dispute THEIR statement -
> "but also influences the way the application behaves."
> 
> In my book, these comment blocks are 'annotation' is it's simplest form,
> and we add tags within that annotation to make particular details of
> that annotation both machine readable and humanly prominent. That some
> of these keys may be used to "influences the way the application
> behaves." is secondary?
> 

It is totally secondary but still possible, hence, stating it is
correct. A problem is the that attributes that were added via
annotations are per definition not guaranteed to be executed (influence
the way the application behaves) and are as such not a good fit for
design by contract, validation, nor security checks. However, "per
definition" does not mean that one is not allowed to model it in such a way.

On 4/27/2016 11:36 PM, Lester Caine wrote:
> My continuing irritation is that while subsets keep getting discussed as
> duplicate elements outside of the phpdoc wrapper, there is no provision
> for the annotations that would actually help data validation.
> 

Value objects are a better approach towards validation in the very core
than annotations could ever be.

Validation of user input should happen at the most outer layer to fail
early.

Validation of developers should happen via design by contract where we
currently only have assert() at our disposal.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Annotations VS Attributes

2016-04-28 Thread Fleshgrinder
On 4/28/2016 11:36 AM, Rowan Collins wrote:
> While I personally prefer the name "annotations", I don't see it as
> particularly urgent, or nearly as clear-cut as you claim.
> 

That's okay and why we are discussing things. ;)

On 4/28/2016 11:36 AM, Rowan Collins wrote:
> I clicked through on your MSDN link [1] because I was pretty sure .net
> referred to them as "attributes", and am amused to find sentences like
> this:
> 
>> The System.ComponentModel.DataAnnotations namespace contains the
> classes that are used as data attributes.
> 
> In other words, the implementer of that particular library preferred the
> word "annotations", but the language/framework itself calls them
> "attributes"; here's a nice summary [2]:
> 
>> For example, the accessibility of a method in a class is specified by
> decorating it with the /method-modifiers/ |public|, |protected|,
> |internal|, and |private|. C# enables programmers to invent new kinds of
> declarative information, called attributes.
> 
> So, that's one rather large ecosystem that calls them "attributes".
> 

Actually Microsoft got it exactly right and they are explaining in depth
what I wrote as well. The result of an annotation is an attribute. So it
is only natural to call the classes attributes.

  public class Customer {

[DataType(DataType.EmailAddress)]
public string EmailAddress { get; set; }
  }

The `[DataType(DataType.EmailAddress)]` is the annotation and the
attribute that we add to the property is a DataTypeAttribute of DataType
EmailAddress.

https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.datatypeattribute%28v=vs.95%29.aspx

Note that you could achieve the above in PHP with the property type RFC:

   class Customer {

  public EmailAddress $email;

   }

Here public and EmailAddress are attributes of the instance variable
email and hence properties of a property that together result in a class
or instance attribute.

On 4/28/2016 11:36 AM, Rowan Collins wrote:
> Your claims for Perl also don't make much sense:
> 
>> Last but not least, Perl has/attribute/  support. However, Perl actually
>> uses it for interaction with*all*  attributes that can be set. Hence,
>> this is what attributes really do.
>>
>> http://perldoc.perl.org/attributes.html
> 
> None of the built-in attributes mentioned in that manual are standard
> syntax used in the majority of Perl programs; in fact, they are all
> marked as experimental, and most of the examples are of defining custom
> attributes. As far as I can see, this is Perl's version of precisely the
> feature that is being proposed for PHP.
> 

The name they chose is okay because Perl does not offer any other way of
adding attributes to any kind of data in any way (at least none that I
am aware off but I am not a Perl programmer). Hence, it is not too
dangerous to call this functionality attributes as it would be in our
context where many other attributes are already available.

The fact that it is experimental does not add anything to this discussion.

On 4/28/2016 11:36 AM, Rowan Collins wrote:
> I haven't looked through any of your other links to see if you've fallen
> foul of similar confirmation bias, but am satisfied in my mind that
> there are plenty of people outside Hack who call them "attributes".
> 
> 
> [1] https://msdn.microsoft.com/en-us/library/dd901590%28VS.95%29.aspx
> [2] https://msdn.microsoft.com/en-us/library/aa664611%28v=vs.71%29.aspx
> 
> Regards,

No confirmation bias and as I said, Microsoft got it completely right.
To give you an analogy, Microsoft is calling the egg an egg and the
chicken a chicken. We would be calling a chicken an egg because it is
able to create eggs.

In other words: an *annotation* allows you to add additional custom
*attributes* to data that cannot be added by other means.

:)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


[PHP-DEV] [RFC] PHP Annotations VS Attributes

2016-04-27 Thread Fleshgrinder
I am writing this in a separate thread because of the urgency that I see
regarding the naming of past, current, and future proposals regarding
this functionality.

It was and is proposed to create this feature with the name *Attributes*
as Facebook did in their Hack language. Main argument is to blindly
follow /because/.

On 4/25/2016 10:31 AM, Dmitry Stogov wrote:
> Different languages names this differently.
> I may add an additional voting question - "annotation vs attributes?".
>

It is true and only natural that different languages choose different
names for equivalent features but this discussion is not about taste,
style, nor coolness. It is about natural language, proper computer
science terminology, and what PHP users will search for in search
engines. I already tried to explain this in the actual thread but I
guess my attempts resulted in more confusion than clarification, let me
try again.

 ATTRIBUTE 

The word *attribute* has several meanings in computer science and this
is mainly due to its extremely generic nature:

> a usually good quality or feature that someone or something has
>
> --- http://www.merriam-webster.com/dictionary/attribute

> In computing, an attribute is a specification that defines a property
> of an object, element, or file. [...] For clarity, attributes should
> more correctly be considered metadata. An attribute is frequently and
> generally a property of a property.
>
> --- https://en.wikipedia.org/wiki/Attribute_%28computing%29

This pretty much sums it up already. An attribute is the metadata that
is attached to an element of source code. This metadata is anything
unessential that is additionally added but not necessarily required.

  class A {
var $x;
  }

The `class` and `var` keywords are essential in this example and define
the actual element and the names are required too.

  public final class A {
private static int $x = 42;
  }

Class A has the attributes `public` and `final`.
Property `$x` has the attributes `private`, `static`, `int`, and `42`.

All of these attributes of the class and the property add additional
metadata to the source code elements that define their qualities or
features and consequently their behavior and usage.

http://www.onelook.com/?w=attribute&ls=a
http://encyclopedia2.thefreedictionary.com/attribute

Sebastian Bergmann already explained this but I think it is important to
be repeated and further clarified. The word attribute is often used to
refer to properties with additional metadata (e.g. access modifiers,
default values, ...; illustrated above) in an OO context. This makes the
usage of the word attribute additionally to its generic nature ambiguous
as well:

https://en.wikipedia.org/wiki/Attribute_%28computing%29

http://encyclopedia2.thefreedictionary.com/instance+attribute
https://en.wikipedia.org/wiki/Instance_variable

http://encyclopedia2.thefreedictionary.com/static+attribute
https://en.wikipedia.org/wiki/Static_variable

*All* userland implementations that are called /attributes/ in the free
and open world deal with completely different things:

https://packagist.org/search/?q=attribute

Last but not least, Perl has /attribute/ support. However, Perl actually
uses it for interaction with *all* attributes that can be set. Hence,
this is what attributes really do.

http://perldoc.perl.org/attributes.html

 ANNOTATION 

> Extra information associated with a particular point in a document or
> program. Annotations may be added either by a compiler or by the
> programmer. They are not usually essential to the correct function of
> the program but give hints to improve performance.
>
> --- http://encyclopedia2.thefreedictionary.com/annotation

http://www.onelook.com/?w=annotation&ls=a

The term *annotation* is not only used by Java:

https://packagist.org/search/?q=annotation

https://en.wikipedia.org/wiki/Annotation
https://en.wikipedia.org/wiki/Ruby_character
https://en.wikipedia.org/wiki/Java_annotation

https://msdn.microsoft.com/en-us/library/dd901590%28VS.95%29.aspx
http://docs.scala-lang.org/tutorials/tour/annotations.html
https://kotlinlang.org/docs/reference/annotations.html
https://www.python.org/dev/peps/pep-3107/
https://ghc.haskell.org/trac/ghc/wiki/Annotations
http://ceylon-lang.org/documentation/1.2/tour/annotations/
http://clojure-doc.org/articles/ecosystem/core_typed/start/annotations.html
https://www.dartlang.org/effective-dart/style/
...

https://rubygems.org/search?utf8=%E2%9C%93&query=annotation
http://rustbyexample.com/scope/lifetime/explicit.html
https://www.google.de/search?q=javascript+annotation
...

Ignoring these facts just because Facebook did not do proper research is
a total no go. It is also not up for a vote, it is just proper English
and computer science terminology!

Last but not least, it also ensures that users find the correct PHP
manual page when they search for this new feature that migh

Re: [PHP-DEV] Re: Request for Karma

2016-04-27 Thread Fleshgrinder
On 4/27/2016 7:56 PM, Dmitry Stogov wrote:
> Hi Richard,
> 
> I already got help from Pierrick. He is the author of previous RFC 
> https://wiki.php.net/rfc/annotations
> sorry, I have no idea who can give the karma.
> 
> Thanks. Dmitry.
> 

Ah, alright.

Well it says in the HowTo that one needs to send a request to internals
list to ask for karma so somebody knows. I keep the request, I am sure
it will be useful to step in and help on other occasions. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-27 Thread Fleshgrinder
On 4/25/2016 10:04 AM, Dmitry Stogov wrote:
> 
> 
> On 04/24/2016 11:24 AM, Fleshgrinder wrote:
>> The invariant could also be added as an additional branch to the class
>> instead of a method, since it would not work like a method.
>>
>>class A {} invariant {}
>>
>>function f() {} require {} ensure {}
>>
>> This would also align nicely with closures and anonymous classes, which
>> is kind a problematic with annotations.
>>
>>$A = new class {} invariant {};
>>
>>$f = function () {} require {} ensure {};
>>
>> The only thing that remains that might be of interest to both is
>> `@throws` but that was not discussed at all as of yet.
>>
>>use Ns\SomeException;
>>
>>@throws SomeException
>>function f() {
>>
>>}
>>
>> This is at least how one would expect it to work and it is something
>> that should be covered by annotations and not as part of the language.
>> The ABNF should account for that:
>>
>> ANNOTATION= "@" NAME [ " " VALUE ]
>> NAME  = STRING
>> VALUE = QUOTED-STRING / PHP-REFERENCE / EXPRESSION
>> QUOTED-STRING = ( "'" / DQUOTE ) STRING ( "'" / DQUOTE )
>> EXPRESSION= PHP-CODE ";"
>>
>> Where PHP references are any of the already possible ones:
>>
>>use F\Q\C\N;
>>
>>@annotation \F\Q\C\N
>>@annotation N
>>@annotation \F\Q\C\N::CONSTANT
>>@annotation N::CONSTANT
>>@annotation \F\Q\C\N::function()
>>@annotation N::function()
>>@annotation \F\Q\C\N::$variable
>>@annotation N::$variable
>>
>> I also though some more about function support for annotations and this
>> would actually be a nice thing for userland.
>>
>>annotation deprecated(Reflection $element, string $message = '') {
>>  @trigger_error($message, E_USER_DEPRECATED);
>>}
>>
>>@deprecated('because')
>>function x() {}
>>
>>@deprecated
>>function y() {}
>>
>> This would allow users to implement simple and easy reactive annotations
>> in userland. Even if this could or should be an extension of the feature
>> in the future, it should be thought about know. Simply because the
>> brackets make sense if such a feature is to be implemented. ;)
>>
> Looks interesting, but try to think where the "annotation deprecated"
> should be declared,to be visible in every compiled script, when the
> corresponding code should be called (in what context), what if we need
> to do something at compile-time? Single answers to these question are
> going to be great for "deprecated" use case, however they will limit
> usability for other cases.
> 
> Thanks. Dmitry.
> 

Reactive annotations would have their limitations, e.g. calls to the
reactive annotation function only happen during runtime and any attempts
to perform something at compile time directly results in an engine
error. It limits their use cases but allows interesting ones at the same
time.

Another approach could be to allow registration of reactive annotation
functions at runtime, this would make it even more useful. Of course
that would mean that the function is only called for each encountered
annotation at runtime after it was registered. However, such a
limitation is pretty much the same as we have it for any other function
right now too.

  class User {

public function hasRole($right) {
  if (false) {
throw new InsufficientPrivileges;
  }
}

  }

  $user = new User();

  register_annotation('Framework\Role', [ $user, 'hasRole' ]);

  class Controller {

@Framework\Role('admin') public function editAction(){}

  }

  // ENGINE (pseudo code)

  array registered_annotations = [];

  void register_reactive_annotation(annotation, callback)
  {
registered_annotations[annotation] = callback;
  }

  void reactive_annotation_call(annotation, ...arguments)
  {
if (annotation exists in registered_annotations) {
  call registered_annotations[annotation](...arguments);
}
else {
  log_info("Unknown reactive annotation %s", annotation);
}
  }

However, this is a story for another RFC. It is only important because
usage of the brackets in the current RFC would make such a feature more
complicated to implement.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


[PHP-DEV] Request for Karma

2016-04-27 Thread Fleshgrinder
Hello fellows!

I would like to request karma for the PHP wiki to support others in
writing RFCs and maybe some time in the future contribute RFCs. For now
I plan to help Dmitry Stogov as co-author with the already existing
Attributes RFC.

A few words about my person might not hurt I guess. I am an MSc and PHP
developer from Austria. I work with PHP since many years, however, I am
also fluent in Java, JavaScript, Shell, ... and know my ways around in
C, C++, Rust, ... I am currently working at trivago in Germany as lead
PHP developer of a small development team.

I already registered a wiki account under the name "fleshgrinder".
-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-26 Thread Fleshgrinder
On 4/25/2016 10:31 AM, Dmitry Stogov wrote:
> 
> 
> On 04/23/2016 06:29 PM, Fleshgrinder wrote:
>> +1 for the basic idea, however, I have various remarks.
>>
>> The RFC text is hard to read and contains many grammatical mistakes. How
>> could one help you here?
> I would need a co-author :)
> 

I would love to help you but would require some karma. I need to check
how to get it. I will answer more tomorrow.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Patch for Union and Intersection Types

2016-04-26 Thread Fleshgrinder
On 4/26/2016 9:40 PM, Levi Morrison wrote:
> I think he meant to post a different case:
> 
> function (Foo $foo = null, $concrete_param);
> 
> This is based on a conversation I've had with him elsewhere.
> 

Gosh, I know such code. That should result in an error! :P

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Patch for Union and Intersection Types

2016-04-26 Thread Fleshgrinder
On 4/26/2016 9:13 PM, Bob Weinand wrote:
> There's undefined (= not a value) and there's the value null. We just don't 
> expose undefined to userland. [You see it when accessing undefined variables, 
> which PHP converts to null with a notice for example.]
> 
> Null is definitely a value. You can pass it around, reflect on it, assign it 
> etc..
> And as it is a value, it also has a type, which is null.
> 
> Null is not special, it just has specific behavior, like any other primitive 
> type has. The only special thing is that it's allowed as a default value with 
> function (Foo $foo = null), but this should be somewhen deprecated and 
> removed once we have proper null unions.
> 
> If you want to continue arguing, please open a new thread, but don't 
> side-track this thread to much, please.
> 
> Bob
> 

Null is a type, no argument there!

Deprecation of null as default value makes no sense, nor does it make
sense to deprecate 42 as default value. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2016-04-26 Thread Fleshgrinder
On 4/26/2016 10:38 AM, Alexander Lisachenko wrote:
> Hello, Nikita!
> 
> It's a great news! Having this stuff in the 7.1 core is awesome!
> 
> But I have several petitions for this API:
> 1) Could it avoid using of raw functions for parsing API, like
> ast\parse_file or ast\parse_code
> 2) Could you please put all the parsing stuff into the `Parser` class and
> put it into the `Php\` namespace, as well with node classes?
> 

The current coding standard still prescribes to do so. However, these
requests keep popping up and I think that this should be discussed at
some point. However, putting everything into a static class just to
mimic some OO that you might like makes absolutely no sense. We have
multi-paradigm support for a reason: best tool for the job?

That being said, the current implementation violates more rules of the
coding standard (camelCase vs. snake_case).

Currently we have the following:

  namespace ast {

parse_file()

parse_code()

get_kind_name()

kind_uses_flags()

class Node {
  public $kind;
  public $flags;
  public $lineno;
  public $children;
}

  }

  namespace ast\Node {

class Decl extends ast\Node {
  public $endLineno;
  public $name;
  public $docComment;
}

  }

From a pure coding standards view and current conventions in core at
least the following has to change:

  ast_parse_file()

  ast_parse_code()

  ast_get_kind_name() // ast_kind_name?

  ast_kind_uses_flags() // ast_kind_has_flags?

  class AstNode {
public $kind;
public $flags;
public $lineno;
public $children;
  }

  class AstDecl extends AstNode {
public $end_lineno;
public $name;
public $doc_comment;
  }

Of course usage of the \Php\Ast or \PHP\AST or \Php\AST or \PHP\Ast
namespaces is possible but you already see from the four variations that
this opens a huge can of worms that would require discussion.

Personally I would design the API as follows, given that it is not a
goal to have an anemic model in order to support direct changes of the
public properties without any kind of validation. If that is an intended
functionality things might need to be implemented a bit differently (and
the anemic DTO approach could even make sense). Also note that I am
modelling it in an OO way because it fits the actual data structure (tree).

  enum AstKind {

/*API = [ ORDINAL, NAME ]*/

FUNCTION = [ 66, 'AST_FUNC_DECL' ];

CLASS = [ 67, 'AST_CLASS' ];

// ...

/** @see \AstKind::getName() */
public function __toString(): string;

/** bitfield */
public function getFlags(): int;

public function getName(): string;

public function getOrdinal(): int;

public function hasFlags(): bool;

  }

  final class AstNode implements Countable, Traversable {

private AstKind $kind;

private int $line_number;

private array $children = [];

public function getKind(): AstKind;

public function getLineNumber(): int;

  }

  final class AstDeclarationNode extends AstNode {

private string $doc_comment;

private int $end_line_number;

private string $name;

/** @see \AstDeclarationNode::getName() */
public function __toString(): string;

public function getDocComment(): string;

public function getEndLineNumber(): int;

public function getName(): string;

  }

  final class Ast implements Countable, Traversable {

private AstNode $root;

private function __construct();

public static function fromFile(string $path): Ast;

public static function fromCode(
  string $code,
  string $filename = 'string code'
): Ast;

/** @see \Ast::getDump() */
public function __toString(): string;

public function getDump(bool $line_numbers = false): string;

  }

I do not think that it is necessary to use the exact same constant names
as are used in the C source (e.g. AST_FUNC_DECL vs. AST_CLASS). The
userland API could be more consistent here. You might disagree thought
but in the end only the ordinal must be an absolute perfect match.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-25 Thread Fleshgrinder
On 4/25/2016 10:04 PM, Rowan Collins wrote:
> On 25/04/2016 19:37, Stanislav Malyshev wrote:
>> Hi!
>>
>>> @attr() - is a valid "silenced" call to function named "attr".
>>> This syntax can't be reused.
>> Not valid if it's in the middle of class definition, and not valid in
>> form of:
>>
>> @attr() function foo() { ... }
>>
>> This is not a valid PHP syntax now. So I'm not sure why it can't be
>> used. << is an operator too and so is >> .
>>
> 
> No, but this is valid:
> 
> @atrr(); function foo() { ... }
> 
> That's perhaps a little too close for comfort...?
> 
> Regards,
> 

Actually I agree with Stanislav (in pretty much every point he made so
far) on the syntax discussion, however, I already said that the brackets
are the main problem and it seems as it nobody sees it but your example
illustrates it perfectly.

@fopen('file', 'r'); function foo(){}

@deprecated function foo(){}

@throws InvalidArgumentException function foo(){}

@route ['name' => 'foo'] function foo(){}

Leaving out the brackets makes it very clear. I am in an extreme rush
and will read more in the thread the next days, sorry.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
On 4/24/2016 6:57 PM, Levi Morrison wrote:
> Genuine question[1]: how is @attr() different than `<>`? Also,
> isn't `@attr()` 100% valid user-land code today that can precede
> function or constant declarations?
> 
>   [1] I don't like that I have to make that explicit but it is what it is.
> 

ROFL, that is actually totally true and I never thought about it. Damn
silencing operator! :P

However, i still think that the brackets are unnecessary and make it
look like function calls.

  <>
  function f() {}

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
On 4/24/2016 2:54 PM, Fleshgrinder wrote:
> Another way to illustrate what I mean:
> 
> The feature will be used /to annotate/ (add metadata) and the so
> /annotated/ data has additional /attributes/ afterwards.
> 
> Trying building the sentence if the feature is called /attributes/.
> 
>   @entity
>   @invariant
>   final class A {
> 
> @inject
> private static $x;
> 
> @test
> public memoized function f(){}
> 
>   }
> 
> r = reflect A
> r.getModifiers   = [ final ]
> r.getAnnotations = [ entity, invariant ]
> r.getAttributes  = [ final, entity, invariant ]
> 
> r = reflect A.x
> r.getModifiers   = [ private, static ]
> r.getAnnotations = [ inject ]
> r.getAttributes  = [ private, static, inject ]
> 
> r = reflect A.f
> r.getModifiers   = [ public, memoized ]
> r.getAnnotations = [ test ]
> r.getAttributes  = [ public, memoized, test ]
> 
> Note that there are programming languages that allow adding of metadata
> solely via annotations: Ceylon. No matter the data to annotate. Hence,
> in Ceylon no differentiation would be made between modifiers and
> annotations. However, one could check the actual annotation type to
> determine what it is.
> 
> https://modules.ceylon-lang.org/repo/1/ceylon/language/1.2.2/module-doc/api/index.html#section-annotations
> 

The example isn't actually complete, sorry:

  @entity
  @invariant
  final class A {

@inject
private static $x = 0;

@test
public memoized function f(){}

  }

r = reflect A
r.getModifiers   = [ final ]
r.getAnnotations = [ entity, invariant ]
r.getAttributes  = [ final, entity, invariant, $x, f() ]

r = reflect A.x
r.getModifiers   = [ private, static ]
r.getAnnotations = [ inject ]
r.getAttributes  = [ private, static, inject, value((int) 0) ]

r = reflect A.f()
r.getModifiers   = [ public, memoized ]
r.getAnnotations = [ test ]
r.getAttributes  = [ public, memoized, test ]

I hope I didn't forgot any attribute. :P

All in all, attributes are things that things have to describe those
things and annotations allows us to add additional attributes to things,
on top of possible other attributes that are already addable by other
means (modifiers, values, ...).

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
Another way to illustrate what I mean:

The feature will be used /to annotate/ (add metadata) and the so
/annotated/ data has additional /attributes/ afterwards.

Trying building the sentence if the feature is called /attributes/.

  @entity
  @invariant
  final class A {

@inject
private static $x;

@test
public memoized function f(){}

  }

r = reflect A
r.getModifiers   = [ final ]
r.getAnnotations = [ entity, invariant ]
r.getAttributes  = [ final, entity, invariant ]

r = reflect A.x
r.getModifiers   = [ private, static ]
r.getAnnotations = [ inject ]
r.getAttributes  = [ private, static, inject ]

r = reflect A.f
r.getModifiers   = [ public, memoized ]
r.getAnnotations = [ test ]
r.getAttributes  = [ public, memoized, test ]

Note that there are programming languages that allow adding of metadata
solely via annotations: Ceylon. No matter the data to annotate. Hence,
in Ceylon no differentiation would be made between modifiers and
annotations. However, one could check the actual annotation type to
determine what it is.

https://modules.ceylon-lang.org/repo/1/ceylon/language/1.2.2/module-doc/api/index.html#section-annotations

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
I am not arguing against the RFC nor the feature itself, on the
contrary, I like it. I just do not like certain aspects and design
decisions of it; that is all.

Configuration and AOP are the best usecases for annotations and those
should be stressed in the RFC. They are not mentioned at all!

Another usecase that I am missing completely is the usage of it for
documentation and static code analysis. I already mentioned the /throws/
annotation, this could help e.g. IDEs to warn you better about uncatched
exceptions form methods you call.

DbC is a possible usecase but better implemented at language level. The
RFC could mention the possibility of it. However, right now it is the
sole usecase beside the not very PHP applicable `<>` and
`<>` examples.

You see, this is more a problem of the RFC text and not of the feature. ;)

Another think I complained about is the proposed syntax because it makes
annotations look like function calls, which they simply are not and will
not be. The syntax is misleading and a possible built-in functionality
of reactive annotations (not saying we need them) at the language level
for userland is blocked. I know I just repeated myself.

The extension you mentioned works just fine without the brackets.

  @invariant CONDITION;
  class A {

@ensure CONDITION;
@require CONDITION;
function f(){}

  }

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
On 4/24/2016 1:58 PM, Benjamin Eberlei wrote:
> The article *you* reference about attributes lists C# attributes as the
> *first* example.
> 
> And defines an attribute as:
> 
> "For clarity, attributes should more correctly be considered metadata
> <https://en.wikipedia.org/wiki/Metadata>. An attribute is frequently and
> generally a property of a property."
> 
> HHVM uses the name attribute, for the same syntax that Dimitry proposes
> here.
> 
> *MUST* is such a strong word in this context, this is not an 0 XOR 1 issue.
> 

On 4/24/2016 2:07 PM, Zeev Suraski wrote:
> Thanks for the programming 101 lesson :)
>
> I pointed out to Sebastian, who suggested that 'attributes' are
equivalent to 'member variables' or 'properties', that they're very
consistently referred to in PHP as 'properties' and that I'm not aware
that they were ever referred to as 'attributes'.
>
> Nothing in your links suggested otherwise, arguably the opposite.
According to https://en.wikipedia.org/wiki/Attribute_(computing), "An
attribute is frequently and generally a property of a property", and
while "the term attribute can and is often treated as equivalent to a
property depending on the technology being discussed", when the
technology in question is PHP, this is not the case.
>
> Of course, member visibility modifiers and access modifiers
(public/protected/private, static, etc.) are a different thing.  Saying
member variables are referred to as attributes (incorrect in the context
of PHP, AFAIK) is very different from saying these modifiers are
referred to as attributes (correct and sensible).
>
> Last, we're absolutely allowed to have our own definitions of terms as
long as they're sensible.  Both attributes and annotations are sensible
here, and the fact there may be languages that treat attributes as
equivalent to properties isn't a strong reason against using that term
for something sensible, that is different from these other languages, in
PHP.
>
> Zeev
>

As I said, unless somebody knows an even better term. It also depends on
which source code is going to be allowed to have this kind of additional
metadata. If we limit it to functions, classes, properties, and methods:
/all good./

Why?

We might want to allow adding of metadata to other parts of the source
code in the future. I already asked regarding annotating files
themselves (as is possible with PhpDoc's file-level docblock) and then
it becomes complicated. I am not saying we need this, I am saying we
need to clarify this.

Using the term attribute without defining what the term means is
problematic. I know, Facebook/HHVM/Hack but we are not required to be
compliant with them and they are not our benchmark.

Using the term annotation is not so problematic because it has a clear
definition (not only in computer science) and it does not say anything
about the applicability of what it does, it only states the
functionality of the feature itself: /adding metadata to data/.

You want to avoid writing extensive definitions of terms that are going
to be used since people then need to learn these terms. Just think about
the normal usage of the word attribute in language, e.g. describe the
attributes of this image. The answer could be "it shows a woman with
long hair and blue eyes". Hence, /long hair/ and /glue eyes/ are
attributes of the woman. However, asking for the annotations of this
image would result in a different answer, the asked person, assuming she
knows what the word in general means, turns the image and would tell us
the date and time it was taken or printed, or maybe the ISO level, ...
whatever.

Is *public* an attribute of the property? /Yes/
Is *static* an attribute of the method? /Yes/
Is *name* an attribute of a person? /Yes/
Is *__toString* an attribute of the class? /Yes, behavioral/
Is *inattentive* an attribute of the child? /Yes/
...

So, what should `$r->getAttributes()` return? It is to broad, it is to
generic, it is too often mixed up.

`$r->getAnnotations()` is less ambiguous in the context of programming
and thus a better choice.

I hope you can follow my /Gedankenspiel/ (mind game) better now. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
On 4/24/2016 1:36 PM, Benjamin Eberlei wrote:
> On Sun, Apr 24, 2016 at 10:24 AM, Fleshgrinder  wrote:
> 
>> The invariant could also be added as an additional branch to the class
>> instead of a method, since it would not work like a method.
>>
>>   class A {} invariant {}
>>
>>   function f() {} require {} ensure {}
>>
>> This would also align nicely with closures and anonymous classes, which
>> is kind a problematic with annotations.
>>
> 
> You are way off topic with this imho.
> 

No, not at all!

The RFC explicitly mentions design by contract (DbC) and that is why I
am responding to that. I do not think that annotations should or could
be used for DbC and want to raise this issue here. Of course all of the
above is a completely different story and requires its own RFC as well
as implementation. However, DbC should not be used to justify the
addition of annotations to PHP. (If libraries choose to use it for that,
different story.)

On 4/24/2016 1:36 PM, Benjamin Eberlei wrote:
> Attributes as proposed by Dimitry are not executing functions, they are
> only metadata
> that can be retrieved through reflection API. I think a python style
> decorator approach
> that you propose here, executing functions is not what the different
> pro-annotations,
> pro-attributes or pro-DesignByContract fractions want/need.
> 
> You are proposing something along the lines of AOP, which is an entirely
> different beast
> in my opinion.
> 

I know and that is why I am writing that the usage of brackets is not a
good idea because it suggests exactly that. We need to think about a
possible feature as outlined by myself (reactive annotations or /Python
style decorator approach/ as you call it) in order to not implement
annotations in a way that would kill exactly such a feature in a
possible future.

Hence, I am not off topic because I am thinking outside of the box in
the context of the whole ecosystem. Something that I see not happening
in this RFC nor its discussion.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
On 4/24/2016 1:00 PM, Zeev Suraski wrote:
> 
> 
>> -Original Message-
>> From: Sebastian Bergmann [mailto:sebast...@php.net]
>> Sent: Sunday, April 24, 2016 12:14 PM
>> To: internals@lists.php.net
>> Subject: Re: [PHP-DEV] [RFC] PHP Attributes
>>
>> On 04/21/2016 11:13 PM, Dmitry Stogov wrote:
>>> I would like to present an RFC proposing support for native annotation.
>>
>> Dmitry,
>>
>> please use "annotation" as the name for this feature and not "attribute".
>>
>> We already have attributes: it's what we use to store data in objects. And
>> while some people call them "member variables" or "properties" the correct
>> term for them (AFAIK) is "attribute".
> 
> I don't think I've ever heard properties referred to as attributes in the 
> context of PHP.  The PHP manual defines them and refers to them throughout as 
> 'properties'.
> 
> (I'm not voicing an opinion on attributes vs. annotations;  Just pointing out 
> that data storage inside objects isn't named attributes).
> 
> Zeev
> 

The terminology here is pretty clear and you can just look it up, it has
nothing to do with PHP or Java or whatever. The main problem is simply
that people do not know the terminology and get mixed up. That is
usually okay in a casual discussion where each peer understands what the
other is referring to. However, we are dealing with language
specification here and need to be very exact or we fuck it up for the users.

`$x` is a property in the following example:

  class A {
$x;
  }

https://en.wikipedia.org/wiki/Property_%28programming%29

`private` is an attribute of property `$x` and an access modifier (not
visibility, because the property is still visible, e.g. via reflection,
and it only alters access to the property):

  class A {
private $x;
  }

https://en.wikipedia.org/wiki/Attribute_%28computing%29

Note that these things go further up in the terminology hierarchy to:
Field - https://en.wikipedia.org/wiki/Field_%28computer_science%29
Record - https://en.wikipedia.org/wiki/Record_%28computer_science%29
Data Structure - https://en.wikipedia.org/wiki/Data_structure

This is not the whole image yet, there are more things like (random order):
- functions
- methods
- members
- class variables
- static variables
- behavior
- data
- ...

You will notice, if you read all Wikipedia articles and related
documents, that these terms are too often used interchangeable. This is,
as mentioned before, mainly the case because people to not care about
terminology in general.

To sum it up, calling them attributes is outright wrong because not all
parts of a source code of a programming language has attributes. That is
why Sun chose the word annotation. Annotation means metadata that was
added to data. It does not say anything about the data itself and it
does not necessarily alter the data in any way, however, it can. This is
exactly what this feature is about. Since, an entity annotation does not
alter the data (in this case a class) itself but this additional
metadata may be used to configure other parts of the program.

The same is true for a method that has been annotated with test. The
data is not altered at all but is helps other parts of the program to
configure specific data and behavior based on this additional metadata
that was added to the data. Execution of the same method without those
other parts that react on the metadata does not do anything and the
program will execute normally.

TL;DR this feature *MUST* be called annotations (unless someone knows an
even better term) and the annotations *MAY* be used to add attributes to
properties but for many other things too.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
The invariant could also be added as an additional branch to the class
instead of a method, since it would not work like a method.

  class A {} invariant {}

  function f() {} require {} ensure {}

This would also align nicely with closures and anonymous classes, which
is kind a problematic with annotations.

  $A = new class {} invariant {};

  $f = function () {} require {} ensure {};

The only thing that remains that might be of interest to both is
`@throws` but that was not discussed at all as of yet.

  use Ns\SomeException;

  @throws SomeException
  function f() {

  }

This is at least how one would expect it to work and it is something
that should be covered by annotations and not as part of the language.
The ABNF should account for that:

ANNOTATION= "@" NAME [ " " VALUE ]
NAME  = STRING
VALUE = QUOTED-STRING / PHP-REFERENCE / EXPRESSION
QUOTED-STRING = ( "'" / DQUOTE ) STRING ( "'" / DQUOTE )
EXPRESSION= PHP-CODE ";"

Where PHP references are any of the already possible ones:

  use F\Q\C\N;

  @annotation \F\Q\C\N
  @annotation N
  @annotation \F\Q\C\N::CONSTANT
  @annotation N::CONSTANT
  @annotation \F\Q\C\N::function()
  @annotation N::function()
  @annotation \F\Q\C\N::$variable
  @annotation N::$variable

I also though some more about function support for annotations and this
would actually be a nice thing for userland.

  annotation deprecated(Reflection $element, string $message = '') {
@trigger_error($message, E_USER_DEPRECATED);
  }

  @deprecated('because')
  function x() {}

  @deprecated
  function y() {}

This would allow users to implement simple and easy reactive annotations
in userland. Even if this could or should be an extension of the feature
in the future, it should be thought about know. Simply because the
brackets make sense if such a feature is to be implemented. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-24 Thread Fleshgrinder
On 4/24/2016 1:48 AM, Benoit Schildknecht wrote:
> If I was a popular framework creator, this wouldn't stop me. I would
> release two packages : one for 7.0, another one for 7.1. And the 7.0 one
> would be the 7.1 one that has been processed through a script to remove
> any <<>> syntax, or to transform it (if pre/post attributes instructions
> were to be implemented in the core).
> 
> Regards,
> Ben.
> 
> Le Sun, 24 Apr 2016 01:09:08 +0200, "Thomas Bley" 
> a écrit:
> 
>> The <<>> syntax comes with the problem that previous versions cannot
>> ignore it on parsing.
>> So poeple write new frameworks for 7.0 which cannot be parsed in 5.x,
>> then they write new frameworks for 7.1 which cannot be parsed with 7.0
>> and 5.x and so on.
>> For companies staying on Linux distributions with long term support on
>> 7.0, this is rather a nightmare for both users and framework maintainers.
>> When choosing <<>> or any other non-backward compatible syntax for
>> 7.1, there should be a patch for 7.0 to ignore the new syntax without
>> parse errors.
>>
>> Regards
>> Thomas
>>
> 

That is the nature of a feature release, you find many of those in any
PHP feature release. Think of for instance `yield`, directly results in
a parse error in older PHP versions.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-23 Thread Fleshgrinder
On 4/22/2016 4:15 AM, Sara Golemon wrote:
> All that said, I love the proposal overall, and I can't wait to
> propose builtin annotations like <<__Memoize>>, <<__Mock>>, and
> similar.
> 

I'd rather see these two functionalities added as modifiers at the
language level instead since they change the code behavior rather
dramatically. Not sure if knowledge of them is of interest in stages
where annotations might not be readily available; this was a driving
factor in Kotlin's decision what becomes a modifier or annotation.[1]



I know that this is true for `@invariant`, `@require`, and `@ensure` as
well, they are fully-fledged assertions after all. Especially the
`@invariant` could be easily added as a magic method.

[assert]
assert.invariants = 1



Both `@require` and `@ensure` are a bit harder to implement at language
level. The following is the best I can come up with and is inspired by
the Eiffel syntax.[2]

[assert]
assert.preconditions = 1
assert.postconditions = 1

balance -= $this->balance - $sum;
  }
  require {
$sum >= 0;
$sum <= ($this->balance - self::MIN_BALANCE);
  }
  ensure {
$this->balance === (old::$balance - $sum);
  }

}

$account = new Account;

$account->withdraw(-10);
/*
Uncaught PreconditionError: $sum >= 0
*/

$account->withdraw(10);
/*
Uncaught PreconditionError: $sum <= ($this->balance - self::MIN_BALANCE)
*/

$account->deposit(10);
$account->withdraw(5);
/*
Uncaught PostconditionError: $this->balance === (old::$balance - $sum)
*/

?>

I actually think now that it would be better to go for this than for
annotations.

[1] http://blog.jetbrains.com/kotlin/2015/08/modifiers-vs-annotations/
[2]
https://archive.eiffel.com/doc/online/eiffel50/intro/language/invitation-07.html

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] PHP Attributes

2016-04-23 Thread Fleshgrinder
+1 for the basic idea, however, I have various remarks.

The RFC text is hard to read and contains many grammatical mistakes. How
could one help you here?

I think that the Hack name attributes is unintelligible and annotations
would be much clearer to any audience. Simply because the name is very
well known.

I do not see the need for multi-annotation nor multi-value support. It
just creates multiple ways to achieve the exact same thing for no good
reason.

I do not like the <<>> syntax. It requires many key strokes, is hard to
read, and looks ugly. Why not simply @ and be done with it. I am not so
sure about the bracket requirement, is it somehow required for the
parsing? Otherwise I would leave it off. I guess it might be hard to
find the end of an annotation but have you considered to use the
semicolon for that? Would align nicely with existing PHP syntax. The
following would be the ABNF for my proposal:

ANNOTATION= "@" NAME [ " " VALUE ]
NAME  = STRING
VALUE = QUOTED-STRING / PHP-CONSTANT / EXPRESSION
QUOTED-STRING = ( "'" / DQUOTE ) STRING ( "'" / DQUOTE )
EXPRESSION= PHP-CODE ";"

A semicolon would only be required if it is not a single quoted string
(see following example) or constant. A question that I see unanswered is
how embedding of variables in quoted strings should be dealt with. I see
no need for this but people might assume it is supported because PHP
supports it everywhere else.

"
class A {}

<")>>
class B {}

?>

Requiring PHP code to be terminated with a semicolon should also ensure
that people do not start to write fully-fledged programs in annotations.
Since that is not what they are intended for. An alternative approach I
see here would be to go for the brackets but then again only for PHP code:

EXPRESSION = "(" PHP-CODE ")"

Then again, it looks similar to a function call and this is imho not
good. Unless of course new annotations can be defined as special
functions directly in userland, e.g. with an `annotation function`
and/or `annotation class`. However, this would require more thought.

Another question that is unanswered for me is: how to go about adding
annotations to a complete file as is currently possible with PhpDoc and
its file-level doc block:

'
@copyright '2016 Richard Fussenegger'
@license 'MIT'

declare(strict_types=1);

namespace Fleshgrinder\PhpInternals;

@description 'True annotation support could be a very good thing.'
@invariant $this->balance >= self::MIN_BALANCE;
class Account {

  private const int MIN_BALANCE = 0;

  private int $balance;

  private Person $owner;

  @require $sum >= 0;
  @ensure $this->balance === (old::$balance + $sum);
  public function deposit(int $sum): void {
$this->balance += $sum;
  }

  @require $sum >= 0;
  @require $sum <= $this->balance - self::MIN_BALANCE;
  @ensure $this->balance === (old::$balance - $sum);
  public function withdraw(int $sum): void {
$this->balance -= $sum;
  }

  @deprecated 'for various reasons'
  public function setOwner(Person $wner): void {
$this->owner = $owner;
  }

}

@inheritDoc
class OverdraftAccount extends Account {

  private const int MIN_BALANCE = -1000;

}

?>

We also need to make sure to add something regarding coding standards
for annotation names. I would propose to go for camelCase (same as for
method names) since this is what PhpDoc used to use for many years now.

We also need to define how people can avoid to collide with internal
annotations. The typical double-underscore prefix approach that we have
for magic methods creates a lot of visual clutter and looks weird if
spread among all kinds of places. A namespace approach as we have it
already for userland code could help here.

 'user',
  'unique_constraints' => [
    'name' => 'user_unique',
'columns' => [ 'username' ],
  ],
  'indexes' => [
'name' => 'user_idx',
'clumns' => [ 'email' ],
  ],
  'schema' => 'schema_name',
];
class User {}

?>

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Types

2016-04-23 Thread Fleshgrinder
On 4/22/2016 11:42 AM, Quim Calpe wrote:
> IMHO, the point of Optional types is the intention, if you get an
> Option from a method, you have to deal with a None branch. Of course
> you can just unwrap and go on, but it's a developer decision to do that,
> not an oversight as using a Foo|null (or ?Foo) as an object directly.
> 

IMOH, the point of ?T is the intention, if you get a null from a method,
you have to deal with a null branch. Of course you can just ignore it
and go on, but it's a developer decision to do that, not an oversight as
using a Option as an object directly.

Sorry, but this works in both directions. The problem is not null, the
problem is that there is no system that warns you (e.g. a compiler)
about the missing null check. I think that Ceylon solved this problem
extremely nicely without the introduction of something special.

function fn(): ?T {}

$x = fn();
if (is $x T) {}
else {}

Not doing as above is a compiler error in Ceylon. However, I already
wrote multiple times that there are already statical code analysis tools
available that can find exactly such things in your code. One just needs
to use them.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Types

2016-04-21 Thread Fleshgrinder
On 4/21/2016 1:00 PM, Lin Yo-An wrote:
> I think this is not to make PHP like Java, and it totally makes sense -
> Nullable should be a type of a type instead of a state. In Haskell it's
> named Maybe or Option, and It's better than NullPointerException.
> 
> Here is a discussion from Haskell community:
> https://mail.haskell.org/pipermail/haskell-cafe/2011-April/091269.html
> 

Why is it /better/?

final class None {}

final class Some {

public $value;

public function __construct($value) {
$this->value = $value;
}

}

final class Maybe {

private static $none;

private $value;

private function __construct($value) {
$this->value = $value;
}

public static function NOTHING() {
if (self::$nothing === null) {
self::$nothing = new Nothing();
}
return new static(self::$nothing);
}

public static function SOME($value) {
return new static(new Some($value));
}

public function hasSome(): bool {
return $this->value !== static::$none;
}

public function isNone(): bool {
return $this->value === static::$none;
}

public function unwrap() {
if ($this->value === static::$none) {
trigger_error('NullPointerException', E_USER_ERROR);
}
return $this->value->value;
}

}

// 

function f1(): Option {}

$x = f1();
if ($x->hasSome()) {
echo $x->unwrap(); // 42
}

$x = f1();
if ($x->isNone()) {
echo -1;
}

echo f1()->unwrap(); // error: NullPointerException :P

// 

function f2(): ?int {}

$y = f2();
if (isset($y)) {
echo $y; // 42
}

$y = f2();
if ($y === null) {
echo -1;
}

echo f2(); // null

You can easily build your own Option or Maybe and add the additional
bookkeeping to your runtime but it will not make your program more
secure or anything. It just adds more method calls and makes it more
verbose.

You can already use static code analyzers to detect if null is being
ignored in your code, however, right now they mainly have to rely on
PhpDoc that is often not properly documented. Adding an explicit syntax
to PHP for documentation would make PhpDoc obsolete and allow static
code analyzers to perform their job better and PHP to error out during
runtime if something else is being returned.

Honestly, null is not our problem. Every language has its null, just
because they wrap it or rename it does not make null suddenly vanish
from the universe. :P

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Types

2016-04-21 Thread Fleshgrinder
On 4/21/2016 6:33 PM, Thomas Bley wrote:
> Hello Tom,
> 
> with default return value I mean to return a certain value if nothing else is 
> returned (similar to method parameters with a default value).
> 
> example 1:
> 
> declare(strict_types=0);
> 
> function my_strpos(string $haystack, string $needle): int = false {
>   return 42; // return 42
>   return false; // return false
>   return true; // return 1
>   return; // return false
> }
> 
> example 2:
> 
> declare(strict_types=1);
> 
> function my_strpos(string $haystack, string $needle): int = false {
>   return 42; // return 42
>   return false; // return false
>   return true; // fatal error
>   return; // return false
> }
> 

I definitely do not like the equal sign in there because it goes against
all my mathematical knowledge; an int is false?!?

Note that the same /would/ be possible with union types if given precedence:

function fn(): int|false {}

That being said, it is way too magic! A return without an argument is
*void* and has to result in a `TypeError`. Really, start to think about
the types as /checked annotations/ ...

/**
 * @return int|false
 */
function fn() {}

function fn(): int|false {}

... are equivalent and the former does not suddenly return *false* on
its own and hell it shouldn't.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-21 Thread Fleshgrinder
On 4/20/2016 10:18 PM, Dominic Grostate wrote:
> Just a thought that crossed my mind which might satisfy both worlds.  Has
> anyone every considered unions as a type declaration?
> 
> namespace Vector/TypeDefs
> 
> union Stringable
> {
> as string;
> as int;
> as float;
> 
> private $value;
> 
> public function __make($type)
> {
> switch (type) {
> case 'string': return (string) $this->value;
> case 'int':return (int)$this->value;
> case 'float':  return (float)  $this->value;
> }
> }
> }
> 
> my_echo_func("123"); // << A scalar variable on the outside.
> 
> function my_echo_func(Stringable $stringable) // << a union on the inside
> {
> var_dump($stringable as string); // string(3) "123"
> var_dump($stringable as int);   // int(123)
> var_dump($stringable as float);  // float(123.0)
> }
> 
> Perhaps not exactly like this, but adding unions as type of class
> declaration should save a hell of a lot of keywords, and may save a number
> of "instanceof" type checks as well.
> 

I do not like the idea because these types directly become part of your
public API and you end up including a dozen packages just to get the
basic union types in. More IO, more cache utilization, more
dependencies, ...

Also, one cannot change any type that was ever declared without a direct
BC. No, sorry, I thing that this is very bad. :(

However, the idea to make objects castable to more of the various scalar
types is not new and would be awesome.

interface Object {

  function __toBool(): bool;
  function __toFloat(): float;
  function __toInt(): int;
  function __toString(): string;

  function __toArray(): array;
  function __toObject(): object;
  function __toResource(): resource;

}

Auto-conversion only if not ambiguous (`$o1 + $o2` where both have
`__toInt()` and `__toFloat()` throws an ?Error but `(float)$o1 +
(float)$o2` works so does `intdiv($o1, $o2)`), next is operator
overloading. ;)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Quick sanity check ...

2016-04-21 Thread Fleshgrinder
On 4/20/2016 11:03 PM, Stanislav Malyshev wrote:
> No of course not. The specific instance of error you had *this time* may
> be solved. The problem won't be. You still have to deal with:
> - How this object is initialized? How you ensure it *is* initialized and
> that initialization is correct (0 is perfectly valid int)?
> - How this object is unserialized and what if unserialized data has
> non-integer or 0 or __wakeup has a bug?
> - What if some code just writes 0 into $olderThan - you declared it as
> public so anybody could mess with it?
> - What if some code mixes signed and unsigned and you get negative
> number instead of positive?
> - What if this code runs on 32-bit but receives 64-bit value and
> truncates it?
> 
> And so on, and so forth, I probably missed more possibilities than I
> mentioned. Declaring a type does not magically free one from correct
> design and testing, and typed programs have bugs as much as non-typed
> ones (maybe slightly different ones). Actually, one of the harms relying
> on it would be the same problem safe_mode had - it's full of holes, it's
> not safe and it creates wrong expectations. If you just write "int" and
> expect your problems to magically go away - you're in for big and bad
> surprises.
> 

While I agree with Stanislav and the others that a stricter type system
would not have prevented the bug. However, a stricter type system helps
to limit the amount of tests one has to perform and that is often a good
thing. That does not mean that dynamic type systems are shit. Actually
the opposite is the case, it is the same situation with paradigms.

What I love about PHP is that we have a lot under one hood:
multi-paradigm as well as loose and strict types. This allows one to
choose the best tool for the current job.

Relying on your language for a bit of safety as asked of it cannot be
compared to `safe_mode` where magic happens in the background. When one
declares and `int` than it should be an `int`. Of course that also means
that one should know what an `int` is and how to validate it according
to the current business rules.

That being said, isn't Lester's goal to validate scalar strings all the
time anyways? I mean, at least `mysqlnd` transforms all data from the DB
automatically to the proper scalar types for optimal performance in your
program. But if one keeps scalar strings everywhere and leaves proper
type coercion to PHP, I mean, why not. It is definitely doable and
strict types are definitely not necessary if done properly.

The big difference I see is that Lester is working on his code for
himself (or for a customer) and does not have to design APIs for
hundreds of other developers. PHP is used in the way it was initially
designed, as a glue language. I repeat myself but I cannot see the need
for strict types here.

If you are developing APIs that are going to be (ab)used by hundreds of
other developers in ways you would never have foreseen things change.
One wants to ensure that the API is as self-explanatory as possible and
as easy to use as possible. This includes (to get back to one of your
examples) that objects that should not be serialized are not
serializable (`private function __sleep()`) and not deserializable
(`private function __wakeup()`) nor cloenable if necessary. This
includes self-explanatory required types, sane default values, and
appropriate visibility of things.

PhpDoc is the classical tool for us here and Stanislav wrote in another
thread that this is the tool of choice. I completely disagree with this
because PhpDoc might be nice and already features more complicated types
(e.g. unions), however, it is also lacking many features as the
development of the PSR-5 shows. Another problem is that documentation is
not kept in sync and it is extremely hard to teach people how important
proper documentation is. Believe me, I know. You might say now that
those programmers are bad, well, yes, maybe. But that is what you get
when you are working in huge teams; ask Google.

In the end it is about better APIs for me as I explained in many other
messages and I stay true to that. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Quick sanity check ...

2016-04-21 Thread Fleshgrinder
On 4/21/2016 2:52 AM, Lester Caine wrote:
> PHP5.4 http://lsces.org.uk/   0.41s 3.65Mb
> PHP5.6 http://php6.lsces.org.uk/  0.54s 11.77Mb
> PHP7   http://php7.lsces.org.uk/  0.45s 1.83Mb
> 
> Same set of code ... 3 different fpm instances
> PHP5.2 one with eaccelerator will not run :( but I think I now have PHP7
> configured properly with OPcache but it still does not match the speeds
> I get on the PHP5.2/eaccelerator production machines!
> 

Well, hard to tell if you could improve further without any info on
setup and/or configuration but the numbers look good to me. Also, do not
forget that the times and memory consumption you get from PHP might not
reflect the real world. I would suggest to measure this with independent
tools.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Quick sanity check ...

2016-04-20 Thread Fleshgrinder
I do not see a single reason why you would need to change anything if
you are not requiring any of the new features and would say that the
only reason to upgrade for you is security patches.

However, I hardly believe that you cannot see a speed improvement; or at
least less memory consumption.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-20 Thread Fleshgrinder
I am not quoting anything because the formatting of your emails is
completely off in Thunderbird. However, I want to add one to the list:

declare(strict_types=1);

interface Stringable {
function __toString(): string;
}

function fn(string|Stringable $arg) {
$param = (string) $arg;
}

We could add a new *stringable* primitive to PHP though, but do we guys
really want to start doing so? There is pretty much an endless amount of
combinations and finding names alone is endlessly hard.

declare(strict_types=1);

function fn(int|string $maybe_bigint) {
// mysqlnd automatically creates the proper type based on the value.
// Expressing this in userland is impossible ... :(
}

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-20 Thread Fleshgrinder
On 4/19/2016 10:19 PM, Zeev Suraski wrote:
> I can only repeat - primitive types can and should get dedicated solutions.  
> There's really no need for allowing over creativity with userland-customized 
> scalar types.  If we think that a certain scalar definition makes a lot of 
> sense, we can add it at the language level.  There's no need to complicate 
> the language, add syntax which makes no sense for objects and isn't really 
> needed for scalars either.
> 

We can for many:

type number := int|float
type object := 
type scalar := bool|int|float|string
...

However, what about:

type ? := array|Traversable
type ? := int|string
type ? := float|string
type ? := bool|null
...

I actually argue that we do not even want to define them on a language
level (with the exception of array|Traversable) because these
combinations are too usecase specific.

>> interface HouseCat {
>> function drink();
>> }
>>
>> interface Dog {
>> function eat();
>> }
>>
>> -interface Lion {
>> +interface Lion extends HouseCat, Dog{
>> function drink();
>> function eat();
>> }
> 
> Pardon me saying this but it doesn't appear as if you've read what I wrote.  
> Please take a look at the 'diff' I made in the definition of your Lion class, 
> because without it, your sample and mine have little to do with each other.
> 
> With that change in place, please reevaluate whether what you said is 
> relevant:
> 

I guess I just jumped over that fact and misinterpreted it because what
you are proposing is a magic intersection type limited to interfaces.
While I cannot think of a situation where this creates problems from a
technical point of view (it is duck typing after all) I find it highly,
highly unusual and way too magic as well as even confusing.

I think there are two ways:

- No union/intersection at all!
+ Union and intersection!

Going somewhere in between destroys generics, bounded quantification,
and F-bounded quantification in the future or at least makes it harder
to implement cleanly. You need to consider that this RFC might be voted
negative but it might come back in PHP 8 or PHP 9 where the landscape
has changed so vastly that it might become a yes.

Let's not introduce half backed features that nobody ever implemented
and found useful in any context or we end up with more weirdness that we
already have a some points.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [VOTE] Catching Multiple Exception Types

2016-04-19 Thread Fleshgrinder
On 4/19/2016 9:39 PM, Stanislav Malyshev wrote:
> Hi!
> 
>> Except these two are in separate libraries that cannot share an interface.
> 
> If these are separate libraries, you can't be sure that method does the
> same thing, or even that it will be existing in both.
> 
>> An interface is not possible: separate libraries. Duck-typing is not
>> appropriate: only these two specific classes are supported.
> 
> This looks very strange and brittle design - two random classes from two
> unrelated libraries, which you rely on have exactly the same
> functionality and keep it that way. Not a robust design if you ask me.
> Also, it looks strange why only those two random classes can be
> converted to arrays but none others can. What if you had third class
> that also can be converted to array? What if you had 20 of them? Again,
> looks like brittle and ad-hoc design.
> 

Stanislav is completely right here, this is exactly one of the usages of
union types that is completely wrong. You had this example:

namespace Application;
function log(Eloquent\Collection | Haldayne\Map $entity) {
$logger->log($entity->toArray());
}

try {
log(Config::find());
} catch (Eloquent\Exception\UnexpectedValue | \UnexpectedValueException
$ex) {
die('Configuration is neither array nor object');
}

The problem with this is that you now require both libraries to be
installed at the same time because otherwise the union type cannot be
verified by PHP's type system. This will bite you in the ass in no time.
Just think of your composer:

"require": {
"eloquent/collection": "*",
"haldayne/map": "*"
}

Both do the same?!? Better rely on duck typing in such cases.

function log($entity) {
if (method_exists($entity, 'toArray')) {
$logger->log($entity->toArray());
}
else {
// handle is in another way.
}
}

If you really want to ensure that the method is not being called by a
dev in that way go for assertions.

function log($entity) {
assert('method_exists($entity, "toArray")', 'entity must implement
`toArray` method');

// Check in production too to avoid fatal errors?
if (method_exists($entity, 'toArray')) {
$logger->log($entity->toArray());
}
}

Union types only have a few special use cases but those are worth
exploring imho.

function div(int|float $x, int|float $y): int|float {
if (is_float($x) || is_float($y)) {
return $x / $y;
}
else {
    return intdiv($x, $y);
}
}

function even(int|string $x): bool {
if (is_int($x)) {
return $x % 2 === 0;
}
else {
return gmp_mod($x, 2) == 0;
}
}

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-19 Thread Fleshgrinder
On 4/19/2016 8:48 PM, Zeev Suraski wrote:
>> but it does not help with primitive types. :(
> 
> Which is fine.  Primitive types can and should get dedicated solutions.  
> There's really no need for allowing over creativity with userland-customized 
> scalar types.
> 

Hmmm... nope. I already brought various examples where I personally see
the strength of union types and that is exactly with the primitives.[1]
*int|string* is so powerful if you deal with MySQLi and its BIGINT stuff
because I can fully type hint it now (like the /mysqli/ extension does
in C) and check very fast if I need to use GMP or not.

I can only repeat. I am fully supporting to block union types if we
instead commit to the introduction of additional primitive types (as
outlined in the generics RFC)[2] and operator overloading in userland.

However, use cases remain and union/intersection types can help
especially if you do not want any kind of is-a relationship in your
classes. In other words, we do not want to introduce an additional
interface for something because we do not want the instance to pass
through other checks. Or, of course, the situation where it is simply
impossible for me to introduce the interface: built-in classes. I might
want to decorate them and pass through all checks but I cannot because,
well, how?

[1] http://marc.info/?l=php-internals&m=146080503103988&w=2
[2] https://wiki.php.net/rfc/generics#related_enhancements

> I believe you think I meant that instead of checking that $b's class actually 
> implements foo and bar, we'd check whether $b has all of the methods needed 
> by foo and bar - which means that theoretically means that it may have 
> methods foo() and bar() but not actually 'officially' implement their 
> respective interfaces.  But there's no reason to do it this way and that's 
> not what I meant.
> Instead, with my proposal, a $b object whose class implements both foo and 
> bar - will automatically be accepted as one that also implements baz.  The 
> checks will be conducted at the interface level, not the function list level. 
>  In other words, if $b doesn't explicitly implement baz, we'd take a look at 
> 'baz', see it's comprised of foo & bar, and check whether $b's class 
> implements them.
> 
> At this point, I can't imagine any negative side effect to automatically 
> deducing that an object that implements foo and bar also implements baz 
> (other than a small performance hit, probably roughly the same as the AND 
> union type).  Like I mentioned in my original post, I don't necessarily think 
> it's needed - I personally see no reason not to add 'baz' to the list of 
> interfaces impl implements, or as you said, replace foo and bar with baz 
> altogether.
> 

interface HouseCat {
function drink();
}

interface Dog {
function eat();
}

interface Lion {
function drink();
function eat();
}

A lion drinks and eats but is neither a HouseCat nor a Dog. This is
dangerous and introduces many potential hard to find bugs. Better don't
touch it and go for duck typing or the introduction of a dedicated
interface: *always*

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Proposal: Startup snapshot for optimizing app load time

2016-04-19 Thread Fleshgrinder
On 4/19/2016 6:54 PM, David Zuelke wrote:
> I think this solution is merely a band-aid for a more profound architectural 
> weakness of current PHP setups, where a web server call out to the engine 
> (via embedding or FastCGI) to execute a script, which causes this recurring 
> initialization overhead in the first place.
> 
> The future is (or should be) servers implemented fully in PHP code (e.g. 
> PHP-PM), just like every other comparable language (Ruby, Python, Java, ...) 
> already does. That also brings many other benefits, such as the ability to 
> handle upgrades to WebSockets in the same codebase, stream request bodies as 
> they're being uploaded, and so forth.
> 
> And the performance figures that PHP-PM delivers with Symfony validate that 
> approach IMO.
> 

This requires proper memory management, no matter how:

https://software-gunslinger.tumblr.com/post/47131406821/php-is-meant-to-die

https://software-gunslinger.tumblr.com/post/48215406921/php-is-meant-to-die-continued

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-19 Thread Fleshgrinder
On 4/19/2016 4:36 AM, Tom Worster wrote:
> On 4/18/16 4:34 AM, Tony Marston wrote:
> 
>> I repeat, where was the insult in the post in question?  What exactly
>> were the insulting words?
> 
> I chose just one example:
> 
>> Those who cannot write effective software without these "clever"
>> additions to the language are doing nothing but announcing to the
>> world that they are not clever enough to write effective software
>> using their own limited abilities.
> 
> I think it's hard to avoid construing an implication that people
> proposing and/or supporting changes to how PHP handles type in the
> current discussions here are incompetent programmers.
> 
> There's no doubt that this sentence posits a class of incompetent
> programmers who need crutches ('these "clever" additions') and a
> complementary class of competent programmer who don't. Saying so is
> pointless without some assignment (imaginary, implied or real) of
> individuals to the classes. It's hard to imagine that present company or
> the people whose interests we attempt to represent are not involved in
> the assignment. I find this a bit insulting.
> 
> Insult is something experienced as well as something performed. If
> enough people experience it then probably it was performed, regardless
> of intent. So to this extent I just disagree that...
> 
>> The fact that you don't like what I say does
>> not make it an insult.
> 
> "It's Not What You Say, It's What People Hear"
> 
> 
> But we are now completely off topic. To bring us back on topic I repeat
> my request that you try to be specific about what you want and why, with
> respect to the RFCs under discussion.
> 
> Tom
> 
> 

Very well said! :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-19 Thread Fleshgrinder
On 4/19/2016 11:41 AM, Zeev Suraski wrote:
> It could actually implement all of them - the two parents, and the child.  
> That sounds like a pretty good, explicit way that requires no introduction of 
> any new syntax, concepts or engine complexity in order to do what you're 
> describing.  This works fine:
> 
> interface foo { function foo(); }
> interface bar { function bar(); }
> interface baz extends foo,bar {}
> 
> class impl implements foo, bar, baz {
>   function foo(){}
>   function bar(){}
> }
> 
> function sth(baz $b){}
> 

`class impl implements baz {}` is actually already enough here because
`baz` extends `foo` and `bar`. This is the only way to solve such
situations right now but it does not help with primitive types. :(

> One thing we could consider is adding some intelligence for these cases, and 
> for interfaces that only extend other interfaces (without adding new 
> signatures) - a class would be considered to implement that interface if it 
> implements all of the 'parent' interfaces that the child interface extends: 
> 
> class impl implements foo, bar {
>   function foo(){}
>   function bar(){}
> }
> 
> function sth(baz $b){}   <-- would work, as impl implements both foo and bar, 
> and baz does nothing but extending those.
> 
> I'm not sure that's necessary, and believe the current mechanisms and syntax 
> satisfy these use cases already, but it's probably a possibility.
> 

That sounds like runtime checked duck typing. This actually makes the
type system less strict and might have horrific side effects and that is
exactly the opposite of what union/intersection types are meant for:
preventing this. Above code is the same as:

function sth($b) {
$b->foo();
$b->bar();
}

It will definitely fail if something else is passed in but if it is
`foo`, `bar`, or `baz` everything is fine. The problem is that any
object that satisfies the implementation of the methods `foo` and `bar`
would ultimately fulfill the contract here.

function sth(foo&bar $b) {}

This is a different situation because now we know that it is something
that actually implements exactly those two interfaces. Including
possible additional constraints like argument and return type hints.
There might even be a documentation shipped together with them that the
implementer should take care of honoring. The intersection type hint is
much stricter in such cases.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Return Type Declaration

2016-04-19 Thread Fleshgrinder
On 4/19/2016 12:02 AM, Lester Caine wrote:
> On 18/04/16 20:08, Fleshgrinder wrote:
>> This is however a useful shortcut and shortcuts are good things in
>> terms of usability if done write. Think of  +  vs. right click
>>>> copy (or any other example of useful keyboard shortcuts).
> 
> Except when some sod adds a  or decides left click is quicker ...
> all of which are in use on one or other Linux desktop tool :(
> 
> A CONSISTENT way of doing things would save a lot of time, so adding
> even deeper levels of functionality is just overkill ...
> 

Everything that is good can backfire if overused. We need to ensure that
we do not do that and the fact that we are discussing it right here
shows that we are not taking the decision lightly. :)

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Return Type Declaration

2016-04-18 Thread Fleshgrinder
On 4/18/2016 7:22 AM, Marcio Almada wrote:
> 2016-04-17 23:56 GMT-04:00 Larry Garfield :
>> Rather than debate the relative merits of Null as a concept, since I think
>> all agree removing Null from the language is not even a thing, what do you
>> think of my recommendation to NOT have the ? shorthand for "or null" on
>> types, but keep the |null for union types?  That is, if you want to return
>> Foo or null, you have to use the long-hand version:
>>
>> function foo($a) : Foo|null
>>
>> That
>>
>> 1) Allows for explicit or-null behavior.
>> 2) Doesn't make it quite so easy, which hopefully discourages (but does
>> not prohibit) its usage.
>> 3) Neatly avoids the ?Foo / Foo? question entirely.
>>
>> I think that's a win-win arrangement.
>>
> I can agree with that.
> 
> Language design wise, if you have no way to forecast how language features
> independently proposed are going to interact then it's a good idea to have
> a converging strategy. Fortunately, this seems to be happening almost
> spontaneously towards union types representation, as in the "multiple
> catch" RFC (https://wiki.php.net/rfc/multiple-catch) now in voting phase.
> 
> Even if we decide not to commit to a full union types implementation now,
> the design process will be much easier in the future if we decide to use
> Foo|null instead of Foo? or ?Foo and we will not end up with 2 or 3 ways
> alternative to declare the same thing.
> 

I actually do not see a problem with the shorthand notation. I am
usually an extreme opponent of duplicated or aliased functionality
because it increases the cognitive load to keep all this crap in your
mind. This is however a useful shortcut and shortcuts are good things in
terms of usability if done write. Think of  +  vs. right click
> copy (or any other example of useful keyboard shortcuts). The usage of
*null* as an union type is the most common case compared to all the
others that are truly rare in comparison.

There are other shortcuts in PHP that are perfect:

- Iterator vs. Generator: they can achieve the exact same thing but
  slightly different and a generator can almost always be used to
  replace an iterator with less code, even if the special effects of
  it are irrelevant.
- `$x = $x + $y` vs. `$x += $y`: we have many of those and that is just
  fine as it is.
- `$x = $x + 1` vs. `++$x` vs. `$x++`: ditto
- `

signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Return Type Declaration

2016-04-18 Thread Fleshgrinder
On 4/18/2016 8:24 PM, Stanislav Malyshev wrote:
>> to have them calls them a "billion dollar mistake", many languages
>> actively avoid having NULL in favor of something deliberately more
>> structured.  NULLs are a very common cause of avoidable fatal errors in
>> many languages (including PHP). NULLs are rude to users of your API, as
>> it balloons the error handling code they need to deal with.
> 
> I think this description is misleading in a way. Nulls are immediate
> causes of many errors, technically, in a meaning that "if I find null
> where I expected to have DB connection, I get an error" - but this is
> only a technical cause. The *real* cause is the failure to check whether
> your attempt to connect to the database succeeded, or that you have
> proper DB configuration, or such, and null is just a symptom of that
> error - and that error is not automagically fixed by having some other
> object instead of null. You have to actually design and write code for
> it, there's no replacement for it.
> 
> So declaring null "cause of all evils" is ignoring the real causes and
> blaming immediate technical cause instead, and it would not be helpful.
> It is true that for some languages with more complex type systems it is
> possible to largely get rid of nulls by using those complex types and
> ensure type system controls for all checks at least to be present (note
> that doesn't guarantee proper function either, since no type system can
> ensure you handle the case of missing DB connection properly, it just
> can ensure you have a branch for it). But that requires much more
> complex and involved type system that PHP has - or, in my opinion,
> should have.
> 

I agree with Stanislav here. *NULL* is not evil per se and just because
some functional languages get some attention right now does not mean
that they solved the biggest mistake in CS history. On the contrary,
they just invented another way of handling it by introducing new types
that require more book keeping and by refusing to compile if they
encounter a place where proper handling is missing.

As I wrote earlier, we could introduce such a feature into the language.
However, static code analyzers can already provide this functionality.
People just need to use them.

TL;DR *NULL* is just fine if used correctly and we cannot make sure that
people use it correctly.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] RFC: Functional Interfaces

2016-04-18 Thread Fleshgrinder
+1 for the feature, very nice syntactic sugar to solve some edge cases.

I agree with Rowan, i also do not like the name and propose to call them
*closure interfaces*. There are already various synonyms for closures:

- anonymous function
- lambda function
- callback*

However, the strongest argument to call them *closure* is the fact that
the the class in PHP itself is actually called *\Closure*. I would even
go as far as saying that the documentation should be updated to always
use that word everywhere.* The fact that only closures can implement
such interfaces strengthens the reason to call them as proposed in my
opinion. Just because Java calls them /functional/ does not mean that we
should.

Regarding error messages:

Fatal error: cannot implement non functional interface IFoo in
/in/65W6i on line 7

Fatal error: cannot implement nonclosure interface IFoo in
/in/65W6i on line 7

Note on grammar:
http://www.chicagomanualofstyle.org/qanda/data/faq/topics/HyphensEnDashesEmDashes/faq0079.html

*) There is of course the situation of the various other ways to declare
the so called *user functions* (/call_user_func()/ and
/call_user_func_array()/) and those should always be referred to as
*callback*; imho.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-17 Thread Fleshgrinder
On 4/17/2016 5:58 PM, Lester Caine wrote:
> And this is where the likes of Hack should be exactly where you are
> working ... The vast majority of grass roots users don't need another
> layer of complexity loaded on top of what IS a perfectly functional
> platform. Adding types, complicating procedure calls and lumbering
> everything with 'optional' layers of complexity is not something that a
> small jobbing shop user has time to investigate the implications on his
> client base. I'm still working through code that other have written and
> trying to in many cases unravel exotic code that no longer fits the
> modern programming style. I no longer take on any new clients as there
> is enough work keeping my existing client base working, but there are a
> LOT of people still using PHP5.2/3 who now need help if they are ever to
> be brought forward.
> 
> Now if you were proposing something that actually validated the data
> fully rather than some very restricted 'type' elements then it might be
> worth the effort, but 'int' is only a very small part of validating a
> number and we still need the rest of the validation library after you
> install a replacement for that bit mf it ...
> 

Union and intersection types already get us closer to stricter data
types that are flexible too. Of course they are not the best solution. I
already mentioned in another mail that operator overloading is the only
way to get us there. It is the only thing that allows us to create truly
meaningful types.

However, the problem of primitives remains, as was illustrated in this
and related threads multiple types, e.g. `array|Traversable`.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-17 Thread Fleshgrinder
On 4/17/2016 2:57 PM, Lester Caine wrote:
> On 17/04/16 13:35, Fleshgrinder wrote:
>> If you are only afraid that usage of your libraries declines because
>> users demand these new features to be part of it and you do not want to
>> implement them. Sorry, but that would be a clear sign that the features
>> are good and should be used.
> 
> I have two major libraries I have used since day one of PHP5 ... ADOdb
> and Smarty ... both of these have provided the core of my framework, but
> have needed a lot of work simply keeping my code in sync with them, and
> the latest 'improvements' to both are not BC for reasons that are blamed
> on needing to 'modernise' the code. Now I DID keep my own copies of both
> for many years to keep the PHp5.2 code working, and perhaps I should
> simply close the door on PHP7 and stay with what is currently working.
> But PHP7 ... ignoring any of the new features ... does provide
> improvements in some areas if you REMOVE the legacy stuff which prevents
> the optimisations from giving their best. The 'improvements' to ADOdb
> and Smarty are claimed to help this process but unfortunately the people
> pushing those changes are 'new school' and expect all the new stuff as
> well. So exactly where is PHP heading? Do we keep with the original
> simple flexible language that even today still works fine, or do we
> accept that everything that is being demanded should also be included
> and just roll over.
> 
> I do not accept the statement that 'You do not have to use it'! That may
> have been true in the past, but today one has to live with the fact that
> legacy code and modern hosting simply do not co-exist. One HAS to take
> care that the key third party bits still work, and it's libraries like
> the mapping extensions which relied on many key elements that HAVE now
> been removed from PHP.
> 

The situation you describe is a pain that I know myself and I agree.
There are too many libraries that try to solve things in the most
possible generic way and abuse OO to ridiculous excesses instead of just
solving a single, simple problem with a few functions (as our old but
gold Unix philosophy has taught us). The simple rule "If it ain't broke
don't fix it" is also violated too much.

The reasons for this are manifold and hard to grasp from time to time. I
guess most often the problem boils down to "my library is not cool if it
does not use the latest language features". Ignoring completely if those
language features are actually appropriate for the problem. E.g.
excessive usage of exceptions without a single assertion spread all over
a code base to validate developer input.

However, you should seek the discussion with the maintainers of these
libraries and have a serious talk about BC, stability, and appropriate
usage of language constructs to solve problems. Instead of trying to
block advancement and evolution within the language itself.

Most features that are currently discussed are aiming at enterprise
applications that require more built-in functionality to ensure
correctness, reduce the amount of tests (unit as well as runtime) to
detect bugs, and where many developers work together at the same code
base. Most features can increase agility and productiveness of such
teams and allow them to implement new features and A/B tests faster. Of
course many features require more knowledge about programming. This can
also be bad for such teams because big teams almost always suffer from a
huge knowledge gap. Despite that, it helps the more advance developers
to create richer APIs that are harder to abuse and in turn allow the
overall design to achieve previously mentioned goals.

This is the sole reason why new language like Rust and Ceylon were
invented in the last years. Of course there are also projects that aim
at the novice user, e.g. Golang[1]. PHP currently achieves both in the
context of web projects and support for enterprise was grew and grew and
big companies like Facebook or my employee trivago who decided to go for
PHP do not want to invest a shitload of money into rewriting everything
from scratch in another language[2] like Twitter did (and exchange all
their developers who were already extremely hard to find in the first
place with new ones) just to get enterprise features. No, they want to
see advances in PHP to support exactly those features.

Facebook did not see those advancements and sent out their OCaml/C++
team to create something that has exactly those enterprise features
while we at trivago plan to upgrade to PHP 7, while I am writing these
lines, to get more performance out of the language and strict type checks.

There are always pros and cons and it is hard to satisfy everyone but
the type system of PHP is definitely one of its main weak spots and it
must be improved to 

Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-17 Thread Fleshgrinder
On 4/17/2016 2:19 PM, Lester Caine wrote:
> On 17/04/16 11:29, Fleshgrinder wrote:
>> Especially since its not needed at all. HHVM already solved most of
>> these issues extremely nicely:
>>
>> - https://docs.hhvm.com/hack/types/type-system
>> - https://docs.hhvm.com/hack/type-aliases/introduction
>> - https://docs.hhvm.com/hack/shapes/introduction
>>
>> We want the same but do not want to copy?!?
> 
> The simple answer NO
> 
> If that is how you think it should be done, then use it. On my platform,
> 'point' is a number of floating point numbers depending on your
> geometry. And shapes use those points. So that area of 'hack' is of
> little use to any mapping system, and trying to shoehorn existing code
> to fit is 'pointless' ...
> 
> It's the fact that many of these problems HAVE been solved without
> resorting to overloading PHP with a subset that does not provide a
> complete solution to the alleged problems that is the reall problem
> here. Having to re-write libraries because some one else thinks the
> basic rules are wrong and need fixing :(
> 

Why do you need to rewrite anything?
Why do you need to use it?

Especially, why do you thing that PHP was made solely for auto-mappers
from some SQL to PHP?

$array_point = array('x' => 0.0, 'y' => 0.0); // valid

type Point = shape('x' => float, 'y' => float);
$point = shape('x' => 0.0, 'y' => 0.0); // valid

function distance(array|Point $p1, array|Point $p2) {
// works
}

function distance(Point $p1, Point $p2) {
// works better
}

var_dump($point);

// array(2) {
//   ["x"]=>
//   float(0.0)
//   ["y"]=>
//   float(0.0)
// }

Both works and both is valid. Only the latter case ensures that it is as
defined and the former allows arbitrary changes. If you need arbitrary
changes go for it. It does not matter why you want to use the former
(anemic domain, legacy support, no time to adopt, no muse to adopt,
"everything was better in the old days", ...) as long as it solves your
use case and satisfies your users. All changes that were proposed are
*without any BC!*

If you are only afraid that usage of your libraries declines because
users demand these new features to be part of it and you do not want to
implement them. Sorry, but that would be a clear sign that the features
are good and should be used.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-17 Thread Fleshgrinder
On 4/17/2016 12:22 PM, Lin Yo-An wrote:
> On Sun, Apr 17, 2016 at 6:06 AM, Bastian Schneider <
> bastian.schnei...@commerce-plus.com> wrote:
> 
>> Just a quick thought.
>>
>>
>> union Iterable {
>> use array;
>> use ArrayAccess;
>> use Traversable;
>> }
>>
> 
> I think this example creates another meaning on the "use" syntax, which
> make "use" context depended.
> 
> The "use" statement is already used to "create an class name alias in the
> current namespace." and this makes "use" confusing.
> 

Especially since its not needed at all. HHVM already solved most of
these issues extremely nicely:

- https://docs.hhvm.com/hack/types/type-system
- https://docs.hhvm.com/hack/type-aliases/introduction
- https://docs.hhvm.com/hack/shapes/introduction

We want the same but do not want to copy?!?

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] Re: Improving PHP's type system

2016-04-17 Thread Fleshgrinder
On 4/17/2016 11:19 AM, Tony Marston wrote:
> Where is the insult in what I wrote?
> 

You are not only insulting people in this thread, you do it in every
thread you contribute to. You were exhorted multiple times for doing so.
Pretending otherwise does not change these facts so *please* get a grip.

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] [RFC] Nullable Return Type Declaration

2016-04-17 Thread Fleshgrinder
On 4/15/2016 5:50 PM, Larry Garfield wrote:
> That there are a few small cases where PHP's current design makes NULL a
> reasonable sentinel value (custom iterators, fread() as you mention,
> etc.) does not mean that in most cases, returning ValueObject|Null is
> rude and abusive to users of your API.  Yes, end-of-file is not an
> exceptional case so should not throw an exception.  I completely agree
> there.  But "user not found" I'd argue is.  (Or rather, if it's not an
> exceptional case your data model is kinda broken to begin with, because
> why are you asking for a missing user?)  Or you're better off having an
> "empty" value instead, such as an anonymous user object.  That's still
> type safe.
> 

I disagree here. Your user example with the anonymous user object works
if I am asking for e.g. the creation of a session but it is a very
different situation if I would be asking for a user profile. The fact
that a user might have deleted her account is not an exceptional case,
is is to be expected and should be handled accordingly. How is up to the
caller. Otherwise any `array_key_exists($k, $a)` should result in an
exception or some default value according to your logic here.

I completely agree that `NULL` is not the best type and others languages
have other means to solve the issue but absolutely every language has
some way to indicate the absence of a meaningful value. PHP has `NULL`
like many others and that is fine. The problem is not that we have
`NULL` the problem is that it is just too often not checked if it can be
`NULL`.

Rust and many functional language solve this with an Option or Maybe
that requires creation, allocation, and userland checks for every return
and the compilers fail if you do not unpack it.

Ceylon solves this with union types as we are discussing it right now,
however, the difference to other languages is that the compiler will
fail if you are not checking the return value and bugs are avoided in
this way. This is something that we could adopt.

http://ceylon-lang.org/documentation/faq/language-design/#optional_types

The absence of something must be modellable.

class ConstraintViolation {

private ?Throwable $cause;

private string $message;

public function __construct(
string $message,
?Throwable $cause = null
) {
$this->message = $message;
$this->cause = $cause;
}

public function getCause(): ?Throwable {
return $this->cause;
}

public function hasCause(): bool {
return isset($this->cause);
}

// ...

}

An example of a class I was just working on. How could, would, or should
one model this without `NULL`? Throwing an exception? It is not
exceptional for such an object and expected that there is no cause
available. It is up to the caller how she wants to take care of this.

/** @var ConstraintViolation $violation */
if ($violation->hasCause()) {
// Handle cause ...
}

$cause = $violation->getCause();
if (isset($cause)) {
// Handle cause ...
}

// Or maybe we just want it stringified?
// Works nicely with `NULL`. :)
echo $violation->getCause();

Throwing exceptions everywhere for non exceptional cases is a code smell
too and I see that ever to often in current open source code. Especially
throwing extremely low-level exception everywhere for real errors from
which one should not recover (e.g. `InvalidArgumentException`) because
they indicate developer mistakes and only add a lot of checks in
production for no reason. That being said, the above could be rewritten to.

class ConstraintViolation {

public function getCause(): Throwable {}

public function hasCause(): bool {}

}

This would mean that PHP emits an Error if someone calls `getCause` and
there is no cause and there would be only one way to check: `hasCause`.
This is a valid design decision since it minimizes the amount of
possibilities to work with the class and avoids `NULL` altogether.
However, the caller code did not really become less verbose; as was
already illustrated in the above examples. Plus, the ability to directly
use the `__toString`ability paired with `NULL` in a string is gone.

Everything always has pros and cons and I do not think that there is one
answer to all of these questions. Different languages handle this
problem differently. PHP has `NULL` and we should keep it this way. To
minimize bugs resulting from unchecked `NULL` usage a compiler feature
could be implemented that warns a developer in such cases. We already
have it for uncatched exceptions (although IDEs are currently not
telling one about that; Eclipse does in Java though).

-- 
Richard "Fleshgrinder" Fussenegger



signature.asc
Description: OpenPGP digital signature


<    1   2   3   4   5   >