Re: [PHP-DEV] [RFC] [VOTE] Deprecate PHP's short open tags, again

2019-08-20 Thread Rowan Tommins

On 20/08/2019 17:56, Peter Kokot wrote:

Probably. But fact is that PHP opening short tags can be used. We can
enable them in controlled environments and use the short tags knowing
they will never be removed now. No deprecation warning is standing in
our way to do that now. And such code (or better put app) is honestly
now also not so bad. Because it will still work in at least let's say,
PHP 9 at least or considering the feedback and discussions for ever...
Also users who are already using short tags can now postpone the
upgrades for another ~5+ years at least :)



I don't think anything has changed in that regard. If there's text in 
the manual that short open tags are deprecated then it was wrong before 
this pair of RFCs; if there's text in the manual stating other reasons 
not to use them (portability, possibility of mixing in XML, etc) then it 
is still just as valid as it ever was.


If your impression was that the feature was already deprecated before 
the v1 RFC, and has somehow become *less* deprecated as a result of this 
vote, that may be explain some of the disconnect over the issue. As far 
as I'm aware, it had no such status, it was simply a feature that used 
to be more commonly used than it is today.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] [VOTE] Deprecate PHP's short open tags, again

2019-08-20 Thread Rowan Tommins

On 20/08/2019 22:18, Peter Kokot wrote:

The approach was: add the deprecation notice in PHP 8, and remove short open 
tags in PHP 9 or PHP 10 (purposely left vague to get more support for the idea 
- as getting the deprecation underway is the most important move).


I guess we should really highlight also
such option and discuss this more rationally back then. Now, we have
postponed this until who knows when and also without any clear
guideline for what will happen with short tags if they will be ever
removed or not...



I honestly don't think it would make any difference to most people who 
voted against. The counter-arguments people have presented, again and 
again, are not about the pace of removal, but about whether removal is 
needed at all. If anyone wants to revive this proposal in future, it is 
that counter-argument that they would need to understand and address.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] [VOTE] Deprecate PHP's short open tags, again

2019-08-20 Thread Rowan Tommins

On 20/08/2019 17:18, Peter Kokot wrote:

About the docs - there are
very minor changes needed where "backwards compatibility" is mentioned
maybe. Because they are not in PHP for keeping BC anymore now. Nobody
proposed a better solution than this RFC, then they are a feature.



Being "for Backwards Compatibility" and being "there forever" are not 
mutually exclusive. There are a huge number of things in this world 
which exist only to be compatible with an older technology or use case, 
but which will never be phased out, because the effort to change them 
exceeds the benefit.


On the other hand, I think it might be useful to have a status of 
"officially discouraged" distinct from "deprecated". I occasionally hear 
people ask to "deprecate" something without any particular timeline or 
criteria for when it would be removed; my suspicion is that what they 
really want is a clearer message to users that they shouldn't use the 
feature.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] [VOTE] Deprecate PHP's short open tags, again

2019-08-20 Thread Rowan Tommins

On 20/08/2019 13:51, G. P. B. wrote:

   - I seriously don't appreciate that the RFC has been edited*WITHOUT*  my
knowledge to add endorsement names on the counterargument to the RFC on the
RFC itself  when the appropriate place would have been the counter argument
document.



While I appreciate that there is a certain implication of "ownership" 
when you are the author of an RFC, it is ultimately a resource for the 
community as a whole to understand the discussion, which is why the 
guide at https://wiki.php.net/rfc/howto explicitly mentions including 
both positive and negative feedback.


The only problem I can see with other people editing "your" RFC is if 
later readers could mistake the edits for your own opinion; even if the 
whole counter-argument had been a section rather than a separate page, 
it would be clear that readers shouldn't do that. In this case, the only 
edits are to add a list of names, which is basically what the voting 
widget does anyway, so I really can't see any reason to be upset about it.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-08-28 Thread Rowan Tommins
On Wed, 28 Aug 2019 at 12:57, Nikita Popov  wrote:

> However, I feel pretty strongly that converting any of these to
> deprecations is not a good idea. While there's certainly different views on
> this, I've seen it often enough deprecation warning are considered an even
> lower error level than notices (imagine my surprise when PEAR stopped
> working completely in PHP 8 because nobody ever saw the hundreds of
> suppressed deprecations). We could throw a deprecation in addition, but I
> think this will make the development experience really suck for anyone who
> is not actively working on a migration right now (imagine seeing lots of
> warnings/notices during development twice).
>


Again, I considered this carefully for undefined constants and discussed it
extensively on the RFC and resulting thread. In short, "deprecation notice"
doesn't have to mean "E_DEPRECATED". Arguably, "severity" and "type" should
be two different dimensions, and E_DEPRECATION_WARNING would be
E_DEPRECATION & E_WARNING; but in practice, a Warning containing the text
"this is deprecated" achieves the goal just fine.

Whatever the mechanism, the point is to make people aware as far in advance
as possible, so that they can start addressing the problem before it
becomes a blocker to upgrading. As briefly mentioned, third-party libraries
are a key case here: if a library raises extra Warnings, I can take the
time to submit a patch to that library, wait for the maintainer to accept
it, and make sure I can use the latest version; if the library raises extra
Errors, I have to delay my upgrade, or run a patched version of the
library, until it's fixed.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-08-28 Thread Rowan Tommins
On Wed, 28 Aug 2019 at 10:33, Nikita Popov  wrote:

> I think it's time to take a look at our existing warnings & notices in the
> engine, and think about whether their current classification is still
> appropriate. Error conditions like "undefined variable" only generating a
> notice is really quite mind-boggling.
>


While I agree with the reasoning behind this, I think we should be very,
very careful of promoting anything beyond Warning. While it's certainly
true that bugs may be hiding behind Notices and Warnings, it's equally
certain that there is code that is poorly written but has entirely correct
behaviour; for such code, the cure will be worse than the disease, because
an unhandled Error is like suddenly pulling the plug out of the server in
the middle of a transaction.

That's why I was very careful with my undefined constant RFC [1] to first
raise the Notice to a Warning, and leave an appropriate period before
raising to Error. I would be 100% behind raising undefined variable from
Notice to Warning, but think the impact of raising to Error is high enough
that it would risk delaying take-up of PHP 8. Is it too late to raise to
Warning in 7.4, with a clear message that it will be an error in 8.0? That
would give time for people to discover it in rare code paths, get changes
pushed to third-party libraries, etc, before it becomes an unavoidable
error.

[1] https://wiki.php.net/rfc/deprecate-bareword-strings
-- 
Rowan Collins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-05 Thread Rowan Tommins
On Thu, 5 Sep 2019 at 14:29, Brent  wrote:

> I believe GitHub is the way to go. Several large communities manage their
> OSS on it and have proven it works, PHP should simply do the same.
>


I think this is just as simplistic as saying "never". What are these
communities using it for, and what would we want to use it for? Are our
requirements the same as theirs, and is GitHub the best solution for those
requirements?

For instance:

- Rust does not use GitHub as its primary co-ordination mechanism, it has
an online forum at https://internals.rust-lang.org/
- The ECMA TC39 committee has a specific membership structure and holds
regular in-person meetings
- There are undoubtedly more open-source communities _not_ using GitHub
than who _are_ using it

To be clear, I'm not saying these are reasons against GitHub in themselves,
but it's a rather huge leap from "here are four repos I found" to "GitHub
is the way to go"; we should be making specific arguments for why it will
meet our needs, and evaluating it among all the alternatives.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-05 Thread Rowan Tommins
On Thu, 5 Sep 2019 at 13:05, Mark Randall  wrote:

> Something I am finding hard on Github, and maybe it's just because I
> haven't found the option yet, is finding new posts.
>


Yes, so far, I've been forced to choose between two imperfect options:

- follow the discussion using the e-mail notifications only, giving worse
context for the sub-threads than I'd get on a mailing list
- scanning all the sub-threads on the PR to see if there are new replies I
haven't read yet

The ability to attach sub-threads to lines in the PR is certainly useful
for some types of discussion, but a lot of the longer threads would be
better off with just a subject line.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-06 Thread Rowan Tommins
On Fri, 6 Sep 2019 at 14:14, Benjamin Morel 
wrote:

> As a code collaboration platform, GitHub is pretty good, but it's not built
>> as a discussion forum, and there are plenty of limitations to using it as
>> one.
>
>
> Could we work on agreeing on a set of requirements for such a discussion
> "forum" to replace mailing lists?
>


That could be an interesting exercise, yes. Ideally, we should consider RFC
drafting, voting, and bug tracking as well - not because we have to replace
all of them with one platform, but because we might want to divide things
up differently from how we do at the moment.




> Using GitHub Issues as a starting point, what would you change?
>


That's pretty much the opposite of your previous question. For one thing,
it's unanswerable without knowing the scope - e.g. would it just be for
RFCs, or all discussions?

Besides that, if we're going to introduce an anchor that we compare
everything to, surely we should say "using the setup we have as a starting
point, what would you change?"

Until we know what we're looking for, I'm really not clear why GitHub
issues should have any starting advantage over Discourse, or PHPBB, or
Trac, or Phabricator, or Bugzilla, or probably hundreds of suggestions we
could evaluate.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-06 Thread Rowan Tommins
On Fri, 6 Sep 2019 at 12:31, Peter Kokot  wrote:

>
> Plastic analogy - adding "127.0.0.1 github.com" to your /etc/hosts
> file shows that developer cannot bring most of the today's (PHP)
> projects to any working state without using it. That's what is meant
> by inevitable because everything open source today is either on GitHub
> and some minor ones scattered around custom Git repos and other Git
> hosting providers.
>


Ah, I see. Yes, having some usage of GitHub is currently pretty much
inevitable in that sense. Of course, that may change eventually, just as
SourceForge fell out of favour, but that's not something we need to worry
about.

However, projects over a certain size generally *don't* use it as their
main or only discussion platform, which is what we're talking about here.



> PHP is already using GitHub. Is it moving to
> something else? No, so let's not complicate things more with other
> hosting providers now.
>


The question is not "should PHP ban the use of GitHub for any kind of
activity?" it's "should PHP abandon the discussion processes it's been
using for most of its history and use GitHub as a discussion forum?".

As a code collaboration platform, GitHub is pretty good, but it's not built
as a discussion forum, and there are plenty of limitations to using it as
one.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-12 Thread Rowan Tommins
On Thu, 12 Sep 2019 at 12:32, Arvids Godjuks 
wrote:

> Every single workplace I worked in past 5 years always had 0 tolerance
> policy for all notices, warnings and E_STRICT.
>


Well, that's fine then, you don't need this change. It will make zero
difference to you whether something is classified as Notice or Warning.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-13 Thread Rowan Tommins

On 13/09/2019 10:02, Robert Korulczyk wrote:

Why? If "assume $key2 exists as a key and is an integer" is so bad that PHP should halt 
my program, why should "assume $key1 exists and is an array"
be perfectly OK?

Warning is triggered by reading non-existing key, not assigning value to it. In 
`$foo[$key1][$key2] ??= 0` you never try to read non-existing key.



$foo[$key1] has to be read to determine if it's already an array, and if it has 
the key $key2, in the same way that in $foo[$key1]++, $foo[$key1] has to be 
read to determine if it's already an integer and what it's value is.

If we're talking about being strict, we shouldn't limit ourselves to what 
happens to give a warning today, we should be consistent in our reasoning. So 
if the reasoning is that accessing uninitialised array keys is dangerous, I 
should not be able to mention $foo[$key1][$key2] if $foo[$key1] doesn't yet 
exist.

Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-12 Thread Rowan Tommins
On Thu, 12 Sep 2019 at 11:32, Benjamin Morel 
wrote:

> I don't think there are that many such *potentially *legitimate use cases,
> so maybe we could just list the use cases and think about a more elegant
> solution to solve them?
>


Yes, please. If we can focus less on vague anecdotes and opinions *on both
sides*, we can look at *making the language more pleasant to use*.


For instance, for undefined array keys, what if we had an operator for
"initialise and retrieve", such as $foo[? 'bar']. Then we could simplify
ugly code like this:

if ( ! isset($foo[$key1]) {
   $foo[$key1] = [];
}
if ( ! isset($foo[$key1][$key2]) {
   $foo[$key1][$key2] = 0;
}
$foo[$key1][$key2]++;


With something safe but succinct like this:

$foo[? $key1][? $key2]++;

Unlike the error suppression @ operator, this is not saying "I know I'm
doing something wrong, do it anyway"; it's saying "I want to do this
specific thing, I just want to do it in fewer lines of code".

The more helpers like this we have, the more I'd be amenable to
*eventually* raising things to Error - although I still think that should
be done over a longer period of time than a single release cycle.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-12 Thread Rowan Tommins
On Thu, 12 Sep 2019 at 14:55, Claude Pache  wrote:

> Le 12 sept. 2019 à 15:33, Marco Pivetta  a écrit :
>
> $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1;
>
> Marco Pivetta
>
>
> That violates blatantly DRY (twice the exact same lengthy expression
> `$foo[$key1][$key2]`), so it is not a satisfactory solution.
>


Agreed; it's certainly neater than all the isset() checks, but it's
definitely a bit ugly.

To clarify my point, the reason why people write this:

$foo[$key1][$key2]++;

Is not because they're lazy, it's because *it expresses their intent*.

The ?key syntax was one suggestion for how to express the intent safely in
that particular scenario. Another way might be that the array is
initialised a different way; completely off the top of my head, something
like this:

$foo = new Dictionary>;

That could express the intent of "this variable is going to be used as an
accumulator with these dimensions".

The "if isset" lines, in my opinion, don't express any intent, and they
don't protect against any real errors; they're just noise to work around a
short-coming in the language.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-12 Thread Rowan Tommins
On Thu, 12 Sep 2019 at 15:02, Arvids Godjuks 
wrote:

>
> This message contains a healthy dose of sarcasm.
>


I think we need less sarcasm on this thread, and more empathy. I'm doing my
best to discuss a real scenario, and how to improve the language for it,
and move away from oh-so-hilarious parodies of each other's positions.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-12 Thread Rowan Tommins

On 12/09/2019 15:43, Robert Korulczyk wrote:

One additional line will make your code much more obvious and easier to read 
and understand:

$i ??= 0;
$i++;



I don't find this code at all obvious:

foreach ( $something as $foo ) {
    $i ??= 0;
    $i++;
}

I mean, huh? What's that zero doing there, is it resetting the variable 
every loop?


Now, in that simple case, you can and probably should initialise the 
counter before the loop:


$i=0;
foreach ( $something as $foo ) {
    $i++;
}


But that's not the example I gave earlier! The example I gave earlier 
was a multi-dimensional array:


$foo = [];
foreach ( $something as $key1 ) {
    foreach ( $somethingElse as $key2 ) {
  $foo[$key1][$key2]++;
    }
}

Even using ??= the initialise-everything-before-use version looks like this:

$foo = [];
foreach ( $something as $key1 ) {
    foreach ( $somethingElse as $key2 ) {
  $foo[$key1] ??= [];
  $foo[$key1][$key2] ??= 0;
  $foo[$key1][$key2]++;
    }
}


Again, the values are confusing: the end result will never contain an 
empty array at the first level, and will never contain a 0 at the second 
level.


Those two lines aren't aiding the readability of that algorithm in any 
way; I have to read past them to find the actual business of the loop, 
which is counting something, using the ++ operator.


What's more, they're not preventing any bugs either! If I accidentally 
reuse $foo from a previous loop, the extra lines won't reinitialise 
anything for me; if I initialise it to empty, the two loops are 
functionally identical.



So that's where I came up with two suggestions to actually add to the 
language, rather than just taking away:


- a more granular way to express that this code is not actually 
error-prone, combining the 3 lines back into one
- or, a way to express the intent of the code more clearly, such as 
declaring the shape of an array



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-12 Thread Rowan Tommins

On 12/09/2019 15:13, Nikita Popov wrote:
FTR this is basically what Python does via defaultdict: 
https://docs.python.org/3/library/collections.html#collections.defaultdict



Thanks, I'm glad I wasn't completely daft thinking there might be some 
way to express it. :)



I think it is the "cleanest" solution to this problem overall. Though 
it does need a separate structure, rather than our favorite PHP array.



Indeed it does, and I think that's the better route to making PHP a 
stricter language: before we take away the existing features, add the 
new ones that let you express things better.


PHP's array type, and its type system in general, allow a lot of very 
expressive algorithms which are hard to do with more rigid type systems. 
Modern languages like C# bring back that expressiveness using things 
like generics, a rich library of built-in collections and interfaces, 
and so on; they don't just say "sorry, you can't do that".


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Object Initializer

2019-09-13 Thread Rowan Tommins
Hi Rasmus,

On Fri, 13 Sep 2019 at 11:18, Rasmus Schultz  wrote:

> All in all, I find this feature is useful or applicable only to a few,
> select patterns within the language - it isn't general enough.
>


I've trimmed the quote for readability, but agree with basically everything
in this message. :)

I like the reasoning behind this RFC, but think it is unnecessarily
limited. It's not about "public properties are bad", it's just that if we
can come up with a feature that works for public properties *and* other
programming styles, we should prefer that.

A related proposal that's come up before is short-hand constructors:

class Foo {
private int $foo;
public function __construct($this->foo) {
// automatically assigns first parameter to $this->foo so body is
simplified
}
}

Combine that with opt-in named parameters, and the Customer example from
the RFC might look something like this:

class Customer
{
  private $id;
  private $name;
  private DateTimeImmutable $createdAt;

  public function __construct(id => $this->id, name => $this->name,
createdDate => string $dateString = 'now')
  {
$this->createdAt = new DateTimeImmutable($dateString);
  }
}$customer = new Customer(
   id => 123,
   name => 'John Doe',
   createdDate => '2019-01-01 12:34'
);


It's slightly more verbose, but a lot more flexible.


As a side note, I have always thought stdClass was a bit of a kludge, and
now we have real anonymous classes I would love to see it gradually phased
out. I would much rather see syntax for capturing variables in an anonymous
class declaration than new ways to create stdClass objects.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-10 Thread Rowan Tommins
On Tue, 10 Sep 2019 at 08:37, Côme Chilliet  wrote:

> > >  PHP have no control over github, and cannot know how it will evolve.
> > >
> > >  (they can change the platform tomorrow and internal won’t be able to
> do anything about it).
> >
> > Those are hypothetically problems. But they do not appear to be
> > currently problems.
>
> The fact that PHP has no control over github is current, this is not
> hypothetical.
>


The idea that the platform will change overnight in a way that makes it
unusable by the project is hypothetical.




> It’s not the same when the project can act to fix it and when the project
> is powerless.
> If github blocks someone from commenting we cannot do anything about it.
>


Are you aware of any heavy-handed moderation on github, or is this, again,
a hypothetical problem?

As you will see from my other responses on this thread, I'm not totally
sold on github in particular, but I can see pros and cons more generally:

- our own systems, fully in our control, but used by nobody else, and
managed by a handful of volunteers
- or: a well-established third-party system, which could change in
unpredictable ways, but is widely used, and supported by hundreds of paid
staff

Even the mailing list relies on third-party software; I presume it gets
updated regularly, and those updates could include changes in functionality
we disagree with. There is a pragmatic decision to be made between building
absolutely everything from scratch, and trusting some third parties, with
contingency plans if that trust proves ill-founded.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-10 Thread Rowan Tommins
On Tue, 10 Sep 2019 at 10:39, Lynn  wrote:

>
> Are you aware of any heavy-handed moderation on github, or is this, again,
>> a hypothetical problem?
>>
>
> As much as I like Github for these kind of things, we're forgetting about
> a critical part here; The US trade restrictions. Github being a company in
> the US, is required to block certain access to users from certain countries.
>


That's a reasonable point; that (and the inverse: governments blocking
access to github in response to some perceived offence) would be a
potential issue to weigh up against the risks of running our own
infrastructure.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Object Initializer

2019-09-16 Thread Rowan Tommins
On Mon, 16 Sep 2019 at 08:29, Michał Brzuchalski <
michal.brzuchal...@gmail.com> wrote:

> Please keep in mind that initializing properties through object initializer
> applies to visible properties and is possible to assign
> protected or private properties from the class scope as well.
>


The problem with that is that you need an extra static method to make use
of it, and you still need to get the arguments into that method. It might
be useful occasionally, but it still doesn't help constructors which are
setting a large number of private / protected properties.



> I don't see the reasons why many of you consider public properties a bad
> solution. PHP language has support for public properties
> and with typed properties, it is possible to ensure valid object state
> using VO's which are valid all the time, consider Uuid userland
> implementation
> no one checks if that's valid UUID, cause it's ensured by VO.
>


Firstly, it's not necessarily a case of "considering public properties a
bad solution"; it's about evaluating where the new feature could be used,
and where it wouldn't help. If there was a feature which helped this use
case *and* other use cases, I think that would be "better", but that
doesn't make this feature "bad".

Secondly, typed properties certainly make public properties more appealing,
but there are still a bunch of things that you can't do with them, like
declaring them readonly, or having logic other than type validation in
getters and setters. Note that C#, which has object initializers, also has
these features, making them a lot more powerful.




> Any kind of features like promoting arguments from the constructor or named
> arguments are fine but not efficient in those cases.
> Any good practices suggest limiting function|method arguments while the
> case is where there is a significant amount of properties
> to be initialized and additionally which don't need any kind of validation
> due to VO, or simple scalars.
>



That's a good point; named parameters make function calls scale much better
to long lists of parameters, but *declaring* the constructor would still be
unwieldy. The only way to improve that would be for the class to
effectively opt into having an initializer using a special syntax for the
constructor. Larry gave this example syntax:

class Employee {
  protected int $age;
  protected string $name;
  protected ?Employee $boss;

  public function hoist __construct() {
if ($age < 18) throw new ChildLaborException();
  }
}

And Paul M Jones mentioned this version from Hack, where the parameters are
listed in the constructor, but don't need to be re-listed outside it:

class Employee {
 public function __construct(
protected int $age,
protected string $name,
protected ?Employee $boss
  ) {
if ($age < 18) throw new ChildLaborException();
  }
}


Either of those, with named parameters, would be almost indistinguishable
from object initializers at the call site. Depending on the syntax chosen,
it might be as similar as:

// Call initializer, requires public properties
new Employee { age => 42, name => 'John Smith' };
// Call constructor, requires special constructor definition
new Employee( age => 42, name => 'John Smith' );


That would require multiple new features, though, so initializers might be
more achievable in the short term, and perhaps there is room for both,
particularly if support for getters and setters improves.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Object Initializer

2019-09-16 Thread Rowan Tommins
On Mon, 16 Sep 2019 at 15:37, Michał Brzuchalski 
wrote:

>
>
>> The problem with that is that you need an extra static method to make use
>> of it, and you still need to get the arguments into that method. It might
>> be useful occasionally, but it still doesn't help constructors which are
>> setting a large number of private / protected properties.
>>
>>
> This RFC is not trying to help those constructors but tries to simplify
> instantiation objects and initializing properties
> there where any kind of constructor won't help, but rather would be
> unnecessary at all.
>


I realize that, I was responding to a specific point: you said that the
syntax would work for protected or private properties if used where those
are visible. I was saying that I don't think that combination would be used
very often, so it's easiest to just discuss the public property case.



> You wouldn't want to put 15+ arguments in your constructor to initialize
> public properties which
> don't need other validation than proper type, right?
>
> Even if it would be just adding "public" keyword in front of them.
>


Why not? You've got to list those 15 properties somewhere; if the syntax
was such that you only needed to list them once, it makes no difference
whether we call the result "class initializer" or "automatic constructor
with 15 named parameters", IMO.



>
>
>> Either of those, with named parameters, would be almost indistinguishable
>> from object initializers at the call site. Depending on the syntax chosen,
>> it might be as similar as:
>>
>> // Call initializer, requires public properties
>> new Employee { age => 42, name => 'John Smith' };
>> // Call constructor, requires special constructor definition
>> new Employee( age => 42, name => 'John Smith' );
>>
>>
> Last RFC treating about named arguments has similar syntax with curly
> braces, but all together with previous ones
> tries to solve the issue through additional syntax inside parentheses,
> which means both features can coexist together.
>
> Calling instantiation always used parentheses as the way to pass
> constructor arguments let's keep it that way.
> Using object-initializer would use curly braces - just like it's used to
> be solved in other languages.
>



My intention here was just to show that using named parameters would be
just as concise as using an object initializer; I just picked a pair of
syntaxes that were as similar as possible to illustrate that.




>
>
>>
>> That would require multiple new features, though, so initializers might be
>> more achievable in the short term, and perhaps there is room for both,
>> particularly if support for getters and setters improves.
>>
>>
> Here again, IIRC you're trying to solve the issue which is off-topic.
> Improving protected and private properties initialization through
> constructor is not the main target of current RFC.
>



I don't think it's off-topic to consider whether a related feature would
make this one redundant. However, you've picked a weird sentence to reply
to, because I'm agreeing with you, that the two features could exist side
by side without being redundant.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Object Initializer

2019-09-14 Thread Rowan Tommins
is { yearOfProduction = 1975, vin = "12345678"} 
really any different from an instance of an anonymous class with the properties 
yearOfProduction and vin?


Named parameters are (or would be) a way of setting a bunch of 
variables; they're not linked as an object of any sort, so I don't think 
there's a natural comparison to anonymous classes at all.




we could use something like func_get_args(ARGS_OBJECT) to allow us to capture 
the grouped parameters as an instance of an object of anonymous class 
containing properties for each named parameter


This again is an interesting proposal, but completely unrelated to 
object initializer syntax.



If I understand it right, the next example relies on the combination of 
anonymous class initialisers, named class initialisers, and named 
parameters all using the same syntax, with context determining whether 
someFunction({bar => 1, baz => 2}) means a) pass two integer parameters; 
b) create and pass a single anonymous class instance; or c) create and 
pass a single instance of some class. The examples look really neat on 
their own, but imagine coming on that syntax in someone else's code and 
trying to work out what it was doing.



There's definitely some interesting ideas here, but they're not all part 
of one feature, and they all rely on particular ways of structuring your 
code.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Features related to Object Initializers

2019-09-17 Thread Rowan Tommins
On Tue, 17 Sep 2019 at 01:10, Mike Schinkel  wrote:

> But as I said before, naming is hard — except for abstract examples where
> you can just name it "Something" :-) — and developers often don't know what
> object schema they will need until they have written much of the code. So
> the ability to have a syntax that supports stepwise refinement rather than
> starting with one and having to switch to the other makes a lot more sense
> to me.
>
> Allowing developers to start with doSomething(int $a, object $options =
> null) and then later refine the code to doSomething(int $a,
> SomethingOptions $options = null) creates less discontinuity for development
>


There is a tip that I picked up somewhere that if you're struggling to name
something (e.g. a function or a class), it may be because you've defined
its responsibilities poorly, and it needs splitting or merging.

I, too, work with a legacy codebase that makes heavy use of $params arrays,
and I frequently see things like `$params = array_merge($product,
$customer); $params['sendEmails'] = true;` and then a bunch of functions
whose docblocks say basically "@param array $params No idea what's in this,
we just pass it on somewhere else". There is no better name for the $params
array because it has no particular responsibility, it's just a bag of data.

So I'm unconvinced by the anonymous class -> named class refactoring path
(and even more so with some of your further proposals like populating named
parameters from an object), because I don't actually want to end up with a
SomethingOptions object with 50 unrelated properties. What I want to end up
with is a function signature like doSomething(Product $product, Customer
$customer, bool $sendEmails). The step in between might look like
doSomething(Product $product, array $params) or even doSomething(array
$product, array $customer, bool $sendEmails) rather than doSomething(object
$params).


> rather than giving them only one option for anonymous class initializer,
e.g. the array initializer syntax?

I'm not a fan of (object)$array, or of stdClass in general, but I think the
solution to that is to expand the existing "new class" syntax with a way to
capture lexical variables.

I understand the desire to make a new syntax that does as much as possible,
but I think we have a few different combinations to achieve that:

- object initializers & simple anonymous class initializers look the same;
named parameters may or may not look similar; complex anonymous classes
have to use a different syntax
- object initializers are just constructors with named parameters;
anonymous class definitions don't look similar, but support both simple and
complex cases in one syntax

Either way, the whole set of features isn't going to be implemented in one
go, so we don't need to work out all the details, just a direction of
travel.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-06 Thread Rowan Tommins
On Thu, 5 Sep 2019 at 22:45, Peter Kokot  wrote:

> GitHub usage is inevitable.



Did you use the wrong word here, or are you saying that, of all the
hundreds of different platforms we could investigate, there is no chance
that we would end up using something other than github?



> The interface is so good with clear discussion and review options
>


As my previous message, and those of several other people, show, that is
far from an established consensus. The power of an e-mail list is that
different users can use different interfaces - I've yet to see a forum
suggested that I would find easier than Thunderbird's tree view. There are
certainly downsides to e-mail, and upsides to GitHub, but let's stay calm
and evaluate our options rather than jumping at the first thing we see.

Regards,
-- 
Rowan Tommins
[IMSoP]


[PHP-DEV] Re: Features related to Object Initializers

2019-09-16 Thread Rowan Tommins
On 16 September 2019 04:13:24 BST, Mike Schinkel  wrote:
>
>> On Sep 14, 2019, at 4:47 PM, Rowan Tommins 
>wrote:
>> I think that's only true because you've actually proposed a number of
>related but different features.
>
>
>See my other email to the list asking about what is in-bounds and what
>it out-of-bounds regarding RFC discussion.
>
>I seemed logical to me to discuss how to improve an RFC, but maybe what
>you are saying is that we are only suppose to discuss RFC as it exists
>today in order to give a black and white, up or down vote on the entire
>RFC?  That seems counter-productive, but if that is the case and others
>concur then so be it.


I'll try to reply in detail later, but to clarify, I was not saying that your 
message was off topic. What I was saying was that what you described as one 
feature with lots of applications seems to me like lots of features with 
overlapping syntax.

There's nothing wrong with that, but it means that we don't get some of the 
stated benefits unless/until all the features are implemented, and I think it's 
useful to break down what each feature gives on its own.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Features related to Object Initializers

2019-09-16 Thread Rowan Tommins
gt;


I agree, and I never said otherwise. I do think that an important part of
deciding whether to implement a feature is evaluating its limitations, and
what use cases it would and wouldn't help with.

I'm not saying this feature should never happen because it doesn't work
with interfaces, I'm just saying that is a limitation to consider.



Named parameters are (or would be) a way of setting a bunch of variables;
> they're not linked as an object of any sort, so I don't think there's a
> natural comparison to anonymous classes at all.
>
>
> I did not say they _were_ linked, I asked why couldn't/shouldn't they be
> linked?
>
> They are both a group of named "properties" with associated values. Why
> are they all not equivalent to an object?
> And why not allow all of them to be treated as an object?
>
>


I don't particularly see them as a "group". If I write foo($a, 42), I don't
think of $a and 42 being bound together in any way; each is passed as a
value to one variable in the function. So that's my answer to "why not";
they just don't feel like related ideas to me.



If I understand it right, the next example relies on the combination of
> anonymous class initialisers, named class initialisers, and named
> parameters all using the same syntax,
>
>
> No, I would say that is not what I am proposing. What I am proposing is
> that one syntax and one set of functionality be used to address all three
> use-cases rather than have three different functionalities with three
> different syntaxes, because they seem to be to be all equivalent:
>
> 1. anonymous class initialisers,
>
> 2. named class initialisers, and
>
> 3. named parameters
>
>


Even if they use the same syntax, those are not the same piece of
functionality, or equivalent. The first two are certainly related, but the
last one I just don't see the connection.




>
> The examples look really neat on their own, but imagine coming on that
> syntax in someone else's code and trying to work out what it was doing.
>
>
> If I see someFunction({bar => 1, baz => 2}) that tells me that
> someFunction expects bar and bar as integers. When calling functions we are
> not supposed to know how they are implemented, so why should it matter to
> the caller whether internally they are captured to individual parameters or
> into a single parameter array?  And when inside the function, why does it
> matter how they are passed?
>
> The reason I proposed this is I would really *prefer *to come on to this
> syntax in other's code rather than coming onto the prevailing type of code
> I see in userland instead; arrays upon arrays.
>
>


This feels like a straw man to me: "if we don't unify named parameters with
object initializers, everyone will use arrays". I would definitely be happy
seeing objects being passed around more; but this syntax isn't the only way
to encourage that, and I think its costs outweigh its gains.




> What is not clear to me is why you see it to be confusing?
>
>


Consider this code:

class Customer {
public string $name;
public ?int $age=null;
}
function doSomething(?Customer $customer=null, ?string $name=null) {
   // ...
}
doSomething({name => 'John Smith'});


Is this equivalent to:
doSomething(new Customer{name='John Smith'}, null);
or:
doSomething(null, 'John Smith');


If I change the public properties of the Customer class, does that change
the result? If the parameter was mandatory, would that be different? If it
wasn't type-hinted, would I get an anonymous object? It's all too ambiguous
and context-dependent.

Compare that to separate syntax for the separate features:

doSomething(new class extends Customer { string $name='John Smith'; });
doSomething(new Customer{ name='John Smith' });
doSomething(name => 'John Smith');

All are nice and short, but there's no ambiguity; I don't need to read the
rest of the code to understand what each line is doing.




>
> There's definitely some interesting ideas here, but they're not all part
> of one feature,
>
>
> Can you clarify what you are implying?  That I should start other threads
> to discuss?  That I should create new RFCs?
>
>


I wasn't really implying anything beyond what I said: there's lots of
different ideas in here, but I wouldn't expect them all to be listed as one
feature in, say, a user manual.




>
> and they all rely on particular ways of structuring your code.
>
>
> Is that problematic?  Most language features require code to be structured
> a particular way.
>
> I am assuming that PHP is not an opinionated language that defines one way
> to structure code and shuns all other ways, except for those ways that have
> been explicitly deprecated by RFC such as magic quotes.  Am I incorrect
> about this?
>
>


I didn't say it was "problematic"; again, I'm just trying to evaluate these
ideas, and part of that is working out their limitations, and whether there
are alternatives that can be used in more scenarios.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-08 Thread Rowan Tommins
On 8 September 2019 11:42:07 BST, Brent  wrote:
> - We could add community guidelines, clearly stating that RFC comments
>should stay on topic
> - People could be appointed to moderate the comments, allowing
>contributors to focus on the code instead of community management
> - Conversations on GitHub can be locked as a last measurement.
>Repository members can still comment.
>
>I fear that separating the main discussion from the PR will cause
>unnecessary confusion: important, generals remarks could be made on the
>"main thread", and I think there's value in keeping these remarks
>together with everything else.


I'm sceptical of that as a solution for two reasons:

Firstly, the conversations weren't necessarily wrong, they were just a slight 
drift of topic. The problem is not removing them from the PR, it's encouraging 
them to move somewhere else. I fear that saying "sign up to the mailing list 
and repeat that point in a completely different format" will be taken up less 
than "make a new thread on this same list/forum".  

Secondly, the problem is partly a technical one: GitHub PRs have very poor 
support for replies and sub-threads, so even on-topic discussions that don't 
relate to a specific part of the text are hard to follow.

I think Nikita's suggestion is a good one: use a PR for making targeted 
suggestions to the RFC text itself, but raise the general points on the main 
list. That might even include saying "I've added a handful of suggestions 
relating to X" and discussing the wider issue that links them.

I agree it would be interesting to experiment further, and I think this hybrid 
approach would be a good one to try next.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Union Types v2 (followup on github usage)

2019-09-05 Thread Rowan Tommins
On Thu, 5 Sep 2019 at 11:22, Côme Chilliet  wrote:

> Le jeudi 5 septembre 2019, 12:04:55 CEST Brent a écrit :
> > > Huge "no" from me on using github for discussing RFCs.
> >
> > Care to elaborate why? The majority seems to like it. Though I am also
> curious about Nikita's experience with it, as he is the one having to
> process the feedback.
>
> Because the PHP project should avoid depending on a privately owned
> centralized service for its technical discussions, and should not encourage
> (some would say force) people to use such platforms.
>
> PHP is already on github but it’s only a mirror, the main git repository
> is at git.php.net .
>


The "privately owned" and "centralized" parts don't bother me particularly,
but there's potentially an issue in splitting the discussion between
multiple platforms, with different logins required. An example of this is
the discussion on this RFC about type aliases - Nikita requested it to be
split into a separate discussion, but the people involved may not be
subscribed to this list, and if they are, it's hard to maintain context
when jumping between different forums.

That conversation also highlighted a limitation of the particular platform:
inline comments on GitHub PRs show as threads, but comments on the whole PR
don't, so that interleaved discussions are hard to follow. Admittedly,
that's true on a lot of e-mail clients as well (thanks to GMail
popularising "conversations" rather than "threads"), but at least views
like externals.io and news.php.net can let you navigate the tree.

I wonder if a hybrid approach would work better - the RFC is a PR (perhaps
against the language spec repo, as Andrea suggested) but the main
discussion stays on the list. Suggestions to improve the RFC itself could
be made inline on the PR by anyone who wanted to, but non-inline PR
comments would be heavily discouraged so that wider comments on the
proposal would stay here.

Either way, I think it's interesting to experiment with different ways of
working, and maybe there are other platforms we should trial as well.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-13 Thread Rowan Tommins

On 12/09/2019 22:56, Andreas Hennings wrote:

$var[$k0][? $k1][? $k2]++;

This is great but the second "?" is redundant isn't it?



If the rule is "you cannot read a non-existent array element without ?" 
then no: $var[$k0][? $k1] allows you to read that element, and from 
context treat it as an array; but that array won't have a key $k2, so 
you also need to say that reading *that* was deliberate, and from 
context treat it as an integer.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Reclassifying engine warnings

2019-09-13 Thread Rowan Tommins

On 13/09/2019 09:01, Robert Korulczyk wrote:

Actually you need only one additional line:

$foo = [];
foreach ( $something as $key1 ) {
 foreach ( $somethingElse as $key2 ) {
   $foo[$key1][$key2] ??= 0;
   $foo[$key1][$key2]++;
 }
}



Why? If "assume $key2 exists as a key and is an integer" is so bad that 
PHP should halt my program, why should "assume $key1 exists and is an 
array" be perfectly OK?




It does not look confusing. You have two lines, for two intents - start 
counting from zero and increment counter on every loop iteration.



There is no intent to start counting at zero; the counter will never be 
lower than 1. If we really wanted to express the intent, we would have 
to write something like this:



$foo[$key1] ??= [];
if ( ! isset($foo[$key1][$key2]) ) {
   $foo[$key1][$key2] = 1;
}
else {
   $foo[$key1][$key2]++;
}



If one additional line is to much for making your code less ambiguous and more 
bug-free, then I won't even try to change your mind.



Please can you show me a bug that adding this line has avoided? I don't 
doubt that the same warning saves bugs in other scenarios, but in this 
scenario, the logic is unambiguous, and any additions are just to 
suppress unnecessary errors.


To reiterate, my motivation here is to discuss features that help write 
these scenarios with less boilerplate, and separate them from other 
scenarios where there's a real bug risk which should raise an error.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Improving productivity of internals mailing list

2019-09-20 Thread Rowan Tommins
On 18 September 2019 18:33:19 BST, Dan Ackroyd  wrote:
># Problem 2 - Some threads are not a good fit for a mailing list.
> ...
>We should move as many conversations off the internals list as we can,
>while still retaining ways of people finding where those conversations
>are being held.
> ...
>For example, it's appropriate for people who are release managers to
>be sending as many emails as they need to, to manage the release
>process. People who have only recently joined the mailing list,
>probably shouldn't be sending as many emails.


I notice that in several of your recent messages, on and off list, you identify 
the *number* of messages to the mailing list as a key problem. While it's 
certainly true that this can be quite a high-volume forum, I think we should be 
making that volume easy to work with, not trying to reduce it as an end itself.

One of the points in your proposed etiquette guide is "you don't have to reply 
to every message". I think there is a corollary, "you don't have to read every 
message". For instance, if a proposal or question leads to a series of 
back-and-forth clarifications, those should be visible to anyone interested, 
and easily skipped for anyone not. However, the current platform perhaps makes 
this more difficult than it should be.

Although I'm subscribed using a Gmail account, I access the list mainly through 
Thunderbird, display posts in a tree view, and regularly leave individual 
messages and whole sub-threads unread, even if I'm actively participating in a 
different branch of the same thread. Other clients make this much harder - 
GMail's "conversations" are optimised for linear exchanges between two or three 
people, and are frankly awful for working with a mailing list.

Although initially resistant, I'm coming around to the idea that the mailing 
list should be replaced with some other kind of forum. One of the key features 
would be good support for branching threads, ideally including the ability to 
move messages which have drifted away from an original topic into their own 
top-level thread.

Notably, GitHub PRs fail to meet this requirement, as was clear in the recent 
experiment. Like Gmail, they're built for a very different task.

On a final note, there are definitely times when people do send too much to the 
list, but it's generally not the volume itself that's the problem, but 
repetition, lack of clarity, or lack of focus. Better support for threads or 
topics wouldn't solve those, but it would solve the common case of "this part 
of the conversation isn't relevant to me but I want to read the rest".

Regards,
Hi Dan,
-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Improving productivity of internals mailing list

2019-09-21 Thread Rowan Tommins
On 21 September 2019 12:18:20 BST, Dan Ackroyd  wrote:
>On Fri, 20 Sep 2019 at 19:52, Rowan Tommins 
>wrote:
>>
>> I think we should be making that volume easy to work with, not trying
>to reduce it as an end itself.
>
>As I've said elsewhere, I think having a central place for people to
>find interesting conversations/things to work on, would help direct
>people's energy for making PHP better to productive activities. Hence:
>https://github.com/Danack/RfcCodex/blob/master/project_coordination.md


This is definitely an interesting idea, but I think it's solving a different 
problem. A notice board for finding "interesting conversations" across half a 
dozen different platforms is very different from having a central place where 
suggestions can be made, feedback given, and ultimately decisions taken.

Right now, the mailing list is officially that central place. If you think it's 
not the right tool for the job, then we need to discuss what other tools to 
replace it with. Similarly, if you think there are types of discussion which 
should be considered off-topic, we should have somewhere to send those, rather 
than putting them in the same category as abusive messages.

My concern with keeping some things on the list, but sending some elsewhere, is 
that it's not always easy to move a conversation once it's started. People will 
either try to carry it on against advice, or simply give up contributing. So if 
we're discussing moving some things off the list, then I think it makes sense 
to discuss the option of moving everything instead.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Prevent disruptions of conversations

2019-09-28 Thread Rowan Tommins
On 19 September 2019 18:18:40 BST, Dan Ackroyd  wrote:
>Here is an RFC to "Prevent disruptions of conversations"
>https://wiki.php.net/rfc/prevent_disruptions_of_conversations


Looking at this RFC purely from the stated motivation, I think that there are 
two key things that need improving before it is considered for a vote.


Firstly, it doesn't define things clearly enough. It is certainly easier to 
define general principles than it is to codify every possible scenario in 
advance; however, the looser those definitions, the more trust needs to be 
placed in whoever has the task of interpreting them. As it stands, this 
proposal carefully avoids appointing anyone to have that authority, meaning 
that every application of the process would be subject to open-ended debate.

If the intention is to put a short-term rule in place without opening too many 
additional questions, it would perhaps be clearer to propose a small set of 
specific rules, which don't cover everything, but can be applied clearly and 
immediately.


Secondly, it only handles the most extreme cases; there is no halfway between 
asking nicely and an indefinite ban. Not only does that leave a lot of grey 
areas that are not addressed at all, but it reduces the deterrence power - all 
that's needed to avoid punishment is to be not quite bad enough for the 
harshest penalty. 

A simple approach that I've seen work well is to have a short ban - say a week, 
or a month - for a first offence, scaling to a year (or indefinite) after three 
or more. That gives warnings more "teeth", and punishments more flexibility.


I would be interested to hear your thoughts on these suggestions.


Regards,
Hi Dan,
-- 
Rowan Tommins
[IMSoP]

Re: [PHP-DEV] Re: [VOTE] Reclassifying engine warnings

2019-09-26 Thread Rowan Tommins
On Thu, 26 Sep 2019 at 10:48, Peter Cowburn  wrote:

> I just want to go on the record in saying that I am very, very disappointed
> that a choice that only got 28% of the overall votes, and only 33% of votes
> in the "we want change" scenario, is being taken as the will of the
> overwhelming majority, which is the bar that is needed to be crossed for
> RFC votes. This is wholly irresponsible.
>


Three-way votes are always tricky in this respect, but I think in this case
Nikita has taken a very sensible approach.

Firstly, the interpretation of the three-way vote was laid out very clearly
on the page, and I'm not aware of anyone objecting to it prior to this
point.

Secondly, it makes sense intuitively: it seems unlikely that someone who
would vote yes to the question "Should undefined variables give an Error
instead of a Notice?" would vote no to the question "Should undefined
variables give a Warning instead of a Notice?"

Thirdly, the options are not mutually exclusive in the way that, say, a
syntax decision would be. Raising the level to Warning now doesn't prevent
a future proposal to raise it to Error (e.g. on a different timescale).

Finally, and perhaps most importantly, RFC votes are intended to be
measures of consensus. Taken alongside the discussion, the result strongly
suggests that there is a consensus (but not a unanimous one) to change the
error level, but there is some concern about raising it as high as Error.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Prevent disruptions of conversations

2019-09-27 Thread Rowan Tommins
On Fri, 27 Sep 2019 at 09:27, Brent  wrote:

> Zeev, while I agree with many of your points, you also don't offer a
> concrete solution.
>


To be fair to Zeev, he did in fact try to kick off a discussion about
Workflows and Voting back in January: https://externals.io/message/103917 |
https://wiki.php.net/rfc/voting2019 For various reasons, both within the
community and outside it, this proposal was suspended.

The other problem with demanding people propose solutions at this point is
that we haven't agreed on what the problems are. Depending who you ask, the
problems to be tackled might include any of:

- the tone of the list is too aggressive, and needs moderation
- discussions are happening on the list which should be elsewhere
- people are posting too many messages
- proposals are being made which are against the spirit of the language
- the language is evolving too fast, or too slowly
- the direction of the language is poorly defined
- proposals are being put to a vote which should be decided a different way
- core developers are wielding undue influence, or being denied necessary
influence
- voting rights are ill-defined

... and many more besides.

Some of these should be tackled as separate issues, but some are symptoms
of each other. If I had to pick one root cause, it would be the lack of
clear leadership and process, because without that it's not clear who has
authority to tackle the others. But we need to reach some consensus on the
right question before we start digging into detailed answers.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] PHP 7.4 BC break with openssl_random_pseudo_bytes()

2019-09-24 Thread Rowan Tommins
On Tue, 24 Sep 2019 at 15:26, Larry Garfield  wrote:

> And no, random_int(0,0) does what it says on the tin: return a random int
> between 0 and 0.  If you call it that way, well, it's your own PEBCAK.  But
> it throws an exception if the underlying sources of entropy are not working
> for some reason, rather than returning something that can easily be
> mistaken for a valid integer.
>


I think the argument was that the consistent behaviour would be for
random_bytes(0) and openssl_random_pseudo_bytes(0) to return '' (i.e. a
random string which was zero bytes long). The result is just as logical,
and just as meaningless, as "a number between 0 and 0" - in both cases,
there is exactly one valid value, so every random choice returns that value.

The BC break is a separate discussion - the RFC listed some changes to
openssl_random_pseudo_bytes but not this one.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Prevent disruptions of conversations

2019-09-30 Thread Rowan Tommins
On Sun, 29 Sep 2019 at 20:22, Dan Ackroyd  wrote:

> On Sat, 28 Sep 2019 at 20:10, Rowan Tommins 
> wrote:
> >
> >
> > I would be interested to hear your thoughts on these suggestions.
> >
>
> I encourage you to work on them. Or anyone else who cares to. And the
> sooner there is concrete alternative proposal the better.
>



Hi Dan,

The purpose of the two week discussion period for RFCs is so that we can
work together to improve them, not so that people can independently work on
overlapping proposals.


>  But in the meantime, I think this RFC is an improvement on the current
> situation.


As I said, I have tried to measure the proposal against its stated aim: to
prevent disruption of the mailing list. In its current form, I do not think
it will achieve that aim.


> Although I agree with the action of removing those people, there were
> no clear rules, or people who could 'officially' tell those people
> "your behaviour is being disruptive". This RFC at least provides a
> framework for that.


Your proposal provides neither clear rules, nor clear authority, and indeed
goes out of its way to avoid both, with an open definition of "disruptive
behaviour" and a careful avoidance of the word "moderator".

In some extremely rare cases there is consensus that a ban is clearly
warranted; in such cases, any vote would be a formality. It would feel more
legitimate than a "dictatorial" decision, but the situation arises so
rarely it would make very little difference to the general tone of the
community.

In any other case, a vote under this proposal would be extremely
contentious, and is likely to result in more disruption than it removes.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] PHP 7.4 BC break with openssl_random_pseudo_bytes()

2019-11-07 Thread Rowan Tommins
On Wed, 6 Nov 2019 at 19:44, Jakub Zelenka  wrote:

> I have to say that the RFC wasn't really well done as the implementation
> followed which caused this omission. We should really look properly to the
> implementation when creating RFC so it's more detailed and doesn't cause
> omission like this.
>


There's a bit of a Catch-22 there: voters want to know all the edge-cases
before they approve an RFC; but developers want to know the RFC will be
approved before they spend hours refining a patch. In some ways, it would
be good to have two votes: one on the principle, and one on the detailed
implementation; but that could make the process feel quite long and
bureaucratic.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Optional pre-compiler for PHP8?

2019-10-30 Thread Rowan Tommins

Hi Dik,

On 29/10/2019 21:44, Dik Takken wrote:

Opcache already performs type inference. [...]
Here is an interesting read on the subject:

https://depositonce.tu-berlin.de/bitstream/11303/7919/3/popov_etal_2017.pdf



Thanks for the link, and the insight into how much OpCache can already do.

I guess preloading gets us pretty close to the tool I was imagining - 
OpCache could make assumptions that cross file boundaries, within the 
preloaded set, and could spend longer optimizing during the preloading 
phase than might be expected on a simple cache miss.


I think it will be interesting to see how tools adopt that feature, and 
whether eventually we'll see autoloader functions as just a fallback 
mechanism, with most packages being enumerated in advance as large 
preloaded blocks.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: php 7.{3,4}/git ext/curl builds FAIL with recent curl/libcurl 7.67+: "error: ‘CURLE_OBSOLETE20’ undeclared ...".

2019-11-15 Thread Rowan Tommins
On Fri, 15 Nov 2019 at 08:19, Christoph M. Becker  wrote:

>
> That appears to be due to a recent change in libcurl[1].  We'll have to
> work around that, but I'm not sure how.  Define both constants for BC?
>
> [1]
> <
> https://github.com/curl/curl/blob/b3eb7d172aab6c7f423aea2f97c27099d6b65f7a/include/curl/curl.h#L504-L506
> >
>


It looks like last time this happened (value 16 reused for HTTP2), the
removed constant was reintroduced in curl to avoid just this scenario:
https://github.com/curl/curl/pull/106

Perhaps a patch should be submitted to do the same thing again this time?

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-17 Thread Rowan Tommins

On 17/11/2019 14:41, Aimeos | Norbert Sendetzky wrote:

PHP frameworks would profit from support of an "arrayable" pseudo type
hint that matches "array" and all objects that implements "Traversable",
"ArrayAccess" and "Countable".


...


It would be useful to implement an Arrayable interface too:

interface Arrayable extends \Iterator, \Countable, \ArrayAccess
{
 public function toArray() : array;
}



It feels like there are two alternative suggestions here. Not only do 
they use the same keyword to mean different things, but "convertible to 
array", and "usable as array" seem like distinct concepts to me.


For the "convertible to array" case, I think __toArray, or an interface 
specifying just that one method, would make more sense than combining it 
with the existing interfaces. I'm sceptical of that concept, though, 
because most objects could be converted to many different arrays in 
different circumstances, each of which should be given a different and 
descriptive name.


For the "usable as array" case, the big advantage would come if internal 
array_* functions could take such objects, but that requires a bit of 
thought on how each function should behave. There could also be some 
surprising behaviour passing infinite iterators, or objects where the 
output of ArrayAccess and iteration don't match up. It might make sense 
to have objects opt into an Arrayable interface, to make clear they're 
expecting to be used this way; but require no additional methods other 
than those required by Iterator (or Traversable), Countable, and 
ArrayAccess.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-17 Thread Rowan Tommins
[Note: I've included the full text of the previous message as it wasn't 
sent to the list.]


On 17/11/2019 18:35, Aimeos | Norbert Sendetzky wrote:

It feels like there are two alternative suggestions here. Not only do
they use the same keyword to mean different things, but "convertible to
array", and "usable as array" seem like distinct concepts to me.

The name of the interface isn't perfect because it may be too close to
the type hint and therefore misleading. Suggestions for a better name
are always welcome.

The concept contains three parts:
- arrayable type hint: Use objects and arrays alike
- \Arrayable interface: To enable implementing objects that are "arrayable"
- __toArray(): To convert objects to arrays



Like I say, the name is part of it, but the purposes also overlap the 
way you describe them. It makes more sense to me to have two separate 
features for two separate use cases:


- If I just want to know that the object I've received can be iterated, 
counted, and accessed using square brackets, then I need either a 
special type hint or a new interface, but not both.
- On the other hand, if I just want to know I can call toArray or 
__toArray on an object, I don't care whether it implements Iterator, 
Countable, etc as well.





For the "convertible to array" case, I think __toArray, or an interface
specifying just that one method, would make more sense than combining it
with the existing interfaces. I'm sceptical of that concept, though,
because most objects could be converted to many different arrays in
different circumstances, each of which should be given a different and
descriptive name.

Can you give some examples for different conversions?



Well, pretty much any method that returns array *could* be called "to 
array", but not many would be good candidates for such a generic name. 
You might return an array structure to be incorporated into a JSON 
response, or to be passed to a template renderer, or to map to database 
columns, etc.


The only case I can think of where a generic "toArray" method would make 
sense is if you're creating a general-purpose "collection" or "list" 
object, in which case you're probably better off directly implementing 
methods like map and sort, rather than encouraging users to convert it 
back to a plain array. It doesn't seem like a common enough use case to 
need a new language feature, when it's simple enough to write 
"$foo->toArray()" without anything new.




The possibility to pass arrayable objects to the array_* methods should
be out of scope for the moment and is better discussed later to keep the
pieces small, I think. You are totally right, there may be some
unexpected behavior when doing that.



The reason I mentioned it is that without it the new type hint or 
interface seems rather limited: I can't imagine many "array" type 
constraints being replaced with "arrayable" if you had to remember not 
to pass the variable to array_map, sort, etc.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-17 Thread Rowan Tommins

On 17/11/2019 23:01, Mike Schinkel wrote:


Consider this: __toArray() is hardly a rare case where a short
name can be applied in multiple contexts.  We have infinite
contexts where we need to name methods for one context that might
conflict with others, and so I have been agonizing for years over
how to deal with this conundrum without resorting to really long
method names.



I'm not sure avoiding the name "toArray" necessarily leads to "really 
long method names" - even with extremely specific distinctions, you 
don't need to call the method "toJsonArrayForVersion5OfTheApi", just 
"toV5Json" or "getV5Array" or "formatForJsonV5".


The important thing is that the method name is now communicating its 
*purpose*, whereas "toArray" communicates only its return type, and a 
hugely flexible return type at that.





Recently I have been experimenting with using namespaces instead
of long method names, and I think using them can result in the
best of both worlds and resolve your concern.  Consider the
following classes, each of which could have their own __toArray()
method /specific/ to their use-case:


\Widgets\Widget\Widgets\JSON\Widget\Widgets\Mustache\Widget\Widgets\DbColumns\Widget



I'm not clear what these objects represent. If I have a Widget object 
passed out from some business logic, how do I make use of these other 
classes? Would I have to call "(array)(new 
\Widgets\Mustache\Widget($myWidget))", as sugar for "(new 
\Widgets\Mustache\Widget($myWidget))->__toArray()"?


If so, I don't really see the benefit of the magic method over just 
standardising a method name, like "interface MustacheFormatter { public 
function getData(): array; }"


Which is basically my objection to __toArray() - I can't think of many 
situations where writing (array)$foo saves or gains you anything over 
writing $foo->asArray() or $foo->somethingMoreSpecific()



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-18 Thread Rowan Tommins
where __toArray() would
> actually cause a problem for someone like you who cannot think of a
> benefit.  Can you present a use-case how it would cause you a tangible
> problem that *could not be resolved* with namespaces or by just creating
> your own somethingMoreSpecific() method and ignoring __toArray()?
>
>

Well, I started this sub-thread saying I was "sceptical" rather than
"strongly opposed". If the feature was added, I would simply ignore it, and
probably argue against its use in code review and style guides.

However, other people have pointed out that unlike (string)$object,
(array)$object does have a default behaviour, and adding an overload for it
has the potential to break code relying on that. So it's not an entirely
zero-cost feature.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-18 Thread Rowan Tommins
 an object that implements __invoke() will
> return an array whereas there should be a reasonable guarantee that if
> function_exists($object,'__toArray') is true that casting to (array)
> would be valid.
>
>

Which brings us back to square one: knowing that a method returns an array
isn't enough; I need to know what kind of array that is, and the thing that
normally tells me that is the method's name.



Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Inline switch as alternative to nested inline conditional

2019-10-16 Thread Rowan Tommins
On Wed, 16 Oct 2019 at 14:58, Robert Hickman  wrote:

> > >  > > $say = switch (date("w")) {
> > > case 0 => "weekend!";
> > > case 1, 2, 3, 4, 5 => "weekday :(";
> > > case 6 => "weekend!";
> > > };
> > > echo "Today is {$say}";
>
> If you had a really long expression, it may be easier to read if the
> assignment was moved to the end, perhaps like this:
>
> switch (date("w")) {
> case 0 => "weekend!";
> case 1, 2, 3, 4, 5 => "weekday :(";
> case 6 => "weekend!";
> // lots more cases ...
> } => $say;
>
> echo "Today is {$say}";
>


The assignment is not part of the switch syntax, the proposal is for a
switch expression which evaluates to a value, and can be used anywhere a
value is wanted. Your example is no different from a complex function call:

$say = doSomething(
$foo,
'weekend',
[ 'blah => 42, 'bob' => 'smith' ],
moreStuff()
);

It might be nice if there was a left-to-right assignment operator (there
are some languages which write it that way around), but that should be a
separate feature, where you could also write this:

doSomething(
$foo,
'weekend',
[ 'blah => 42, 'bob' => 'smith' ],
moreStuff()
) => $say;

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] 'switch-expression' and the 'type guard' unary operator demo

2019-10-20 Thread Rowan Tommins

Hi Kosit,

There's some really interesting ideas in here, thanks for sharing them.


On 19/10/2019 17:40, Kosit Supanyo wrote:

Like function declaration and function expression in JavaScript, if
`switch` appears as first token at statement level it will be recognized as
statement but if `switch` is in expression context it will be
switch-expression.

switch ($expr) {
 case $cond1 => $result1,
 case $cond2 => $result2,
 case $cond3 => $result3,
 default => $default_result,
};
// Parse error: syntax error, unexpected '=>' (T_DOUBLE_ARROW)

But this is OK.

!switch ($expr) {
 case $cond1 => $result1,
 case $cond2 => $result2,
 case $cond3 => $result3,
 default => $default_result,
}; // semicolon is still required because it is an expression



This feels like an odd restriction to me, and one that as far as I'm 
aware PHP doesn't have anywhere else. For instance, it might be 
considered bad style, but it's possible to use a ternary operator as an 
abbreviated if statement:


isset($_GET['logout']) ? $session->logout() : $session->extend();

Was this restriction added to make the implementation easier, or because 
you thought it was a useful feature?




You can omit parenthesized expression which is shortcut to `switch (true)`.
This change applies to switch statement as well.

$v = switch {
 case $x >= 0 && $x <= 100 => 1,
 case $x >= 100 && $x <= 200 => 2,
 default => 3,
};

switch {
 case $x >= 0 && $x <= 100:
 doSomething1();
 break;
 case $x >= 100 && $x <= 200:
 doSomething2();
 break;
 default:
 doNothing();
 break;
}



This is an interesting idea, given that switch(true) is the documented 
way to do this right now. However, I've always felt switch(true) was 
rather limited in its advantage over if-elseif. I would prefer a syntax 
that reduced the boilerplate for:


* Different comparisons applied to the same variable/expression, e.g. 
match($user->getScore()) { case <0 => foo(), case >100 => bar(), default 
=> baz() }
* Different values compared against the same expression using the same 
operator, e.g. match( $exception instanceOf ) { case FooException => 
handleFoo(), case BarException => handleBar() }





You can also use `return` and `throw` in result expression. I recalled some
languages have this feature (but I've forgotten what language). This
feature can be very handy and useful in many use cases.

$x = 'd';
$v = switch ($x) {
 case 'a' => 1,
 case 'b' => 2,
 case 'c' => return true,
 default => throw new Exception("'$x' is not supported"),
};



This seems confusing to me, because it mixes statements and expressions 
in a rather unusual way. The "return" case in particular seems ambiguous 
- if $v is visible outside the function, will it have a value assigned 
to it by the "return" branch, and if so what would that value be? I can 
imagine more use cases for the "throw" version, and it's reasonably 
obvious how it would behave, so it might be reasonable to have that one 
special case.





Additional feature in the demo patch is the 'type guard' unary operator
which is an operator that will perform type check on given value and throw
`TypeError` when type mismatch occurred, otherwise return the value as is.
It has the same precedence  as `new`.

$a = 'This is a string';
$v = $a; // TypeError: Value is expected to be int, string given



This is a very interesting feature, although I think what would be even 
more useful would be syntax to check if something _can_ be cast, i.e. 
the same check you have here, but as an operator evaluating to boolean.


That way, you could write code like this:

if ( $_GET['id'] ) {
   $user = getUser($_GET['id']):
}
else {
   echo "Invalid ID provided";
}

Which would be equivalent (given a type hint on getUser() and no 
strict_types declaration) to this, but without needing to use exceptions 
as flow control:


try {
   getUser($_GET['id']);
}
catch ( TypeError $e ) {
   echo "Invalid ID provided";
}


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] anti-coalescing-operator

2019-10-25 Thread Rowan Tommins
On Fri, 25 Oct 2019 at 03:37, Ken Stanley  wrote:

> This got rejected for being too large???
>


If you trim the quotes in your replies to just the parts needed for
context, it keeps the message shorter, and makes it much easier to read
through.




> > The fact that it’s a counterpart to an existing syntax l, I believe,
> > further warrants it’s inclusion into the language.
>


As I mentioned before, it doesn't feel to me a very natural complement. The
use cases for the new operator don't feel like "the negation" of the use
cases for the existing ?? operator, and although different from null-safe
calls, have more in common with them than "coalescing".




> >> The repetition becomes more relevant if the expression we would repeat
> >> is really long:
> >>
> >> isset($something['something']['something']['something']) !??
> >> $something['something']['something']['something']->foo();
> >
> >
> > This would be invalid because isset() returns Boolean



I suspect that was just a mistake; the point was the new operator doesn't
save any repetition in an expression such as:

$something['something']['something']['something'] !??
$something['something']['something']['something']->foo();

Which in this particular case could be rewritten if we had a null-safe call
operator, and would gain a lot more readability:

$something['something']['something']['something']?->foo();




> > As far as flow control, let’s make no mistake, ??, ?:, and the idea of
> !??
> > are all succinct forms of flow control. To pretend otherwise is a bit
> > naive.
>


I think you're misunderstanding what people mean by "flow control"; the key
point is whether you're using the operator to obtain a value, or to trigger
a side effect.

For instance, this would not generally be considered "flow control":

$x = $someFlag ? 1 : 2;

Yes, strictly speaking, you're selecting one of two paths, but the only
side-effect is an assignment, outside the expression. Compare to this,
where the value of the expression is never even used, and you're just
choosing a side-effect:

$someFlag ? deleteUser() : logOut();



Your second example was better in this respect, because it used the result:

$user = $application->getUser() !?? $this->getUser();

However, is this actually the desired code? If I'm not mistaken, it would
de-sugar to this:

if ( isset($application->getUser() ) {
$user = $this->getUser();
} else {
$user = null;
}

Given that your specified aim is to look up a default, isn't this actually
a case for the existing null-coalesce operator?

$user = $application->getUser() ?? $this->getUser();
// or if the precedence is the other way around:
$user = $this->getUser() ?? $application->getUser();



Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] anti-coalescing-operator

2019-10-25 Thread Rowan Tommins
On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo  wrote:

> But I think this functionality should be of something like pipeline
> operator:
>
> // send tmp variable to the next expression unconditionally
> $ret = $_SERVER['fname'] |>  $user->setName($$);
> // send tmp variable to the next expression only when $_SERVER['fname'] is
> set.
> $ret = $_SERVER['fname'] ?|>  $user->setName($$);
>
> Also the syntax like above will be consistent with the proposed
> safe-navigation operators.
>


I really like this idea, and it actually makes the pipeline operator itself
feel more useful, too.

Imagine this chain, where not only might the variable not be set, but it
might not match a user, or the user might have no name:

$upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName()
?|> strtoupper($$);

As well as not needing to repeat the expression each time, as you would
with an "anti-coalesce", "null-safe chain" feels a clearer reading of the
intent here than "if not unset".


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Optional pre-compiler for PHP8?

2019-10-27 Thread Rowan Tommins

On 27/10/2019 02:12, Mike Schinkel wrote:

While reading the [RFC] Union Types v2 thread and comments from Dmitry[1], and especially 
Benjamin[2] who suggested "building a static analysis tool which could prove that 
certain type checks would never fail, and prime OpCache" it occurred to me that a 
PHP pre-compiler could potentially be used to resolve numerous issues the community has 
been debating.



I chose the phrase "static analysis tool" deliberately, because I wanted 
to think about the minimum requirements for such a tool, rather than its 
long-term possibilities. The basic requirements are fairly straight-forward:


- a static analyser that can infer types in a PHP program; we know 
that's possible from a number of third-party tools, although they do 
rely on docblock comments for things the language doesn't (yet) let you 
define
- the ability to generate OpCodes for some code and store it to disk; 
this is more or less what OpCache does if enabled for CLI mode


However, combining those usefully may not be that easy.

The first problem is that OpCache is designed to work one file at a 
time, because a program can load any combination of files at run-time. 
Static analysers, on the other hand, need to process a whole directory 
at a time, so that calls can be matched to definitions; multiple 
definitions of the same function or class tend to cause problems, even 
though only one is loaded at run-time. So we'd probably need some 
built-in definition of a "package", which could be analysed and compiled 
as one unit, and didn't rely on any run-time loading.


The second problem is that, as I understand it, type checks aren't 
actually separate OpCodes, so eliminating them from the compiled program 
may not be that easy. There are some cases where you can just eliminate 
the type check from a definition, e.g.:


class A {
    private int $x=1;
    private function foo(int $x) { }
    public function bar() {
   $this->foo($this->x);
    }
}

Since we know that function foo is only ever called with the correctly 
typed argument, we can compile it as though it had no type declaration. 
However, in the seemingly obvious case Benjamin gave, the optimisation 
isn't so easy:


function x(): int {}
function y(int $foo) {}
y(x());

We can't eliminate the type check for all calls to x(), or for all calls 
to y(), but we want to eliminate the duplicate check for that particular 
line. So the OpCodes need to represent that somehow. I've no idea how 
easy or hard that would be.



In order to extend this to a full compiler, we need at least one more 
thing: a stable compilation target. What I mean by that is that if I 
distribute a package in binary form, it needs to run on a reasonably 
large range of PHP versions and installations. My understanding is that 
the OpCodes in the Zend VM are not designed to be stable across 
versions, so you can't just ship today's OpCache output like you would a 
Java class file or .net assembly. Again, I don't know how much effort it 
would be to make the VM work as such a stable target.




4. Ability to deprecate features for pre-compiled code while still supporting 
them when not precompiled.



Unlike P++, Editions, or Strict Mode, this would undeniably define that 
the deprecated features were "the wrong way". If the engine had to 
support the feature anyway, I'm not sure what the advantage would be of 
tying it to "compiled vs non-compiled", rather than opting in via a 
declare() statement or package config.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Optional pre-compiler for PHP8?

2019-10-28 Thread Rowan Tommins
On Sun, 27 Oct 2019 at 23:56, Mike Schinkel  wrote:

>
> So we'd probably need some built-in definition of a "package", which could
> be analysed and compiled as one unit, and didn't rely on any run-time
> loading.
>
>
> That idea of a "package" came up during a debate on this list at least
> once, a few months ago, and I think it makes a lot of sense. And what I
> proposed effectively implies that namespaces would be treated like packages
> from the perspective of the compiler.
>
> But then again a new package concept might be needed in addition to
> namespaces, I am not certain either way.
>
>


Current tools tend to actually work on a directory level, because you don't
actually know what namespaces are involved until after you've loaded it,
and a file can include code for two completely separate namespaces. My
thinking was that a package would pre-define the full list of files that
define it, with no auto-loader, and no conditional definitions evaluated at
run-time. As Benjamin points out, this is closely related to preloading.




> Unlike P++, Editions, or Strict Mode, this would undeniably define that
> the deprecated features were "the wrong way".
>
>
> I am not sure I cam agree that it would define them as the "wrong way."
>
>
> The way I would see it is there would be a "strict way" and an "unstrict
> way."  If you prefer the simplicity of low strictness and do not need
> more/better performance or the benefits of type-safety that are needed for
> building large applications, then the "right way" would still be the
> "unstrict way."
>
>


And what if you want simplicity *and* performance? Most of the things
people want to make strict about the language don't make it faster, so if
we limited "pre-compiled mode" to be strict, we'd be making a deliberate
choice to group objectively good things (fast vs slow) with subjective
preferences (strict vs simple). That pretty clearly marks strict mode as
"the better way".




> If the engine had to support the feature anyway,
>
>
> I think we are talking two engines; one for compiling and another for
> interpreting.  They could probably share a lot of code, but I would think
> it would still need to be two different engines.
>
>


That sounds like the worst kind of fork: two different engines, running two
different dialects of the language. At that point, you might as well just
switch to Hack.

Note that this was exactly what "P++" was intended to avoid - the two
dialects would exist in the same engine, and get the same performance and
security enhancements.




> I'm not sure what the advantage would be of tying it to "compiled vs
> non-compiled", rather than opting in via a declare() statement or package
> config.
>
> The advantage would be two-fold:
>
> 1. Backward compatibility
>
> 2. Allowing PHP to continue to meet the needs of new/less-skilled
> programmers and/or people who want a more productive language for smaller
> projects that do not need or want all the enterprisey type-safe features.
>
>


Both of these are reasons to have some sort of "strict mode", but not for
tying it to some other feature.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Adding explicit intent for SWITCH/CASE fall through?

2019-10-18 Thread Rowan Tommins
Hi Bishop,

I'm not the proposer, but would like to answer your questions anyway.


On Fri, 18 Oct 2019 at 04:14, Bishop Bettini  wrote:

> Do you envision this token accepting an optional argument, as break does,
> to fall-through multiple nesting levels? Eg:
>
>  $x = $y = $z = 1;
> switch ($x) {
> case 1:
> switch ($y) {
> case 1:
> switch ($z) {
> case 1: fallthrough 3;
> case 2: echo 'z2';
> }
> }
> break;
> case 2: echo 'x2'; break;
> }
> ?>
>


I think we should keep it simple - we can always add more features later if
a real need reveals itself.

I note that the Go version linked to explicitly forbids the use of
"fallthrough" in a conditional, and a multi-level fallthrough is
effectively the same thing: the control flow in your example is something
like if ( $y==1 && $z == 1 ) { fallthrough; } else { break; } I would have
thought that by the time you've got nested switch statements with
conditional fallthrough on multiple levels, the code is going to be very
hard to reason about, so unless there's a key use case, I'd leave the
complexity out of the language.

There might be use cases for single-level conditional fallthrough, but I'd
lean towards defining it as Go has: as a marker at the end of the case
block only. By far the most common use of it I've seen is like Mike's:

case x:
   additional pre-processing
   fallthrough
case y:
   shared processing
   break




> What do you envision the result of indicating fall-through to no subsequent
> case? Eg:
>
>  switch ($x) {
> case 1: fallthrough;
> }
>


I think it would be perfectly fine for this to do nothing. Currently you
can write both

switch ($x) {
case 1:
}

and

switch ($x) {
case 1: break;
}



In general, I really like this idea; I've always wished switch worked this
way.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] 'switch-expression' and the 'type guard' unary operator demo

2019-10-21 Thread Rowan Tommins
Hi Kosit,

On Sun, 20 Oct 2019 at 16:20, Kosit Supanyo  wrote:

> You can recognize the difference of those by looking for `=>` right? But
> the parser generator (bison) cannot do that in LR mode (it maybe can in GLR
> mode but I'm sure that would be unacceptable due to performance losses/more
> memory usage). So workarounds have to be used. I did it by simply return
> different tokens from the lexer base on previous token before `switch`.
>>
>>


Thanks for clarifying, I thought it might be something like that.




> * Different comparisons applied to the same variable/expression, e.g.
>> match($user->getScore()) { case <0 => foo(), case >100 => bar(), default
>> => baz() }
>
>
> I'd thought about that feature too. But since I also introduced type guard
> operator which uses `<` token it would have parser conflicts and simple
> workarounds cannot apply.
>



I'm not sure  is the right syntax for type guards, but it's possible
we'd want a different syntax for new switch/match functionality anyway. For
instance, using a placeholder for the value being tested, like $$ (a common
choice in other languages is _, but that's a valid and commonly used
function name):

match ( $user->getScore() ) {
$$ < 0, $$ > 100 => foo(),
$$ < 10 => bar(),
default => baz()
}

You could also allow the placeholder in the opening clause to define the
same operation for each case:

match ( $user->getScore() < $$ ) {
0, default => foo(),
10 => bar(),
100 => baz()
}


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] 'switch-expression' and the 'type guard' unary operator demo

2019-10-21 Thread Rowan Tommins
On Sun, 20 Oct 2019 at 22:35, Mike Schinkel  wrote:

> What restriction are you referring to?  The forced `default` or the
> semi-colon being required?
>
>

Neither; I was referring to not being able to put a switch expression as a
statement on its own, which Kosit has explained is a limitation of the
parser.



> I would much prefer to use a switch for multiple, mutually exclusive cases
> no matter what how complex the expression is because with a switch the
> cases expressions line up vertically. With `if` and `else if` it is harder
> to vertically eyeball the different mutually exclusive cases.
>


I've never particularly been bothered by it, but wouldn't adding four
spaces in your "if" statement make it line up with all your "elseif"
statements?



> The "return" case in particular seems ambiguous - if $v is visible outside
> the function, will it have a value assigned to it by the "return" branch,
> and if so what would that value be?
>
>
> It should have its prior value, since the expression did not complete.
>
> Alternately we could choose to always assign it null on return or break.
>
> But how often will we have this use-case?  Only for global variables,
> which hopefully will eventually become extinct in userland code.
>
>


Not just global variables, no; it could be assigning an object property
($this->foo = switch($x){ case 1 => return 1; }) for instance. It could
also be in the argument for a function call ( doSomething(switch($x){ case
1 => return 1; }) ) in which case presumably the function would not be
called at all? Overall, having a "return" in the middle of an expression
would be very confusing, I think.





> That said, we should almost be able to do *both*, and just let PHP throw
> an error if there is a problem. This would be useful if you know 100% that
> the code won't fail because of the code that came before it:
>
> if ( is_numeric($_GET['id'] ?? 0 ) ) {
> $id = intvar($_GET['id'] ?? 0);
>
>  $user = getUser($id):
>
> }
>
>

I'm not sure what the point of this example is. You've just cast to int, so
the assertion can never fail, and if getUser has a type hint, it's about to
make that assertion anyway.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] 'switch-expression' and the 'type guard' unary operator demo

2019-10-21 Thread Rowan Tommins
On Mon, 21 Oct 2019 at 15:13, Mike Schinkel  wrote:

> Ok, so let's look at a scenario. Will we be able to do this in the future,
> if we decide to allow multiple expressions to result in a final value?
> $y = switch ($x) {
>case 1  => $arr = get_array(), array_pop($arr),
>case -1 => $arr = get_array(), array_unshift($arr),
>default => null,
> };
>


Unlike some languages, not every statement in PHP is a valid expression
(e.g. you cannot write "$foo = echo $bar"), so regardless of whether we use
commas or semi-colons, the right-hand-side in those examples would have to
be some new construct, so we could choose whatever syntax we wanted for it.
We'd probably want something other than bare commas anyway, to make it more
widely usable, e.g. in array declarations.

If what you want is a full *statement* block on the right hand side, then
you'll need to use the current switch statement anyway.



> What if in the future PHP implements variadic syntax for assigning to
> arrays, e.g. $var = 1,2,3 where $var could satisfy a $variadic parameter
> set of parameters w/o requiring `...`?   If PHP embraces that — note GoLang
> has something similar — then will comma syntax allow for it with hacky use
> of parentheses?
> $y =  switch ($x) {
>case 1  => $var = 1,2,3, $var[1],
>case -1  => $var = 9,8,7, $var[1],
>default => null,
> };



I'm not really clear what feature you're suggesting here, but I'm pretty
sure it conflicts with existing uses of commas, so shouldn't constrain us
from using them elsewhere.

foo(1,2,3);
foo($var = 1,2,3);
$a = [0, $var = 1,2,3];
// etc

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Reclassifying some PHP functions warning as exceptions

2019-10-21 Thread Rowan Tommins
 Hi David,

Firstly, I agree with Nikita's general rule of which Warnings should be
promoted and which need deeper thought.

I would like to challenge one assertion in your e-mail, which is related to
that thought process:


On Mon, 21 Oct 2019 at 14:52, David Negrier 
wrote:

> We would be happy to promote more warnings to exceptions as those:
> - are more predictable
> - can be more easily caught / handled
>


I have always thought, and continue to think, that converting all Warnings
(and Notices) to Exceptions is inappropriate, because Exceptions have some
very specific behaviours, which are not always desirable:

- They immediately jump control out of the current frame of execution.
Unless you put a separate "try-catch" around every line, there is no
"acknowledge and run next line".
- Their default behaviour if not handled is to completely terminate
whatever is happening, right up to showing a blank white screen.

There is no general way to know whether the result of aborting execution
completely is better or worse than carrying on with unexpected values. In a
program that's not expecting it, either one could lead to data loss or
corruption.

There are definitely places where a Warning can reasonably be converted to
an Exception; but I don't think this should be done as some kind of bulk
change. Each Warning we promote should have at least one person answer the
question "is it likely that terminating processing when this happens at
run-time will be better than flagging a Warning and returning a defined
value?"

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Reclassifying some PHP functions warning as exceptions

2019-10-21 Thread Rowan Tommins

On 21/10/2019 18:45, Benjamin Morel wrote:
I personally like exceptions in all cases, as they allow for 
fine-grained error handling, for example:


```
try {
    mkdir('somedir');
} catch (FileExistsException $e) {
    // only catch *this* exception, which my program expects,
    // let any other exception (say a PermissionException or a generic 
IoException) bubble up!
    // this *is* what you want: it will be caught by your top-level 
exception handler which will log it to inform you that something is 
wrong with your system

}
```



I think this argument is something of a logical fallacy: just because 
exceptions are (or can be) more fine-grained than the current return 
value, that doesn't mean they're the best tool for the job.


If I'm remembering it correctly, an example is the old PEAR 
error-handling model, where rather than false, functions returned a 
PEAR_Error object. This could be just as fine-grained (using sub-classes 
or error code constants) as an exception, but without the additional 
behaviour of blowing through the stack.


In some cases, you can go one step further, and have a "result" object, 
with methods like isSuccessful(), getErrorCode(), and getOutput().


Importantly, this can and should be different for different functions.

In a previous message you wrote this, which I think mischaracterizes / 
misunderstands previous discussions:




To play the devil's advocate, however, IIRC some discussions in the past
mentioned that the BC breakage that comes with it is such an issue that it
would be preferable to create a brand new API rather than attempting to fix
the existing one.
Nobody ever jumped in to propose such an API, though :-(



It's not that we need "a brand new API", singular, it's that some of the 
more complex sets of functions should be redesigned, with error handling 
considered as part of each design.


So, a new file-handling API could provide a much richer set of error 
codes for its equivalent of fopen(), which might or might not involve 
exceptions. It might instead have a file handle object which could 
represent closed and errored handles, so that attempting to open a file 
would always give the same result type, but would have information about 
what failed.


Meanwhile, if we were to design a new string API to make things more 
consistent, and perhaps introduce better Unicode support where relevant, 
that would be a good chance to throw exceptions for truly exceptional 
cases. However, we might also include more forgiving variants of 
functions, for "best effort" processing of user input (like iconv's 
//TRANSLIT and //IGNORE modes).



On the other hand, there are some errors where the answer to the 
question "would it be better to halt processing than continue in an 
unknown state?" is "yes", so it's reasonable to introduce an exception, 
even though existing programs aren't expecting it. But again, this 
should be considered for every case, not as a general rule that all 
Warnings should be promoted.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Reclassifying some PHP functions warning as exceptions

2019-10-21 Thread Rowan Tommins

On 21/10/2019 21:38, Benjamin Morel wrote:
Sure, you can do without exceptions. I think what you're suggesting is 
similar to Go's error handling. But PHP at some point decided in 
favour of exceptions, so it would be logical to pursue in that direction.



I didn't say "do without exceptions", I said "use exceptions when 
they're the right tool, and other tools at other times".



I would classify most, if not all, filesystem-related functions as 
mostly "yes, do stop execution by default when something fails". So 
this is, as well, in favour of exceptions.



You've backed that up with exactly one example function, and immediately 
concede a case where you might want a non-exception flow. Here are a 
handful more examples off the top of my head:


* Attempt to atomically lock and open file, returning either a file 
handle or a "could not lock" status.
* Attempt to read from a file, terminate loop when the file handle 
reaches EOF.

* Attempt to delete file, ignore if it doesn't exist.

All of these are candidates for returning false, or an error code, or an 
object in a particular status. They could be handled with exceptions, 
but that would force common patterns to use exceptions for flow control, 
which is generally seen as a "bad smell".



Handling each and every error manually by using the return value 
requires a lot of discipline, which could be a very steep learning 
curve for PHP developers used to a fast prototyping language.



Again, I am not saying that every function should have a complex 
error-handling system. It may well be sensible to have a function for 
"open file, I don't expect anything to go wrong" which throws an 
exception, and a separate one for "try to open file, and report the 
result without ever triggering an exception". That's the point of 
designing a new API, to work out what the use cases are, and cater for 
them in a clean way.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] 'switch-expression' and the 'type guard' unary operator demo

2019-10-21 Thread Rowan Tommins

On 21/10/2019 21:18, Mike Schinkel wrote:


But to follow up to clarify what I was thinking consider the
following/ (hypothetical) /PHP syntax. Note that the return value
has two comma separated values, and the assignment can accept
those multiple values into two comma separated variables in the
assignment:


function read_file(string $filepath):string,PHP\Error {
$content = file_get_contents( $filepath ); $error = false ===
$content ? new PHP\Error( "failed to open '%s'", $filepath ) :
null; return $content, $error; }$content, $err= read_file(
__DIR__ . '/myfile.txt' ); if (!is_null( $err ) ) {
error_log($err->message); }



Ah, I see. Yes, multiple return values would be nice sometimes.

Note that you can get a lot closer to this in current versions of PHP 
than your example, because you can use the [...] syntax for both 
creating and destructuring arrays:


    function read_file(string $filepath):array {
   $content = file_get_contents( $filepath );
   $error = false === $content
  ? new PHP\Error( "failed to open '%s'", $filepath )
  : null;
   return [ $content, $error ];
    }

    [ $content, $err ] = read_file( __DIR__ . '/myfile.txt' );
    if (!is_null( $err ) ) {
   error_log($err->message);
    }



With the first example PHP could type check at load time vs.
having to wait for coverage of this code at runtime, and `:array`
type hint in the latter is not as good as the `:string, PHP\Error`
type hint of the former.



The ability to typehint multiple return values like that would be indeed 
be useful, but I'm not sure it would need to reserve that syntax. One 
way it could be achieved is using a "tuple" declaration, like in Hack: 
https://docs.hhvm.com/hack/built-in-types/tuples


In general, grouping things with commas and no parentheses is always 
going to *look* ambiguous IMO, even if you can limit where it's used to 
not be *technically* ambiguous.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Reclassifying some PHP functions warning as exceptions

2019-10-24 Thread Rowan Tommins
On Thu, 24 Oct 2019 at 16:38, Mike Schinkel  wrote:

> > Here, try() would swallow only FileException, other exceptions are still
> > thrown. I'm not sure if this construct is worth introducing though, the
> > difference compared to a proper try / catch is much smaller.
>
> I would want it to capture every exception. Why not?



Because you might want to convert "FileLockedByAnotherProcessException" to
a locally-handled error, but allow "ServerIsOnFireException" to bubble up
to a higher-level exception handler.  That's why catch blocks basically
force you to specify class/interface names: you should catch only the
exceptions you actually know how to handle in that particular piece of code.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-24 Thread Rowan Tommins
Hi Dmitry,

On Wed, 23 Oct 2019 at 16:43, Dmitry Stogov  wrote:

> Actually, I think PHP already took wrong direction implementing "typed
> references" and "type variance".
> Introducing more "typing", we suggest using it, but this "typing" comes
> with a huge cost of run-time checks.
> From 10% (scalar type hint of argument) to 3 times (typed reference
> assignment) performance degradation.
> Anyone may rerun my benchmarks
> https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9
>


I think this performance impact is a real concern; PHP is the only language
I know of which implements type checks entirely at run-time in production
code, and we should ask ourselves if that's definitely the right approach.

Would it be possible, at least in principle, to build a static analysis
tool which could prove that certain type checks would never fail, and prime
OpCache with code that leaves them out? As I understand it, this is how
Dart works: the compiler only emits run-time checks for assertions it can't
prove true by static analysis.

The simpler idea I had in this area was caching what type checks a value
had passed, either on each zval or perhaps just at the class level, so that
checking the same type again would be much faster, even if it was a complex
union with multiple interfaces.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] anti-coalescing-operator

2019-10-24 Thread Rowan Tommins

Hi Ken,

This is definitely an interesting idea, and when described as "the 
opposite of ??" the !?? syntax makes sense.


Looking at the example, though, the "negating" part becomes a bit confusing.

The verbose form reads naturally as a positive assertion - "if this is 
set, do this":

 if (isset($_SERVER['fname']) {
 $user->setName($_SERVER['fname']);
 }



If we used the ?? operator, it would be a negative, "if this is not set, 
do this":



 $_SERVER['fname'] ?? $user->unsetName();


So the short-hand form becomes a kind of double negative - "if this is 
not set, don't do this", or "if this is not not set, do this":



 $_SERVER['fname'] !?? $user->setName($_SERVER['fname']);



That makes me think that the choice of syntax isn't quite right, but I'm 
not sure what to suggest instead.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Optional pre-compiler for PHP8?

2019-10-29 Thread Rowan Tommins

On 29/10/2019 19:04, Mike Schinkel wrote:

Note that this was exactly what "P++" was intended to avoid - the two
dialects would exist in the same engine, and get the same performance and
security enhancements.


It could also be one engine, it just seemed like that coupling
would be more problematic than separating them.



I think the problem is that as soon as you have two engines targeting 
different feature sets, it will be hard to persuade people to spend 
equal attention on both. If all the new features end up being added to 
one engine, the other one is going to increasingly feel like "legacy 
mode", rather than "equal but different".





Both of these are reasons to have some sort of "strict mode", but not for
tying it to some other feature.


I don't understand your reply, but maybe it is moot considering
the rest of the dialog?

What we have today is a rock vs a hard-place, and no one wants to
give even a millimeter.

So, if this is not a viable solution in your mind to break the
logjam between BC and the desire for strictness-in-all-the-things,
do you have an alternate, better proposal?



The idea of an "extra strict" and/or "less backwards compatible" mode 
has been mentioned on the list several times, but you're the first to 
suggest making it mandatory when using an otherwise unrelated 
performance feature.


It would be much better to keep it separate, and opt into it via a 
declare() statement, or a package configuration, or a file extension. 
There have been proposals for a single flag, lots of separate flags, a 
complete "P++" dialect, or bundles of settings ("Editions").


Whatever the approach, a key goal in my mind should be to maximise the 
compatibility between the two, and share as much implementation as 
possible. Both/all modes should get the same performance improvements, 
except where the actual features are necessarily slower or faster.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Optional pre-compiler for PHP8?

2019-10-29 Thread Rowan Tommins

On 29/10/2019 21:56, Mike Schinkel wrote:



It would be much better to keep it separate, and opt into it via a 
declare() statement, or a package configuration, or a file extension. 
There have been proposals for a single flag, lots of separate flags, 
a complete "P++" dialect, or bundles of settings ("Editions").


Correct me if I am wrong, but all of those have been objected to,
strenuously, by at least several people on the list.



Indeed, but adding "the strict mode will be faster than the legacy mode" 
is likely to make those objections stronger, not resolve them, unless 
you can demonstrate _why_ the strict mode needs to be mandatory for the 
pre-compiled mode.




Both/all modes should get the same performance improvements, except 
where the actual features are necessarily slower or faster.


Fine. But a pre-compiler still could have merit.



Absolutely! In case you've forgotten, it was my remark that started this 
whole discussion: https://externals.io/message/106844#107656




One of the things I would like to see from a pre-compiler is
getting rid of the need to deal with an autoloader and hence we
able to store multiple related classes in the same file.



Yes, I think moving from auto-loading to eager loading would make sense 
for a lot of projects.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Reclassifying some PHP functions warning as exceptions

2019-10-22 Thread Rowan Tommins
On Tue, 22 Oct 2019 at 14:38, Benjamin Morel 
wrote:

>
> I used this one function as an example, but I'm happy to apply my point of
> view to other examples if you wish.
>


You have phrased this as though your point of view is different from mine,
but I think you've just misunderstood it. I said:

> All of these are candidates for returning false, or an error code, or an
object in a particular status.


That's precisely what your examples show: the functions returning false. So
we're in agreement, some errors should become exceptions, others should be
handled a different way, and some cases need new functions.




> This proposal would be as good under the form of a new API though, but in
> this case the naming should be changed to clearly differentiate both APIs.
>


Yes, new names is almost entirely the point of "a new API". The idea is
that you don't have to recalibrate people's expectations of what fopen()
does, breaking thousands of lines of existing code, nor compromise the
design to minimise that impact. Instead, you say "here's a new function, it
has these nice features, and handles errors in this really smooth way,
please use it" - and more importantly, "here's a consistent set of
functions which all work in this same way, please use them".


Finally, to reiterate what's been said several times, there are definitely
functions where the error cases are so "exceptional", that just throwing an
exception would be perfectly fine. It's the commonly used sets of functions
with a variety of different error conditions and use cases, like file
handling, where more careful redesign is prudent.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Adding explicit intent for SWITCH/CASE fall through?

2019-10-20 Thread Rowan Tommins

Hi Mike,

On 20/10/2019 01:39, Mike Schinkel wrote:

Not yet having experience working on PHP's parser I do not know how it is 
configured nor what about the design of PHP requires keywords unable to be used 
as constants, class names, function or method names. I know this is a tangent 
but that seems like a requirement designed to simplify the parser maybe, and 
not because of any logical requirement. So I assume whatever word was used for 
this would also have to be a reserved keyword?  Or not?



I don't know the full implications in the parser, but at the language 
level, any constant can technically appear where this keyword would. 
That is, the following is valid right now:


const fallthrough=null;
fallthrough;

It doesn't do anything, but it's valid because any expression on its own 
is a valid statement, and a constant on its own is a valid expression.



Interestingly, that actually makes a single keyword *more* appealing to 
me, because it means you can get *forwards* compatibility by writing this:


if ( PHP_VERSION < 8 && ! defined('fallthrough') ) {
    define('fallthrough', null);
}
switch ( $x ) {
    case 1:
    stuff();
    fallthrough;
    case 2:
    moreStuff();
 break;
}


For this common case where the new keyword is just a no-op, you then 
have code that supports and works identically across a range of versions:


* On versions without the keyword, the constant expression is a no-op 
(and may even be optimised out by OpCache?)
* On versions where the keyword is present but optional, the define is 
skipped, and the keyword is a no-op
* On versions (or external tooling) where omitting the keyword is a 
warning, or even an error, the keyword indicates intent



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Inline switch as alternative to nested inline conditional

2019-10-17 Thread Rowan Tommins
On Wed, 16 Oct 2019 at 18:10, Bob Weinand  wrote:

> what's the concrete advantage of this syntax as opposed to the already
> possible:
>
> $value = [
> A1 => A2,
> B1 => B2,
> ][expr()] ?? C;
>


What's the concrete advantage of switch over if-elseif? What's the concrete
advantage of if blocks over conditional jumps? The primary answer in all
three cases is surely "expressiveness".

If I came upon code like that, it would take me a while to understand its
intent - does $value end up as an array, or something else? what's the ??
there for, and when will expression C be used?

Now, it may be that the task in question isn't common enough to deserve its
own syntax, or you may not like the proposed syntax, but I think that's
very different from coming up with lots of clever ways of writing
something, and requiring new syntax to have a "concrete advantage" over
each one.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-19 Thread Rowan Tommins
On Tue, 19 Nov 2019 at 03:19, Mike Schinkel  wrote:

> Should we make decisions about future language enhancements based on
> conflicting and impossible to forecast predictions, or when a significant
> subset of PHP developers see value in a feature for their use-cases *and*
> others can simply ignore if they do not want to use it?
>



Neither. We should discuss the advantages of the feature, the potential
costs, and whether other features would be even better.



I challenge that assertion that having a huge number of magic or standard
> methods is the *"only"* way this provides benefit.
>
>


Not the only way it can bring *any* benefit, but the only way it can bring
the *particular* benefit of eliminating the need to agree method names
across code bases.

I think that's where this conversation has broken down a bit, which may be
my fault: I wasn't intending to argue against all the possibilities of the
feature, only the specific arguments you were raising. We disagree over
whether (array)$foo would be used more consistently than meaningful method
names, so maybe we should leave that there, and look at some other pros and
cons of the feature.




> Since conversion to array from object is a common need just this one
> method could provide a similar level of benefit that __toString() already
> provides.
>
>


What makes __toString() worthy of a special case in my mind is that there
are fairly common scenarios where variables are _implicitly_ cast to
string: in double-quoted strings, echo, etc. Having the language be able to
automatically call a particular method in those situations is therefore
more valuable. I think I'd actually be more receptive to a proposal to
allow _all_ casts to be overloaded, rather than adding array as a second
special case, because *implicitly* casting to array doesn't seem like it
would be any more common than other types.




> Yes, if your class is named Transaction then isSuccessful() probably *is*
> a better name than __toBool().
>
>
> But if your class name itself is isSuccessful()?
>
>


Yes, I would see that as a better example. I think operator overloading in
general makes sense when the object itself can be thought of as a
special-case of the primitive it's emulating operators for. So in this
case, the IsSuccessful class would be "a special kind of boolean"; and the
hypothetical List or Collection classes I mentioned a couple of days ago
would be "a special kind of array". We even have that in PHP for built-in
types: GMP objects can now be used with mathematical operators like $foo *
$bar, and those operations do what you'd expect them to do on an integer or
float.

Operator overloading can also be used just as a cute way of spelling
something - probably most famously, C++ uses the << and >> operators for
writing to and reading from streams, even though they're actually overloads
of the bit-shift operator. This kind of use is, I would say, more
controversial - going back to consistency, it's easier to reason about code
if $foo * $bar always does some kind of multiplication than if it's been
overloaded to mean "$foo is the star of $bar".

Overloading of cast operators is no different - the clearest use cases for
__toString() are where the whole class basically represents a piece of
text, and the more controversial are where (string)$foo is actually a cute
spelling of one method on a complex class.

That's not necessarily a reason to not add a feature - any feature can be
abused - but it potentially makes it harder for users to understand each
other's code, and that's a cost we should at least consider.





> Let me count the ways.  Here are several examples:
>
> https://gist.github.com/mikeschinkel/361bbcf44da1dac0da6afd786b6b8c3a
>
>
> A great example of this is the AllowedHtml class I wrote for the above
> gist whose sole purpose is to streamline the specification of allowed HTML
> using to KSES library.
>
>


This is an interesting example. On the one hand, there is only one array
ever going to be produced by that class; but on the other hand, the
ultimate use of it is explicitly passing to a function that expects a
different type. Assuming the same behaviour as __toString, the code shown
would give an error under strict_types=1, and need changing to
wp_kses((array)$allowed_html)

A different interpretation would be that this is the Builder Pattern, and
the target type happens to be an array rather than an object. So you might
decide that the consistency you really needed is that all builders should
have a build() method, and the last line of the example would become:

$clean_html = wp_kses($_POST[ 'content' ] ?? null,
$allowed_html_builder->build());

That doesn't mean the version you wrote is *wrong*, but should make us
consider why one version deserves special treatment by the language and the
other one doesn't.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Concept: "arrayable" pseudo type and \Arrayable interface

2019-11-19 Thread Rowan Tommins
make us
> > consider why one version deserves special treatment by the language and
> the
> > other one doesn't.
>
> What other version, and what special treatment is needed?
>



The version using "$foo->build()" rather than "(array)$foo", and the
special treatment of "(array)$foo" actually calling "$foo->__toArray()".





> I think I am sensing a pattern in your objections:  For you, providing
> benefits in one area is to be avoided unless all areas can receive similar
> benefits?




Almost. It's more that I'm against adding a large number of small features
that each make one use case slightly easier, but don't generalise very well.




>   ... even if the areas proposed to be improved represent the ~80
> percentile of use-cases?
>



Quite the opposite! I'm sceptical of this feature precisely because I think
the use cases for it are rather narrow.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Opt-in "use function *;" for skipping check for function/const in alternate namespace

2019-11-30 Thread Rowan Tommins
On 29 November 2019 19:48:37 GMT+00:00, Claude Pache  
wrote:
>I don’t think it should be a declare() directive, because:
>
>* It changes incompatibly the meaning of valid (non-error-throwing)
>code. The current existing declare() directive,
>declare(strict_types=*), has the nice property that code that does not
>throw error in *both* modes does not change behaviour.
>
>* When you want to know the FQN of a random identifier, it is necessary
>and sufficient to look at the “namespace” and the “use” declarations.
>With `use function *`, that won’t change. With
>`declare(lookup_functions_somewhere)`, you have now to look at an
>additional place.


Hi Claude,

I understand both of these points, but both are subtly inaccurate.

1) strict_types is not the first or only declare directive. Declaring an 
encoding fundamentally changes the meaning of a source file; probably it would 
be invalid in a different encoding, but errors are not the primary purpose of 
the directive. Declaring a value of "ticks" actually changes the *runtime* 
behaviour of the code. The manual defines declare vaguely as "used to set 
execution directives", so it's not particularly clear to me that changing 
namespace resolution would be outside of its purpose.

2) The existing fallback to global scope means that looking at the use 
statements of a file is not sufficient to resolve the ambiguity of an 
unprefixed function name. Indeed, the same line of code can execute two 
different functions within a running program if the namespaced function is 
defined at the right time.

I'm generally not convinced that beginning the special directive with the word 
"use" automatically makes it easier to find or understand. Given some code 
mentioning "strpos", you wouldn't be able to scan the list of use statements 
for the word "strpos", you'd have to understand that there are two modes of 
execution, and look for a line that switches between those modes.

I would expect that if it was worded as a use statement, coding standards would 
place it at the top of that list, so we're talking about the difference between:

declare(strict_types=1);
namespace Foo;
use global functions;
...

and

declare(strict_types=1);
declare(global_functions=1);
namespace Foo;
...


Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: Opt-in "use function *;" for skipping check for function/const in alternate namespace

2019-11-28 Thread Rowan Tommins

On 28/11/2019 18:52, tyson andre wrote:

An opt-in mechanism is certainly easier to migrate to, but it would be a
shame if every PHP file in 10 years time included a line like this:

use function *; // don't know what this does,
but apparently it's good for performance ¯\_(ツ)_/¯

I'm not sure what assumptions you're making about php in 10 years
(e.g. do you assume the other RFC will pass and this would become a no-op)



My assumptions weren't particularly about the future of PHP, but about 
people's usage patterns. If nobody uses namespaced functions, then 
everyone will just turn on this option all the time, without ever 
needing to know what it does. The effect of adding it to 99% of PHP 
files would be nothing but a "magical" performance boost.




if someone were to fully qualify all function calls for a library for 
performance,
there'd be around 10 lines per file instead of 1


Only if they did it by adding use statements, rather than prefixing the 
function calls with backslashes. I'm confused why anyone would bother 
keeping a long list of use statements up to date, rather than just 
making "use leading backslashes on global functions" part of the 
project's coding style. I can see that adding a single statement to each 
file would be better than either, though.




My reasons for this syntax instead of that are:

- This syntax can go in one block of code, instead of separated by dozens of 
lines:

   

I think it's more than just a different choice of syntax, it's a 
different way of looking at the feature: rather than a special namespace 
import, it's an option for how the language behaves. My thinking is that 
if unprefixed functions *always* referred to the global namespace, we 
wouldn't say "the global namespace is imported by default", we'd just 
describe the behaviour.


Looked at from that perspective, it seems natural to say "in this file, 
I want the behaviour where unprefixed functions mean global by default"; 
and in future, maybe be able to say "in this entire module, I want that 
behaviour".



A more cosmetic consideration is that the more generic the syntax looks, 
the more people will want it to work for other use cases. I can imagine 
"use function * works but use Foo\* doesn't" ending up on websites like 
PHPSadness. A more specific statement, like a declare, or "use global 
functions", is more obviously a one-off.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Opt-in "use function *;" for skipping check for function/const in alternate namespace

2019-11-28 Thread Rowan Tommins
On Thu, 28 Nov 2019 at 00:02, tyson andre  wrote:

> - Due to the absence of function autoloading (not supported in php to
> performance overhead), functions outside the global scope are rare in
> practice.
>


If this is a valid justification, perhaps we should do the opposite of the
"deprecate fallback to global scope" RFC you mentioned, and make the "use
function *" behaviour the default in some future version. That would
provide us longer term benefits, such as being able to introduce function
autoloading.

An opt-in mechanism is certainly easier to migrate to, but it would be a
shame if every PHP file in 10 years time included a line like this:

use function *; // don't know what this does, but apparently it's good for
performance ¯\_(ツ)_/¯

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Opt-in "use function *;" for skipping check for function/const in alternate namespace

2019-11-28 Thread Rowan Tommins
On Thu, 28 Nov 2019 at 11:01, Claude Pache  wrote:
> I think it is better to keep the language as regular as possible, and
consider that every non-fully-qualified name is relative to the current
namespace, unless there is an explicit `use` declaration that says otherwise

That's already false, and will only be true if we deprecate and remove the
fallback to global scope.


> use function *; // don't know what this does, but apparently it's good for
> > performance ¯\_(ツ)_/¯
>
> Or: “don't know what this does, but apparently it silences deprecation
> notices...”
>


Silencing deprecation notices is always a temporary side-effect of fixing
code to work *at all* in some future release. Or rather, it should be - I
am 100% against any notion of "indefinitely deprecated and may never be
removed", that should always be some other type of notice.

If we were deprecating unqualified functions from being looked up in the
current namespace, we would not need to add this new directive, we could
raise deprecation notices whenever the current lookup logic succeeded in
finding a namespaced function. Silencing the deprecation notice would
require either fully qualifying the function name, or explicitly adding a
"use" statement.



The issue indeed is that the meaning is far from self-evident. Maybe one
> could use something that everyone and their mother could understand at
> first reading, such as:
>
> use function from global namespace;
>


That still doesn't really explain what's happening, because in code that
doesn't use any namespaced functions, the line has no user-visible effect
at all - functions are *always* used from the global namespace. What it
actually does is switch *off* a language feature, so perhaps it should be
something more like:

declare(lookup_functions_in_current_namespace=false);

That would also mean that it can be covered by any future way of setting
language directives, such as settings per "module", bundling into
"editions", etc.

Regards,
-- 
Rowan Tommins
[IMSoP]


[PHP-DEV] Changelog / upgrading notes for promoted warnings

2019-12-19 Thread Rowan Tommins

Hi all,

Earlier, I was writing an application-specific wrapper around the 
password_hash function, and was surprised that it could return false, 
rather than throwing an error.


I then found this commit to master making it throw errors for PHP 8.0: 
https://github.com/php/php-src/commit/37c11714


That's great! But ... it is a breaking change, and I can't see any note 
in UPGRADING. Is there a running list of the Warnings that have been 
promoted to Errors anywhere, and if not, should we create one before we 
forget?


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: Changelog / upgrading notes for promoted warnings

2019-12-20 Thread Rowan Tommins
On Fri, 20 Dec 2019 at 08:37, Christoph M. Becker  wrote:

> Maybe a sensible compromise would be to assemble a detailed list of
> these changes, and to hand it over to the doc team at some point, so
> that the manual pages could (hopefully) be updated in time just before
> PHP 8.0.0 will be released.  Then users could check the manual's
> changelog[1] regarding the details.
>


Yes, that sounds reasonable. In many cases, the individual function listing
should also have a note added at the same time; and at some future date,
some will be able to lose their "may return false" notes.


On Fri, 20 Dec 2019 at 00:34, G. P. B.  wrote:
> Moreover, I'm not sure it's helpful to have a massive list of functions
where some warnings have been promoted and others not. But this is only my
opinion

I think this makes it even *more* important to collect the list of changes.
In the case of password_hash, my understanding is that it will now never
return false; in other cases, it may still be necessary to check the return
value. The documentation should clearly state which is the case for each
function, so we need to keep track of which functions are fully-promoted
and which partially-promoted.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: memcache, without a d, as in Venezuela

2019-12-20 Thread Rowan Tommins

On 19/12/2019 12:51, Christoph M. Becker wrote:

On 20.11.2018 at 11:26, Rowan Collins wrote:


It seems to me that *neither* extension is properly maintained right now
(the with-a-d extension has recent releases, but all wrapping an abandoned
upstream library); so if the without-a-d extension has better
cross-platform support, it might make sense to keep *only* that one
(revived from https://github.com/websupport-sk/pecl-memcache) and encourage
anyone interested to contribute rather than splitting the effort.

FWIW, PECL/memcache has had a new release today. \o/



That's good news, thanks to everyone who's worked on it!

I notice that the situation with memcache-with-a-d hasn't changed in the 
18 months since I started this thread [1]: there continue to be fixes to 
the extension, mostly to work with newer PHP versions, but the upstream 
library remains abandoned (the README rather optimistically recommends 
"libmemcached 1.0.18 or higher", but there have been no releases for 
nearly six years).


I've CCed Aaron Stone, who tagged the last few releases, to say: thank 
you for your work keeping that extension working, but what do you think 
of officially deprecating it in favour of the revived without-a-d 
extension? The immediate benefit would be less confusion for users over 
which extension they should use, and hopefully an increase in 
collaboration on the chosen extension. My understanding is that the 
with-a-d extension is self-contained and cross-platform, so a better 
target for that combined effort.


The first step would probably be to create a userland wrapper which 
emulates the classes and functions from the without-a-d on top of the 
with-a-d extension, so people can migrate.


[1] https://externals.io/message/102375

Again, thank you all for your efforts!

Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Inconsistent class behavior and undocumented(?) BC change

2019-12-08 Thread Rowan Tommins

On 08/12/2019 05:03, Mike Schinkel wrote:

Hi Larry,


I am not clear on why __construct() is special in this case;

I believe that is the Liskok substitution principle at work, and that fact the 
principle does not apply to constructors.

For reference:

-https://softwareengineering.stackexchange.com/a/302477/9114
-https://www.sitepoint.com/constructors-and-the-myth-of-breaking-the-lsp/



I'm not sure either of those links do a good job explaining why 
constructors in particular are special.


My first thought was "you call them on the class not an instance", but 
that's also true of static methods, and yet this is an error:


class Ancestor {
    public static function constructMe(int $a, string $b) { }
}
class Child extends Ancestor {
    public static function constructMe(...$args) {
    return parent::constructMe(...$args);
    }
}

In PHP, it is actually possible to call a static method based on an 
instance, using the syntax "$foo::somethingStatic()", so it is 
theoretically logical to constrain a set of related classes to have 
compatible static methods. But you can also write "new $foo()" to invoke 
a constructor based on an instance, so that doesn't explain the 
difference either.


The best explanation I can think of is more pragmatic than theoretical: 
it's often useful to have related objects with unrelated constructors, 
so it's useful for the language not to restrict that. I'd be interested 
to hear if there's a more fundamental reason, though.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Rowan Tommins
On Thu, 13 Feb 2020 at 12:04, Manuel Canga  wrote:

>
>
> On Thu, 13 Feb 2020 at 08:58, Rowan Tommins 
> wrote:
>
>> On 12 February 2020 23:12:34 GMT+00:00, Manuel Canga <
>> manuelca...@gmail.com> wrote:
>> >El mié., 12 feb. 2020 23:01, Rowan Tommins 
>> >escribió:
>> >In your example, you has the same options:
>> >
>> >>
>> >1. Change import
>> >2. Add namespace:
>> >
>> >['Acme\Global\I18N',\translate::function]
>>
>>
>> There is no collision between 'Foo::translate()' and 'translate()', so
>> there is no reason to change the import. That's true of executing the
>> functions, so it should remain be true of resolving them to strings.
>>
>> There is collision with import which you added.
>


There is no collision. This is perfectly valid PHP code:

namespace Foo;
use \explode;

class Bomb { public static function explode() { return 'Bang! Bang!'; } }

$bangs = explode(' ', Bomb::explode());


There is no ambiguity here, explode(...) refers precisely to the global
function 'explode' which is unrelated to the class method 'Bomb::explode'.
The same applies if I import the function from somewhere other than the
global namespace:

namespace Foo;
use Acme\BetterArrayFunctions\explode;

class Bomb { public static function explode() { return 'Bang! Bang!'; } }

$bangs = explode(' ', Bomb::explode());

Again, there is no ambiguity, explode(...) refers precisely to the function
'Acme\BetterArrayFunctions\explode,  which is unrelated to the class method
'Bomb::explode.

"explode::function" should mean "if I run explode() here, what is the
fully-qualified name of the function that would run?" If there's no
ambiguity of which function would run, there's no ambiguity of what value
::function should return.





> * Here, 'my_function' is only a string. Maybe a global function( without
> namespace  ) or maybe a method or other case. With native array_map is a
> global function. However, you can have a function like this:
>
> function array_map( $method, $array) {
>   \Collection::$method( $array );
> }
>
> In both cases, you could do:
>
> array_map(\my_function::function, [] );
>



In the second case, it would be incorrect to use \my_function::function,
because you do not want the answer to the question "if I run \my_function()
here, what is the fully-qualified name of the function that would run?"

Annotating the argument that way wouldn't be useful for tools, either -
e.g. an IDE like PHPStorm would see ::function and offer "jump to
definition", but in this case it would jump to the definition of the global
function my_function, which is actually irrelevant.




>
>
>> Importantly, it might not work at all, if ::function gives an error if
>> the function doesn't exist.
>>
>>
> ::function only would retrieve string, like as ::class, exists or not. In
> fach, that code might not work at all due to class. What matter if Class
> does't exist ?. ::class doesn't produce error. Look:
> http://sandbox.onlinephpfunctions.com/code/0a8466a00974bc1ffc12b219569ced55753327bd
>



As pointed out elsewhere, an implementation of ::function would need to be
smarter than ::class, because unqualified function calls look first in the
current namespace, then fall back to global scope. For example:

namespace Foo;
function explode() {}

echo implode::function; // Should return 'implode', because that is what
implode() would run
echo explode::function; // Should return 'Foo\explode', because that is
what explode() would run


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC]

2020-02-13 Thread Rowan Tommins
On Thu, 13 Feb 2020 at 17:06, Mike Schinkel  wrote:

> 1. IF foo::function returns a name string THEN using
> Closure::fromCallable( foo::function ) can provide a closure.
>
> 2. IF foo::function returns a closure THEN how to we get the name string?
>


Right, I'm with you now. However, I think the answer people are suggesting
to "how do we get the name string?" is "why do we need to?"

Or as Chase Peeler more eloquently put it:

> Can anyone think of a use-case where you would want a string name of a
> function and a callable would not be acceptable, besides possibly
debugging
> code that said 'echo "I'm calling ".myfunction::function;'? Everything
that
> I can think of that accepts a function name, also accepts a callable
(e.g.
> array_map), but I could be forgetting something.


There's a Venn diagram, essentially, of:
a) use cases where a Closure would be useful, but a string wouldn't
b) use cases where a string would be useful, but a Closure wouldn't
c) use cases where either a string or a Closure would be useful

If (and it's a genuine open question) all the use cases fall into
categories (a) and (c), we can make the syntax for closures simpler by
skipping the "get name" step and making foo::fn return a closure straight
away.

So the question is, are there use cases that fall into category (b)?


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Explicit call-site pass-by-reference (again)

2020-02-23 Thread Rowan Tommins

On 23/02/2020 09:47, Nikita Popov wrote:
The prefer-ref/prefer-val thing is indeed a bit peculiar. It's an 
artifact of the current way of implicit by-reference passing, where 
the decision of whether to pass by-value or by-reference has to be 
made based on an "educated guess" at the call-site. That leaves us 
with always-val, always-ref, prefer-val and prefer-ref as the possible 
passing modes. In the explicit by-ref passing regime, the latter two 
consolidate, and we have by-val, by-ref and "either" as the options, 
which is a lot more obvious.



Thanks, that's a good summary of how this all relates to the RFC. If 
there is a use case for such a mode, perhaps we need a way to annotate 
userland functions as "either", so that they too can take advantage of 
the call-site annotation. In a sense, they'd be opting in to the pre-5.4 
behaviour, for that particular parameter.





Instead of having __call(), what we really should have is __get_method().



That is a really interesting idea. The lack of function signature is 
currently a big turn-off for using __call, because it means manually 
recreating a lot of the unpacking and type checking that the language 
would normally do for you.




I believe we talked about this in some detail in the previous 
discussion on this topic. My basic stance on in/out is that it's 
*probably* not worth the complexity, unless it is part of an effort to 
eliminate references from PHP entirely (which would be hugely 
beneficial). Unfortunately I don't really see a clear pathway towards 
that. "out" parameters can remove one use-case of references, and I 
can see how that would work both in terms of semantics and 
implementation. The case of "inout" parameters is much more 
problematic. While these can nominally work without references, I 
don't see how they could do so efficiently (we would have to "move 
out" the value from the original location to avoid COW). Similarly, I 
don't have any answer to how &__get() and () would work 
without references.



That's fair enough. I guess the reason I've fixated on them is that I'd 
really like "out" parameters, independent of what else happens with 
references, in order to get the clear signal of "variable is initialised 
here" on a call like "preg_match($foo, $bar, out $matches)". That would 
make out parameters more attractive to build APIs around, e.g. when you 
want multiple strongly typed outputs from one call.


Even if we can't eliminate references entirely, perhaps there's value in 
reducing the use cases where they're necessary? A bit like how property 
accessor syntax wouldn't allow us to remove __get and __set, but would 
mean fewer cases where people needed to deal with them.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Explicit call-site pass-by-reference (again)

2020-02-23 Thread Rowan Tommins

Hi Mike,

First, I'd just like to reiterate that I absolutely see benefits in this 
proposal, and am definitely not campaigning for it to be abandoned as a 
bad idea. Like with any proposal, we have to weigh those benefits 
against the costs, and my current personal opinion is that the scales 
come down *very slightly* on the cost side.


I will also just say that you have made some valid points about 
different ways people might perceive this change, and my fears on that 
score may be overblown.



On 23/02/2020 07:03, Mike Schinkel wrote:


The RFC does not require mandatory use, period.

The "cost" you worry about will not exist unless and until a future RFC 
proposes to make it mandatory and that RFC is accepted.


The RFC states very clearly that the full benefit of the change will 
only be realised by making the markers mandatory in some way, and 
includes specific discussion of how that might be introduced. Put 
simply, tools (and even humans) get most from knowing that a particular 
line of code *won't* pass anything by reference, and optional markers 
can't guarantee that.


I am analysing the proposal on that basis, just as I would analyse a 
proposed deprecation on the basis that the deprecated feature will one 
day be removed.


If we analyse it on the basis of it *never* becoming mandatory, we have 
to adjust our analysis of both costs *and* benefits.



Regarding prefer-ref and prefer-val:


function call_with_current_user(Callable $callable, int &$foo, int $bar ) {
return call_user_func( $callable, current_user(), &$foo, $bar );
}



If you define the function this way, all callers are *required* to pass 
the parameter by reference. That immediately means that this is a fatal 
error:


call_with_current_user('foobar', 42, 42);

Internal functions have the magical ability to accept both literals 
values and reference variables, whereas userland functions have to 
choose one or the other.




As an example of the second, even under strict settings, calls to certain internal 
functions will have an optional & at the call site, which changes their 
behaviour.

To those without knowledge of the core, those functions simply have to be remembered as 
"magic", because their behaviour can't be modelled as part of the normal 
language.

I am unclear how the optional ampersand at the call site will change the 
behavior.



I was referring to this line in the RFC:

If the argument is a prefer-ref argument of an internal function, then 
adding the |&| annotation will pass it by reference, while not adding 
it will pass it by value. Outside this mode, the passing behavior 
would instead be determined by the VM kind of the argument operand. 



That means that for any function implemented internally as "prefer-ref", 
the user can now *choose* whether their variable will be overwritten by 
the function. I don't know exactly which functions this would affect, 
because as far as I know, the manual doesn't have a standard way to 
annotate "prefer-ref". Which is kind of my point: it's magic behaviour 
which sits outside most people's understanding of the language.



I don't particularly see a problem with requiring a third change in 
the future. Hindsight is a wonderful clarifier. And I believe 
elsewhere you have been debating me over the need for incremental 
change. Caveat emptor. 



The distinction I would make is between incremental change, and 
contradictory change. If we later introduce out parameters in a way 
that's compatible with call-site &, that would indeed be incremental 
change; the effort spent adding & would move code closer to the final 
state. If we end up introducing call-site "out", the effort spent adding 
& will simply be compounded with the effort spent adding "out".


Predicting the future is a mug's game, but it's at least worth exploring 
some possible futures, and how decisions now might help or hinder them.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-24 Thread Rowan Tommins

Hi Paul,

I left this thread to settle a bit, because I felt we were going round 
in circles a bit. I think there's some fundamental differences in 
outlook that no amount of discussion is going to resolve, so I've 
trimmed this reply to the more specific points.




On 20/02/2020 14:56, Paul M. Jones wrote:
Aha! If nothing else, then, this conversation has revealed a 
documentation flaw: specifically, my failure to document the 
ServerRequest $url property. That failure is now remedied: 
<https://github.com/pmjones/ext-request#the-url-array> 



Aha indeed! When I was talking about "selling it to me", this is exactly 
the kind of thing I was looking for. This kind of functionality is much 
more interesting to me than copying half a dozen arrays from constructor 
parameters into read-only properties.




Which is the purpose of the documentation; it describes the differences between 
$files and $uploads.



That's no reason not to *try* for descriptive names, though. I presume 
the idea is that one array is expected to be more useful for new code, 
and the other is mostly there for compatibility with old code? If so, 
perhaps the names could reflect that somehow.


Incidentally, the current documentation doesn't describe the differences 
particularly well, just saying one is "more like $_POST". Some details 
of the structure, or examples comparing the two arrays, would be useful.





I was actually thinking of the opposite: given a request body which didn't come 
from global state, but which contains data in multipart/form-data format, 
extract the key-value pairs and attached files.

Is that something PHP "itself" already does? If not, I have to consider it 
out-of-scope for this RFC.



a) Yes: Every time you submit a form as multipart/form-data, PHP parses 
it into the global state. If this object is aiming to abstract away from 
global state, then having a non-global-state parser for that seems 
consistent.


b) No: There is no function which currently takes a string and returns 
an array for this scenario. However, that's true of other features you 
have included, such as parsing accept headers, or even extracting just 
HTTP headers from a copy of the $_SERVER array.





Your point on global state is well-taken; I will try to remember in future to phrase it 
as "global *mutable* state." (AFAICT, php://input is not mutable, though as you 
correctly point out, it is global.)



This distinction seems unnecessary. Once created, the object avoids 
global state because it is self-contained, and the fact that it's 
read-only is a separate attribute. We're really just talking about ways 
to construct that self-contained state, and "everything from global 
state" or "nothing from global state" seem like more natural options 
than "one thing from global state, everything else not".



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Support rewinding of generators

2020-02-26 Thread Rowan Tommins
Hi Nikita,

On 26 February 2020 11:47:14 GMT+00:00, Nikita Popov
 wrote:
>There is a relatively simple (at least conceptually) way to make generators
>rewindable: Remember the original arguments of the function, and basically
>"re-invoke" it on rewind().

This is an interesting idea.

There is a gotcha though, neatly demonstrated by your example:

>function map(callable $function, iterable $iterable): \Iterator {
>foreach ($iterable as $key => $value) {
>yield $key => $function($value);
>}
>}

If the $iterable passed in is anything other than an array,
re-invoking the function won't actually rewind it. That can be fixed
by explicitly rewinding at the start:

function map(callable $function, iterable $iterable): \Iterator {
reset($iterable);
foreach ($iterable as $key => $value) {
yield $key => $function($value);
}
}

But now we have a different problem: if we pass an iterator that
doesn't support rewinding, we'll get an error immediately.


In other cases, the side-effects of running the "constructor" itself
might be undesirable. For instance, it might re-run an SQL query,
rather than rewinding a cursor:

public function getResultsIterator($sql) {
 $cursor = $this->runQuery($sql);
 foreach ( $cursor->getNext() as $row ) {
 yield $this->formatRow($row);
 }
}

I think the fix would be to return a generator rather than yielding
directly, like this:

public function getResultsIterator($sql) {
 $generator = function($cursor) {
 $cursor->rewind();
 foreach ( $cursor->getNext() as $row ) {
 yield $this->formatRow($row);
}
 };
 $cursor = $this->runQuery($sql);
 return $generator($cursor);
}


In general, it feels like it would be useful for generators that knew
it was going to happen, but a foot-gun for generators that weren't
expecting it, so I like Judah's suggestion of an opt-in mechanism of
some sort.


Regards,
--
Rowan Tommins
[IMSoP]

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-26 Thread Rowan Tommins
On Wed, 26 Feb 2020 at 16:42, Paul M. Jones  wrote:

> Your presumption is correct! And your point on trying for better names is
> well-taken -- though I think these are "expected" names, based on my
> research into existing implementations. The most-common names are ...
>
> - the word "files" for unparsed or unmodified $_FILES values, leading me
> to think $files is well-understood
>
> - the words "upload(s)", "fileUpload(s)", or "uploadedFile(s)" for parsed,
> transformed, or restructured $_FILES values, leading me to think $uploads
> is well-understood
>


That's a reasonable justification. Just to check, are there other
implementations that have both of these names side by side, or do most
implementations have one or the other, but using this naming?

The main confusion I can see is having to remember which two of these is an
error without having to read the docs each time:

isset( $request->files['attachment']['name'][0] );
isset( $request->files['attachment'][0]['name'] );
isset( $request->uploads['attachment']['name'][0] );
isset( $request->uploads['attachment'][0]['name'] );




> Having said that, I am open to suggestion here. What names do you think
> would be better than the ones presented, contra pre-existing work from
> other authors?
>


Looking at the examples, the difference is rather similar to the
PREG_PATTERN_ORDER and PREG_SET_ORDER options to preg_match_all.

If getUploads was a method, it could take a similar behaviour switch -
GROUP_BY_ITEM vs GROUP_BY_ATTRIBUTE or similar. For a property, that would
have to be part of the name, like $uploadsByItem and $uploadsByAttribute,
which are a bit ugly.

Alternatively, you could lean more heavily on the legacy aspect, and have
$uploads and $uploadsLegacyFormat or something like that.



> Incidentally, the current documentation doesn't describe the differences
> particularly well, just saying one is "more like $_POST". Some details of
> the structure, or examples comparing the two arrays, would be useful.
>
> Good call! On your suggestion, I have added details at <
> https://github.com/pmjones/ext-request#the-uploads-array>.  Suggestions
> for improvement are welcome.
>


Thanks, that makes it a lot clearer. :)




> - "There is no function which currently takes a string and returns an
> array for this scenario." -- True, though (and not to undermine my own
> case) there is json_decode(), which can return an array. But then the
> trouble is how to decide when to apply it, and with what parameters, and
> how to trap & report errors, etc., all of which adds complexity to what I
> think ought to be a simple object. And then once special treatment is given
> to JSON, what about XML? Etc., etc. Given all that, it strikes me that the
> cases not already served by PHP for parsing the body content into $_POST
> are best left to consumers of ServerRequest.
>


Again, any mention of JSON or XML is drifting away from what I'm asking
for. What I'm asking for (or rather, suggesting would be a useful and
consistent addition) is a way to do *exactly what PHP does right now*, but
based on a given input string, rather than the initial request. I am
totally happy with users needing to add any support for JSON, XML, etc,
just like they would have to populate $_POST manually.




> I agree that the default $content value is an exception to everything else
> in ServerRequest. While it stays read-only, it does get read from
> php://input each time you refer to it.
>
> The alternative is to read from php://input once at construction time
> (when the construct $content argument is null) and retain that value in
> $content from the start. But in that case, when you have very large content
> bodies (as when there are PUT file uploads or other large payloads), then
> ServerRequest takes up a lot of memory, when it might not ever be used
> directly. Yes, "it might never be used" could be true of every element on
> ServerRequest, but the maximum memory use for those other elements tends to
> be rather smaller.
>


That's a reasonable justification. I guess that's why PSR-7 exposes it as a
stream, even though that causes a whole load of pain.

To play devil's advocate, does the property belong in the object at all? If
it doesn't interact with any of the other properties (e.g. populating $post
and $uploads based on form data), could "better syntax for getting raw
request for global state" be a separate feature. Then again, maybe the
ability to over-ride it in the constructor is enough to make it useful.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-26 Thread Rowan Tommins

On 26/02/2020 19:57, Paul M. Jones wrote:

I'm sorry, I'm still having trouble seeing what you're getting at. Do you mean 
something like this in the ServerRequest constructor?

 public function __construct(array $globals, ?string $content = null)
 {
 if (
 ($globals['_POST'] ?? null) === null
 &&
 strtolower($globals['_SERVER']['CONTENT_TYPE']) === 
'application/x-www-form-urlencoded'
 ) {
 if ($content === null) {
 $content = file_get_contents('php://input');
 }
 $globals['_POST'] = [];
 parse_str($content, $globals['_POST']);
 }

 // ...
 }



That's the easy part, yes; the harder part is this:


if (
($globals['_POST'] ?? null) === null
&&
strtolower($globals['_SERVER']['CONTENT_TYPE']) === 
'multipart/form-data'
) {
if ($content === null) {
$content = file_get_contents('php://input');
}
[ $globals['_POST'], $globals['_FILE'] ] = 
parse_multipart_form_data($content);
}


Where parse_multipart_form_data is a function which doesn't currently 
exist, but whose logic must all be there in the core somewhere, because 
everything shows up in $_POST and $_FILES when you process such a request.


Recreating that functionality in userland is non-trivial, but is 
essential for several use cases, e.g. an event-based server like 
ReactPHP, or a test using a saved request body as a fixture.


If both content types (application/x-www-form-urlencoded and 
multipart/form-data) were handled, it would also mean that the 
relationship $content -> $input would match the relationship php://input 
-> $_POST by default, which seems consistent with the aim of matching 
existing behaviour.



Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [RFC] Increment/Decrement Fixes

2020-03-01 Thread Rowan Tommins

Hi all,

Following my thread a couple of weeks ago, I would like to put forward 
an RFC to fix some inconsistencies with the behaviour of the ++ and -- 
operators:


https://wiki.php.net/rfc/increment_decrement_fixes

Note that this RFC focusses on three specific cases which I think could 
be considered bugs, but require breaking compatibility:


1) Bring the behaviour of decrementing null in line with subtracting 1 
(and with the equivalent increment operator)
2) Bring the behaviour of incrementing or decrementing true and false in 
line with adding or subtracting 1
3) Throw the same error when incrementing or decrementing an array as 
when adding or subtracting 1


I believe the behaviour of strings, objects, and resources, each raise 
sufficient extra questions that they should be left to future RFCs where 
we can focus on each in more detail.


Please read the RFC for more detail on what is and isn't proposed.

Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-03-04 Thread Rowan Tommins

On 04/03/2020 20:01, Paul M. Jones wrote:

This RFC, in contrast, does not attempt to model HTTP messages. It does not 
attempt to discard previous ways of working. Instead, it proposes a more 
object-oriented representation of functionality that already exists in PHP, 
honoring that previously-existing approach. There is quite a bit of real-world 
experience as to how well it will work, since it takes into account many 
commonalities between existing userland projects. Thus, what the RFC purports 
to get close to is that existing way-of-working, and I think it succeeds about 
as well as can be possible for its goals.



This is something you have said a few times, and is definitely a worthy 
goal, but it's not something that comes across very strongly in the RFC 
itself. There is a comparison to Symfony HttpFoundation, but it mentions 
as many differences as similarities; and there is a list of 13 other 
implementations, but no information on how this proposal compares to them.


I suspect that's just because you didn't want to burden the RFC with too 
many details, but if you have any notes about what functionality is 
common in existing libraries, perhaps that could be posted somewhere as 
a kind of appendix to show where the current design came from?


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Increment/Decrement Fixes

2020-03-02 Thread Rowan Tommins
Hi Alexandru,


On 2 March 2020 09:22:57 GMT+00:00, "Alexandru Pătrănescu"
 wrote:
>For point 1 and 2, both the old and new behavior is silent. Can we
>think of
>a safer way to migrate?

That's a very good question, and one I don't have a particularly good answer to.

The problem with this kind of behaviour change is that there's no way
for PHP to know whether a particular piece of code has been changed to
expect the new behaviour or not, and therefore whether to raise a
deprecation notice. An opt-in notice on *all* usages could allow the
user to build up a list of places in their code to check, but they'd
still need to manually track which they'd already looked at, so I'm
not sure how useful it would be.

What I will look into is how well static analysis tools such as
PHPStan and Psalm could build a similar list, as I think that's
generally a more useful approach.

Regards,
-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Increment/Decrement Fixes

2020-03-02 Thread Rowan Tommins
Hi Marco,

On Mon, 2 Mar 2020 at 14:00, Marco Pivetta  wrote:

>
> Overall against the RFC: `++` and `--` (prefix and suffix) are supposed to
> be used with numeric values, not with other types, as that makes everything
> only more confusing.
>


While I'm generally sympathetic to that principle, it could also be said of
the + and - operators, which currently silently handle both nulls and
booleans. I would be open to changing *all* arithmetic behaviour,
particularly on booleans, but don't think a vague ambition for that
justifies inconsistent behaviour between different arithmetic operators.




> Code written (intentionally) to use `++` and `--` against non-numeric
> values should **NOT** pass a code review, and I am sorry for those that
> have to maintain it if that happens.
>


I think you're taking simplified examples too literally here, and assuming
that all affected code would be obvious at a glance.

Take for instance this innocent-looking patch:

  function foo($bar) {
- $bar -= 1;
+$bar--;
  // more code here
  }

With the current behaviour, any inadvertent calls to the function passing
null, true, false, or an array will change behaviour when this patch is
merged. In particular, the variable $bar would previously have been
guaranteed to be an integer, and will now retain the original type passed
in.

I completely agree that such code has a bug, but the difference in
behaviour is still a massive WTF.


The asymmetry of ++ and -- is even more confusing. Consider this patch:

  function repeatThing($extraTimes) {
-  for ( $i = 0; $i <= $extraTimes ; $i ++ ) {
+ for ( $i =  $extraTimes ; $i >= 0; $i -- ) {
   doThing();
   }
  }

Again, this looks like a safe change - but if passed a value of NULL, the
old code will call doThing() once, and the new code will enter an infinite
loop.

This asymmetry is the primary problem I want to address with this RFC.




> Changing the current behavior, regardless in which way, is a BC break:
> might as well make the BC break useful:
>
> RFC Proposal: `$a = null; $a--; $a === -1`. Let's make this an explicit
> TypeError instead.
> RFC Proposal: `$a = null; --$a; $a === -1`. Let's make this an explicit
> TypeError instead.
>


And what about  `$a = null; $a++;` /  `$a = null; ++$a;`, which currently
has behaviour consistent with other arithmetic operations (in particular,
is identical to $a+=1) and this RFC does not propose to change?

If we change the ++ case to throw a TypeError, would we also change null+1
to throw one? And would we then also examine all the other operators and
utility functions which silently coerce null to zero or an empty string?

I'd rather not go down that rabbit hole to fix something which is seemingly
just a bug in the implementation. If an RFC passes that makes all
arithmetic on NULL an error in PHP 8.0 (i.e. with no deprecation period),
my RFC will be redundant; but that seems unlikely.

I am less precious about the changes to boolean, which is why I propose
three separate votes. I would be open to an alternative RFC removing all
implicit casts on boolean, object, and resource; but unless and until
undefined variable behaviour changes, null is necessarily a special case.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] Increment/Decrement Fixes

2020-03-02 Thread Rowan Tommins
On Mon, 2 Mar 2020 at 14:46, Marco Pivetta  wrote:

>
> The code above is NOT going to pass a code review.
>



It may not pass a code review *from you*, but I don't think your high
standards are a good benchmark for the way PHP is used throughout the world.

Let's put it this way: if my RFC passes, and the following day an RFC makes
it redundant by changing integer coercion in general, I will be happy. If
an alternative is proposed which makes -- an error on arguments where both
-1 and ++ are silently accepted, I will voice my dissent (I don't have a
formal vote).

If you feel that the BC break is too great, even in the null decrement
case, feel free to vote No, and keep the current WTF in the language.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Userspace operator overloading

2020-03-02 Thread Rowan Tommins
On Mon, 2 Mar 2020 at 14:30, Nikita Popov  wrote:

>
> I think others have already expanded on why it's not possible to group
> operators in a meaningful way. The DateTime example is probably the most
> pertinent there, in that DateTime + DateTime is illegal, while DateTime -
> DateTime is legal. If we can't even require both + and - as part of one
> interface, there is very little we can require.
>


In my opinion, not being able to overload both + and - is a sign that the
class is "abusing" operator overloading, in that it is using it to build a
domain-specific language, rather than truly overloading *operations*.

An overload of "DateTime - DateTime" wouldn't represent "subtraction" for
precisely the reason that "DateTime + DateTime" doesn't make sense -
DateTime doesn't follow arithmetical logic. Instead, it would represent a
domain-specific definition of "difference". A more "correct" operator
overloading would be DateTime +  DateInterval, and its inverse DateTime -
DateInterval.

The common consensus seems to be that we don't want domain-specific
overloading (the example of << and >> in C++ has been mentioned several
times). If that's the case, then an interface that prevents you
implementing DateTime - DateTime seems perfectly legitimate.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Userspace operator overloading

2020-03-03 Thread Rowan Tommins
On Tue, 3 Mar 2020 at 14:45, Terje Slettebø <
terje.slett...@sandefjordbredband.net> wrote:

>
> I agree that this makes sense. However, as someone else pointed out, one
> problem with interfaces is that they constrain the types that may be used.
>


An interface doesn't have to define types, and in this case it wouldn't
make sense for it to do so.

Without generics, the only option would be to constrain everything to
"static", but as you say, that rules out a lot of use cases.

So the interfaces would simply require that the functions exist, and not
say anything about their types. This is already the case with other
built-in interfaces; for instance, Iterator places no constraint on the
return of the current() and key() functions:

# https://3v4l.org/U0gKD
class Foo implements Iterator
{
public function current(): Foo { return $this; }
public function key(): Foo { return $this; }
public function next(): void {}
public function rewind(): void {}
public function valid(): bool { return true; }
}

Similarly, the interface can't guarantee that the implementation does
anything useful, or even runs without error. All it does is force the user
to at least consider

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-27 Thread Rowan Tommins
On Thu, 27 Feb 2020 at 02:43, Paul M. Jones  wrote:

> > Recreating that functionality in userland is non-trivial, but is
> essential for several use cases, e.g. an event-based server like ReactPHP,
> or a test using a saved request body as a fixture.
> >
> > If both content types (application/x-www-form-urlencoded and
> multipart/form-data) were handled, it would also mean that the relationship
> $content -> $input would match the relationship php://input -> $_POST by
> default, which seems consistent with the aim of matching existing behaviour.
>
> Yes, it would indeed.  However, it strikes me that the thing to do here is
> not to try and embed that behavior in ServerRequest; rather, it would be to
> expose the existing functionality on its own, so that ReactPHP (and many
> others!) can use them, instead of having to roll their own in userland (a
> la <
> https://github.com/reactphp/http/blob/master/src/Io/MultipartParser.php>).
>




Why not hope that ReactPHP and others will want to use this object,
precisely because it avoids them having to roll their own implementations
of things?

If your concern is that the object should only wrap up features that are
also available via some other mechanism, I'll point again at the $accept
array, which AFAIK is a useful piece of parsing which is not available
outside the proposed object's constructor. If anything, that's *more*
special to this object, because what I'm proposing would directly parallel
the existing behaviour of $_POST and $_FILES.

If somebody really wanted to use the parser without the rest of the object,
they could trivially wrap it in a function:

function parse_multipart_form_data($content) {
$request = new ServerRequest([], $content);
return [ 'input' => $request->input, 'uploads' => $request->uploads ];
}

The only downside I can see to adding it is complexity of implementation.
But that's at best a reason to say "we'll hope to add this later" rather
than "it would be better not to add it".

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-27 Thread Rowan Tommins
On Thu, 27 Feb 2020 at 15:55, Paul M. Jones  wrote:

> > Why not hope that ReactPHP and others will want to use this object,
> > precisely because it avoids them having to roll their own implementations
> > of things?
>
> Like I said earlier: if React ends up wanting to use ext/request, with its
> tradeoffs, of course I would think that's great. But if they want to keep
> using what they have already, with its own tradeoffs, that's great too.
>



This is one place our attitudes differ: if I was proposing something like
this to be included in every copy of PHP, I'd actively want people to use
it, and consider that a measure of success; you seem to be happy to just
put it out there and see. As such, I perhaps place greater value on
functionality that would make it more attractive, and less value on
matching what we already have.




> This is very similar to what I'm saying: to use your phrasing, I opine it
> is better to "trivially wrap" the existing PHP functionality as part of a
> separate RFC, rather than try to embed it in ServerRequest (exposed or
> otherwise).
>



That's not really the same, no. I am saying that once you have the parsing
functionality somewhere in userland, whether it's inside ServerRequest or
its own function doesn't matter, you could still use it to delete 300+
lines of code from ReactPHP.

That's a reason to add it *as soon as possible*, even if in an ideal world
it would be implemented in a slightly different place, or two different
places, or whatever.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-27 Thread Rowan Tommins
On Thu, 27 Feb 2020 at 17:06, Paul M. Jones  wrote:

> Hi Rowan,
>
> > On Feb 27, 2020, at 10:57, Rowan Tommins 
> wrote:
> >
> > you seem to be happy to just put it out there and see
>
> Perhaps it was not your intent, but even so: please don't put words in my
> mouth. We spoke of this before; quoting myself from <
> https://externals.io/message/108436#108650> ...
>
> > I don't *expect* anything from existing published library authors;
> however ...
> >
> > • I *suspect* that some will choose to ignore this extension,
> >
> > • that others will decorate or extend it,
> >
> > • and that still others may find their own work so close to this
> extension that they migrate over to it entirely.
>
> I continue to hold that position.
>


Perhaps I am over-interpreting them, but the words you choose always seem
to me very passive, as though shrugging and saying "it might happen, or it
might not".

In the exchange quoted above, I can see why "expect" might have felt too
strong, but "suspect" is right at the other extreme; do you also "hope",
"desire", or "want" people to use it?

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] iconv vs. mbstring

2020-03-05 Thread Rowan Tommins
On Thu, 5 Mar 2020 at 11:59, Aleksander Machniak  wrote:

>
> Also, I have a case in which iconv_* functions were much much slower
> than mbstring. See wordwrap implementation in
>
> https://github.com/roundcube/roundcubemail/blob/master/program/lib/Roundcube/rcube_mime.php#L589
>
>

Either I misread, or you did: I thought that's exactly what Christoph was
saying, that iconv_* functions will be slower because they basically do
convert-process-unconvert rather than having implementations for each
encoding. So mb_strlen will always be faster than iconv_strlen.

iconv() vs mb_convert_encoding() doesn't have the same penalty. It seems
quite plausible that a library dedicated to converting charsets would be
more optimised for that job than a single function in a larger library
mainly focussed on working with one charset at a time.


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC] [DISCUSSION] Immutable/final/readonly properties

2020-02-24 Thread Rowan Tommins
On 24 February 2020 03:26:19 GMT+00:00, Marco Pivetta  
wrote:
>The solution is trivial: don't use cloning:
>
>final class Foo
>{
>public function withBar($bar):self {
>$instance = new self();
>$instance->foo = $foo;
>// more assignments here - unavoidable
>return $instance;
>}
>}


This works fine on paper, but is completely impractical as the class grows. 
Consider a class with 10 such properties, each with their own with* method: 
switching from clone to explicit assignments means adding 90 lines of code, all 
of it copy-and-pasted boilerplate that's hard to spot mistakes in.

It's also impossible to use with inheritance, or to compose with traits (as 
Diactoros does, for instance), because every with* method needs to know the 
full details of how to create a partial clone.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] [DISCUSSION] Immutable/final/readonly properties

2020-02-24 Thread Rowan Tommins
On Fri, 21 Feb 2020 at 23:18, Larry Garfield  wrote:

> The with*() method style requires cloning the object.  What happens to the
> locked status of a set property if the object is cloned?  Are they then
> settable again, or do they come pre-locked?
>
> Neither of those seem good, now that I think about it.  If they come
> pre-locked, then you really can't clone, change one property, and return
> the new one (as is the standard practice now in that case).  If they don't
> come pre-locked, then the newly created object can have everything on it
> changed, once, which creates a loophole.  I'm not sure what the right
> answer is here.
>


As with typed properties, I wonder if there's a way we can introduce a new
initialisation sequence for objects, so that there's a specific point where
the object is considered "fully constructed" after new or clone.

A couple of brainstormed ideas, with plenty of downsides I'm sure:

An explicit finalise() function or keyword

public function withFoo($foo) {
$inst = clone $this;
// all readonly properties are initially "unlocked"
$inst->foo = $foo;
// now lock them, perhaps also checking that no typed properties are
left uninitialised
finalise($inst); // or finalise $inst;
return $inst;
}

A special code block:

public function withFoo($foo) {
$inst = clone $this {
// all properties are "unlocked" within this special block
$inst->foo = $foo;
};
// from here onwards, readonly properties can't be written to
return $inst;
}

Perhaps could also be used with constructors:

public function createFromOtherThing(OtherThing $other) {
$inst = new static('some parameter') {
 // readonly properties can be written in the constructor, or
within this block
 $inst->foo = $other->getFoo();
};
// object is "finalised" when the block ends
return $inst;
}


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Userspace operator overloading

2020-03-03 Thread Rowan Tommins
Hi Terje,

I think both of your examples are compatible with the idea of grouped
operators, as long as we don't constrain a type to implement all operators
with the same right-hand side.


On Mon, 2 Mar 2020 at 17:23, Terje Slettebø <
terje.slett...@sandefjordbredband.net> wrote:

>
> Adding and subtracting money makes sense, but it makes no sense to
> multiply
> or divide them, and this is just *one* domain.
>


This is true, but it does make sense to multiply and divide them by
numbers, for instance $totalPrice = $unitPrice * $quantity

In general, if $a + $a represents addition, then $a * 2 should logically
give the same result. As has been raised, there is an argument for keeping
/ separate, for types that cannot handle fractional operations; it would be
a matter of choice whether $price / 2 should be supported because it would
lead to fractional pennies/cents.



> $total_discount = $total * $discount;
>
> Here, $total_discount and $total is Money, while $discount is a
> Percentage,
> so we should be able to define a method that allows you to multiply Money
> with Percentage, and return a Money object. Adding Money and Percentage
> would
> make no sense, but multiplying them does.
>


If this operator was implemented in isolation, it would again be drifting
into domain-specific language territory. (I don't personally have a problem
with that, but many people vocally object to it.)

However, it could easily be made part of a consistent set of arithmetic
operators:

On class Money:

Money + Money => Money
Money - Money => Money
Money * int => Money
Money / int => Money
int * Money => Money
int / Money => Error
Money * Percentage => Money
Money / Percentage => Money
Percentage * Money => Money
Percentage / Money => Error

Optionally, on class Percentage:

Percentage + Percentage => Percentage
Percentage - Percentage => Percentage
Percentage* int => Percentage
Percentage / int => Percentage



Regards,
-- 
Rowan Tommins
[IMSoP]


  1   2   3   4   5   6   7   8   9   10   >