Re: [PHP-DEV] [RFC] [Discussion] #[\Deprecated] attribute again v1.3

2024-04-26 Thread Mike Schinkel
> On Apr 25, 2024, at 5:47 PM, Rowan Tommins [IMSoP]  
> wrote:
> I think you missed the context of that sentence - or I'm missing something in 
> yours. I meant specifically that the "deprecated since" information is 
> useless if there's no published policy on how long something will stay 
> deprecated. 

To paraphrase a former US President, "Depends on what the meaning of 'since' 
is."

Given a lack of agreed definition for 'since' it appears you are using narrow 
assumptions about the meaning of 'since' that led you to view 'since' as 
useless.

Conversely, I try not to make limiting assumptions and look for how a feature 
could be useful IF defined appropriately. And to me there is benefit to have a 
standardized way for tooling to recognize deprecation based on versions and 
other criteria, even if the specifics may need to be explored further.

Or at least that is how I see it.  But then, I have no vote, so ¯\_(ツ)_/¯.

-Mike

Re: [PHP-DEV] [RFC] [Discussion] #[\Deprecated] attribute again v1.3

2024-04-25 Thread Mike Schinkel
> On Apr 25, 2024, at 11:28 AM, Rowan Tommins [IMSoP]  
> wrote:
> If the project has no clear deprecation policy, the information is useless 
> anyway.

Not true.

Having standardized notation for deprecation would allow tooling to analyze a 
codebase and determine if it contains deprecated code that needs to be 
remediated without having to run the code with full coverage.  

Actually, `since:` doesn't go far enough because it doesn't indicate if the 
deprecation throws warnings, throws errors, or just no longer works.  The 
latter two would be especially helpful when deciding if code modifications are 
necessary before upgrading to a new version of PHP.

-Mike

Re: [PHP-DEV] [RFC][Discussion] Why can constructors violate LSP?

2023-11-23 Thread Mike Schinkel


> On Nov 23, 2023, at 4:50 PM, Robert Landers  wrote:
> 
> On Thu, Nov 23, 2023 at 10:30 PM Deleu  wrote:
>> 
>> Constructors are an implementation detail of a specialized class and as such 
>> they're not subject to LSP because the goal of LSP is to be able to make 
>> sure that any object of a given type hierarchy can be used to accomplish a 
>> certain behavior. If you take a step back from PHP's dynamic nature and 
>> think about LSP from a more pure type system, the fact you're expecting an 
>> object of type C, but then you completely disregard everything about the 
>> object itself and dive into it's metadata to build another object, that's 
>> the moment you're no longer playing by the rules of OOP. It's like those 
>> mathematical equations that prove that 1 = 2, they all have one thing in 
>> common: they end up dividing by 0 at some point.
>> 
>> OOP here dictates that you should reach for patterns like Builder, Abstract 
>> Factory or similar. That way you constraint yourself to the rules of OOP and 
>> you won't get weird outcomes.
>> 
>> From another point of view, when a type is expected by a function or method, 
>> all we can expect from it is whatever was defined as the blueprint 
>> (class/interface) of that object and the __construct() is a special method 
>> that is not assumed to be part of that blueprint because it's not reasonable 
>> to do `$object->__construct();` after receiving an object. As such, a 
>> constructor cannot break LSP because the constructor is not part of the 
>> object's API from a "receptor" point of view.
>> 
>> I don't have a vote so take my opinion with a bucket of salt, but if I could 
>> I would definitely vote against such RFC.
>> 
>> 
>> --
>> Marco Deleu
> 
> Thanks Marco,
> 
> That's an interesting perspective and one I would agree with for the
> most part, especially if you take my illustration at face value. Where
> it gets weird/breaks down is when you have a class-string, that you
> assert is the correct type, and then try to instantiate it:
> 
> // from somewhere
> $class = "C";
> 
> if(is_subclass_of($class, P::class)) {
>$example = new $class("world");
> }
> 
> If PHP didn't offer these built-in methods, then I would fully agree
> with you, but it does, which puts it into a weird position where
> sometimes a class is substitutable, and in this one special case, it
> is not.

What Marco said pretty much mirrors the answer in Software Engineering SE:

https://softwareengineering.stackexchange.com/a/270738/9114 


As if probably obvious now, when you are using a variable containing a class 
name to instantiate a class you are actually not using OOP, you are using the 
text expansion capabilities of PHP. The fact that it appears to be similar to a 
method call is just likely coincidence,

Now if classes were first class objects in PHP, then there might be an 
argument, but alas, they are not.

Anyway, I always addressed the problem you are running into by defining a 
`make_new()` static method.  Here's what your example might look after an 
initial refactor:

class P {
public $msg;
function __construct($msg){
$this->msg = $msg;
}
}
class C extends P {
static function make_new($props){
return new C($props["msg"]);
}
}

$class = "C";

if(is_subclass_of($class, P::class)) {
   $example = $class::make_new( ["msg"=>"world"] );
   print_r($example);
}

Of course, getting it to production code will take a lot more, like you can see 
here (although this code has now been update for probably five years since I am 
no longer coding in PHP professionally):

https://github.com/search?q=repo%3Awplib%2Fwplib%20make_new=code 


And if you are dealing with 3rd party classes, you'll need to write wrapper 
classes.

Hope this helps.

-Mike



Re: [PHP-DEV] [RFC] [Discussion] Resource to object conversion

2023-11-21 Thread Mike Schinkel
 
 
 
 
>  
> On Nov 21, 2023 at 11:33 PM,  mailto:george.bany...@gmail.com)>  
> wrote:
>  
>  
>  
>  What is the point of a major release if we cannot even do such a BC break? 
> We don't even know when PHP 9.0 is going to happen yet. 
>
>  
 
 

 
I have been using Go for about four years now and it seems they have gotten the 
backward compatibility issue nailed, and that pays great dividends in developer 
confidence in the language, i.e.:
 

 
 
https://www.reddit.com/r/golang/comments/17v4xja/anyone_face_issues_when_updating_version_of_go/
 

 
They recently explained in depth how they do it:
 

 
https://go.dev/blog/compat
 

 
Also see:
 

 
 https://thenewstack.io/how-golang-evolves-without-breaking-programs/
   

 
Although Go is compiled and PHP is not, I think there still may be significant 
insight that can be gained for PHP by studying how Go is handling it and 
applying any lessons learned.
 

 
#fwiw
 

 
- Mike
 

 

 

 

Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-20 Thread Mike Schinkel
Wow. 

This thread has gone from zero-to-toxic in no time flat, and with some 
participants being borderline condescending.  It is almost as if some folk are 
still in kindergarten.

Maybe try a different approach, from both sides of this debate?

For the advocates, how about explaining the use-cases for static classes, why 
you want or need to use them instead of the proposed alternatives, and 
especially pointing out any ways in which the proposed alternatives do not 
address the same issues and/or provide equivalent functionality as static 
classes would?

And for the status-quoians, while I know you feel namespaces address the 
reasons you believe people want static classes, you feel it is bad practice to 
use static classes for those reasons, and you lament that programmers still use 
static classes instead of namespaces, maybe consider exploring *why* developers 
still use static classes instead of namespaces?  And please, consider if there 
is a better way to answer that question rather than falling back on the canard 
that those programmers either don't know any better, or are actively choosing 
to cause harm to all the PHP community and all its collective code across the 
land.

Maybe there are very good reasons developers actively prefer to use static 
classes instead of namespaces? And if you actively try to discover those 
reasons, maybe you can consider discussing how to address them rather than just 
dismissing the desire to use them as developers choosing to use 
"anti-patterns?" 

Are there missing features the language offers users of static classes that it 
does not offer namespaces?  Are static classes more ergonomic to use than 
namespaces?  Or are there other reasons to use static classes over namespaces?  
(Note for this email I am not taking a position pro or con, I just posing the 
question.)

If collectively you discover there are gaps between namespaces and static 
classes, maybe the solution is to fill those gaps instead?  Maybe that means 
improving namespaces, maybe that means adding static classes, or maybe it means 
some unmentioned 3rd option? Either way such an approach is likely going to be 
more productive than a quasi-religious/political rally with extremists on both 
sides protesting the other.

That is, unless those of you participating really prefer to have divisive 
debates that result in no positive outcomes, in which case, knock yourselves 
out. 路‍♂️

-Mike

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



Re: [PHP-DEV] Basic Type Alias

2023-10-27 Thread Mike Schinkel
> On Oct 26, 2023, at 3:23 PM, Larry Garfield  wrote:
> 
> App-wide aliases run into the autoloading problem.  If the engine runs across 
> the add() function above, and "numeric" isn't defined, what can it do?  
> Currently, all it can do is trigger autoloading, which only works for 
> class-ish constructs (class, interface, trait, enum).  Making type aliases a 
> full class-like construct seems... weird, and over-engineered.  

Curious, how do you define a "full class-like construct" in this context?  
Anything more than autoloading?  

And would autoloading actually require something to be a "full class-like 
construct," or could it not be something lighter weight (assuming full 
class-like constructs are not than just autoloading?)

> But if not, how do we autoload them?  And if they do autoload somehow, does 
> that mean we end up with a bunch of files with a single `type` line in them?  
> That seems not-good.  You also then have to ask how they interact with 
> namespaces.


Straw man proposal:

When PHP recognizes a symbol in the context it would expect a type yet PHP does 
not recognize that type, PHP could use the existing autoload mechanism to 
determine files and directories in which those types might be located. This 
would address namespaces, I believe

Then, following PSR 4 is could attempt to autoload via a file of the same name. 
 If there are types and classes, interfaces, traits and/or enums with that same 
name they would all need to be contained in that same named file, much as it 
currently works. 

Of course that would require one .PHP file per type which as you mention would 
not be ideal.

So instead, a new PSR could be created to extend PSR 4 to add type-specific 
considerations. For example, when the type passed in is "Foo" it could first 
look for `/~types.php` and load it but it that did not work then it could look 
for `/~types/Foo.php`.  I picked the tilde (~) since it cannot be part of a 
valid namespace of class name so no backward compatibility concerns.

If the type name passed to the autoloader is `Foo/Bar` then it could look in 
`/~types.php` first, if not there then `/Foo/~types.php` and if not there, then 
`/~types/Foo/Bar.php`.  I picked the tilde (~) since it cannot be part of a 
valid namespace of class name so no backward compatibility concerns.

Having a single `~types.php` per namespace would let developers put all their 
types for that namespace there, if that is what they prefer. Or they could pull 
all types in the root's `/~types.php`.  Or they could create a file for each, 
whichever their preferences.

I am envisioning a new `type_exists()` function would be required.

Even better would be to add an additional optional parameter $type to 
my_custom_autoloader_new() which could either pass in a numeric for some new 
predefined constants like PHP_AUTOLOAD_CLASS=1, PHP_AUTOLOAD_INTERFACE=2, etc., 
or just a string like "class", "interface", etc.

Based on that idea, such an autoloader might look like this:

function my_custom_autoloader_new( $name, $type ) {
$dir = __DIR__ . '/includes';
switch ($type) {
   case PHP_AUTOLOAD_TYPE:
  $file = sprintf("%s/~types.php", $dir);
  if ( file_exists( $file ) ) {
 require_once $file;
  }
  if (type_exists($name)) {
 return;
  }
  $file = sprintf( "%s/~types/%s.php", $dir, $name );
   default:
  $file = sprintf("%s/%s.php", $dir, $name);
}
if ( file_exists( $file ) ) {
   require_once $file;
}
}
 
> So any type alias proposal would need to sort out the above "definition 
> problem" in a way that's generally acceptable.  That's been the hold up for 3 
> years, I think.

The above is potentially one way to skin that cat.  

Anyway, I'm sure there will be lots of opinions on this, so bikeshed away.

-Mike



Re: [PHP-DEV] RFC [Concept] - Interface Properties

2023-06-26 Thread Mike Schinkel
With "Interface Default Methods" potentially becoming a thing, it begs the 
question for the need to have Interface Properties, at least `private` ones and 
`private static` ones. 

How can we have default getters and default setters in an interface if there 
are no private interface properties to get or set? Ignoring special cases, that 
is.

Of course if the RFC for "Interface Default Methods" fails to pass then this 
point is moot.

-Mike

> On May 28, 2023, at 1:51 PM, Erick de Azevedo Lima  
> wrote:
> 
> As others have said: the interface/contract makes available public stuff
> that is what the implementers will make available. So it should not matter
> if those are methods or properties.
> In the case of a public property, the difference from the method-only
> approach is that it's already implicit that the read and write operations
> are available (for non-readonly properties, of course).
> I like it. It can eliminate a lot of boilerplate and make things more
> obvious to the final user of the class that implements the interface.
> 
> --
> Erick
> 
> Em dom., 28 de mai. de 2023 às 14:37, David Gebler 
> escreveu:
> 
>> On Sun, May 28, 2023 at 5:03 PM Larry Garfield 
>> wrote:
>> 
>>> On another level, I'd redefine properties and methods slightly.  (Public)
>>> Properties are not "raw data" but "aspects of the object I can
>> manipulate"
>>> and methods are "behaviors I can ask the object to perform."
>>> 
>> 
>> I just wanted to pull out this sentence in particular because I think it's
>> very much true of the property hooks RFC where you can attach behaviours to
>> what are from the outside accessed as if they were fields - and yes
>> properties on interfaces makes at least more sense in that case...but I
>> don't think it's true of the RFC Nick is proposing, which would very much
>> allow interface designs where a property is simply a (maybe typed) public
>> property and does represent a "raw data" value.
>> 
>> I suppose the difficulty for me is that I appreciate "people could abuse
>> it" isn't a reason in itself to exclude a feature, where it could prove
>> useful in a non-abusive way. But languages have ecosystems and frameworks
>> and conventions and idioms around them which go beyond what the language
>> strictly does and doesn't permit. People who like Laravel will say you can
>> write poor PHP code in any framework and good PHP code in Laravel, and
>> they're right, but personally I'd argue Laravel encourages you to write PHP
>> code in a way which is commonly and conventionally considered to not be a
>> best practice. And I don't like it very much for that reason. It's the same
>> for me with properties on interfaces; I think it will encourage people to
>> do things that some of the conventional wisdom out there says they probably
>> shouldn't.
>> 
>> Anyway, apologies I'm not replying in depth to your comments; I'm just wary
>> of descending into a philosophical wayside about principles of programming
>> and "best practices". And my views on those things are probably quite
>> anodyne, but the margin for difference in good opinions is more than enough
>> that I don't want to go there.
>> 
>> -Dave
>> 
>> On Sun, May 28, 2023 at 5:03 PM Larry Garfield 
>> wrote:
>> 
>>> On Sun, May 28, 2023, at 6:52 AM, David Gebler wrote:
 On Sun, May 28, 2023 at 10:33 AM Rowan Tommins <
>> rowan.coll...@gmail.com>
 wrote:
 
> I don't follow. If a property is public, then code outside the class
>> can
> rely on being able to access it. That seems to me to be a contract
>>> between
> the class and its users, not an implementation detail - e.g. removing
>>> the
> property, or changing its type, would be a compatibility break. A
>>> property
> can also be inherited from a base class, at which point there is a
>>> contract
> that all descendants of that base class will have the property
>>> available.
> So it seems logical that that contract could also be included in an
> interface.
> 
> 
 That's why you can declare constants in an interface (a static final
 property, to use the lexicon of Java) which we can already do in PHP.
>> At
 the point you want to bring mutable state into an interface, it's a
>>> design
 smell that what you want, really, is an abstract class or perhaps
 composition.
>>> 
>>> Almost never is an abstract class what you want, frankly.  An abstract
>>> class unnecessarily conflates "is a special case of" and "reuses code
>> from"
>>> into a single syntax.  "Making one thing do two things" is a design flaw
>> in
>>> most of computer science, and one that PHP has been bitten by multiple
>>> times.
>>> 
>>> cf: https://www.garfieldtech.com/blog/beyond-abstract
>>> 
 A couple of languages do allow mutable properties on interfaces,
>>> TypeScript
 being one of them, so yes it's not an unheard of feature - but in TS/JS
 it's a lot more idiomatic to directly access properties than it is in
>>> PHP.
 I'm not 

Re: [PHP-DEV] PHP Package for PHP

2023-05-19 Thread Mike Schinkel
> On May 18, 2023, at 1:34 PM, Rowan Tommins  wrote:
> On Thu, 18 May 2023 at 16:27, Deleu  wrote:
>> Monolog is a great example of what PHP is missing - a single library for a
>> purpose. I have never worked with any other library besides Monolog and I
>> never worked on any project which didn't have it installed. Perhaps my
>> bubble might be a limiting factor here, but I get a feeling that Monolog is
>> considered to be The Logging PHP Library.
> 
> Then in what sense is it "missing"? What value would be served by placing
> an elephant logo on it, and renaming it "PHPLog™"?
> 
> I know that's a bit of a sarcastic response, but it's also a serious one -
> what would we define as the aims of a replacement for Monolog, which aren't
> currently being served?
> 
> We could guarantee it was installed with every version of PHP, but only by
> severely restricting its release cycle, so that every PHP version had
> exactly one version of Monolog. If it remains an independently versioned
> Composer package, I can't think of much that would change.
> 
> 
> 
> Taking the logging example, imagine we decided that, to paraphrase Dr
> Strangelove, "We can't allow a logging gap!" So we hack together a logging
> package that's worse in every way than Monolog, but call it "official".
> Half the community will ignore it and carry on using Monolog; the other
> half won't realise that a better alternative exists, and be worse off from
> Today.

That statement only envisions inclusion of OR replacement for Monolog, but not 
adding support to PHP core that would offer a standard way to USE Monolog.  Let 
me explain.

And it is helpful logging was mentioned as an example because we can look to 
other languages to see what they have done, and Go just recently did exactly 
that.  

Go proposed[1] then added[2] a Structured Logging package to the Go standard 
library even though there are many logging packages already available for Go 
and in wide use[3], just as PHP has several logging packages[4]. Their design 
doc[5] explains their rationale.

Basically they wanted to include a common set of code that will operate on a 
new standard interface.  For PHP logging there is already a standard interface; 
PSR-3[6], but what PHP does not have is an actual implementation of PSR-3 can 
be depended on to always exists nor a common way all code can get a PSR-3 
logger. 

So rather than providing Monolog in core, provide a minimal implementation in 
core — SimpleLogger maybe? — as well as the PSR-3 interfaces and PSR-3 helper 
classes[7] plus a few new standard functions to always be available in PHP. One 
of those functions — setLogger() maybe? — could allow users to specify the 
PSR-3 logger they want to use, and many developers could choose to use 
Monolog\Logger.

Another of those functions — getLogger() maybe? — could then be called by any 
PHP code to return an instance of `Psr\Log\LoggerInterface` so that all code 
can depend a logger existing.  If no PHP code had previously called setLogger() 
then getLogger() would first instantiate a new SimpleLogger, pass it to 
setLogger(), and then return that object for the caller to use.

So what is "missing" is not the logging library per se, but instead the 
plumbing that would make it possible for code from multiple different authors 
working independently to all be able to write code that logs which will still 
be interoperable, know that a logger will be guaranteed to be available (it 
could even be a null logger), and also have the option to use Monolog, some 
other PSR-3 library, or write their own new special-purpose logger; whatever 
their choice.

Said another way, the value gained by placing an elephant logo on it would be:

1. Interoperability, 
2. Flexibility, and 
3. A guarantee of existence when called.

> I actually wonder if some things in core should be removed to encourage
> userland replacements - ext/soap, for instance, and some of the data
> structures in ext/spl.

Having a PHP core standard library could allow for some of those things to be 
reimplemented in PHP but still included in PHP core. That would reduce the need 
to maintain them in C, and would be a way to slowly deprecate them for userland 
alternatives, ideally with some inclusion of new simple standard interfaces and 
some new functions for could make working with instances  — 
setSOAPClient()/getSOAPClient() maybe? — to allow people to use the built-in 
ones or to replace with their own.

ext/spl could be moved to a PHP core standard library assuming doing so was 
performant enough and/or new features were added to core to allow them to be 
implemented in a performant manner that did not kneecap performant-sensitive 
code that use them.

> IMHO, the things that would benefit from being written in PHP then bundled
> are things that are so low-level that it's hard to get them wrong; the
> building blocks that the community will use to build things like Monolog
> and Guzzle.

Imagine all the PSR interfaces as 

Re: [PHP-DEV] PHP Package for PHP

2023-05-18 Thread Mike Schinkel
> On May 18, 2023, at 10:27 AM, Rowan Tommins  wrote:
> 
> On the one hand, PEAR was a single "baseline" that everyone expected; on
> the other hand, packages tended to be slow to adapt to new needs and
> fashions, and inflexible to different environments. So instead, people
> moved to:
> 
> - Frameworks; which themselves have mostly adopted a "component-based"
> approach interoperating via Composer packages
> - Non-framework groups like The League of Extraordinary Packages
> https://thephpleague.com/
> - Single packages that have become de facto standards - large projects like
> Guzzle and Monolog; and smaller utilities that do one task well, like
> Ramsey/UUID
> 
> There are two ways I can see a "standard PHP package" working:
> 
> - As a server-wide install, part of the distributed PHP. That inherits all
> the downsides of PEAR, but might be appropriate for a fairly small subset
> of really low-level functions.
> - As a set of Composer packages, managed completely outside the PHP
> lifecycle, in which case it's not clear how it would be different from all
> the packages that are already out there.

There is at least a 3rd way. 

There could be server-wide installs with site-root overrides similar to how 
.htaccess works with Apache where a `.php` file (or some other name) in the 
site root could be used to provide overrides for the standard PHP library to 
allow sites to fix bugs, use a newer version, etc. 

This would allow site owners to resolve PHP standard library related issues 
with sites on managed servers where the managed host will not allow server-wide 
install to be modified.

> Composer seems to be serving the community pretty well for a lot of
> functionality.

Except for Composer's lack of ability — by its very nature — to provide a 
single "baseline" that everyone can expect, a benefit of PEAR you noted above. 

> On May 18, 2023, at 10:43 AM, Reinis Rozitis  wrote:
> 
> There is usually the argument - "if this is not in core no one (people on 
> shared environments/hosting) won't be able to use it" and so on..

Many orgs prefer managed hosting so as not to have to pay for system administer 
expertise on staff, and few (any?) managed hosts will modify their installs to 
include more than the few highly popular extensions from PECL.

>  The counter to that are things like Imagick / redis / memcache(d) / APCu 
> which are vastly popular but still live outside core (obviously those are not 
> language rather than engine features).

The list of extensions managed hosts will consider installing is so small — 
compared to the hundreds (1000s?) of extensions they will not — so pointing to 
the few outliers that can live outside core as evidence of developer's ability 
to address their needs with them is much like arguing the US Constitution can 
be amended to solve existing political problems. 

Technically both statements are correct, but practically speaking neither are 
realistic approaches to solving current day needs. 

OTOH, a standard library in core written in PHP that could allow for polyfills 
for future C-in-core changes, a lower bar for implementing additions to core 
(and thus a way to expand those who can actually contribute to core), and a 
starting place for anything that could be written in PHP to be written in PHP 
so as not to require updating and testing C code seems to have many benefits.  
#jmtcw

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



Re: [PHP-DEV] 'Uninitialized' creates a lot of cluttering

2023-02-13 Thread Mike Schinkel


> On Feb 8, 2023, at 9:22 AM, Lydia de Jongh  wrote:
> 
> Hi,
> 
> After posting this in the issues list
> , I was asked to mail it here.
> This is my first time here, so I hope I do it the right way.
> 
> ---
> 
> At last I have the opportunity to start using php8, I am very happy with it
> and how mature it has become; implementing all kinds of code quality.
> 
> But this new *uninitialized state* is really a pain.
> When you set a property in a class, I consider it as set into the class; it
> is part of that class, that object.
> Whether it is undefined or not. You could access it with an easy if or
> ternary operator.
> 
> And you got a *clean overview* of all your properties and how they are
> initialized.
> 
> class Test {
> 
>  protected string $name;
> 
>  protected string $type = 'mytype';
> 
>  protected ?array $arrLog;
> 
>  protected ?string $optionalVar;
> 
>  protected string $table = 'category';
> 
> protected bool $isOk = false;
> }
> 
> *This looks clean and gives clear, easy insight* to the purpose of each
> property.
> But since php8, you have to use isset() or empty() to check whether a
> property is initialized.
> 
> Also php is offering more and more shorthand alternatives like nullsafe
> operator, ternary operator etc. Which I was not in favor of, but it seems
> to be the standard nowadays, so I let phpstorm do its thing and use the
> shorthands.
> 
> But when you start using the (very necessary!!!) typed properties this is
> not working anymore unless you 'initialize' the property with at least an
> empty or dummy value or null.
> I read the RFC trying to understand.
> 
> Maybe it is technically difficult or it is against high-standard rules
> (which I love!), but this is really unpractical and gives to much overhead
> and clutter.
> I love good quality in coding, I endured years of being called crazy by
> colleagues who learned php by google and stackoverflow and loved it because
> it allowed all the bad coding. (Good is good enough)
> 
> But now it seems to go over the top, making php less practical.
> 
> For this uninitialized-thing we can choose one the following solutions at
> the moment:
> 
>   - leave properties untyped, which is really bad
>   - set many properties to null or other empty values, which clutters your
>   property list
>   - add those empty values inside the constructor, which creates useless
>   extra lines of code
>   - use isset or empty to check if it is set or not, and not be able to
>   use shorthands
> 
> To use typed properties and profit from all the new shorthands and nice new
> feature of php 8, my class has to be something like:
> 
> class Test {
> 
>  protected string $name = '';
> 
>  protected string $type = 'mytype';
> 
>  protected ?array $arrLog = [];
> 
>  protected ?string $optionalVar = null;
> 
>  protected string $table = 'category';
> 
> protected bool $isOk = false;
> }
> 
> This looks cluttered. And I do not understand that we get all those nice
> shorthands, but for typed properties, we need to type more
> 
> Why does a nullable type not automaticly default to null, or even to the
> empty variant of the type (by giving it not an question-mark but the
> exclamation mark, maybe...) like:
> 
> class Test {
> 
>  protected !string $name;  // defaults to ''
> 
>  protected string $type = 'mytype';
> 
>  protected !array $arrLog;  // defaults to []
> 
>  protected ?string $optionalVar;  // defaults to null
> 
>  protected string $table = 'category';
> 
> protected !bool $isOk;  // defaults to false
> 
> protected !float $someNumber;  // default to 0
> 
> protected ?myObject $oObject;   // no default for objects... to
> complicated and risky, or not??, so only nullable
> }
> 
> I hope this can be considered again.

Hi Lydia,

I personally appreciate your concern. I program mostly in GoLang these days, 
its variables and struct properties are initialized to a "zero" value by 
default, and that works extremely well and cuts down on an entire class of 
errors.

However, I know this is not what you wanted — and it is likely you already know 
how to do this — but in case this workaround had not already occurred to you 
the following is a proof-of-concept that might reduce the annoyance of having 
to initialize all your typed properties, at least somewhat, given that the list 
does not appear keen to address your concerns.

This workaround uses a base `AutoInit` class with a constructor that uses 
reflection to inspect the properties and if they are uninitialized and without 
a default get their type and then initialize them to an appropriate "zero" 
value. 

Yes it uses reflection which is a bit slow, but you may or may not find that 
the performance drain a concern, given your use-cases. 

Also, it is just a proof-of-concept, so you may end up needing to fix edge-case 
bugs or tweak for your use-cases.

Hope this helps.

-Mike
P.S. This workaround is also a great 

Re: [PHP-DEV] Re: [RFC] Unicode Text Processing

2022-12-17 Thread Mike Schinkel
  
  

  
  
  
>   
> On Dec 17, 2022 at 10:20 PM,   (mailto:voris...@fjfi.cvut.cz)>  wrote:
>   
>   
>   
>  I also suggest `substring` instead of ugly (IMHO) `subString`. - in PHP, we 
> have substring() function, not sub_string() - in C#, there in Substring() 
> method, not SubString() With kind regards / Mit freundlichen Grüßen / S 
> přátelským pozdravem, Michael Voříšek  
>
>   
  
  

  
To add support for this request, it seems “substring” is a complete word in 
English, so no need for camel-case:
  

  
https://www.thefreedictionary.com/substring
  

  
-Mike
  
  
>   
>   
>   
>   
>   
> 
>   
> 
>   
> 
>   
> 
>   
> 
>   
>  

Re: [PHP-DEV] [VOTE] Improve unserialize() error handling

2022-10-17 Thread Mike Schinkel
Larry,

> On Oct 17, 2022, at 6:01 PM, Larry Garfield  wrote:
> 
> On Mon, Oct 17, 2022, at 12:33 PM, Tim Düsterhus wrote:
> 
 Okay, now the Exception message changed. Personally I do not consider
 this a BC break: I believe Exception messages are meant for human
 consumption, not for programs. Otherwise fixing a typo in the message
 would be a BC break. If the code wants to learn about the cause, it
 should either use the '$code' or different types of Exception should be
 thrown to clarify the cause by entering a different catch() block.
 
>>> 
>>> Yes, the specific error message should be part of the BC promise. This
>>> allows building test suites that can assert the message in a stable way.
>> 
>> I'm not talking about test suites here. I believe makes sense to verify 
>> the error message to ensure a specific error message is emitted to the 
>> human observer in the error log.
>> 
>> I was talking about code that does something like this, which I consider 
>> to be inherently unsafe:
>> 
>> try { … }
>> catch (SomeException $e) {
>>   if ($e->getMessage() === 'Foobar') doSomething();
>>   else doSomethingElse();
>> }
>> 
>> As a library author I want to be able to provide the best possible 
>> Exception message to ease debugging for the user. This is not possible 
>> if I am locked into a bad choice forever.
> 
> Just to be clear, such code is sometimes necessary.  If the exception doesn't 
> include sufficient information as dedicated properties, parsing out the 
> string becomes the only option.  I've had to do this myself.
> 
> In 100% of cases, without exception (no pun intended), that's because the 
> code that throws the exception is bad and wrong and should be fixed.  But 
> such code absolutely exists in the wild, including in php-src.  I recently 
> needed to sscanf() and then explode the message of \ArgumentCountError as 
> that was the only way I could find to get the class/method names out of it.  
> I died inside a little.
> 
> So yes, such code is inherently unsafe, but is sadly not as uncommon as it 
> should be.
> 
> All that said, I agree that we have not and should not treat error message 
> strings as part of the API guarantee.  If anything, maybe that will help 
> incentivize people to stop writing bad (unparsable) exceptions.

I am curious what you would envision a better, "parsable" exception from 
sscanf() would look like?

I ask not because I disagree with you here but because maybe the question of 
whether errors messages should be part of BC is focusing on the wrong question?

-Mike

P.S. Also, looking at https://www.php.net/manual/en/function.sscanf.php 
, it is interesting that the 
exceptions it triggers are not documented here.  (I am not picking on sscanf() 
— AFAIK few if any functions document their exceptions.) Shouldn't more thought 
(and documentation) be given to this information which obviously is part of its 
API/usage?



Re: [PHP-DEV] Experimental features

2022-10-11 Thread Mike Schinkel
> On Oct 11, 2022, at 8:24 AM, Christian Schneider  
> wrote:
> 
> We seem to have two different views on experimental feature here: You are 
> saying they could get removed again while others stated it is for stuff which 
> will definitely end up in stable when the next major release is done.
> 
> IMHO there needs to be a consensus about this before we can continue the 
> discussion, otherwise we will go around in circles.

True. In my view experimental would allow to features to be tried that might 
get removed, but others may not want that.

However, I think it is really a moot point because of RFC voting. If enough 
people felt it might get removed they would vote against it. And if after 
something was experimental if enough people felt it should be removed they 
would vote to do so.

So each individual RFC as well as voting addresses that concern.

> That's another thing where we need to find an agreement first: Are we talking 
> new, isolated functions or are we possibly also talking about core new 
> language features (i.e. new syntax / semantics)?
> 
> The work for maintenance by core developers could be much higher if it is not 
> limited to new functions.
> This is IMHO an important aspect as we do not want to make life even harder 
> for the core team.

Again, each individual RFC and voting address that concern. 

If an experimental RFC would resolve it "too much" maintenance by core 
developers then it would get voted down. A 2/3rd bar for success is not a low 
bar, especially in a community with so many divergent opinions. 

> Hot take: If it is only about new functions then we don't need anything in 
> the core, just create an \Experimental package with poyfills and you're done 
> ;-)

My hot take: Having the entire PHP community made aware of a given experimental 
function — including all the blog posts that would be written about it — is != 
to an individual developer creating an \Experimental namespace and writing 
their own blog post about it. 

>> Not all potentially useful functions can reasonably be implemented in 
>> userland PHP.
> 
> ... but almost all of them can.

See reply in prior paragraph.

> I'd go as far as saying that while emulating json_validate() using 
> json_decode()  is slower and uses more memory it still is a valid polyfill. 
> It is IMHO easy enough to develop with a higher memory limit and performance 
> is not that critical for development either.

For json_validate() people have *already* been using a polyfill, and it was 
found sorely lacking for memory-use reasons.  So a reason for making it 
experimental would be to see if the proposed signature was sufficient for 
mainstream needs.

Oh, and a higher memory limit is not always a viable solution.

> And unless you want to ship experimental code to production (which you 
> shouldn't) you will have to wait for the next major PHP release anyway.

Not all "production" code is equal. My blog != Wikipedia, for example.

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



Re: [PHP-DEV] Experimental features

2022-10-10 Thread Mike Schinkel
> On Oct 10, 2022, at 6:20 PM, David Gebler  wrote:
> 
> My two cents...
> 
> Why can't "common users" install a PECL extension? It's not a difficult,
> obscure or undocumented process.

A lot of developers (most?) who build PHP applications run them in 
shared-hosted or managed hosted servers where are never given the option to 
install a PECL extension. 

In the rare cases they can install PECL many of those PHP developers would not 
have the skills to do it or the requisite permissions on the server; I 
certainly did not for the first ~10 years of working with PHP. I do now, but 
ironically because I have mostly moved away from programming in PHP to do more 
DevOps work.

Further, when working in multiple environments having to set up each server to 
have all the same PECL installations can be just too much hurdle so that 
developers won't even try, especially when working in managed environments.

[1] https://stackoverflow.com/a/12750694/102699


> I can accept the reasoning
> 
>> Apply a PECL strategy to try experimental features might not be the
> convenient way always, for example, if we create a new ... sensitive ini
> setting that affects the behavior of PHP somehow... OR ... what about a new
> sensitive funtion in a "core extension" like JSON?
> 
> But why would the answer in those cases not be "compile the PHP fork/branch
> with the experimental feature", rather than find a way to flag the engine
> to switch arbitrary new features on or off, complete with all the
> complications in the primary source code that would cause? We are, after
> all, talking about features which by definition should not be relied upon
> for any production use.
> 
> Or we're talking about features which are stable and valuable enough to
> have passed an RFC process, but then what's gained from an experimental
> designation? Why couldn't they just be included in a preview/beta/RC
> version which anyone could decide to run or not?

It does not seem reasonable that the bar to include a feature as experimental 
should be the same bar as currently exists for forever features.  Opinions 
expressed on the list typically fall into one of three categories:  

1.) Please, please yes! 
2.) No way whatsoever! or 
3.) I am not convinced...

Generally it seems that unless 2/3rd are in the #1 category an RFC fails to 
pass, even if after evaluating in the wild the people in group #3 might come to 
see a lot of value in it and some in #2 might even change their mind. In those 
cases PHP suffers. 

If there were an RFC for Experimental Use then the people on the fence could 
choose to allow it to see how it plays out in real-world userland cases, and a 
few people against it might be convinced to allow people to evaluate it, and 
then later make a decision on a "Forever RFC."

---

Also, the comments along the lines of "Well, this could quickly get out of 
hand" presume that the people voting for experimental use won't take that into 
consideration and vote against things if it seems like things are in-fact 
getting out of hand. But they will take that into consideration just a as the 
take other concerns into consideration now, and thus only the better ideas will 
be likely to make it through to experimental status.

---

One more thing on this topic. PHP could ALSO allow experimental features to be 
written in PHP, and ship those experimental features with PHP so that code 
would always be available, at least when experimental features are turned on, 
and without having to include said code.  

The benefit there would be people could more quickly implement an experimental 
feature to see how it might work in the wild before going to all the effort to 
implement in C in PHP's core code, for things that can be implemented in PHP.

-Mike

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



Re: [PHP-DEV] [RFC] Asymmetric visibility

2022-08-11 Thread Mike Schinkel

> On Aug 11, 2022, at 7:38 PM, André Hänsel  wrote:
> 
> Nicolas Grekas wrote:
> 
>> But I'm also wondering about the use case where asymmetry would be
>> useful in practice now that we have readonly?
>> I voted against readonly at the time because it didn't address
>> cloning, and also because it deprives end-users vs code authors IMHO
>> (alike "final"). I would have very much prefered asymmetric
>> visibility back then. But now that we are here, what are the use cases?
> 
> Isn't it (obviously?) to have setters that ensure all invariants of the
> properties are met? I'd still rather have Property Accessors as
> described in https://wiki.php.net/rfc/property_accessors, but I think
> AV is a step in the right direction.
> 
> As for readonly, I don't understand why that exists at all.


For immutability. 

Here is one reference on immutability offered up by the google gods:

https://hackernoon.com/5-benefits-of-immutable-objects-worth-considering-for-your-next-project-f98e7e85b6ac
 


Immutability goes hand-in-hand with Functional Programming (FP.)  While PHP is 
not a functional programming language,  PHP developers can gain benefits from 
an FP style for which immutability is beneficial. 

Also from the google gods, if you are unfamiliar with FP:

https://alvinalexander.com/scala/fp-book/benefits-of-functional-programming/ 
 

Hope this helps.

-Mike

P.S. Also, the Internals list's very own Larry Garfield is a huge advocate for 
FP in PHP, voilà:

https://leanpub.com/thinking-functionally-in-php
https://www.garfieldtech.com/taxonomy/term/95


> Yes, it's
> good that readonly properties can only be set from within the class,
> but only once, so you get setters that throw when called a second time,
> which I think is very, VERY unexpected behavior. Calling them
> "readonly" is also somewhat misleading because of course the objects
> assigned to those "readonly" properties can still be mutated, they can
> just not be reassigned.
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 



Re: [PHP-DEV] [RFC] Asymmetric visibility

2022-08-07 Thread Mike Schinkel
> On Aug 5, 2022, at 1:08 PM, Larry Garfield  wrote:
> 
> Ilija Tovilo and I are happy to present the first new RFC for PHP 8.3: 
> Asymmetric Visibility.
> 
> https://wiki.php.net/rfc/asymmetric-visibility



Conceptually, I believe this would add useful capabilities to PHP that are 
impossible to implement without:

a.) Likely-sizable performance penalties, and 
b.) Unfortunate edge-cases; e.g. property_exists(), get_object_vars(), etc.

Still, here are my concerns with the RFC as it currently exists:

1.) The syntax of "()" feels inconsistent with the rest of 
the language. 

PHP has function(args...) and (), both of which can be viewed as "a 
function of 'args'." However, "private(set)" is basically a constraint, not a 
"function of 'set'."

PHP also has function(args...): which is a constraint so I propose we 
consider the following syntax instead:

  :

Thus all of these:

 public:get
 public:set
 private:get
 private:set
 protected:get
 protected:set

2.)The idiom "public private:set" is hard to reason about when reading, at 
least for me. 

It also feels inconsistent in that it requires one type of visibility to be 
constrained, but not the other. 

Speaking of "explicit" from one of Larry's latest replies, I propose we 
consider requiring asymmetric visibility *explicitly* declared, in all cases. 
Requiring explicit declaration would: 

a.) Make asymmetric visibility easier to reason about, and 
b.) Ensure consistency when asymmetric visibility is used.

Specifically I would propose we make these INVALID:

public protected:set  $;
public private:set  $;
protected private:set  $;


But all of these following VALID:

These as-is for backward compatibility and an obvious default behavior:

public [] $;
protected [] $;
private [] $;

And these where behavior is explicit:

public:get protected:set  $;
public:get private:set  $;
protected:get private:set  $;

As well as these:

public:set protected:get  $;
public:set private:get  $;
protected:set private:get  $;

And of course these:

public:get public:set  $;
private:get private:set  $;
protected:get protected:set  $;


3.) I have concerns about the proposed methods isProtectedSet() and 
isPrivateSet().  

These names feels like we are asking if some thing "Set" is "Protected" or 
"Private" where no such "thing" exists in this context.  

In other words it reads as if you are asking "Is it a *protected* Set?" or "Is 
it a *private* Set?"  Such naming also does not relate to the Property itself 
which is what the prefix verb "is" is acting on.

I would propose instead we consider the following are these instead would be 
asking the *ability* to "Set" the Property is "Protected" or "Private" where 
The Property is again what the prefix verb "is" is acting on:

isSetProtected()
isSetPrivate()
isGetProtected(), and
isGetPrivate()


#jmtcw

-Mike

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



Re: [PHP-DEV] [RFC] [VOTE] Constants in traits

2022-07-10 Thread Mike Schinkel
> On Jul 5, 2022, at 5:38 PM, shinji igarashi  wrote:
> 
> Hello internals,
> 
> I've started the vote for the Constants in Traits RFC:
> https://wiki.php.net/rfc/constants_in_traits
> 
> The vote will end on 19. July 2022.
> 
> Thanks!
> 
> --
> Shinji Igarashi

The reaction to this RFC has been truly eye-opening to me.  It never occurred 
to me that Traits would be viewed so negatively by some on Internals. 

Personally I have found Traits to be one of the VERY BEST features of PHP for a 
userland developer given their ability to reduce complexity and allow for a 
cleaner code architecture within the applications I have worked on. OTOH I have 
always found Traits to be an incomplete language feature whose design gaps I 
have handled via rigidly standardizing how I use them and by incorporating a 
lot of unfortunate boilerplate.

Though I was surprised at first that some people so strongly dislike Traits I 
then thought more about the incompleteness of Traits and wonder if that is not 
the reason they feel Traits are problematic?  I further wonder how their 
use-cases differ from the ones I have been involved with?

Given the three people who spoke strongly against them on this thread work 
heavily with PHP tools that make heavy use of reflection, code analysis, and/or 
work on PHP core I wonder if their dislike for Traits have a lot to do 
Trait-related problems they have when implementing PHP core itself, frameworks, 
ORMs, testing tools, etc. rather than userland development? 

I am in no-way discounting the importance of core or tool development but I 
wonder if they recognized issues in the implementation-of and design decisions 
related-to Traits that most userland developers rarely ever see because of 
their core and/or tool development work?

Further, I wonder if their dislike of Traits is more of an X-Y problem?  IOW, 
that because they have seen issues with Traits they view the solution to tamp 
down on Traits rather than the solution being to fill in the design gaps and 
implementation issues with Traits?

--

So, can those who spoke against Traits please explain more details about:

1. How do Traits have "built-in accidental complexity?"  

2. How does `use TRAIT1, TRAIT2, TRAIT3` semantics result in "mind-boggling 
over-complicated?"

3. What extra compatibility checks are required for Traits?

4. What are the potential error scenarios that are "unnecessary," why are they 
unnecessary, and what alternative could you envision? 

5. What about the implementation of Traits do you strongly dislike, what type 
of implementation would be better, and could PHP change the implementation and 
still retain backward compatibility?

-

I pose these questions in hopes to discern among Internals if Traits are 
actually the problem or if instead Traits could be improved to solve the 
concerns states in this tread, which might require some longer-term deprecation 
of some of the problematic aspects of Traits.

-Mike
P.S. I also want to talk about the issues I have with the RFC itself and what 
other things I see that I think are design gaps in Traits, but I don't want to 
create an email to the list with more than one focus.  I'll follow up later 
with those other issues.

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



Re: [PHP-DEV] [RFC] Short Closures 2, aka auto-capture take 3

2022-06-14 Thread Mike Schinkel



> On Jun 13, 2022, at 1:39 PM, Rowan Tommins  wrote:
> 
> On 13/06/2022 14:52, Larry Garfield wrote:
>>> That's one perspective. The other perspective is that the proposal is to
>>> extend closure syntax to support automatic capture.
>> As noted before, this is a distinction without a difference.
> 
> 
> It's a difference in focus which is very evident in some of the comments on 
> this thread. For instance, Arnaud assumed that adding "use(*)" would require 
> a change to arrow functions, whereas that never even occurred to me, because 
> we're looking at the feature through a different lens.
> 
> 
>>> By the way, the current RFC implies you could write this:
>>> 
>>> fn() use (&$myRef, $a) { $myRef = $a * $b; }
>> The RFC already covers that.  $b will be auto-captured by value from scope 
>> if it exists.  See the "Explicit capture" section and its example.
> 
> 
> So it does. I find that extremely confusing; I think it would be clearer to 
> error for that case, changing the proposal to:
> 
> > Short Closures support explicit by-reference capture with the |use| 
> > keyword. Combining a short closure with explicit by-value capture produces 
> > an error.
> 
> And the example to:
> 
> $a = 1;
> fn () use (&$b) {
> return $a + $b; // $a is auto-captured by value
>  // $b is explicitly captured by reference
> }
> 
> 
> Clearer syntax for this has been cited previously as an advantage of use(*) 
> or use(...):
> 
> $a = 1;
> function () use (&$b, ...) { // read as "use $b by reference, everything else 
> by value"
> return $a + $b;
> }
> 
> 
>> 1. Auto-capture could still over-capture without people realizing it.  
>> Whether this is actually an issue in practice (or would be) is hard to say 
>> with certainty; I'm not sure if it's possible to make an educated guess 
>> based on a top-1000 analysis, so we're all trying to predict the future.
> 
> 
> I tried to make very explicit what I was and was not disputing:
> 
> > Whether the risk of these side effects is a big problem is up for debate, 
> > but it's wrong to suggest they don't exist.
> 
> The RFC seems to be implying that the implementation removes the side 
> effects, but it does not, it is users paying attention to their code which 
> will remove the side effects.
> 
> 
>> Arguably it's less of an issue only because short-closures are, well, short, 
>> so less likely to reuse variables unintentionally.
> 
> 
> Our current short closures aren't just a single *statement*, they're a single 
> *expression*, and that's a really significant difference, because it means to 
> all intents and purposes *they have no local scope*. (You can create and use 
> a local variable within one expression, but it requires the kind of twisted 
> code that only happens in code golf.)
> 
> If there are no local variables, there is nothing to be accidentally 
> captured. That's why the current implementation doesn't bother optimising 
> which variables it captures - it's pretty safe to assume that *all* variables 
> in the expression are either parameters or captured.
> 
> 
>> 2. The syntactic indicator that "auto capture will happen".  The RFC says 
>> "fn".  You're recommending "use(*)".  However, changing the indicator syntax 
>> would do nothing to improve point 1.
> 
> 
> The reason I think it would be better is because it is a more *intentional* 
> syntax: the author of the code is more likely to think "I'm using an 
> auto-capture closure, rather than an explicit-capture closure, what effect 
> will that have?" and readers of the code are more likely to think "hm, this 
> is using auto-capture, I wonder which variables are local, and which are 
> captured?"
> 
> Of course they can still guess wrong, but I don't think "fn" vs "function" is 
> a strong enough clue.

"Strong enough" is an opinion, and it seems all who have commented have 
differing ones of those.  

But maybe a memory device would help address (some of?) your concerns:

- fn() — It is SHORT and implicit. Short is CONVENIENT. Thus Short 
auto-captures variables because that is the most Convenient thing to do.

- function() — It is LONG. Long is more EXPLICIT. Thus Long requires Explicitly 
declaring variables, which is also more rigorous and robust.

Or for the TL;DR crowd:

- fn() => SHORT => CONVENIENT => Auto-captures
- function() => LONG => EXPLICIT => Requires declaration

Hope this helps. #fwiw

-Mike

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



[PHP-DEV] Constraints vs. values as types?

2022-04-16 Thread Mike Schinkel
Hi PHPers,

As I have been following the discussion about the need for a "true" type to 
allow documenting that a function should only be able to return true vs. bool 
which would allow false, and in the past the same argument for false vs. true, 
it occurs to me that there is another approach to address this rather than add 
values to be types which AFAIK has not been mentioned on the list before.

An alternate solution to possibly consider might be to add the concept of 
"constraints" to PHP that could work alongside types. This occured to me 
because I am mostly doing Go programming now and constraints is effectively how 
Go handled an equivalent conundrum for the Generics they just added.

Consider if PHP allowed the following and if PHP would allow type hints to use 
*either* a type *or* a constraint where the values on the right hand side are 
expressions (I was just spitballing the syntax; other syntaxes or even concept 
names might represent this concept better):

constraint true: true

constraint false: false

If we had constraints in PHP we could also have things like this:

constraint Truthy: !empty($this)

constraint Falsey: empty($this)

constraint Percent: is_numeric($this) && 0 <= $this && $this <=100

constraint DateTimeable: is_object($this)
&& (get_class=($this) == DateTime::class || get_class=($this) 
== DateTimeImmutable::class)

constraint ProductID: is_string($this) && strlen($this)==10 
&& preg_match("#[A-Z]{2}[0-9]{8}#",$this)

With the above, we could write functions like this and know they are more "type 
safe" than otherwise:

function product_exists(ProductID $product_id):bool {...}

Constraints could also be limited to using only standard library functions so 
that it would be possible to do static analysis on a constraint.  Clearly a 
static analyzer could evaluate the constraints I represented above. And I 
*think* this could be backward compatible with false as a type, and even true 
with a type.  

FWIW I am just offering up an approach that seems to have worked well in Go for 
consideration. If you like it, please discuss it. If not, it was worth a try.

-Mike

P.S. I am sure there are many ways to improve what I proposed.  Note this is 
*just* a straw man proposal; please offer suggestions for improvement.



Re: [PHP-DEV] [RFC][Under discussion] Deprecate ${} string interpolation

2022-03-14 Thread Mike Schinkel

> On Mar 14, 2022, at 3:20 PM, Lynn  wrote:
> 
> On Mon, Mar 14, 2022 at 8:04 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> 
> Variable variables provide functionality[1] that if removed would force major 
> rewrites of PHP applications that were architected in a way that depends on 
> that functionality. 
> And while probably between 90% and 99% of the time when someone uses variable 
> variables there are better alternatives, variable variables make certain code 
> possible that would be impossible without them. 

> Do you have examples where this is the case? 

Most of these things cannot be done without the functionality provided by 
variable variables. However a few are examples could be handled differently but 
would require significant rewrite to fix without a new 
get_value_from_variable_name() function.  Either way, these are just from the 
first few pages of those 162.2k results on SourceGraph.com 
<http://sourcegroup.com/>:

https://github.com/microsoft/sql-server-samples/blob/master/samples/development-frameworks/laravel/vendor/jeremeamia/SuperClosure/src/SerializableClosure.php#L200-L208
 
<https://github.com/microsoft/sql-server-samples/blob/master/samples/development-frameworks/laravel/vendor/jeremeamia/SuperClosure/src/SerializableClosure.php#L200-L208>
https://github.com/mockery/mockery/blob/master/library/Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php#L151
 
<https://github.com/mockery/mockery/blob/master/library/Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php#L151>
https://github.com/vlucas/phpdotenv/blob/master/tests/Dotenv/DotenvTest.php#L251
 
<https://github.com/vlucas/phpdotenv/blob/master/tests/Dotenv/DotenvTest.php#L251>
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc#L34-L38
 
<https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc#L34-L384>
https://github.com/kanaka/mal/blob/master/impls/php/interop.php#L19 
<https://github.com/kanaka/mal/blob/master/impls/php/interop.php#L19>
https://github.com/moodle/moodle/blob/master/mod/data/tests/lib_test.php#L1293 
<https://github.com/moodle/moodle/blob/master/mod/data/tests/lib_test.php#L1293>
https://github.com/moodle/moodle/blob/master/mod/data/tests/generator_test.php?L105#L104
 
<https://github.com/moodle/moodle/blob/master/mod/data/tests/generator_test.php?L105#L104>
https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php#L236
 
<https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php#L236>
https://github.com/phpipam/phpipam/blob/master/functions/PEAR/Net/Ping.php#L284 
<https://github.com/phpipam/phpipam/blob/master/functions/PEAR/Net/Ping.php#L284>
https://github.com/api-platform/core/blob/main/src/Core/Annotation/ApiProperty.php#L154-L159
 
<https://github.com/api-platform/core/blob/main/src/Core/Annotation/ApiProperty.php#L154-L159>
https://github.com/wp-cli/wp-cli/blob/master/php/WP_CLI/Runner.php#L1285-L1287 
<https://github.com/wp-cli/wp-cli/blob/master/php/WP_CLI/Runner.php#L1285-L1287>
https://github.com/phpmyadmin/phpmyadmin/blob/master/libraries/classes/Database/Qbe.php#L878-L879
 
<https://github.com/phpmyadmin/phpmyadmin/blob/master/libraries/classes/Database/Qbe.php#L878-L879>
https://github.com/PrestaShop/PrestaShop/blob/develop/classes/SpecificPrice.php#L474
 
<https://github.com/PrestaShop/PrestaShop/blob/develop/classes/SpecificPrice.php#L474>


> Using arrays is a compatible replacement as far as I know, and I highly doubt 
> these kinds of hacks are necessary.

"Necessary" is a judgement call.  If you never do meta-programming in PHP then 
these _techniques_ — calling them "hacks" is a bit incendiary — would not ever 
seem necessary. 

However if a developer does work on projects that by-requirement leverage 
meta-programming then variable variables are a tool in one's toolkit that one 
would be hobbled without.

An area where I have seen them required is in theming where the CMS or plugin 
vendor wants to make it easier on the themer by creating dynamically-named 
variables in scope and then including a PHP file intended to be used as a 
template, and the in other functions being able to access those 
dynamically-named variables.

Other areas are in developer tools written in PHP for PHP developers.

That said, are you objecting to the "variable variable" syntax, or more broadly 
to the ability to access the value of a variable given its name (as a new 
function could provide)?

-Mike

P.S. BTW, I agree that if a developer can avoid variable variables there would 
be doing themselves and future maintainers a big favor. I am only commenting 
because in

Re: [PHP-DEV] [RFC][Under discussion] Deprecate ${} string interpolation

2022-03-14 Thread Mike Schinkel
> On Mar 12, 2022, at 5:44 AM, Lynn  wrote:
> 
> Variable variables should be removed from PHP asap. It's 2022 and I still
> encounter bugs due to this "working" in legacy applications.



> On Mar 12, 2022, at 5:48 AM, Kamil Tekiela  wrote:
> 
> +1 on removing variable variables as soon as possible.



Variable variables provide functionality[1] that if removed would force major 
rewrites of PHP applications that were architected in a way that depends on 
that functionality. 

And while probably between 90% and 99% of the time when someone uses variable 
variables there are better alternatives, variable variables make certain code 
possible that would be impossible without them.

So, *assuming* removing variable variables is important enough to break any the 
existing code that uses it — sourcegraph.com reports[2] 162.2k examples of its 
use — PHP should at least add a function that would allow getting the variables 
value by name.  Something like `get_variable_value_by_name($name)` but 
hopefully with a less verbose name than I used in my example just now.

#jmtcw

-Mike

[1] https://stackoverflow.com/questions/16339658/php-variable-value-from-string 

[2] 
https://sourcegraph.com/search?q=context:global+lang:php+%5B%5E:%5C%5C%5D%5C%24%5C%7B%5C%24++count:all=regexp
 




Re: [PHP-DEV] RFC: Trait expects interface

2022-01-17 Thread Mike Schinkel


> On Jan 7, 2022, at 1:56 PM, Rowan Tommins  wrote:
> 
> On 07/01/2022 13:47, Robert Korulczyk wrote:
>> I'm not really sure why would you not want this - what is the point of 
>> marking method as interface implementation, if it is not reflected by type 
>> system in actual execution?
> 
> 
> It's really quite simple: I don't want traits to tell me how I "must" use 
> them, but am quite happy for them to document how I "can" use them.

About any of these someone could say "I don't want to be told..." 

"...I must implement an abstract method"
"...I must implement all the methods in an interface"
"...I must pass all arguments declared in a function"
"...I must pass arguments that are of the type that were type-hinted"
"...I cannot extend a final class"
"...I cannot access a private property outside the class"
"...I cannot change a readonly property after it has been initialized"

And yet specifying appropriate constraints for a specific use-case has its 
benefits.  I'm sure you can see benefit to the above constraints so it is 
strange to me you cannot see the benefit of traits that would constrain their 
uses to requiring an interface.

If it were possible to specify that a trait required an interface then I don't 
envision anyone other than those who need bespoke traits would do so, and those 
are not likely traits you would want to use anyway because they could be 
changed by the developer when their use-case evolved.

#jmtcw #fwiw

-Mike

> 
> Unless we allow a trait to *automatically* implement the interface (or 
> similar features, such as an interface with default implementation) there is 
> no direct impact on the actual type system. There are, as far as I can see, 
> three things the feature would provide:
> 
> - Documentation: the trait can tell me as a programmer that it contains 
> everything I need to implement a particular interface
> - Code generation: the trait can import the list of methods from an interface 
> as abstract methods which it requires
> - Policing: the trait can force me as a programmer to use it in a certain 
> way; this is the part I don't see the need for
> 
> Regards,
> 
> -- 
> Rowan Tommins
> [IMSoP]
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 



Re: [PHP-DEV] Function list declaration syntax?

2021-10-09 Thread Mike Schinkel
> On Oct 5, 2021, at 3:18 PM, Dan Ackroyd  wrote:
> 
> On Tue, 5 Oct 2021 at 18:47, Mike Schinkel  wrote:
> 
>> Consider the `Type` class[3] in the `SebastianBergmann\Type` namespace. It 
>> contains 60 lines of function declaration to define 14 functions that all 
>> return `false`.
> 
> PHP allows you to define functions on one line:
> 
>function isCallable(): bool { return false; }
>function isFalse(): bool { return false; }
>function isGenericObject(): bool { return false; }

The benefit I was proposing was not just fewer lines, but also reduced visual 
complexity making it easier to read and comprehend code quickly. 

Your argument addresses the former benefit but not the latter.

> If you don't like having functions take up lots of lines, it's easier
> to just not follow that PSR guide line on formatting,

It is not always easier for developers where whose organizations dictate code 
standards.

Besides, your alternative is a bit reductio ad absurdum.

> rather than modify the language.

You state this without justification that it has been established that changing 
the language is a bad thing. If that were true, why does the RFC process even 
exist as in most cases RFCs are passed to change the language?

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



[PHP-DEV] Function list declaration syntax?

2021-10-05 Thread Mike Schinkel
Hi all,

This email proposes a shorthand syntax for declaring a list of 
single-expression functions. 

A similar albeit more verbose attempt to provide short functions[1] failed late 
last year, but I was recently inspired by Sebastian Bergmann's Type library[2] 
that he referenced in a comment on another thread.

Consider the `Type` class[3] in the `SebastianBergmann\Type` namespace. It 
contains 60 lines of function declaration to define 14 functions that all 
return `false`.  Even though it really is a simple class it is rather hard to 
wrap one's head around quickly because of all the bloating boilerplate 
required. At least IMO.

Consider instead if we had the following syntax?

public function list: bool
{
  isCallable() => false,
  isFalse() => false,
  isGenericObject() => false,
  isIntersection() => false,
  isIterable() => false,
  isMixed() => false,
  isNever() => false,
  isNull() => false,
  isObject() => false,
  isSimple() => false,
  isStatic() => false,
  isUnion() => false,
  isUnknown() => false,
  isVoid() => false,
}

The idea here is to group a 'list' of functions — in this case of the same type 
— and then use shortened single expression fn() syntax for each function. And 
with a monospace font in your editor of choice this code could be made even 
easier to grok by left-aligning the return values.

I chose the keyword `list` because it is already a reserved word, but the word 
`case` could also be used for the same reason, if people prefer that.

Further, instead of `function list` or `function case` we could have `fn list`, 
`fn case`, `fn() list` or `fn() case`, whichever feels best to the most people.

This could also work for abstract functions noting that the typehint is applied 
to each function instead of the list declaration, e.g.:

abstract public function list 
{
  isAssignable(self $other): bool;
  name(): string;
  allowsNull(): bool;
}

Those two changes shorten Type.php from 140 lines down to 90 lines, and IMO, 
make the class much easier to read. You can see it here[4].

One more example, this time his `NullType` class[5] using mixed type hints and 
going from a total of 38 lines down to 26 lines[6]:

public function list
{
name(): string => 'null',
asString(): string => 'null',
allowsNull(): bool => true,
isNull(): bool => true,
}

What do you think?  Is this approach any more appealing than the last one 
proposed?

-Mike

[1] https://wiki.php.net/rfc/short-functions
[2] https://github.com/sebastianbergmann/type
[3] https://github.com/sebastianbergmann/type/blob/master/src/type/Type.php
[4] https://gist.github.com/mikeschinkel/6f8c9cf6700a75e75e2725db1ed4da61
[5] https://github.com/sebastianbergmann/type/blob/master/src/type/NullType.php
[6] https://gist.github.com/mikeschinkel/a93aabd61127b0c3ba28c5caf4ebe005
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Allow null as standalone type

2021-10-05 Thread Mike Schinkel
> On Oct 2, 2021, at 11:06 AM, G. P. B.  wrote:
> 
> Hello internals,
> 
> I'm proposing a new RFC to make 'null' usable as a standalone type.
> 
> RFC: https://wiki.php.net/rfc/null-standalone-type

Regarding the RFC's proposed disallowing of `?null`, is that really needed?

Obviously it doesn't make sense for a developer to write that, but I could see 
that a code generator would have add special-case logic to avoid outputting `?` 
with the type `null`.

Does it hurt anything if it is allowed?

-Mike

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



Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?

2021-09-25 Thread Mike Schinkel
> On Sep 25, 2021, at 12:03 PM, Marco Pivetta  wrote:
> 
> Hey Tyson,
> 
> On Sat, 25 Sep 2021, 18:00 tyson andre,  wrote:
> 
>> My original message had a section with reasons why an end user might want
>> that.
>> 
> 
> Yeh, it sounds like stuff we wanna get away from 

Point of order here: "we" is not unanimous.

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



Re: [PHP-DEV] Adding `final class Deque` to PHP

2021-09-21 Thread Mike Schinkel
> On Sep 21, 2021, at 1:12 PM, Pierre Joye  wrote:
> On Tue, Sep 21, 2021, 11:56 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> > On Sep 21, 2021, at 3:45 AM, Pierre Joye  > <mailto:pierre@gmail.com>> wrote:
> > 
> > On Tue, Sep 21, 2021 at 11:21 AM Mike Schinkel  > <mailto:m...@newclarity.net>> wrote:
> > 
> >> Honestly, at first I confused `Deque` with `Dequeue` and was wondering why 
> >> we would name a class with a verb?  It wasn't until Rowan's comment that I 
> >> realized `Deque` is an abbreviation.
> >> 
> >> Which begs the question: how many other PHP developers will know computer 
> >> science terms like this well enough to know `Deque` is a noun when they 
> >> see it, and more importantly how many PHP developers will think to search 
> >> for `Deque` when they need a queue?
> > 
> > Unlike the Vector name which is really confusing as it is not a
> > vector, Deque is actually relatively known for anyone needing a double
> > ended queue. It even comes first in google search, wikipedia or java
> > implementations, which matches this implementation.
> 
> Being able to google what Deque means is one thing, but thinking to search 
> for it when you don't know it exists *and* you don't know that Deque is the 
> term you would need to be searching for.
> 
> > We expect our
> > users to know all weird names of different patterns, I trust them to
> > be able to learn what a Deque is. :)
> 
> So we expect PHP developers to have a computer science background? Maybe you 
> are assuming everyone minimally has your expertise?  Have we as a group 
> decided to forsake beginners? 
> 
> 
> It is not what I was trying to explain.
> 
> However if one looks at the php documentation looking for specific things 
> like these, the Deque will be there. 
> 
> So I am not expecting anyone to have a CS background (btw, I don't), however 
> I do have a minimal trust in users reading the docs and doing a minimum of 
> research. 

And what I was trying to explain is that given my past experience working with 
other PHP developers, I believe that trust is misplaced for many.  

And why make it harder than it needs to be? For PHP, jargon is Bad(tm), IMHO 
anyway.

-Mike



Re: [PHP-DEV] RFC: Add `final class Vector` to PHP

2021-09-21 Thread Mike Schinkel
> On Sep 19, 2021, at 8:55 AM, tyson andre  wrote:
> 
> Hi Mike Schinkel,
>> 
>> Hmm. I must have missed that thread as I was definitely following the list 
>> at that time. 
>> 
>> But I found the thread, which only had three (3) comments from others:
>> 
>> https://externals.io/message/112639
>> 
>> From Levi Morrison it seems his objection was to adding `push()` and `pop()` 
>> to a class including the name "Fixed."  Levi suggested soft-deprecating 
>> `SplStack` because it was implemented as a linked-list, but he proposed 
>> adding `Spl\ArrayStack` or similar, so it seems he was open to iterating on 
>> the `Spl` classes in general (no pun intended.) 
>> 
>> From Nikita is seemed that he did not object so much as comment on Levi's 
>> suggestion of adding `Spl\ArrayStack` and suggested instead an `SqlDeque` 
>> that would handle queue usage more efficiently that plain PHP arrays.
>> 
>> So I think those responses were promising, but that you did not followed up 
>> on them. I mean no disrespect — we all get busy, our priorities change, and 
>> things fall off our radar — but it feels to me like you might have more 
>> success pursing your use-cases related to the `Spl` classes than via a pure 
>> `Vector` class.
> 
> Experience in past RFCs gave me the impression that if:
> 
> 1. All of the responses are suggesting using a different approach(php-ds, 
> arrays),
> 2. Other comments are negative or uninterested.
> 3. None of the feedback on the original idea is positive or interested in it.
> 
> When feedback was like that, voting would typically have mostly "no" results.

Understood, but for clarity I was implying that wanting to change 
`SplFixedArray` was an "XY problem" and that maybe the way to address your 
actually use-cases was to pursue other approaches that people were suggesting, 
which _is_ what you did yesterday.  :-)

>> Maybe propose an `SplVector` class that extends `SplFixedArray`, or 
>> something similar that addresses the use-case and with a name that people 
>> can agree on?
> 
> I'd be stuck with all of the features in `SplFixedArray` that get introduced 
> later and its design deisions.

You wouldn't be stuck with all the feature of `SplFixedArray` if you did 
"something similar." 

(I make this point only as it seems you have dismiss one aspect of my 
suggestion while not acknowledging the alternatives I present. Twice now, at 
least.)

>> I wavered on whether or not to propose a configurable growth factor, but 
>> ironically I did so to head off the potential complaint from anyone who 
>> cares deeply about memory usage (isn't that you?) that not allowing the 
>> growth factor to be configurable would mean that either the class would use 
>> too much memory for some use-cases, or would need to reallocate more memory 
>> too frequently for other use-cases, depending on what the default growth 
>> factor would be.
>> 
>> That said, I don't see how a configurable growth factor should be 
>> problematic for PHP? For those who don't need/care to optimize memory usage 
>> or reallocation frequency they can simply ignore it; no harm done. But for 
>> those who do care, it would give them the ability to fine tune their memory 
>> usage, which for selected use-cases could mean the difference between being 
>> able to implement something in PHP, or not.
>> 
>> Note that someone could easily argue that adding a memory-optimized data 
>> structure when we already have a perfectly flexible data structure with PHP 
>> arrays that can be used for the same algorithms is "excessive for a 
>> high-level language."  But then I don't think you would make that argument, 
>> so why make it for a configurable growth factor? #honestquestion
> 
> The growth factor is even lower level than shrinkToFit/reserve, and requires 
> extra memory to store the float,
> extra cpu time to do floating point multiplication rather than doubling,
> and additional API methods for something that 99% of applications wouldn't 
> use.
> I consider it more suitable for a low level language.

I respect your points here, but disagree.

> And if we discover a different resizing strategy is better, it prevents us 
> from changing it.

This is not true. 

We could easily no-op the GrowthFactor method and it would not break anything 
in 99.9...% percent of use-cases.

The relevant question here should be, what is the likelihood of us discovering 
a better resizing strategy that would not benefit at all from a growth factor?  
Is there evidence of one anywhere else?  I know that Go — designed to be 
performant to the extent i

Re: [PHP-DEV] Adding `final class Deque` to PHP

2021-09-21 Thread Mike Schinkel
> On Sep 21, 2021, at 3:45 AM, Pierre Joye  wrote:
> 
> On Tue, Sep 21, 2021 at 11:21 AM Mike Schinkel  wrote:
> 
>> Honestly, at first I confused `Deque` with `Dequeue` and was wondering why 
>> we would name a class with a verb?  It wasn't until Rowan's comment that I 
>> realized `Deque` is an abbreviation.
>> 
>> Which begs the question: how many other PHP developers will know computer 
>> science terms like this well enough to know `Deque` is a noun when they see 
>> it, and more importantly how many PHP developers will think to search for 
>> `Deque` when they need a queue?
> 
> Unlike the Vector name which is really confusing as it is not a
> vector, Deque is actually relatively known for anyone needing a double
> ended queue. It even comes first in google search, wikipedia or java
> implementations, which matches this implementation.

Being able to google what Deque means is one thing, but thinking to search for 
it when you don't know it exists *and* you don't know that Deque is the term 
you would need to be searching for.

> We expect our
> users to know all weird names of different patterns, I trust them to
> be able to learn what a Deque is. :)

So we expect PHP developers to have a computer science background? Maybe you 
are assuming everyone minimally has your expertise?  Have we as a group decided 
to forsake beginners?  

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



Re: [PHP-DEV] Adding `final class Deque` to PHP

2021-09-20 Thread Mike Schinkel
> On Sep 19, 2021, at 8:03 PM, tyson andre  wrote:
> 
> Hi internals,
> 
> I've created a new RFC https://wiki.php.net/rfc/deque to add a `final class 
> Deque`
> 
> This is based on the `Teds\Deque` implementation I've worked on
> for the https://github.com/TysonAndre/pecl-teds PECL.

With one caveat, this is a much stronger RFC than the Vector one.  Good job!

However...

> On Sep 20, 2021, at 4:25 PM, Rowan Tommins  wrote:
> 
> On 20/09/2021 14:46, tyson andre wrote:
>> The choice of global namespace maintains consistency with the namespace used 
>> for general-purpose collections already in the SPL
> 
> I find this argument unconvincing. If the intention is for this to fit with 
> existing classes in the SPL, it should be called "SplDeque", or more 
> consistently "SplDoubleEndedQueue", and the RFC should talk about how the 
> design aligns with those existing classes.
> 
> If it is intended to be the first of a new set of data structures which are 
> *not* aligned with the existing SPL types, then putting it in a new namespace 
> would make most sense.
> 
> In the RFC and the list you've mentioned a few comparisons, but I don't think 
> any of them hold:
> 
> * ArrayObject, WeakReference, and WeakMap are all classes for binding to 
> specific engine behaviour, not generic data structures
> * Iterators all have an "Iterator" suffix (leading to some quite awkward 
> names)
> * Reflection classes all have a "Reflection" prefix
> * Having both "Queue" and "SplQueue", or both "Stack" and "SplStack" would be 
> a terrible idea, and is a pretty strong argument *not* to add data structures 
> with such plain names

I am in complete agreement with Rowan.  

Honestly, at first I confused `Deque` with `Dequeue` and was wondering why we 
would name a class with a verb?  It wasn't until Rowan's comment that I 
realized `Deque` is an abbreviation.  

Which begs the question: how many other PHP developers will know computer 
science terms like this well enough to know `Deque` is a noun when they see it, 
and more importantly how many PHP developers will think to search for `Deque` 
when they need a queue?

So here is a straw man argument; name the class one of:

- DataStruct\DoubleEndedQueue, or
- DataStruct\DE_Queue

Let the bike-shedding begin! 

(Or is that "Let it continue?")

-Mike

P.S. BTW re: https://github.com/TysonAndre/pecl-teds 
, who is Ted? (pun intended)

Re: [PHP-DEV] RFC: Add `final class Vector` to PHP

2021-09-18 Thread Mike Schinkel
Hi Tyson,

Thanks for the reply.

> On Sep 18, 2021, at 7:26 PM, tyson andre  wrote:
> 
> Hi Mike Schinkel,
> 
>> Given there seems to be a lot of concern about the approach the RFC proposes 
>> would it not address the concerns about memory usage and performance if 
>> several methods were added to SplFixedArray instead (as well as functions 
>> like indexOf(), contains(), map(), filter(), JSONSerialize(), etc., or 
>> similar):
>> 
>> ===
>> 
>> setCapacity(int) — Sets the Capacity, i.e. the maximum Size before resize
>> getCapacity():int — Gets the current Capacity.
>> 
>> setGrowthFactor(float) — Sets the Growth Factor for push(). Defaults to 2
>> getGrowthFactor():float — Gets the current Growth Factor
>> 
>> pop([shrink]):mixed — Returns [Size] then subtracts 1 from Size. If 
>> (bool)shrink passed then call shrink().
>> push(mixed) — Sets [Size]=mixed, then Size++, unless Size=Capacity then 
>> setSize(n) where n=round(Size*GrowthFactor,0) before Size++.
>> 
>> grow([new_capacity]) — Increases memory allocated. Sets Capacity to 
>> Size*GrowthFactor or new_capacity.
>> shrink([new_capacity]) — Reduces memory allocated. Sets Capacity to current 
>> Size or new_capacity.
>> 
>> ===
>> 
>> If you had these methods then I think you would get the memory and 
>> performance improvements you want, and if you really want a final Vector 
>> class for your own uses you could roll your own using inheritance or 
>> containment.
> 
> I asked 8 months ago about `push`/`pop` in SplFixedArray. The few responses 
> were unanimously opposed to SplFixedArray being repurposed like a vector, the 
> setSize functionality was treated more like an escape hatch and it was 
> conceptually for fixed-size data.

Hmm. I must have missed that thread as I was definitely following the list at 
that time. 

But I found the thread, which only had three (3) comments from others:

https://externals.io/message/112639

From Levi Morrison it seems his objection was to adding `push()` and `pop()` to 
a class including the name "Fixed."  Levi suggested soft-deprecating `SplStack` 
because it was implemented as a linked-list, but he proposed adding 
`Spl\ArrayStack` or similar, so it seems he was open to iterating on the `Spl` 
classes in general (no pun intended.) 

From Nikita is seemed that he did not object so much as comment on Levi's 
suggestion of adding `Spl\ArrayStack` and suggested instead an `SqlDeque` that 
would handle queue usage more efficiently that plain PHP arrays.

So I think those responses were promising, but that you did not followed up on 
them. I mean no disrespect — we all get busy, our priorities change, and things 
fall off our radar — but it feels to me like you might have more success 
pursing your use-cases related to the `Spl` classes than via a pure `Vector` 
class. Maybe propose an `SplVector` class that extends `SplFixedArray`, or 
something similar that addresses the use-case and with a name that people can 
agree on?

BTW, here are two other somewhat-related threads:

- https://externals.io/message/110731
- https://externals.io/message/113141

> I also believe adding a configurable growth factor would be excessive for a 
> high level language.

I wavered on whether or not to propose a configurable growth factor, but 
ironically I did so to head off the potential complaint from anyone who cares 
deeply about memory usage (isn't that you?) that not allowing the growth factor 
to be configurable would mean that either the class would use too much memory 
for some use-cases, or would need to reallocate more memory too frequently for 
other use-cases, depending on what the default growth factor would be.

That said, I don't see how a configurable growth factor should be problematic 
for PHP? For those who don't need/care to optimize memory usage or reallocation 
frequency they can simply ignore it; no harm done. But for those who do care, 
it would give them the ability to fine tune their memory usage, which for 
selected use-cases could mean the difference between being able to implement 
something in PHP, or not.

Note that someone could easily argue that adding a memory-optimized data 
structure when we already have a perfectly flexible data structure with PHP 
arrays that can be used for the same algorithms is "excessive for a high-level 
language."  But then I don't think you would make that argument, so why make it 
for a configurable growth factor? #honestquestion

> This has been asked about multiple times in threads on unrelated proposals 
> (https://externals.io/message/112639#112641 and 
> https://externals.io/message/93301#93301 years ago) throughout the years, but 
> the maintainer of php-ds had a long term goal of developing the 

Re: [PHP-DEV] RFC: Add `final class Vector` to PHP

2021-09-18 Thread Mike Schinkel
Hi Larry,

> On Sep 18, 2021, at 12:03 PM, Larry Garfield  wrote:
> 
> Rather than go point by point, I'm going to respond globally here.
> 
> I am frequently on-record hating on PHP arrays, and stating that I want 
> something better.  The problems with PHP arrays include:
> 
> 1. They're badly performing (because they cannot be optimized)
> 2. They're not type safe
> 3. They're mutable
> 4. They mix sequences (true arrays) with dictionaries/hashmaps, making 
> everything uglier
> 5. People keep using them as structs, when they're not
> 6. The API around them is procedural, inconsistent, and overall gross
> 7. They lack a lot of native shorthand operations found in other languages 
> (eg, slicing)
> 8. Their error handling is crap

Would you mind elaborating on points #3 and #8?  

It is not clear to me what you are getting at with those points.

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



Re: [PHP-DEV] RFC: Add `final class Vector` to PHP

2021-09-17 Thread Mike Schinkel
> On Sep 16, 2021, at 10:09 PM, tyson andre  wrote:
> 
> Hi internals,
> 
> I've created a new RFC https://wiki.php.net/rfc/vector proposing to add 
> `final class Vector` to PHP.
> 
> PHP's native `array` type is rare among programming language in that it is 
> used as an associative map of values, but also needs to support lists of 
> values.
> In order to support both use cases while also providing a consistent internal 
> array HashTable API to the PHP's internals and PECLs, additional memory is 
> needed to track keys 
> (https://www.npopov.com/2014/12/22/PHPs-new-hashtable-implementation.html - 
> around twice as much as is needed to just store the values due to needing 
> space both for the string pointer and int key in a Bucket, for non-reference 
> counted values)).
> Additionally, creating non-constant arrays will allocate space for at least 8 
> elements to make the initial resizing more efficient, potentially wasting 
> memory.
> 
> It would be useful to have an efficient variable-length container in the 
> standard library for the following reasons: 
> 
> 1. To save memory in applications or libraries that may need to store many 
> lists of values and/or run as a CLI or embedded process for long periods of 
> time 
>   (in modules identified as using the most memory or potentially exceeding 
> memory limits in the worst case)
>   (both in userland and in native code written in php-src/PECLs)
> 2. To provide a better alternative to `ArrayObject` and `SplFixedArray` for 
> use cases 
>   where objects are easier to use than arrays - e.g. variable sized 
> collections (For lists of values) that can be passed by value to be read and 
> modified.
> 3. To give users the option of stronger runtime guarantees that property, 
> parameter, or return values really contain a list of values without gaps, 
> that array modifications don't introduce gaps or unexpected indexes, etc.
> 
> Thoughts on Vector?

Given there seems to be a lot of concern about the approach the RFC proposes 
would it not address the concerns about memory usage and performance if several 
methods were added to SplFixedArray instead (as well as functions like 
indexOf(), contains(), map(), filter(), JSONSerialize(), etc., or similar):

===

setCapacity(int) — Sets the Capacity, i.e. the maximum Size before resize
getCapacity():int — Gets the current Capacity.

setGrowthFactor(float) — Sets the Growth Factor for push(). Defaults to 2
getGrowthFactor():float — Gets the current Growth Factor

pop([shrink]):mixed — Returns [Size] then subtracts 1 from Size. If 
(bool)shrink passed then call shrink().
push(mixed) — Sets [Size]=mixed, then Size++, unless Size=Capacity then 
setSize(n) where n=round(Size*GrowthFactor,0) before Size++.

grow([new_capacity]) — Increases memory allocated. Sets Capacity to 
Size*GrowthFactor or new_capacity.
shrink([new_capacity]) — Reduces memory allocated. Sets Capacity to current 
Size or new_capacity.

===

If you had these methods then I think you would get the memory and performance 
improvements you want, and if you really want a final Vector class for your own 
uses you could roll your own using inheritance or containment.

Would this not work?

-Mike

P.S. I also think asking for new methods on SplFixedArray has a much greater 
chance of successful than an RFC for Vector. #jmtcw

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



Re: [PHP-DEV] Class static initialization block

2021-09-13 Thread Mike Schinkel
> On Sep 13, 2021, at 12:26 PM, Rowan Tommins  wrote:
> 
>> 2.) Make the initialization function private.
> 
> I'm not sure how that would work: a private constructor means that it has to 
> be explicitly called from within the same class, but a static initialiser 
> would be called by the engine, before the class scope even existed.

I think we are getting in the weeds here and loosing sight of the desired 
outcome.

Currently it is not possible for a developer to disallow calling a class 
initialization method from outside of the class. However that would end up 
being achieved — via private methods, protected methods, or even voodoo — those 
details are unimportant to ultimately disallowing the calling of initialization 
code from outside the class.

> From your link, it seems that C# restricts them much more than methods or 
> constructors:
>> 
>>A static constructor doesn't take access modifiers or have parameters.
>>A class or struct can only have one static constructor.
>>Static constructors cannot be inherited or overloaded.
>>A static constructor cannot be called directly and is only meant
>>to be called by the common language runtime (CLR). It is invoked
>>automatically.

Those all sound like they would be appropriate restrictions for PHP too.

> Apparently, the JS implementation does allow multiple static initialiser 
> blocks in one class, which are simply processed in order. But JS classes are 
> weird creations, implemented as a complex sugar on top of a classless object 
> system, so may not be the best point of reference for PHP, whose object 
> system much more closely resembles Java or C#.

I did not reference JS — I only referenced Java and C# — so JS' approach was 
not part of my argument.

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



Re: [PHP-DEV] Class static initialization block

2021-09-13 Thread Mike Schinkel
> On Sep 11, 2021, at 7:35 PM, Marco Pivetta  wrote:
> 
> On Sun, 12 Sep 2021, 01:28 David Rodrigues,  wrote:
> 
>> Hello!
>> 
>> I would like to suggest a feature I saw being implemented in the V8 9.4
>> engine called "*class static initialization block*".
>> 
>> https://v8.dev/blog/v8-release-94
>> 
>> In short, it is a method that is executed once when a class is imported and
>> loaded, allowing for some more advanced initialization process to be done.
>> 
>> class Test {
>>static readonly Carbon $now;
>> 
>>static () {
>>self::$now = now();
>>}
>> }
>> 
>> Currently I can only do this in a very hacky way, usually by creating a
>> public static method and calling it after class initialization.
>> 
>> class Test {
>>static Carbon $now;
>> 
>>public static function init(): void {
>>self::$now = now();
>>}
>> }
>> 
>> Test::init();
>> 
>> I think the way the V8 does is much more interesting.
>> 
>> Another alternative would be to create a magic method like __initialize().
>> 
> 
> This already works without any magic.

Not true.  Here are three (3) things you cannot currently do with your proposed 
solution and without said magic:

1.) Use static analysis to recognize a class has an initialization 
functionality and thus provide lint-specific to best practices for static 
initialization.
2.) Make the initialization function private.
3.) Override and/or change order of initialization of parent in child class.

I do not know of use-cases of #3, but #1 and #2 use-case should be obvious.

> ```
> MyClass::horribleInitializationPractices();
> ```

You named that in a rather condescending and passive-aggressive way.  Is that 
really helpful for respectful dialog?


> That's really all there is to it.
> 
> What you define as hacky is really normal/boring, and does not need special
> constructs.
> 
> Also, it's generally not a good idea to sprinkle static mutable
> runtime-bound all over the place: it should be an exception, not a rule.

Valid use-cases I have come across:

1. Hooking actions and filters in plugins for frameworks and CMS that use hooks 
as an extension mechanism.

2. Initializing what would ideally be constants but because of PHP's 
constraints regarding constant initializes cannot be constants.

> On Sep 12, 2021, at 6:42 AM, Rowan Tommins  wrote:
> 
> On 12 September 2021 00:28:02 BST, David Rodrigues  
> wrote:
>> Hello!
>> 
>> I would like to suggest a feature I saw being implemented in the V8 9.4
>> engine called "*class static initialization block*".
> 
> 
> Hi David,
> 
> There was a similar proposal for PHP a few years ago: 
> https://wiki.php.net/rfc/static_class_constructor
> 
> Although it didn't go to a vote, the proposal was dropped for lack of 
> support. There's some discussion summarised in that RFC, and you can probably 
> find the rest by searching for its title on https://externals.io
> 
> Regards,
> 
> -- 
> Rowan Tommins

Here is the external thread:  

https://externals.io/message/84602

Rowan, you were definitely the most vocal one to argue against it with the most 
messages on that thread.

But all the arguments against appeared to bog down into discrediting Johannes 
Ott's desired use-case for static class constructors and did not really look 
for other reason why they would be useful.

As I mentioned above, hooking actions and filters in plugins for frameworks and 
CMS is where it would be useful, especially since these generally need to be 
hooked upon initial load of the plugin. 

Also, initializing variables to act as constants because PHP does not support 
complex initializations on constants is another use-case.

One of your arguments against was the timing of the initialization because 
evidently Johannes Ott wanted them to be lazily evaluated.  Given the use-case 
I just stated I think they should always be loaded immediately whenever the 
file is loaded. That makes that argument about debugging cause-and-effect 
becomes a moot point. 

And lazy evaluation should be considered as a separate feature. I blogged about 
that a while back but never brought to the list:

https://mikeschinkel.org/2021/lets-add-lazy-evaluation-to-php/

The other main argument you had against was Singletons. But that was a moot 
point because one of the reasons to use static initialization *is* to 
instantiate a Singleton.

Java has static initialization blocks[1], C# has static constructors[2] so the 
idea they would be useful for PHP is not a stretch,

-Mike

[1] https://www.geeksforgeeks.org/g-fact-79/
[2] 
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

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



Re: [PHP-DEV] [RFC] $this return type

2021-09-09 Thread Mike Schinkel
> On Sep 9, 2021, at 10:26 AM, Flávio Heleno  wrote:
> 
> On Tue, Sep 7, 2021 at 10:27 AM Sebastian Bergmann 
> wrote:
> 
>> Am 07.09.2021 um 12:28 schrieb Nikita Popov:
>>> I have some reservations about this (which basically come down to $this
>> not
>>> being a proper "type", so should it be in the type system?) but I can see
>>> the practical usefulness, so I think it's worth discussing this.
>> 
>> I am not conviced that there is enough value in this to introduce syntax
>> for it, but if at all, then please not "$this" as the name for a type.
>> 
>> Off the top of my head, I think that "same" could make sense.
>> 
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: https://www.php.net/unsub.php
>> 
>> 
> Hi all,
> 
> I'm sorry if I'm being naive, or simply put dumb, but the main difference
> that we're trying
> to achieve with having "$this" (or variations of it) as a valid return type
> as opposed to simply
> using "self" is to ensure that the underlying code is actually doing a
> "return $this" rather
> than returning any other valid "self" instance (such as "return new
> self();")?

So a *mutable* fluent style vs. an *immutable* fluent style?

-Mike

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



Re: [PHP-DEV] Alias stdClass to DynamicObject?

2021-09-08 Thread Mike Schinkel
> On Sep 8, 2021, at 4:59 PM, Rowan Tommins  wrote:
>> I assume we would also disallow dynamic properties in anonymous classes too, 
>> right? After all, they are just statically declared classes that the 
>> developer do not assign a name.
> 
> The difference I see is that stdClass/DynamicObject allows you to add or 
> remove properties from an object *after it has been created*. I think a lot 
> of use cases don't actually need that, and would benefit from error messages 
> when doing so accidentally.

The concern is *not* were they are not needed, but instead where they *are* 
needed.  Such as when loading JSON from a source that does not ensure the 
schema is 100% stable over time.

That's also why I was hoping some of those complaining about deprecating 
stdClass would explain explain their use-cases as they may know of use-cases we 
are not considering.


> You mentioned short-hand syntaxes like this:
> 
>> $obj = {
>> foo: 1,
>> bar: "hello",
>> baz: true,
>> };
> 
> I would love for that, or some other short-hand, to be equivalent to this:
> 
> $obj = new class(foo: 1, bar: "hello", baz: true) {
> public $foo;
> public $bar;
> public $baz;
> public function __construct($foo, $bar, $baz) {
>$this->foo  = $foo;
>$this->bar = $bar;
>$this->baz = $baz;
> }
> }
> 
> That is, an anonymous class, with exactly those three properties. If you 
> *also* want to be able to define extra properties after it's created, you 
> could opt into that using whatever mechanism a named class would (parent 
> class, trait, attribute, etc; see other thread).

Exactly!

Actually the same functionality for named classes is something I have wanted 
since literally the very first day I starting using PHP so I wouldn't have to 
run userland code that loops through an array that runs for so many object 
instantiations. I have to believe it would be more performant if in C. (Reasons 
I do that? Loading from JSON, XML and/or SQL.). We've need either a magic 
method or ability to pass a close for name translations and short circuiting.  

That functionality is the primary reason I almost always use a base class; it 
would be nice to get rid of that requirement. 

> Similarly, the objects created by json_decode or PDO_FETCH_OBJECT only need 
> the *initial* properties to be dynamic, not to allow properties to be added 
> later.

How do you define "initial?"

-Mike

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



Re: [PHP-DEV] Alias stdClass to DynamicObject?

2021-09-08 Thread Mike Schinkel
> On Sep 8, 2021, at 5:44 AM, Rowan Tommins  wrote:
>> Is it just a special-cases that will cause as much confusion for developers 
>> trying to understand why there are too names for the same thing as it will 
>> help those who will better understand the new name
> 
> That is certainly a risk, and a factor in favour of having some plan to 
> retire the old name, even if only after a long overlap.

Ironically I believe if we add `DynamicObject` as an alias of `stdClass` where 
`DynamicObject::class === 'stdClass'` that would not provide much ability to 
retire `stdClass` any sooner than if we just deprecated it today. All future 
code that needs to refer to the class name will still refer to `stdClass`, so 
we won't be gaining much by creating an alias.

OTOH if we introduce a **completely new class** named `DynamicObject` having 
exactly the same behavior as a `stdClass` object (at least initialize) then we 
could add any new behavior to `DynamicObject` and leave `stdClass` fully 
in-tact for as long as we need to, except for notes in the docs that say to 
move to `DynamicObject` and tools like PhpStorm, Psalm and Phan could start 
suggesting a move away from `stdClass` right away.

With a new independent class `'DynamicObject' === get_class( new DynamicObject 
)` would always be true, and people who want to future proof their code could 
start replacing `stdClass` with `DynamicObject. People that don't (want to) 
make the change could maybe get a warning in PHP 9 and then maybe we remove 
`stdClass` in PHP and they must evolve or stick with PHP 8.

#fwiw I think `DynamicObject` is the best semantic name floated thus far albeit 
sadly on the rather long side.  `DynamicClass`, also long, could work too...



Of course having a different class begs the question of what  
`get_class((object)array())` should return? Clearly for BC it needs to be 
`stdClass`, but as long as it is `stdClass` then we get no real benefit from 
aliasing with DynamicObject. 

Further, although the expression style of `(object)['prop' => 'value']` is the 
simplest way to initialize a basic `object` with literals in a single 
expression it is still a bad workaround that is far from intuitive for new 
developers, and feels like we are just leveraging an accidental capability 
rather than a well-designed language feature.  

If we want `DynamicObject` to eventually replace `stdClass` why not ALSO 
provide new syntax to give people a reason to switch to it? Why not leverage 
the named constructor concept but as a special case for `DynamicObject`, and 
only for `DynamicObject` (not `stdClass`); allow any arbitrary names to be used 
in constructor promotion?  Instead of this:

$obj = (object)array(
   "foo" => 1,
   "bar" => "hello",
   "baz" => true,
);o

We could do this instead:

$obj = new DynamicObject(
foo: 1,
bar: "hello",
baz: true,
);

AND since we are talking a singular special case, why not also add a 
`DynamicObject()` function to streamline it a bit:

$obj = DynamicObject(
foo: 1,
bar: "hello",
baz: true,
);

OR we could get inspired by the shortening of `function()` to `fn()` and used 
obj() (since `do()` is probably unworkable):

$obj = obj(
foo: 1,
bar: "hello",
baz: true,
);

OR my personal favorite (though I know that would be a bridge too far for many) 
why not just this, too?

$obj = {
foo: 1,
bar: "hello",
baz: true,
};

While we are at it, DynamicObject could add a few really useful methods such as 
`fromArray()`, `toJSON()` and more?  (And if I really want to get crazy, 
`toSqlUpdate()`, `toSqlInsert()`, etc, but now I fear I am just scaring people 
off.)

If we gave a better developer experience with literal initializers and useful 
methods then we've give a lot of developers reason to update their code to use 
`DynamicObject` and thus we could deprecate `stdClass` sooner. 

A couple more things; add a `JSON_OUTPUT_DYNAMIC_OBJECT` flag to output to 
DynamicObject for `json_decode()`,  add a 3rd parameter for flags to 
var_export() for the same reason, a `'return_dynamic_object'` option for 
`unserialize()`, and so on.

(BTW, we don't have to do ALL these things in one RFC. But we could go ahead 
and discuss the potential of having future RFCs that would add these features.)

>>  or is it more fully addressing the use-case for why people use dynamic 
>> objects?
> 
> The thread comes from a comment I made in Nikita's discussion about 
> deprecating dynamic properties on normal objects. There was no grand vision 
> behind it, just a long-standing dislike of the name "stdClass", and a concern 
> that documenting "extends stdClass" as a way to enable dynamic properties on 
> a custom class would make the confusion worse.

Yes, I followed that discussion. But the fact you had a discussion doesn't 
ensure that the proposed solution is the proper one. Hence why I was trying to 
illicit a discussion about what would be more proper.

> The one thing missing from 

Re: [PHP-DEV] Alias stdClass to DynamicObject?

2021-09-08 Thread Mike Schinkel


> On Sep 6, 2021, at 11:28 AM, Nikita Popov  wrote:
> 
> Hi internals,
> 
> In the thread for deprecation of dynamic properties, Rowan suggested that
> we alias "stdClass" to "DynamicObject" in
> https://externals.io/message/115800#115802. I wanted to split this
> discussion off into a separate thread, as this can be decided independently.
> 
> The rationale for this is that "stdClass" is something of a misnomer: The
> name makes it sound like this is a common base class, as used in a number
> of other languages. However, PHP does not have a common base class. The
> only way in which "stdClass" is "standard" is that it is the return type of
> casting an array to (object).
> 
> The actual role of stdClass is to serve as a container for dynamic
> properties, thus the suggested DynamicObject name.
> 
> What do people think about adding such an alias? Is this worthwhile?

So I am trying to get around what this would actually mean in practice, and 
what the ramifications would be.

Given this proposal would `(object)array()` return an object of class 
'DynamicObject' instead of 'stdClass'?

Will I be able to do a `new DynamicObject` just like I can currently do `new 
stdClass`?  I assume that instance would have a class of 'DynamicObject'?

And what of `new stdClass`?  Would `get_class(new stdClass)==='DynamicObject'` 
or would it continue to be `get_class(new stdClass)==='stdClass'`

Or would this be just like any class we can define today but that would still 
support dynamic properties whereas all other classes would disallow dynamic 
properties per the other proposal?

What about standard library functions that return a `stdClass` object?  (I 
assume there has to be at least one but I am not certain there is.). Assuming 
there are standard functions that return objects, will they now return 
'DynamicObject' or still 'stdClass'?

===

So while trying to get my head around the ramifications I prepared this bit of 
introspection, which is still missing some applicable tests I am sure:

https://3v4l.org/MDlOn#v8.0.10 

===

What I am struggling with here is to understand the vision for this change. Not 
that I find the change a bad idea — I do think it intimates a good direction — 
but at least as presented if feels like the vision for this may not have been 
fleshed out, or at least not fully communicated.

Maybe what I am looking for is a vision for what this change would mean for 
future PHP.  Is it just a special-cases that will cause as much confusion for 
developers trying to understand why there are too names for the same thing as 
it will help those who will better understand the new name, or is it more fully 
addressing the use-case for why people use dynamic objects?  

Maybe that's where we should start. I know there are some people who (I think) 
strongly argue that we should never use non-typed objects ever again but why do 
people use dynamic objects, still? This is a legitimate question, not a 
rhetorical, snide or sarcastic one. 

===

So what are the use-cases where dynamic objects still make sense, and just as 
importantly what about those use-cases is still suboptimal besides just the 
class name? (I can think of a few, but want to hear from others before I 
explain mine.)

-Mike

Re: [PHP-DEV] Make namespace part of runtime

2021-08-28 Thread Mike Schinkel


> On Aug 28, 2021, at 5:12 PM, Olle Härstedt  wrote:
> 
> 2021-08-27 23:07 GMT+02:00, Rowan Tommins  >:
>> On 27/08/2021 20:47, Olle Härstedt wrote:
>>> As a followup for my previous post, I think this could be a good place
>>> to start to enable attribute writers to create encapsulation mechanics
>>> for composition, like namespace visibility, "internal" access or
>>> friend classes.
>> 
>> 
>> In my experience PHP projects tend to use namespace hierarchies which
>> are deep rather than broad, and I'm not sure how easily those
>> hierarchies could be re-purposed as scopes.
>> 
>> Clicking through the Symfony source at random for an example, I found
>> "namespace
>> Symfony\Component\Messenger\Transport\Serialization\Normalizer", which
>> contains only one class.
>> 
>> A trivial implementation of namespace visibility which just matched the
>> exact namespace string would be completely useless for that class (it
>> would be the same as "private"). A slightly less trivial
>> implementationmight allow access from "child namespaces", but that
>> wouldn't help in this case.
>> 
>> However, it might be really useful to restrict usage of that class, or
>> some of its members, to classes in the "Symfony\Component\Messenger"
>> namespace; or maybe to those in the
>> "Symfony\Component\Messenger\Transport\Serialization" namespace.
>> 
>> I can see two ways of enabling that:
>> 
>> - Allowing visibility modifiers to specify exactly what level of prefix
>> they refer to. This is apparently how Scala approaches things, allowing
>> you to write the equivalent of "private[Symfony\Component\Messenger]
>> $foo; protected[Symfony\Component\Messenger\Transport\Serialization] $bar;"
> 
> Yes, I assume this is why Psalm introduced a new annotation
> @psalm-internal , which does take such a parameter. A PHP
> attribute can do this, _if_ it has access to runtime namespace.
> 
>> - Introducing a separate concept of "package", either orthogonal to
>> namespaces or overlapping with them, e.g. "package
>> Symfony\Component\Messenger; namespace
>> Transport\Serialization\Normalizer;" would still give a class name
>> beginning
>> "Symfony\Component\Messenger\Transport\Serialization\Normalizer", but
>> would define "internal" to mean accessible within the
>> "Symfony\Component\Messenger" package.
> 
> What's the estimated effort for adding package support to PHP? Did
> anyone outline a possible implementation?

In case you have not seen these, which discuss possibilities but at a higher 
level than actually how to implement:

https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/-language-evolution.md
 

https://phpinternals.news/45  

-Mike

Re: [PHP-DEV] Make namespace part of runtime

2021-08-27 Thread Mike Schinkel
> On Aug 27, 2021, at 5:07 PM, Rowan Tommins  wrote:
> 
> On 27/08/2021 20:47, Olle Härstedt wrote:
>> As a followup for my previous post, I think this could be a good place
>> to start to enable attribute writers to create encapsulation mechanics
>> for composition, like namespace visibility, "internal" access or
>> friend classes.
> 
> 
> In my experience PHP projects tend to use namespace hierarchies which are 
> deep rather than broad, and I'm not sure how easily those hierarchies could 
> be re-purposed as scopes.
> 
> Clicking through the Symfony source at random for an example, I found 
> "namespace Symfony\Component\Messenger\Transport\Serialization\Normalizer", 
> which contains only one class.

I have noticed the same, including in some of my earlier PHP code soon after 
namespaces became available.

I often wonder if those implement deep namespaces did so because "it seemed 
like a good idea at the time?"

I have since worked hard to minimize depth of any PHP namespace hierarchy I 
have worked with, and as a happy coincidence it reduces the complexity of the 
code in the projects that use those libraries.  #fwiw

> A trivial implementation of namespace visibility which just matched the exact 
> namespace string would be completely useless for that class (it would be the 
> same as "private"). A slightly less trivial implementationmight allow access 
> from "child namespaces", but that wouldn't help in this case.
> 
> However, it might be really useful to restrict usage of that class, or some 
> of its members, to classes in the "Symfony\Component\Messenger" namespace; or 
> maybe to those in the "Symfony\Component\Messenger\Transport\Serialization" 
> namespace.
> 
> I can see two ways of enabling that:
> 
> - Allowing visibility modifiers to specify exactly what level of prefix they 
> refer to. This is apparently how Scala approaches things, allowing you to 
> write the equivalent of "private[Symfony\Component\Messenger] $foo; 
> protected[Symfony\Component\Messenger\Transport\Serialization] $bar;"

+1 

> - Introducing a separate concept of "package", either orthogonal to 
> namespaces or overlapping with them, e.g. "package 
> Symfony\Component\Messenger; namespace Transport\Serialization\Normalizer;" 
> would still give a class name beginning 
> "Symfony\Component\Messenger\Transport\Serialization\Normalizer", but would 
> define "internal" to mean accessible within the "Symfony\Component\Messenger" 
> package.

+100

> 'm personally quite keen on the idea of packages, because they're how a lot 
> of PHP code is developed in practice - as modular libraries linked by 
> Composer - and I think we could optimise the language for that use (e.g. 
> applying more cross-file optimisations within a fully preloaded package).

Yes, agree.

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



Re: [PHP-DEV] [RFC] Deprecate dynamic properties

2021-08-26 Thread Mike Schinkel
> On Aug 26, 2021, at 11:02 PM, Pierre Joye  wrote:
> I don't know how others feel about it, I think most want to go the
> path to (2) and a more strict, if not almost fully strict PHP. Core
> devs to simplify the engine, users to allow them easier checks and
> safety in their frameworks or libs. End user don't really bother as
> far as I can see. We may have to decide once the long term vision for
> PHP and then do the changes accordingly, and more importantly, with
> consistency.

I tend to concur that path (2) would provide the better outcome. 

However, eliminating dynamic variables would be eliminating the ability to 
simulate a(t least one) language feature that some (many?) people have been 
using dynamic variables to simulate. Maybe as part of deprecation of dynamic 
variables we should also consider adding this(ese) feature(s) to the PHP 
language?

There are two approaches I can envision, Both would better enable the 
S.O.L.I.D. "open-closed" principle in PHP.  

1.) Allow PHP class declaration across multiple files — A use-case for this is 
what I think is effectively the command dispatcher pattern where properties 
contain instances of classes that might be contributed by 3rd party code to 
allow those developers to access the instances by named property: e.g. 
$cms->map->display() where $map is added by a 3rd party library to the class 
for the $cms instance before $cms is instantiated.  See:

https://gist.github.com/mikeschinkel/ed4f9594c105dae7371bfce413399948

Some might view this as "monkey patching" but I view it as a more structured 
approach, like C# partial classes.

2.) Allow trait usage for a class from another file — This is just a slightly 
different spin on #1. See:

https://gist.github.com/mikeschinkel/5b433532dc54adf53f5b239c8086fd63

Each approach has its own pros and cons but it probably depends on which would 
be easier and more performant to implement.

-Mike

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



Re: [PHP-DEV] Alternatives for encapsulation when using composition instead of inheritance

2021-08-26 Thread Mike Schinkel
> On Aug 26, 2021, at 9:47 AM, Olle Härstedt  wrote:
> 
> Don't know if this already exists, but maybe we could consider
> brainstorming or gather alternatives for different types of
> encapsulation when using composition? Currently, encapsulation like
> private and protected is only possible when using inheritance - when
> using composition, that is, class A is using (aggregating) class B,
> your only alternative is public, so full visibility (or
> getters/setters, which also is full visibility, since you can't limit
> who's using those methods).

When you say "composition" I think of traits, but it does not appear that is 
what you mean?

I have often wanted to be able to create a trait-private property so that I 
could write a `trait` and be confident that the classes that use it don't start 
using its internal properties and tie my hands in terms of being able to 
upgrade the trait to better internal approaches as I evolve the trait.

Would trait-private address any part of what you need?  Or would other 
trait-specific visibility address what you need? 

And if not, what about traits makes them not-applicable here?  Maybe we could 
also address that?

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



Re: [PHP-DEV] [RFC] Deprecate dynamic properties

2021-08-26 Thread Mike Schinkel
> On Aug 26, 2021, at 4:04 AM, Reindl Harald (privat)  wrote:
> Am 26.08.21 um 09:24 schrieb Mike Schinkel:
>> https://3v4l.org/HAkhjW#v8.0.9
>> Total execution time for 5000 iterations for BadActor = 0.351906 milliseconds
>> Total execution time for 5000 iterations for GoodActor = 0.758886 
>> milliseconds
>> Total time difference for 5000 iterations = 0.406981 milliseconds
>> Total time difference for 1 iteration = 1/12,286 millisecond
> 
> that's 46% dude

146% of effectively zero is still effectively zero.

-Mike



Re: [PHP-DEV] [RFC] Deprecate dynamic properties

2021-08-26 Thread Mike Schinkel
> On Aug 26, 2021, at 2:27 AM, Reindl Harald (privat)  wrote:
> Am 26.08.21 um 00:59 schrieb Mike Schinkel:
>>> On Aug 25, 2021, at 6:41 PM, Reindl Harald (privat)  
>>> wrote:
>>> Am 26.08.21 um 00:37 schrieb Mike Schinkel:
>>>> That said, I'd be really interested in seeing use-cases where having 
>>>> dynamic properties is essential to an architecture and where it could not 
>>>> be easily refactored.  I cannot envision any, but I am sure that I am just 
>>>> limited by the extent of my vision and so would like to know what those 
>>>> use-cases would be.
>>> 
>>> public function __get(string $subclass)
>>> {
>>>  $include_file = "{$this->basedir}/modules/{$subclass}/api_{$subclass}.php";
>>>  $class_name = "cl_{$subclass}";
>>>  if(!include $include_file)
>>>  {
>>>   $this->misc->trigger_error("API-LOADER FAILED: '{$subclass}'");
>>>   }
>>>  $this->$subclass = new $class_name;
>>>  $this->$subclass->cl_api = $this;
>>>  return $this->$subclass;
>>> }
>> Easily refactored:
>> public function __get(string $subclass)
>> {
>>   if (isset($this->subclasses[$subclass])) {
>> return $this->subclasses[$subclass];
>>   }
>>   $include_file = "{$this->basedir}/modules/{$subclass}/api_{$subclass}.php";
>>   $class_name = "cl_{$subclass}";
>>   if(!include $include_file)
>>   {
>> $this->misc->trigger_error("API-LOADER FAILED: '{$subclass}'");
>>   }
>>   $this->subclasses[$subclass] = new $class_name;
>>   $this->subclasses[$subclass]->cl_api = $this;
>>   return $this->subclasses[$subclass];
>> }
> 
> and now get is called every single time a property or method in the 
> class-tree is called instead only at the first call
> 
> means in the real world probably thousands of times for each website call - 
> congratulations

https://3v4l.org/HAkhjW#v8.0.9

Total execution time for 5000 iterations for BadActor = 0.351906 milliseconds
Total execution time for 5000 iterations for GoodActor = 0.758886 milliseconds
Total time difference for 5000 iterations = 0.406981 milliseconds
Total time difference for 1 iteration = 1/12,286 millisecond

"Premature optimization is the root of all evil" 
— Sir Tony Hoare 

-Mike

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



Re: [PHP-DEV] [RFC] Deprecate dynamic properties

2021-08-25 Thread Mike Schinkel
> On Aug 25, 2021, at 6:41 PM, Reindl Harald (privat)  wrote:
> Am 26.08.21 um 00:37 schrieb Mike Schinkel:
>> That said, I'd be really interested in seeing use-cases where having dynamic 
>> properties is essential to an architecture and where it could not be easily 
>> refactored.  I cannot envision any, but I am sure that I am just limited by 
>> the extent of my vision and so would like to know what those use-cases would 
>> be.
> 
> public function __get(string $subclass)
> {
>  $include_file = "{$this->basedir}/modules/{$subclass}/api_{$subclass}.php";
>  $class_name = "cl_{$subclass}";
>  if(!include $include_file)
>  {
>   $this->misc->trigger_error("API-LOADER FAILED: '{$subclass}'");
>   }
>  $this->$subclass = new $class_name;
>  $this->$subclass->cl_api = $this;
>  return $this->$subclass;
> }

Easily refactored:

public function __get(string $subclass)
{
  if (isset($this->subclasses[$subclass])) {
return $this->subclasses[$subclass];
  }
  $include_file = "{$this->basedir}/modules/{$subclass}/api_{$subclass}.php";
  $class_name = "cl_{$subclass}";
  if(!include $include_file)
  {
$this->misc->trigger_error("API-LOADER FAILED: '{$subclass}'");
  }
  $this->subclasses[$subclass] = new $class_name;
  $this->subclasses[$subclass]->cl_api = $this;
  return $this->subclasses[$subclass];
}

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



Re: [PHP-DEV] [RFC] Deprecate dynamic properties

2021-08-25 Thread Mike Schinkel
> On Aug 25, 2021, at 10:04 AM, Chase Peeler  wrote:
> 
> On Wed, Aug 25, 2021 at 9:51 AM Rowan Tommins 
> wrote:
> 
>> On 25/08/2021 13:45, Nikita Popov wrote:
>> 
>>> We obviously need to keep support for dynamic properties on stdClass,
>>> and if we do so, I would expect that to apply to subclasses as well.
>> 
>> Does that actually follow, though? Right now, there is no advantage to
>> extending stdClass, so no reason to expect existing code to do so, and
>> no reason for people doing so to expect it to affect behaviour.
>> 
>> 
>>> Second, I consider "extends stdClass" to be something of a last-ditch
>>> option. If you encounter a dynamic property deprecation warning, you
>>> should generally resolve it in some other way, and only fall back to
>>> "extends stdClass" as the final option.
>> 
>> 
>> That's a reasonable argument in terms of the multiple inheritance case.
>> 
>> My concern about the name remains though: people already do get confused
>> by the name "stdClass", because it's not in any way "standard", and
>> tells you nothing about what it does.
>> 
>> Reading "class Foo extends stdClass" gives the reader no clues what
>> magic behaviour is being inherited; "class Foo extends DynamicObject"
>> would be much more clear. Similarly, "$foo = new DynamicObject;
>> $foo->bar = 42;" is clearer than "$foo = new stdClass; $foo->bar = 42;"
>> 
>> Regards,
>> 
>> --
>> Rowan Tommins
>> [IMSoP]
>> 
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: https://www.php.net/unsub.php
>> 
>> 
> Please don't do this. Call it bad coding practices or not, but this was
> something I've considered a feature of PHP and have actually built things
> around it. It's not something that can be easily refactored since it was
> part of the design.

While I tend to really object to BC breakage, when I saw this proposal I was 
all for it because it disallows a practice that I have seen used all too often 
in cases where there was no good reason to not declare the properties, and I 
know that to be fact because the cases I am referring to are ones where I 
refactored to use declared properties.

That said, I'd be really interested in seeing use-cases where having dynamic 
properties is essential to an architecture and where it could not be easily 
refactored.  I cannot envision any, but I am sure that I am just limited by the 
extent of my vision and so would like to know what those use-cases would be.

-

Speaking of, it would seem like if dynamic properties were to be deprecated PHP 
should also add a function that would allow registering a callable as global 
hook to be called every time ANY object has a property dynamically accessed or 
assigned — conceptually like how spl_autoload_register() works — so that 
developers could run their programs to see what properties are used.  The hook 
could collect class names, property names and data types to help developers who 
need to update their code discover the information required for their class 
declarations.  Because doing it manually is a real PITA.  As would be adding 
__get()/__set() to every class when you have lots of classes and you'd need to 
delete all that code later anyway.

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



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-15 Thread Mike Schinkel
> On Aug 15, 2021, at 7:06 PM, Alexandru Pătrănescu  wrote:
> 
> If I see an interface that was created just so it can be implemented by
> multiple classes but the caller doesn't use the interface but it uses the
> actual classes, I call it out as that is the wrong abstraction and the
> interface should just be removed.
> 
> Your example with ArrayAccess is similar with this; when using it, you know
> exactly what implementation you have. The interface is not helping here
> related to polymorphism but it is actually required to allow a language
> construct related to the engine itself, to translate accessing an object
> with the same syntax as for an array.
> 
> If the 4 functions would have been magic methods, without an interface, you
> would not have this problem.

That is very insightful. 

It seems that back when PHP only had a hammer, PHP used a hammer. But now that 
PHP has a better tool for the job maybe PHP should change course?

More specifically, since ArrayAccess is primarily being used as a class 
annotation and not to enable polymorphism maybe the best course of action would 
be to deprecate having `ArrayAccess` the interface being an annotation and to 
instead having `#[ArrayAccess]` the attribute tell PHP to allow indexing 
instances of the class like an array?


> On Aug 15, 2021, at 6:22 AM, Jordan LeDoux  wrote:
> 
> 2. Interfaces have more purposes than just standing in for classes in a
> type hint. Interfaces also guarantee an implementation.

Correct.  Which is why interfaces that allow for non-specific types — e.g. 
`mixed` or `never` — weaken that guarantee[1].

If `never`-parameter interfaces were to exist then code that passes a parameter 
to a `never`-parameter method would first have to check via reflection if the 
type if wants to pass will be accepted. That nullifies the guarantees of an 
interface.

I think the reason for envisioning `never` as an option to address the concerns 
it attempts to address is the unfortunately ramification of, as Alex 
identified, the choice to use an interface as a signal to provide language 
specific behavior to a class rather than to enforce polymorphic behavior. 

So rather than double down on features based on leaky abstractions better to 
backtrack and correct the original sin IMO.

-Mike



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Mike Schinkel
> On Aug 14, 2021, at 10:40 AM, Jordan LeDoux  wrote:
> 
> Never is treated as the bottom type for the purpose of Liskov substitution
> already with its use as a return type. The exception to this in its use as
> a return type is that it isn't treated as the union identity in the return
> type. However, for LSP never is the bottom type when it comes to return
> values. It would, in my mind, be highly inconsistent to have a different
> bottom type for return values than for arguments, so personally I am very
> against using a term other than never. As mentioned in the doc, I wasn't
> able to find a single existing language that has multiple bottom types. If
> anyone is able to provide an example of this, I would appreciate it.

Reading through all the replies on this topic it seems that the functionality 
for the proposal is less controversial than the keyword chosen to identify it.  

It occurs to me that while `never` is the correct keyword for the bottom type 
given past decisions, maybe choosing to use a bottom type to provide this 
functionality is not an idea choice?

If we approach this use-case requirements from a perspective of "this keyword 
indicates that you must implement in a child" then I think we already have a 
keyword that has appropriate semantics compared with the confusing semantics of 
`never` used for a parameter: `abstract`.

So then instead of `never` we could choose the following:

 interface CollectionInterface
 {
 public function add(abstract $input): self;
 }

`abstract` could also work for return types and property types:

 interface Foo
{
 public abstract $bar;
 public function baz(): abstract {}
}

Or am I missing something?  Is there a reason `abstract` would not be a better 
choice than `never`?



That said, I do have a rhetorical question to ask, to be pondered by those who 
are better attuned to the ramifications of allowing interfaces to become less 
strict than they already are.

From my career-long understanding of declared interfaces the primary (only?) 
reason to use them is to signal and enforce a guarantee that a specific set of 
signatures are available in an instance of a class that implements the 
interface. But if an interface can be defined as something that can can easily 
change based on the implementor, the guarantee that we could previously depend 
on its signatures will no longer be, well, guaranteed.

My gut feeling tells me that will be a bad direction for us to take with PHP.  
What do other's think?



After writing the above it occurred to me the solution to the above problem 
already conceptually exists, too, classes get to use the `abstract` keyword 
when their children need to be required to implement something.

If PHP requires interfaces with parameters defined as type `abstract` (or 
`never` if we must)  then those interfaces should also be required to be 
declared `abstract`:

 abstract interface CollectionInterface
 {
 public function add(abstract $input): self;
 }
 Class IntCollection implements CollectionInterface 
 {
 public function add(int $input): self;
 }

The primary tangible difference between abstract and concrete interfaces would 
be in documentation, reflection, and possible an is_abstract() function so that 
code that needs to ensure an exact specific interface could do so.

The benefit of this approach as it appears to me is that (concrete) interfaces 
can retain their same level of guarantee where abstract interfaces would not be 
required to maintain such a guarantee.  #jmtcw

Thoughts?

-Mike

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



Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-11 Thread Mike Schinkel
> On Aug 11, 2021, at 5:25 AM, Jordan LeDoux  wrote:
> 
> I want to avoid this. :) The implementations in my actual math libraries are 
> much more thorough and thought out. This is an example. If people want to see 
> something that is closer to what would actually be done in a library, they 
> should look at an actual library. So instead, that's what I'll link to:
> 
> Here's the multiply method: 
> https://gist.github.com/JordanRL/98cceb392ba5ba943462fe574f18de51 
> 
> Here's the translateToParts method: 
> https://gist.github.com/JordanRL/2c67acb3b5d3069c3a4d2f0448a480d1 
> 
> Here's the PolynomailFunction: 
> https://gist.github.com/JordanRL/673e357e7f5cf63bd4554fb3161c026b 
> 
> 
> You can think of ImmutableDecimal as Real|Imaginary, but with methods such as 
> $obj->isReal() and $obj->isImaginary() on it.
> 
> This is just for the __mul() method. The intent of this example is to show 
> the nature of the problems being solved, not to show the actual solutions. 
> Think of this as syntactically correct pseudo-code, not an actual 
> implementation.

Well, I refactored not to provide an actual implementation but to try to show 
the problems being solved in a manner that could be more easily understood. But 
it is your RFC, so it's yours to decide how code is presented.



Anyway, I'll summarize as I am going to try to wrap up my participation in this 
topic, at least for now:

1. I argue that it would likely be a mistake to add general purpose operator 
overloading to classes in PHP (or at least before a lot of experience with #2.)

2. However, I recognize there are use-cases which beg for operator overloads I 
think PHP. And I believe those use-cases are finite: money, the math examples, 
and units[1] being three (3) subsets.  I think PHP would be better served by 
adding those use-cases as standard library classes[2] instead of adding general 
purpose operator overloading to the language.

3. However, *if* there is strong consensus that we should add general purpose 
operator overloading then I argue that it should be limited to "value" objects, 
which currently would mean only classes where all public and protected 
properties are read-only[3].

4. And even if we do #3 that is no reason for us not to consider also doing (at 
least some of) #2.

#fwiw

-Mike



[1] https://www.nist.gov/pml/weights-and-measures/metric-si/si-units 


[2] I mean, how great would it be to have a Length class with unit conversions 
built into PHP?  Or a Money class that all libraries that deal with Money would 
be able to interoperate with? Having these non-changing concepts built-in to 
PHP would be a strong reason developers to choose PHP over other options like 
Node where they have to manage tons of ever-changing and incompatible 3rd party 
dependencies. Better that than 10+ different userland implementations of the 
same bedrock concepts, many of which are incomplete and all of which are 
incompatible with each other.

[3] Yes, private property values could be changed by methods and thus leak to 
the outside. But that could be considered an anti-pattern. If said private 
property(s) (partially) represent the state of the object and are not readonly 
then we could simply recognize that as an unchecked bad practice.



Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-11 Thread Mike Schinkel
> On Aug 11, 2021, at 12:06 AM, Jordan LeDoux  wrote:
> 
> Here is a quick and dirty example of just the complex number use case. It
> assumes that the operator overloads already are built in. A couple of
> things of note:

Excellent. Thank you for taking the time to do this.  Very helpful.

One thing I looked for at first but did not find was an actual example of how 
you would use them vs. how they would be implemented.  So I forked it and 
created such a file to see if I could understand how they would be used:

https://github.com/mikeschinkel/operator-overloading-rfc/blob/master/use-cases/complex-numbers/example.php

It that what you envision?  To create a ComplexNumber() do I first need to wrap 
in Real() and in Imaginary()?  Or where you intending I could just pass numeric 
literals? If yes, PhpStorm said your type hints did not allow it.

> 1. The actual mathematical logic to cover all the possible input and return
> types is extensive. Though the execution time and complexity are quite
> limited, the code complexity is high due to the number of conditionals.

Yes, the complexity overwhelmed me at first glance, but I don't think it needs 
to be so complex, which I will get to below.

> 2. I chose to implement the various operator overload functions in
> different ways to illustrate different methods that might accomplish the
> same task in userland code. For instance, in some cases I typed against the
> SimpleNumber abstract, while in others I expanded SimpleNumber out into its
> concrete implementations, Real and Imaginary.

Yeah, that kind of threw me to, because I looked at the code before I read your 
email.

And it still throws me because I'm not 100% clear how SimpleNumber is supposed 
to behave. 

1. In your examples would I use `SimpleNumber` anytime I see `Imaginary|Real`?

2. I notice in SimpleNumber methods you pass SimpleNumber $self as a first 
parameter to __add() and __mul() and in ComplexNumber you pass ComplexNumber 
$self as a first parameter, but in ComplexNumber you never use it. Obviously 
the __add() and __mul() signatures would need to be equivalent, but I didn't 
grok why you didn't just use $this instead of $self so I omitted that parameter 
in my fork.

3. I'm not sure why we even need a `Real` class, other than the fact PHP 
doesn't (currently?) support operations on numeric literals and imaginary 
numbers. Check my logic here but if PHP understood complex numbers then `Real` 
could just be a `float`. But with just userland operator overloading we have to 
wrap a float inside an instance of Real, right? 

4. It looks like you added a $left = bool parameter but never used it.  I 
assume the intent is that PHP for some reason might want to convert `$x + $y` 
to $y->__add($x,true)?  When would it need that?  Seems that the $left 
parameter just makes the signature more complex.  I dropped it from my fork.

Also, this really cries out for userland type definitions and type aliases 
(which can and IMO should be two distinctly different things, btw.):

`SimpleNumber|ComplexNumber|int|float $other`

> 3. I only implemented the _add() and __mul() methods for this example, as
> the reality is that getting into some of the more complex operations would
> be so much code that it wouldn't be a digestible example. The __pow()
> method for ComplexNumber would be in excess of 100 lines and also require a
> polar coordinate representation within the class, for instance.

Sure.  

But it would be nice if you could also stub out __pow() and any others abstract 
methods so the full list of expected operations and their parameters. 

BTW, when I asked I wasn't expecting to see an implementation for any of the 
methods, I was just asking for an interface.  You went above and beyond that.

And, since you are writing code that won't run anyway, why not go ahead and 
assume a `typedef`? That would greatly reduce the visual complexity of your 
example:

typedef Number: Imaginary|Real|SimpleNumber|ComplexNumber|int|float;

> This isn't a working implementation, in that this code will produce errors
> if run in PHP (due to the absence of operator overloads). Please note that
> if we were to go the route of creating domain-specific classes to cover
> this use case, the actual classes would be many, many times longer than
> this.

Yes, of course.

> This is some of the simplest logic involved in this particular use
> case, which is why I chose it as the example, and that perhaps illustrates
> why I am willing to explore such objects but do not believe they are the
> best choice at this time.

So I promised to explain how to simplify the logic. This has nothing to do with 
operator overloads so anyone reading who is only interested in the RFC can stop 
reading now.

-Mike



There is a concept called the "Happy Path"[1] which is " is a default scenario 
featuring no exceptional or error conditions." It is often used to refer to 
testing, but there is an emerging trend where people are arguing that 

Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-10 Thread Mike Schinkel
> On Aug 10, 2021, at 10:22 AM, Larry Garfield  wrote:
> 
> Point of order: I do not support a dedicated value-object/data-object 
> construct, and have said so explicitly.  I support targeted tools that make 
> using objects in that fashion cleaner and more robust.  (readonly, asymmetric 
> visibility, clone-with, etc.)  Please do not misrepresent my position, 
> especially when I've been fairly consistent on it.
> 
> Also, one of the biggest failings of SPL is the degree to which it leverages 
> and forces extension rather than interfaces.  Inheritance is a code reuse 
> tool, NOT an architecture tool.  That's what interfaces are for.  We know 
> this.  We've been bitten by this.  Building any kind of inheritance-based 
> operator overloading into the language would be a terrible idea.  Let us 
> never speak of it again.


Seems that you have chosen to callout a distinction and take offense to[*] that 
I was never intending. 

When I referenced value objects the *how* was not the important part of my 
discussion but instead that fact that we do get there, evidenced by my use of 
"Or ???" when hypothesizing.

If the way PHP gets there is that a value object is an object where all 
non-private properties are explicitly declared readonly then that is as 
workable as if we explicitly define the class with a "value" keyword. I don't 
really care as I see it as a distinction without a difference. 

Either way if PHP can identify a value object then it could limit operator 
overloads to just classes that are value objects by whatever approach PHP 
chooses to distinguish.


-Mike
[*] Ironically I mentioned you because I thought you would be appreciate seeing 
another reason PHP could benefit from value objects. But as they say, no good 
deeds go unpunished.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-10 Thread Mike Schinkel
> On Aug 9, 2021, at 8:40 PM, Jordan LeDoux  wrote:
> That is in part of why I asked for use-case examples, to see if there really 
> were a lot of use-cases where operator overloading makes sense.  You only 
> provided two categories; Math and the already existing DateInterval. 
> 
> This seems... a bit reductionist? I suppose if you consider anything that has 
> a numeric value "math", then sure. 

I can see how you might have interpreted my reference to Math as "all math."  

However, I was only referring to the explicit list you provided. Again, for 
reference:

Math

- Complex number objects
- Fractions objects
- Matrix objects (math)
- Vector objects (math)
- Arbitrary precision numbers (which are usually represented as a string in PHP)


> Math is extremely large. Geometry is very different from matrices, which is 
> very different from arithmetic, which is very different from complex numbers.

So that gives me two (2) thoughts

1.) First is Geometry would be another area for PHP to consider adding classes.

2.) Then I thought: What if PHP had the ability to explicitly define *value* 
objects?  I know this has been something Larry Garfield has mentioned[1] in the 
past.  

What if we had a new type of class that is to be used only for value objects. 
Following Larry's lead they would be immutable. And if we had those then I 
think adding generic operators overloading to value objects would make a hell 
of a lot of sense.  Maybe:

#[\PHP\Value]
class ComplexNumber{}

Or:

class ComplexNumber value{}

Or:

???

Can you see any reason why only allowing the addition of operator overloads to 
*value* objects would too limiting? 

IMO that would minimize the abuse potential for implementing operators as a 
leaky abstraction when developers are ignorant of the ramifications and/or are 
more concerning about their convenience than longer term maintainability. 

[1] https://twitter.com/Crell/status/621715583403487232

> Again, I'm providing those examples because I can literally bring up code 
> from my own libraries for those, so I'm a good advocate for them. But others 
> certainly exist. I think you would throw this under "math", but what about 
> unit-based values? If you wanted to do `19cm + 2m`, you could return `219cm`, 
> or `2.19m`, or `2190mm`. Supposing that there was an abstract, how would it 
> know what unit conversion to use? Or what about `2km + 4mi`? Or what about 
> erroring for `2km + 4L`?

Length is a really great example, thanks for bringing it up.  

According to NIST there are seven (7) base units[2] where "Definitions of all 
seven (7) SI base units are expressed using an explicit-constant formulation 
and experimentally realized using a specific mises en pratique (practical 
technique)."  

This means they are well-known and unlikely have changing requirements. They 
are:

• Length e.g. meters
• Time e.g. seconds
• Amount of substance e.g. moles
• Electric current e.g. amperes
• Temperature e.g. kelvin
• Luminous intensity e.g. candela
• Mass e.g. kilogram

Those seem like a great *finite* list of fundamental units I would argue PHP 
could benefit userland developers greatly by adding *standardized* classes to 
handle them, maybe in a `PHP\Units` namespace.  We already have Time.

Then I can envision a `Value` base class, trait(s) and/or interfaces that could 
support generic unit conversion that these specific units, like Length.  1 'm' 
could be defined equal to 100 'cm' and then this could be possible:

use PHP\Units\Length;
$length = (new Length(19,'cm')) + (new Length(2,'m'));
echo $length->toCentimeters(); // prints 219
echo $length->toMeters(); // prints 2.19 
echo $length->toMillimeters();   // prints 2190

$length = (new Length(2,'km')) + (new Length(4,'mi'));
echo $length->toMiles();  // prints 5.24274
echo $length->toKilometers(); // prints 8.43736

Then something like this could also be valid, and be what the above is actually 
built on:

use PHP\Units\Units;
use PHP\Units\Value;
$units = new Units();
$units->addUnit('m','Meter');
$units->addUnit('cm','Centimeter');
$units->addUnit('mm', 'Millimeters');
$units->addConversion('cm','m',100);
$units->addConversion('mm','m',1000);
$length = (new Value(19,'cm',$units)) + (new Value(2,'m',$units));
echo $length->toUnit('cm');// prints 219
echo $length->toUnit('m');  // prints 2.19 
echo $length->toUnit('mm');   // prints 2190

$units->addConversion('m','km',1000);
$units->addConversion('mi','km',1.60934);
$units->addUnit('km', 'Kilometers');
$units->addUnit('mi','Miles');
$length = (new Length(2,'km',$units)) + (new Length(4,'mi',$units));
echo $length->toUnit('km');// prints 5.24274
echo $length->toUnit('mi'); // prints 8.43736

We could even open up the discussion of having scalar literals for these types, 
e.g. where `2m` is a 2 meter  value object of type Length.

Note that having value objects and having these seven 

Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-09 Thread Mike Schinkel
On Aug 9, 2021, at 5:32 PM, Mike Schinkel  wrote:

> On Aug 9, 2021, at 1:48 PM, Jordan LeDoux  wrote:
> You claim that this would be documented on php.net and this would be 
> sufficient. Yet the DateTime class has had operator overloads for comparison 
> operators since 5.2 and there is still *zero* mention on php.net (that I am 
> aware of or can find) of this. Not even a mention that it exists, let alone 
> what the override behavior is. *Not even in the god-awful comments on the 
> manual.*

Improving documentation is an easier fix than adding a complex language 
feature. And a key difference is (almost?) anyone who is motivated can 
contribute to the docs; not so for adding language features. 

For example, why is it not an option for you to update the docs for DateTime 
and DateInterval if the docs are bad? Or other classes that have could have 
operator overloading in the future?

> Simply put, as someone who has spent my entire career working primarily in 
> PHP and been working in it since PHP 4, it has one of the very best free and 
> online manuals for any language I've worked in, and I would still 10 times 
> out of 10 prefer to be able to see the implementation in my IDE than have to 
> look it up on php.net.

So are you arguing that PHP should have no library functionality and have 
everything implemented in PHP? 

I don't mean to commit a reductio ad absurdum, but I am honestly confused by 
your need to see the implementation of behavior in PHP that is well-known and 
well-established in science and business.  

I honestly don't get why it would be important to see the internals of DateTime 
and DateInterval class, or a ComplexNumber or a Money class for that matter. 
Why can't that just be documented, other than your claim that "docs are bad?"  

Why it will be important to see operator overloading implementations in PHP 
when you don't see sin() and cos(), for example?

This really feels like a personal preference and not a driving need for 
everyone. But if others agree that seeing operator overloading in PHP code is 
critical, please do speak up and, for my edification, please do explain why.

>  What I mean is that there would be multiple "number like" abstract classes 
> that would be 80% to 90% similar. That is, if it actually correctly 
> represented the core math ideas. This method however would utterly fail for 
> unit based value overloads, of which Rowan's money example is a specific case.

Yeah, I don't see this as a problem.  Internally if there are a lot of 
similarities than the similarities can be shared by a common function. 

Duplication is not a problem in an of itself. If you only have to write it once 
and rarely ever need to maintain it.

> However, creating abstract classes simply for custom operator overloads would 
> signal to users that this is something internals is willing to do. Despite 
> the fact that I am confident the process would continue to work, I would very 
> much anticipate multiple and continuous threads opened by users wondering 
> when "their" operator overloads are going to be included. While this 
> obviously doesn't force anything, it absolutely is a distraction.

That is in part of why I asked for use-case examples, to see if there really 
were a lot of use-cases where operator overloading makes sense.  You only 
provided two categories; Math and the already existing DateInterval. 

It's not like operator overloading is a feature which without developers 
literally cannot implement functionality. Even though you (currently) cannot 
compose an expression of objects like `$cn1 + $cn2` doesn't keep you from 
implementing `$cn1.add($cn2)`.

Let us assume that because we were to create operator overloads for DateTime 
and DateInterval and for your Math needs people started inundating the list 
with requests to add hundreds of other classes (I really doubt that would 
happen, but I'm running with it anyway.) 

One easy answer is for the list to come up with a checklist for operator 
overloading concerns and request those asking to present userland libraries 
that would want operator overloading and show how the libraries would address 
the concerns in the checklist. Once done, then the list could review and make a 
decision.

OR, *if* the list really is inundated with requests, maybe we *then* realize 
there are many use-cases, and we move towards a generic operator overloading.  

But as of today I am not convinced that there are really that many use-cases 
for operator overloading that would not just be a leaky abstraction.

(As an aside, how are we going to implement operator overloading in DateTime 
and DateInterval within PHP?  Do we have to subclass just to get them to have 
operators?  So minimally, we should start with those two and write it in C for 
PHP core.)

>> https://medium.com/@rwxrob/operator-overloading-is-evil-8052a8ae6c3a
&g

Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-09 Thread Mike Schinkel
> On Aug 8, 2021, at 3:41 AM, Jordan LeDoux  wrote:
> 
> Off the top of my head here are some of the use cases that I think benefit 
> greatly from this:
> 
> - Complex number objects
> - Fractions objects
> - Matrix objects (math)
> - Vector objects (math)
> - Time/Date intervals
> - Collections
> - Arbitrary precision numbers (which are usually represented as a string in 
> PHP)

Thank you for going to the effort to list those out.  I'd like to categorize 
them, if I may?


General Purpose
- Collections

I'm not sure if you there is something about Collections related to Math that 
makes them applicable for operator overloading but otherwise I would be 
question whether there would be a strong consensus around what operators a 
collection would implement and how those operators would behave.  

If you think there would be a strong consensus regarding collections and 
operators maybe you could elaborate on which operators would apply and what 
each would do?


Date/Time
- Time/Date intervals

This seems to me to be a great use-case. Ironically we already have the 
DateInterval class as well as methods that operate on DateTime objects that add 
and subtract DateIntervals as well as proving the different between two dates.

Because we already have the classes, this seems to be a perfect place to start 
with an RFC to introduce operators to PHP for DateTime and DateInterval 
objects.  

More on this in a bit.


Math
- Complex number objects
- Fractions objects
- Matrix objects (math)
- Vector objects (math)
- Arbitrary precision numbers (which are usually represented as a string in PHP)

And these all seem like strong candidates for classes that could use operators. 
 

But mathematical concepts are pretty well set in stone; are there really this 
many different ways to implement them (rhetorical question)?:

> Here are some actual user libraries which would probably use them:
> 
> - samsara/fermat (this library is mine as a matter of disclosure)
> - brick/math
> - markbaker/complex
> - markbaker/matrix
> - krowinski/bcmath-extended
> - malenki/math
> - markrogoyski/math-php
> - rubix/tensor
> - numphp/numphp
> - mcordingley/linear-algebra

Looking at the tests for just complex numbers in just three (3) of these I see 
distinctly different choices, choices which appear to be arbitrarily made by 
each developer:

1. 
https://github.com/SamsaraLabs/FermatComplexNumbers/blob/master/tests/Samsara/Fermat/Values/ImmutableComplexNumberTest.php
2. 
https://github.com/MarkBaker/PHPComplex/blob/3.0/unitTests/classes/src/ComplexOperationTest.php
3. https://github.com/malenkiki/math/blob/master/tests/Number/ComplexTest.php

I really can't critique the math aspects nor fully grok your use-cases, but do 
I understand the benefit of standardization, and it seems like PHP would gain 
greatly for use in the math domain by introducing classes written in C and 
baked into core for each of your math use-cases.

And the same with the Money classes that Rowan proposed.

But I know you objected to that approachmore on that at the end.

> As for constraints... well, if I had absolutely no concern for implementation 
> at all, and was just designing what constraints to put on the magic methods, 
> they would be:

> 1. void is an unsupported return, and failing to return a value results in an 
> error.
> 2. Variables outside the scope of the method cannot be set. This includes 
> properties on the object which is defining the magic method, and includes 
> sets that occur in called functions and methods.

When I mentioned "constrained" I was referring to Rowan's distinction:

> On Aug 7, 2021, at 3:07 PM, Rowan Tommins  wrote:
> In a previous thread [1], I wrote about two fundamental design approaches to 
> operator overloading:
> 
> a) Treating operators as arbitrary symbols, which can be assigned any 
> operation which makes sense in a particular domain.
> b) Treating operators as having a fixed meaning, and allowing custom types to 
> implement them with that meaning.

Where a) would be "unconstrained" and b) would be "constrained."  I think you 
assumed I was referring to something else.

> In any case, it is certainly possible that we could instead implement some 
> magic *objects* which can be extended that have built-in overloading in 
> specific ways. I think this is actually worse for the following reasons:
> 
> 1. It would be far less obvious to the programmer that an object would behave 
> differently with a given operator, because the behavior wouldn't be 
> documented in the code itself.
> 2. It would require many different implementations, some of them very close 
> to each other, to cover the same set of use cases.
> 3. It would likely result in some maintainability concerns as more users 
> demanded different DSL type implementations be included in core, and the 
> existing ones would need to be maintained.

I am going to challenge your 

Re: [PHP-DEV] Revisiting Userland Operator Overloads

2021-08-07 Thread Mike Schinkel
> On Aug 7, 2021, at 10:28 AM, Larry Garfield  wrote:
> 
> The downside is that 30 seconds after that, 15 other libraries would do the 
> same in subtly incompatible ways, and then both Laravel and Symfony would 
> release their own that are incompatible with each other, and it would just be 
> a total mess because you would have NFI what any given operator is going to 
> do.  Then FIG would try to define a few to standardize the madness, would 
> take about 10-12 months to do so, but both Symfony and Laravel would go on 
> using their own instead because they're big enough that they can do that, and 
> we'll have a mess basically forever.  That is what my crystal ball tells me 
> would happen.
> 
> So while this approach appeals to me personally, I think in the long run it's 
> probably a bad idea.  My understanding is that many people consider C++'s 
> adoption of this approach a mistake, although I'm not a C++ developer so 
> cannot speak from first hand experience.

I strongly echo Larry's concern here. 

While I tend to be one who wants more language features, not less, the 
availability of unconstrained operator overloading can beckon an inexperienced 
and/or undisciplined developer to add operators for many of the classes they 
implement, whether or not doing is actually applicable or a good idea.

I am even concerned about constrained operator overloading for the same reason. 
 Here [1][2] are a couple essays to argue against operator overloading.

Ruby has operator overloading, and one of the distasteful aspects I found 
regarding in programming in Ruby was that everybody's Ruby code you looked at 
felt like I was written in a slightly different language. I would hate that to 
become the case with PHP, more than it already is.

I am actually surprised that the last operator overload RFC came close to 
passing because adding it seems like it would open a Pandora's box and yet 
other proposals that are less Pandoric seem to be anathema on this list.

That said, I am not unsympathetic to the fact that operator overloading may 
well have some extremely valid use-cases, just ones that I do not personally 
seem to need on a day-to-day basis when writing code.

Operator overloading seems to me to be of more value to those who are 
essentially wanting to write DSLs (domain-specific languages.) If that is 
indeed the case, and there are some DSL like features I wish we could add to 
PHP that would generally be non-starters for non-DSL usage.

I wonder if there is a way to limit to only DSL use-cases?  I doubt there is, 
but I had to pose the question in case someone else can envision a way to do so.

So my main questions are:  

1.) What are use-cases where operator overloading would really be valuable?  

2.) Would it possible that instead of adding operator overloading we could add 
classes that could be extended where PHP actually defines the operators for 
those classes?  

If we can do #2 we can really work through all the issues with commutativity, 
associativity, etc. and also implement all and only the operators that make 
sense for the use-case.


> On Fri, Aug 6, 2021, at 3:18 PM, Scott Arciszewski wrote:
>> My recommendation is to have a base interface for every operator that can
>> be overloaded, so that these can be composed together.
>> 
>> AddOverloadInterface { __overloadAdd(): self; }
>> SubOverloadInterface { __overloadSub(): self; }
>> MulOverloadInterface { __overloadMul(): self; }
>> DivOverloadInterface { __overloadDiv(): self; }
>> ModOverloadInterface { __overloadMod(): self; }
>> LeftShiftOverloadInterface { __overloadLeftShift(): self; }
>> RightShiftOverloadInterface { __overloadRightShift(): self; }
>> XorOverloadInterface { __overloadXor(): self; }
>> etc.
> 
> That would be roughly how Stringable/__toString works now.  I'd be OK with 
> that, if it's going to be a language trend.

If this is how it turns out, I would hope for consistent naming, e.g. Addable 
vs. AddOverloadInterface, Subtractable vs. SubOverloadInterface, and so on.


> On Aug 7, 2021, at 1:48 PM, Dan Ackroyd  wrote:
> On Fri, 6 Aug 2021 at 21:18, Scott Arciszewski  wrote:
>> It's probably worth exploring whether common combinations are worth
>> defining for convenience.
> My understanding of the current consensus is "let's not".
> 
> That's based from the discussion on whether defining 'number' as 'int
> | float' would be worth doing, mostly because adding aliases don't
> provide much value, 

While it may (or may not?) be consensus, I argue the counter which is that 
adding `number` to PHP to mean `int|float` would provide the value of:

1.) Standardization and 
2.) interoperability between libraries that use `number`.  

This argument *assumes* there would be a strong consensus that `number` should 
actually mean `int|float` and not something else, or not some other name.

For clarity I am not arguing that number *means* int|float — I'd have to review 
the debate and see if there was strong consensus — but 

Re: [PHP-DEV] [RFC] Add parse_query_string as an alternative to parse_str

2021-08-06 Thread Mike Schinkel
> On Aug 6, 2021, at 3:51 AM, Aleksander Machniak  wrote:
> 
> I agree about the _string suffix removal. However, I know we have
> parse_url() already, but parse_query() might be too generic. I would
> suggest adding "http" to the name. And as we already have
> http_build_query() I would rather see http_parse_query().

+1.  http_parse_query() is even better. 

-Mike

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



Re: [PHP-DEV] [RFC] Add parse_query_string as an alternative to parse_str

2021-08-06 Thread Mike Schinkel
> On Aug 5, 2021, at 6:21 PM, Kamil Tekiela  wrote:
> 
> I have added implementation for
> https://wiki.php.net/rfc/parse_str_alternative. If there are no other
> comments, I would like to start voting on Saturday.


I too would appreciate having a function in the PHP library that returns an 
array and that is named more intuitively than parse_str().

However, I would suggest naming it `parse_query()` instead of 
`parse_query_string()` as `_string()` is redundant and I see shorter function 
names being preferable when the intent of the function is clear.

I searched for prior art and it appears that Guzzle's PSR7 helper library v1.x 
had a namespaced parse_query() function:

https://github.com/guzzle/psr7/blob/1.x/src/functions.php#L299 


I found Psr7\parse_query() being called on GitHub in 840 places using 
SourceGraph code search:

https://sourcegraph.com/search?q=context:global+lang:php+Psr7%5Cparse_query%28+count:all=literal
 


There was only one (1) place with SourceGraph code search where someone named a 
function parse_query_string(), and that example did not use 
parse_query_string() in the same way as your RFC:

https://sourcegraph.com/github.com/k0a1a/hotglue2/-/blob/controller.inc.php?L344:1
 


My takeaway is that PHP developers will easily be able to understand the intent 
if named `parse_query()`, especially those who might be familiar with it from 
Guzzle, and thus there is no need for the redundant `_string()`.  

And, of course, a parse_query() in the global namespace won't conflict with 
Guzzle's use because their function is namespaced with Guzzle\Psr7.

> On Aug 6, 2021, at 3:17 AM, ignace nyamagana butera  
> wrote:
> 
> I feel that we are missing a chance to also improve how parse_str
> algorithm is currently used, we could or should (?) use this opportunity
> to fix some long shortcomings around parse_str.

Also, +1 to this.

-Mike

P.S. WordPress has a parse_query() *method* on their WP_Query() class, but as 
someone who has worked with WordPress for 10+ years even I don't see these two 
in conflict. One is a method scoped to the solution domain of its class and the 
other would be a function in PHP's global namespace.

[PHP-DEV] Implicit Interfaces? (was [PHP-DEV] [RFC] Nullable intersection types)

2021-07-28 Thread Mike Schinkel
> On Jul 27, 2021, at 11:02 PM, Jordan LeDoux  wrote:
> 
> Intersection types are very useful if you use composition over inheritance.
> That is, in PHP, they are most useful when you are using multiple
> interfaces and/or traits to represent different aspects of an object which
> might be present. For example, using an actual library I maintain, I have a
> concept of different number type objects.
> 
> NumberInterface - Anything that represents a cardinal number of any kind
> will share this.
> SimpleNumberInterface - Anything that represents a non-complex number will
> share this.
> DecimalInterface - Anything that is represented as a float/decimal will
> share this.
> FractionInterface - Anything that is represented with a numerator and
> denominator will share this.
> ComplexNumberInterface - Anything that has a non-zero real part and a
> non-zero imaginary part will share this.
> 
> To correctly represent the return types for, say, the add() method on
> Decimal, what I would *actually* return is something like
> NumberInterface The add() method on
> Fraction would instead return
> NumberInterface
> 
> Now, internally, the add() method has a check for whether there is an xor
> relationship between real and imaginary parts of the two numbers. If there
> is, then a complex number object is returned instead. This means that to
> fully describe the return type of this function, the type would look like
> this:
> 
> function add(NumberInterface $num): NumberInterface&(
> (SimpleNumberInterface) |
> (SimpleNumberInterface) | ComplexNumberInterface)
> 
> It can return any combination of these depending on the combination of
> types provided as arguments and being called. Now, if I got to just dictate
> how this was implemented from my own userland perspective, I'd provide
> typedefs and limit combination types to those. So, my ideal implementation
> would like like:
> 
> typedef DecimalType =
> NumberInterface
> typedef FractionType =
> NumberInterface
> typedef ComplexType = NumberInterface
> 
> function add(DecimalType|FractionType|ComplexType $num):
> DecimalType|FractionType|ComplexType
> 
> But as I've mentioned earlier, none of this is really affected by
> nullability. To me, that adds very little (though not nothing). Since it
> accepts class types instead of classes themselves, I'd make an
> OptionalInterface that provides the tools to return a null instance that
> has useful information for the user of my library about why the object is
> "null".
> 
> Full combination types between unions and intersections is something that I
> would use heavily, but to me that means it should be implemented carefully
> and thoughtfully.
> 
> As they are currently, I would use intersection types less often, but they
> will still be useful in typed arguments.
> 
> I can provide actual github references to the code of mine that would
> change if that would be helpful, but I wanted to provide a broad example of
> how intersection types in general might be useful and how they might be
> used.

Hi Jordan:

THANK YOU for providing the first real-world example I have seen during this 
debate and RFC of where at least one person finds intersection types to be 
useful.

What this use-case clarified for me is that maybe this is an XY problem[1]?  

Maybe because we only have a hammer ("interfaces") when the hammer is not 
meeting our needs we ask for a better hammer("interfaces supporting nullable 
unions and intersections") when instead maybe we should as asking for a 
screwdriver ("implicitly implemented interfaces")?

Consider the complexity all these interfaces add, especially when every class 
that implements them must explicitly name them. This creates for a very fragile 
architecture when lots of interfaces are used, not to mention being much harder 
to read and follow the code:

- NumberInterface 
- SimpleNumberInterface
- DecimalInterface
- FractionInterface
- ComplexNumberInterface

Consider instead if we had the ability for any class whose signature matches an 
interface to be considered to have implemented that interface?  

Then for the example Jordan gave he could just create the following interface 
(this might not be the exact signature you'd choose, but roll with me on this 
for a bit):

interface AdderInterface {
function add(int|float $x, $y):int|float;
}

Then any class that has an add() method where the signature matches could be 
said to "implement" the AdderInterface. 

For example, assuming this class:

class Foo {
add(int|float $x, $y):int|float;
}

The following code could work:

function bar(AdderInterface $obj) {
echo $obj->add(1,2);
}

Whereas the following code could fail:

function bar(AdderInterface $obj) {
echo $obj->add("hello","world");
}

There are myriad of benefits to implicit vs. explicit interfaces including:

1. You can use your own interfaces in your own code and still use other's code 
that did not declare a class to implement your interface.

2. Implicit 

Re: [PHP-DEV] [RFC] Nullable intersection types

2021-07-24 Thread Mike Schinkel
> On Jul 24, 2021, at 1:33 AM, Tobias Nyholm  wrote:
>> If you are not willing to compromise you will probably get nothing.
>> 
>> It is relevant because I was trying to get you to ask yourself if you would 
>> be happier if you get half of what you want rather than none of what you 
>> want.  
>> 
>> Because there is a very real possibility you will get none of what you want 
>> if the RFC requires the syntax so many have objected to.
>> 
>> BTW, I do not have a strong opinion either way, but since I see than many do 
>> have a strong opinion I was trying to play arbitrator between two sets of 
>> people who each have very entrenched opinions where their opinions are in 
>> conflict.  If neither side will budge, nobody wins.  
> 
> 
> That is a strange attitude. You are saying that you rather see a release with 
> a know flaw than actually trying to find the best solution. 
> The release will be in 4 months. There is a process to clearly find issues 
> like this. There is plenty of time to review this RFC and release it in beta 
> 2 and let people test it. This is not a last minute thing, the process is 
> designed for this. 

That is begging the question. It is not a "known flaw" — it is a perfectly fine 
option — it is just not your preference.  Arguing the syntax is squarely in the 
realm of bike-shedding.

>> That message mentioned the need in abstract, but it did not provide any 
>> real-world examples.  It claims that there were real-world examples, but did 
>> not show any.  
>> 
>> That message was also not part of the RFC.
> 
> The first paragraph under “Rational” mentioned this: 
> https://wiki.php.net/rfc/nullable_intersection_types#rationale 
> 
I see no code examples showing real-world use-cases in the "Rational" section, 
I just see an abstract assertion by the author explain why they believe it is 
needed.

I don't get the pushback on providing real-world use-case examples. Clearly 
with your work in Symfony — given the assumption that nullable intersection 
types are really needed — you must has at least a few examples.  Why not 
provide them?

> In my world maintaining PHP libraries, it is obvious that 7.0 was missing 
> this feature. As Benjamin mentioned, you could see that all libraries that 
> migrated from 5.x just skipped 7.0 and went straight to support 7.1. I did 
> the same for all my packages because of this reason. I made a misstake to 
> assume that everybody had the same “world of maintaining PHP libraries” as I 
> do. 

My understanding from all interactions on this list is that posters saying that 
something is important is (almost?) never sufficient. Instead it is incumbent 
upon RFC authors and RFC supporters to go the extra mile and make a strong case 
for why something is needed.  And thus far, I have not seen any actual cases 
where it is needed, I have only heard assertions.

Note I am not against this. I tend to prefer more functionality in a language, 
not less.  So by asking you to give examples I am actually trying to help you 
make your case. And it is puzzling to me why you are pushing back so hard when 
I ask for use-cases.

> So the “real world examples” you are looking for is: 
> If we don’t merge a version of this RFC in 8.1, PHP packages will not take 
> leverage of the inspection types until PHP 8.2. The reason for a package to 
> drop PHP 7 support is to be able to use the cool features in PHP 8. This will 
> require a major release (something all maintainer should do sparsely). Why 
> would I do a new major release if I cannot properly define my API 
> (interfaces)? I rather wait to next PHP version where I can express my API 
> and do my major release then. 

That is not a real-world example of why nullable intersection types are really 
needed. That is an assertion about library maintainer's concerns who want 
nullable intersection types. 

It is not code nor does it have anything mention of how any use-cases where 
nullable intersection types would be applied.

> Sorry if I sounded (or keep sounding negative). I appriciate you and 
> everybody else participate in this discussion. We are all trying to make PHP 
> better and we are all trying to move this RFC forward. 

Then give some actual examples instead of just repeating assertions that this 
is needed and if you don't get it you believe it will make your life more 
difficult as a library maintainer. 

There are tens of things that make my life difficult every day I program in 
PHP, but this list doesn't care about my own or any of our difficulties, it 
cares about real-world use-cases that would provide reason why a feature needs 
to be added to PHP.

-Mike

P.S. Also, what Deleu said.



Re: [PHP-DEV] [RFC] Nullable intersection types

2021-07-23 Thread Mike Schinkel
> On Jul 24, 2021, at 12:42 AM, Tobias Nyholm  wrote:
> 
>> It seems this RFC is actually trying to accomplish two(2) things:
>> 
>> 1. Add typehints for nullable intersection types to PHP.
>> 2. Get PHP to support a preferred syntax for type-hinting nullable 
>> intersection types.
> 
> Yes of course. You cannot really do #1 without #2. 
> 
> I agree with Nicolas that `?X` makes more sense. You add ? before the type. 
> If the type is scalar, a class or an intersection type should not matter. But 
> I hear some technical arguments from Derick so I won’t argue against that. 
> 
> Im fine with the syntax: `X & Y | null`
> I don’t think parentheses should be required. From a mathematical perspective 
> you want to add parentheses when you want to override the operation order. If 
> you remove the parentheses and the expression has the same order of 
> operations, then the parentheses is clearly not needed. 
> 
> @Larry makes an argument to keep them: 
> 
>> Requiring parenthesis now leaves the option open in the future to make them 
>> optional when doing full mixed types.
> 
> 
> I don’t understand why we should require something that is not needed simply 
> because it would give us an option to remove it later… Could you elaborate 
> why this is important? (Im probably missing something)

The difference is if we make the decision to use the `?X` syntax and we later 
realize it was a mistake then we are stuck with it. 

OTOH if we use the (X)|null syntax and later realize it is okay to also allow 
`?X` PHP could later be changed to allow it.

The later is the choice that manages future risk better.

>> Given both of these sets of assertions I would ask the RFC's author and 
>> proponents what would be a worse outcome?
> 
> I don’t see how this question is relevant. We are not seeking compromises at 
> the moment. We are seeking the best technical solution to a technical issue. 

If you are not willing to compromise you will probably get nothing.

It is relevant because I was trying to get you to ask yourself if you would be 
happier if you get half of what you want rather than none of what you want.  

Because there is a very real possibility you will get none of what you want if 
the RFC requires the syntax so many have objected to.

BTW, I do not have a strong opinion either way, but since I see than many do 
have a strong opinion I was trying to play arbitrator between two sets of 
people who each have very entrenched opinions where their opinions are in 
conflict.  If neither side will budge, nobody wins.  

>> o, the entire discussion has claimed a "need" for nullable intersection 
>> types but AFAIIK they have been presented in completely abstract terms; i.e. 
>> no one has presented any real-world scenarios where they would actually use 
>> nullable intersection types.  
> 
> 
> The “need” is covered by the discussion about PHP 7.0. See this post as an 
> example: https://externals.io/message/115554#115563 
> <https://externals.io/message/115554#115563>
That message mentioned the need in abstract, but it did not provide any 
real-world examples.  It claims that there were real-world examples, but did 
not show any.  

That message was also not part of the RFC.

Listen, I am trying to help make the RFC better to improve its chance of 
passing.  If you don't want that, then I will just demure.

-Mike

> 
> ——
> 
> When reading my message above could make it sound like I am pessimistic. That 
> is not true. I am excited about this change and I am happy PHP has a long 
> feature freeze so issues like this can show up before the release. 
> 
> Regards,
> Tobias
> 
> 
>> On 23 Jul 2021, at 20:53, Mike Schinkel > <mailto:m...@newclarity.net>> wrote:
>> 
>>> On Jul 23, 2021, at 5:58 AM, Nicolas Grekas >> <mailto:nicolas.gre...@gmail.com>> wrote:
>>> 
>>> Hi everyone,
>>> 
>>> as proposed by Nikita and Joe, I'm submitting this late RFC for your
>>> consideration for inclusion in PHP 8.1. Intersection types as currently
>>> accepted are not nullable. This RFC proposes to make them so.
>>> 
>>> I wrote everything down about the reasons why here:
>>> https://wiki.php.net/rfc/nullable_intersection_types 
>>> <https://wiki.php.net/rfc/nullable_intersection_types>
>>> 
>>> Please have a look and let me know what you think.
>>> 
>>> Have a nice read,
>>> 
>>> Nicolas
>> 
>> It seems this RFC is actually trying to accomplish two(2) things:
>> 
>> 1. Add typehints for nullable intersection types to PHP.
>> 2. Get PHP to support a preferred syntax for type-hinting nullabl

Re: [PHP-DEV] [RFC] Nullable intersection types

2021-07-23 Thread Mike Schinkel
> On Jul 23, 2021, at 5:58 AM, Nicolas Grekas  wrote:
> 
> Hi everyone,
> 
> as proposed by Nikita and Joe, I'm submitting this late RFC for your
> consideration for inclusion in PHP 8.1. Intersection types as currently
> accepted are not nullable. This RFC proposes to make them so.
> 
> I wrote everything down about the reasons why here:
> https://wiki.php.net/rfc/nullable_intersection_types
> 
> Please have a look and let me know what you think.
> 
> Have a nice read,
> 
> Nicolas

It seems this RFC is actually trying to accomplish two(2) things:

1. Add typehints for nullable intersection types to PHP.
2. Get PHP to support a preferred syntax for type-hinting nullable intersection 
types.

Further:

A. There seems to be consensus on the value of #1.
B. There seems to be consensus on using a syntax with parentheses for #1. 
C. There is a lot of pushback on #2.
D. The desired syntax in #2 would reduce future flexibility, as Larry Garfield 
commented. 

Given both of these sets of assertions I would ask the RFC's author and 
proponents what would be a worse outcome?

X. Getting typehints for nullable intersection types added to PHP, but not the 
desired syntax?
Y. Not getting typehints for nullable intersection types added to PHP? 

When answering please consider that #X is the outcome that would not preclude 
possibly getting #2 at a future date.

-

Also, the entire discussion has claimed a "need" for nullable intersection 
types but AFAIIK they have been presented in completely abstract terms; i.e. no 
one has presented any real-world scenarios where they would actually use 
nullable intersection types.  

It might be helpful — or at least it would be for me — if the RFC could add two 
or three real-world example use-cases where the author and proponents would 
actually like to use nullable intersection types in their future PHP code.  

#jmtcw

-Mike

Re: [PHP-DEV] Problems with the mailing list [was: Re: [PHP-DEV] Request for karma to vote on RFCs]

2021-07-23 Thread Mike Schinkel
> On Jul 20, 2021, at 3:44 AM, Lynn  wrote:
> 
> On Tue, Jul 20, 2021 at 9:33 AM Peter Bowyer 
> wrote:
> 
>> I have now been contacted by 2 people who tried multiple times to join this
>> mailing list and cannot.
>> 
>> It took me 5 weeks for my signup to work. During that time I emailed the
>> different @php.net mailboxes related to infrastructure and/or the web and
>> received no response. Eventually I managed to sign up - once I created this
>> brand-new Gmail account. The signup form is unreliable.
>> 
>> There are people wanting to take part in discussions who can't.
>> 
> It took me a very long time to get signed up to the mailing list as well,
> so I poked around on twitter back then to see if anyone could help me. I've
> tried several times over the timespan of at least a year and I never
> received a follow up after using the form. I'm not sure what changed, it
> just worked eventually. I'm also still receiving a bunch of messages from
> the mailing list in my spam folder (gmail), and there's not much I can do
> about it. I would love to see a system replacing the mailing list, one
> where we can reliably use things like markdown to properly quote and have
> code blocks and have at least semi-decent threaded discussions.

A fix[1] has been applied in hopes to resolve the mailing list sign-up issue.  
For those who had issues with signing up for the mailing list would you be 
willing to please test the signup process[2]?  

If yes and you still experience a problem, could you please report the issue to 
php-webmas...@lists.php.net  list, or if 
you don't want to sign up for that list you could please email me off-list so I 
could look into the continued problem and communicate about it on the webmaster 
list for you?

Thank you in advance.

-Mike

[1] https://github.com/php/web-php/pull/426
[2] https://www.php.net/mailing-lists.php

Re: [PHP-DEV] Problems with the mailing list [was: Re: [PHP-DEV] Request for karma to vote on RFCs]

2021-07-22 Thread Mike Schinkel
> On Jul 22, 2021, at 1:53 PM, Tiffany Taylor  
> wrote:
> 
> Forwarding this to internals because I mistakenly replied to an email
> directly.
> 
> On Tue, Jul 20, 2021 at 2:33 AM Peter Bowyer 
> wrote:
> 
 Currently there are people with voting permissions that do vote, yet do
>> not interact with RFCs or the mailing list.
>> 
>> On Mon, 19 Jul 2021 at 23:34, Bob Magic  wrote:
>> 
>>> i'd say we need something more modern and transparent than this old
>> mailing
>>> list, but i completely lack a suggestion that isn't somehow worse than
>> what
>>> we got now in terms of massively multiplayer discussion.
>>> 
>> 
>> I have now been contacted by 2 people who tried multiple times to join this
>> mailing list and cannot.
>> 
>> It took me 5 weeks for my signup to work. During that time I emailed the
>> different @php.net mailboxes related to infrastructure and/or the web and
>> received no response. Eventually I managed to sign up - once I created this
>> brand-new Gmail account. The signup form is unreliable.
>> 
>> There are people wanting to take part in discussions who can't.
>> 
>> I volunteer to help sort this. Can someone who knows the PHP group
>> procedures please tell me the next steps?
>> 
>> Peter
>> 
> 
> Disclaimer: I am scanning a previous conversation while composing this
> email. It has been a month since I dived into this code, so this email may
> contain some inaccuracies, I ask for your patience in that regard.
> 
> It was noted off-list that there are difficulties with subscribing to
> mailing lists. Ramsey and I looked at the code about a month ago,
> discovered that there are some broken bits around
> https://github.com/php/web-php/blob/7d6e63b6163e1991077822b71f7ba561e5171286/mailing-lists.php#L66-L89
> and
> https://github.com/php/web-master/blob/819070de35a7b167766d3d64cbb0b450327eed7b/public/entry/subscribe.php#L9-L14.
> He was able to get the subscription code working locally while running 7.4,
> but the code does not work on 8.0, due to removed functions.
> See also: https://github.com/php/web-php/blob/master/include/layout.inc#L251
> , https://github.com/php/web-php/blob/master/mailing-lists.php#L99.
> 
> With that said, I want to invest time to resolve this, but I am currently
> working on other things, and thus haven't had time to volunteer to fix it.
> I can only speak for myself, but if someone wanted to take upon themselves
> to resolve this, I would greatly appreciate it.

I could work on this as I recently got web-php set up and working locally to be 
able to submit some PRs.

But I assume the [PHP-DEV] list is probably not the best list to discuss this.  
Can someone please recommend which list this would be best discussed on?

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



Re: [PHP-DEV] Request for karma to vote on RFCs

2021-07-21 Thread Mike Schinkel
> On Jul 20, 2021, at 9:39 AM, Rowan Tommins  wrote:
> 
> When decisions are just a matter of bikeshedding, or deciding what "style" 
> the language should have, there is a strong argument for general democracy, 
> and a strong voice for those who use the language.
> 
> But some decisions have more fundamental impact on the implementation itself 
> - highly technical features like JIT or Fibers, or conceptually simple 
> features with complex implementations like Intersection Types. The concern is 
> that the small number of people who understand those consequences will be 
> out-voted by people "voting with their heart" because they like the idea of a 
> feature.
> 
> Those core contributors are then expected to maintain the resulting code, 
> with little help from those who wanted the feature. Hence the suggestion, not 
> of an "elite", but of some sort of "meritocracy", where that knowledge 
> carries some weight.
> 
> 
> Perhaps we need a more revolutionary re-organisation into two separate voting 
> groups:
> 
> * a very open community vote, to indicate a breadth of support for the 
> direction a change takes the language
> * a group of Core Contributors, much smaller than the current voting pool, 
> who are equipped to judge the impact of the implementation

This is an excellent observation, and encapsulates why some of the RFC outcomes 
might feel a bit mismatched with what many people want and/or what seems to 
make the most sense for PHP from a core maintenance perspective. 

> An RFC could require separate approval from both groups, regardless of number 
> of voters, like a parliament with two chambers.

But I'm not sure having two houses that can both veto a a solution would 
improve things. I think it would just make it worse. 

If there was the Userland House and the Core Contributor Senate then that would 
mean that things in your category of bike-shedding could still be blocked by 
the Core Contributors even if 99% of userland developers loved an idea.

Instead maybe we should consider those known and respected because of their 
continuous core contributions ("Core Contributors") have the ability to veto an 
RFC if it treads into core territory?

BTW, "membership" in Core Contributors would be managed informally within the 
group of people. Once the initial group was recognized they would handle adding 
new people to the group and/or ejecting existing people completely among 
themselves and then one of them would announce any updates to the list.

Consider if Core Contributors are allowed to classify an RFC as a 
"Core-related" concern, such as 1.) a core maintenance concern and/or 2.)  a 
future-compatibility concern?  And if it is one of those two, then Core 
Contributors could request a veto vote. I think we could assume they would only 
do this in good faith because of the potential for damage to their reputations 
if they were to operate in bad faith.

When an RFC is being discussed a Core Contributor could simply stating their 
belief it is Core-related and if two other Core Contributors seconded that 
concern then the RFC would be susceptible to a potential veto vote and the RFC 
author would be required to mark it as such. Classifying as Core-related should 
happen during discussion period and before the vote starts, and especially not 
after a main vote has passed.

(However if it gets contentious then three (3) Core Contributors could band 
together and simply update the RFC to be Core-related; their view on this would 
be final.  But I doubt that would ever be needed because an author arguing 
against Core Contributors in this way would mean the RFC would probably be 
voted down anyway.)

Then for voting:

1. If an RFC is *not* Core-related then everyone gets to vote just as before, 
but maybe voting access becomes more open and more democratic?

2. If an RFC *is* Core-related then the same vote occurs but if is passes then 
three (3) Core Contributors can request to have a Core Contributor-only vote 
which will require a 2/3rd majority to pass. If this vote fails to gain 2/3rd 
majority approval of the Core Contributors then the RFC is considered "Vetoed." 

The benefits could potentially be:

1. Ensure even if a feature is desired by userland we could still guard against 
approving features that would be a maintenance problem or that could paint PHP 
into an evolutionary corner.

2. Lowering the bar for voting rights because voters couldn't do damage to 
core-related concerns.  

3. Possibly gain more participation from userland

4. An increase in userland satisfaction from either  being allowed to 
participate or for the broader community getting more features userland 
developers want.

5. Very little change procedurally, except to formally recognize the Core 
Contributors separately from others, and giving them the ability to call for a 
veto vote after an RFCs that were previously tagged as core-related passed.

BTW, rather than calling it "bikeshedding" we might 

Re: [PHP-DEV] Request for karma to vote on RFCs

2021-07-20 Thread Mike Schinkel
> On Jul 20, 2021, at 8:55 AM, Andreas Heigl  wrote:
> 
> Hey Mike
> 
> Thank you for your feedback!
> 
> Am 20.07.21 um 11:57 schrieb Mike Schinkel:
>> Quoting the RFC
>> 
>>> the requester has contributed to the PHP sourcecode ecosystem.
>> 
>> You mention what types of contributions apply, but give no indication of 
>> quantity.  If someone fixes one bug, does that give them voting rights?  I 
>> would assume not.  So is it two bugs, 10 bugs, 100?
> 
> As the RFC is still not finished especially in terms of wording that is
> something that definitely needs some improvements. I tried to leave it
> as open as possible in the initial draft to have that as basis for
> further discussions. What do you think would be an appropriate number?

As I don't have voting rights, I don't think I am in an empowered position to 
make specific suggestions.

If I were going to design the PHP's governance I would design differently, but 
since I'm not in a role to do that I can only accept that PHP governance is the 
way that it is, and point out things I think might be problematic. 

As for specific suggestions? I'll let others who already have a vote specify 
those.

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



Re: [PHP-DEV] License for PHP 8.x?

2021-07-20 Thread Mike Schinkel
> On Jul 20, 2021, at 6:16 AM, Nikita Popov  wrote:
> 
> On Tue, Jul 20, 2021 at 12:01 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
>> On Jul 19, 2021, at 3:31 AM, Nikita Popov > <mailto:nikita@gmail.com>> wrote:
>> 
>> On Mon, Jul 19, 2021 at 5:56 AM Mike Schinkel > <mailto:m...@newclarity.net>> wrote:
>> I was just checking to see what the license was for PHP and this page[1] 
>> states:
>> 
>> "PHP 4, PHP 5 and PHP 7 are distributed under the PHP License v3.01, 
>> copyright (c) the PHP Group."
>> 
>> Can I assume that PHP 8 is also distributed under the PHP License v3.01 and 
>> that this page on PHP.net <http://php.net/> <http://php.net/ 
>> <http://php.net/>> has just not yet been updated to reflect the existence of 
>> PHP 8?
>> 
>> Yes, see https://github.com/php/php-src/blob/master/LICENSE 
>> <https://github.com/php/php-src/blob/master/LICENSE>. The page should be 
>> updated to say something like "PHP 4 and newer".
> 
> Thanks for the quick reply.
> 
> Maybe this would be a good first contribution for me?  How could I go about 
> updating that page?
> 
> You can edit the page here: 
> https://github.com/php/web-php/blob/master/license/index.php 
> <https://github.com/php/web-php/blob/master/license/index.php>
Done:  https://github.com/php/web-php/pull/415

-Mike

Re: [PHP-DEV] License for PHP 8.x?

2021-07-20 Thread Mike Schinkel
> On Jul 19, 2021, at 3:31 AM, Nikita Popov  wrote:
> 
> On Mon, Jul 19, 2021 at 5:56 AM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> I was just checking to see what the license was for PHP and this page[1] 
> states:
> 
> "PHP 4, PHP 5 and PHP 7 are distributed under the PHP License v3.01, 
> copyright (c) the PHP Group."
> 
> Can I assume that PHP 8 is also distributed under the PHP License v3.01 and 
> that this page on PHP.net <http://php.net/ <http://php.net/>> has just not 
> yet been updated to reflect the existence of PHP 8?
> 
> Yes, see https://github.com/php/php-src/blob/master/LICENSE 
> <https://github.com/php/php-src/blob/master/LICENSE>. The page should be 
> updated to say something like "PHP 4 and newer".

Thanks for the quick reply.

Maybe this would be a good first contribution for me?  How could I go about 
updating that page?

>  
> -Mike
> P.S. Relatedly, if someone wants to publish code in a GitHub repo with intent 
> to try to have it included in PHP what license should be used?  Would BSD-3 
> be appropriate?
> 
> While both MIT and BSD are compatible, it's generally preferred to license it 
> under the PHP license. This allows free code movement within php-src.

Doh!  Sorry, I had a bit of a brain fart.  

When creating a repo GitHub allows us to select a LICENSE but does not include 
the PHP license as an option, and I was fixated on the list they presented. But 
obviously it is as simple as copying the PHP license into the repo after it is 
created, even though GitHub doesn't provide as a default option.  :-)

-Mike

Re: [PHP-DEV] Request for karma to vote on RFCs

2021-07-20 Thread Mike Schinkel
Quoting the RFC

> the requester has contributed to the PHP sourcecode ecosystem.

You mention what types of contributions apply, but give no indication of 
quantity.  If someone fixes one bug, does that give them voting rights?  I 
would assume not.  So is it two bugs, 10 bugs, 100?

> these contributions show a consistent effort

How is "consistent" defined?  How frequently and for what minimum time period?

> the requester has shown interaction with the main discussion medium of the 
> relevant part


This is unclear to me. I assume "the main discussion medium" is more than just 
the mailing list, otherwise you would have said the mailing list, right? 

 And what does "relevant part" mean?   Maybe some examples would help, at least 
in reply.

> the requester has a proponent that currently has voting karma

Agreeing with Jordan LeDoux, these seems primed to make current voting members 
a target for wanna-be voters. 

Maybe this could discuss processes that would naturally bring people to want to 
sponsor someone, such as (maybe?) recommending they first "apprentice" under 
one or more people by helping document, helping fix bugs, or working with them 
on an RFC? 

> The requester should search a proponent of their case that then proposes the 
> request for voting karma to the dedicated discussion medium for such 
> requests. The proposal should include the reasons why the proponent thinks 
> the requester fullfills the above stated requirements.

Are you really suggesting that allowing someone new to vote would be held out 
in the open, where the discussions about that person will get recorded on 
externals.io  and indexed by Google for all to see, 
forevermore?  

Seems like discussion about an individual should respect the long term privacy 
of the individual a bit more, especially for those who will be turned down. 

> When there are more approvals than objections the voting karma will be 
> granted.

How is voting to be done?  Yay's and nay's on a mailing list?  Or some other 
way?  

And voting right can be approved with 51% whereas most RFCs require 67% to pass?

I ask these questions so people who might be interested in getting voting 
rights would have an objective roadmap for how to get there otherwise it would 
seem to just be documenting an extremely subjective process.  (Which might be 
all you are attempting to do?)

Anyway, #jmtcw.

-Mike



> On Jul 20, 2021, at 2:22 AM, Andreas Heigl  wrote:
> 
> Hey All
> 
> Am 19.07.21 um 17:02 schrieb Andreas Heigl:
>> Hey All
>> 
>> Am 19.07.21 um 16:34 schrieb Levi Morrison via internals:
>>> On Mon, Jul 19, 2021 at 2:38 AM Nikita Popov  wrote:
 
 On Sun, Jul 18, 2021 at 8:48 PM Tobias Nyholm 
 wrote:
 
> Hey.
> I would like to get karma to be able to vote on RFCs. I understand that
> voting karma isn’t usually given out to people who write their first
> mailing list entry.
> 
> But I do believe I qualify as “Lead developers of PHP based projects
> (frameworks, cms, tools, etc.)”
 
 Hey Tobias,
 
 My response here is basically the same as the last time the topic came up:
 https://externals.io/message/110936#110937 Voting is just the very last
 step of the RFC process, at which point the proposal can no longer be
 influenced. If you have feedback about a proposal based on your extensive
 experience in PHP's open source ecosystem, then the discussion phase is the
 time to provide it, while it can still influence the proposal, as well as
 other people's view of the proposal.
>>> 
>>> I second this.
>>> 
 At least in my personal opinion, I think it's important that people granted
 voting rights as community representatives have at least some historical
 involvement in RFC discussions.
>>> 
>>> I agree with this, but have no specific objection to granting Tobias
>>> voting karma, as this is underspecified; how long should they
>>> participate? What kinds of involvement are appropriate? Being
>>> underspecified is not really their fault, and I don't feel like it
>>> would be an abuse to grant them voting karma, but do think it would be
>>> an abuse to deny them voting karma indefinitely because "we" don't get
>>> around to specifying it. It should be less of a decision on a
>>> case-by-case basis and more of a checklist.
>>> 
>> 
>> Sounds like we need an RFC to make it clearer how voting karma for the
>> RFC process will be granted in the future.
> 
> I have created a draft for an RFC to implement future rules for granting
> voting karma.
> 
> If you want to contribute to that, feel free to open a PR against it[1].
> 
> To be able to make the future karma grants more trnasparent this needs
> input from everyone: Opponoents as well as proponents!
> 
> I'm looking forward to a fruitful conversation and to a great RFC that
> can move us to more transparency.
> 
> Cheers
> 
> Andreas
> 
> [1]
> 

[PHP-DEV] License for PHP 8.x?

2021-07-18 Thread Mike Schinkel
I was just checking to see what the license was for PHP and this page[1] states:

"PHP 4, PHP 5 and PHP 7 are distributed under the PHP License v3.01, 
copyright (c) the PHP Group."

Can I assume that PHP 8 is also distributed under the PHP License v3.01 and 
that this page on PHP.net  has just not yet been updated to 
reflect the existence of PHP 8?

-Mike
P.S. Relatedly, if someone wants to publish code in a GitHub repo with intent 
to try to have it included in PHP what license should be used?  Would BSD-3 be 
appropriate?


[1] https://www.php.net/license/index.php 





Re: [PHP-DEV] Readonly properties - immutability by default

2021-07-17 Thread Mike Schinkel
> On Jul 17, 2021, at 1:40 AM, Eugene Sidelnyk  wrote:
> 
> > Having a "readonly" class where the properties are read-only by default 
> > makes sense to me, but maybe the better way to do it is with an attribute?
> 
> We already have such an attribute provided. It is called 
> [`#[Immutable]`](https://blog.jetbrains.com/phpstorm/2020/10/phpstorm-2020-3-eap-4/#immutable
>  
> ).

Actually, you are confusing PhpStorm's inclusion of PhpStorm-specific userland 
attributes where the PhpStorm team are probably trying to drive 
defacto-standard meanings for those attributes they documents with attributes 
that has specific meanings and behavior recognized by PHP itself.

Nothing against PhpStorm — it is my IDE/editor of choice and I applaud 
JetBrain's leadership in this area — but their attributes are still just their 
attributes, not attributes defined by in a PHP RFC.


> If the intention is to add some logic for attributes, then unlikely it is 
> going to be accepted because attributes by definition are meta-data. It 
> doesn't add any logic for program.

Actually, that is not true either.  PHP already has one attribute that PHP 
itself recognizes, named "Attribute."  As Larry Garfield wrote[1]:  "The 
#[Attribute] attribute tells PHP “yes, this class can be loaded as an 
attribute.”  

You can also see that future scope was explicitly envisioned[2] that some small 
number of attributes might potentially be more than just metadata.


-Mike
[1] https://platform.sh/blog/2020/php-8-0-feature-focus-attributes/ 

[2] https://wiki.php.net/rfc/attributes_v2#future_scope 
 

Re: [PHP-DEV] Readonly properties - immutability by default

2021-07-16 Thread Mike Schinkel
> On Jul 16, 2021, at 6:12 AM, Bruce Weirdan  wrote:
> 
> On Fri, Jul 16, 2021 at 9:45 AM Eugene Sidelnyk  wrote:
> 
>> Readonly properties are really useful for DDD, where everything is going to
>> be immutable. It promotes best practices. However for people to use it,
>> syntax should be concise and brief.
> 
> If every property of the class is readonly it would probably be better
> to declare that with a class modifier.
> 
> E.g.
> 
> ```php
> readonly class Entity {
>public int $count;
>public string $data;
> }
> ```

Having a "readonly" class where the properties are read-only by default makes 
sense to me, but maybe the better way to do it is with an attribute?

#[Readonly]
class Entity {
   public int $count;
   public string $data;
}

OTOH, that would be inconsistent with using `readonly` as a keyword for 
properties. 

-Mike
P.S. Maybe readonly properties should be implemented with an attribute instead 
of a keyword?  But then that would be opening a can of worms...
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Type casting syntax

2021-07-12 Thread Mike Schinkel
> On Jul 12, 2021, at 4:28 PM, Lynn  wrote:
> On Mon, Jul 12, 2021 at 10:20 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> It seems you have just illustrated why in reality we really do not need type 
> casting/assertions in PHP given its current features, because we already have 
> what we need.
> 
> That's not an argument I agree with, as it would invalidate the need for 
> short closures, null coalesce, constructor property promotion, etc. 
> 
> Continuing on the previous example:
> ```php
> $service = $container->get(SomeService::class);
> assert($service instanceof SomeService);
> 
> // could be replaced with
> $container->get();

In your hypothetical view here, what happens when the $container does not have 
SomeService to provide?  Does it throw an Exception?

-Mike

Re: [PHP-DEV] Type casting syntax

2021-07-12 Thread Mike Schinkel
> On Jul 12, 2021, at 1:56 PM, Max Semenik  wrote:
> 
> On Mon, Jul 12, 2021 at 8:01 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> Additionally in Go a type assertion can return a second value which is 
> boolean telling if the type assertion succeeded.  Not having this would 
> effectively moot the benefit to a type assertion if you had to wrap with 
> try{}catch{} in case it failed.
> 
> Not necessarily:
> 
> if ($obj instanceof MyClass) {
> // We know its type here
> } else {
>// Try something else
> }

Well there you go.  

It seems you have just illustrated why in reality we really do not need type 
casting/assertions in PHP given its current features, because we already have 
what we need.

-Mike



Re: [PHP-DEV] Type casting syntax

2021-07-12 Thread Mike Schinkel
> On Jul 12, 2021, at 11:00 AM, Larry Garfield  wrote:
> x
> On Mon, Jul 12, 2021, at 9:54 AM, Max Semenik wrote:
> 
>> I was thinking of something akin to many compiled languages' approach of
>> "consider this expression is now of that type, and throw an exception if
>> it's not". An example of this approach from Benjamin's proposal of old^
>> 
>> $service = (EmailService) $diContainer->get('email.service');
>> 
>> Instead of
>> 
>> /** @var EmailService $service */
>> $service = $diContainer->get('email.service');
>> if (!$service instanceof EmailService) {
>>throw new TypeError('Expected instance of EmailService, ...');
>> }
> 
> Hm, that's a different creature.  I... would be probably OK with something in 
> that direction, though I wouldn't work on it myself.  I think what you're 
> describing here is more of a type assertion.  "Assert that this variable is 
> of type X, otherwise bail."  So, some kind of non-disableable (or maybe 
> disableable?) shorthand for `assert($foo instanceof Bar)`.

Regarding prior art on type assertion, the syntax Go uses is `value.(type)` so 
using a similar approach in PHP might look like this (I'm spitballing by using 
the double colon as a sigil but it could anything that doesn't conflict with 
existing usage, whatever those options are):

$service = $diContainer->get('email.service')::(EmailService);


Additionally in Go a type assertion can return a second value which is boolean 
telling if the type assertion succeeded.  Not having this would effectively 
moot the benefit to a type assertion if you had to wrap with try{}catch{} in 
case it failed.

$service, $okay = $diContainer->get('email.service')::(EmailService);
if (!$ok) {
   echo 'Not an EmailService.';
}

#fwiw

-Mike

Re: [PHP-DEV] Type casting syntax

2021-07-11 Thread Mike Schinkel


> On Jul 11, 2021, at 7:19 PM, Larry Garfield  wrote:
> 
> What are the use cases for integrated object to object (ie, class to class) 
> conversion in PHP?  
> I'm not entirely clear on what the use case is in PHP.  When would that be 
> superior to "just write an asFoo() method and move on with life"?

Reading your question triggered the following thoughts. They are not use-case's 
per-se because I can't remember them, but I know I have felt the need for these 
each at least once, and especially the last one.  

Note that you cannot currently do any of these with an asFoo() method, at least 
not directly.

1. It would be nice to be able to create a new instance of a parent, 
grandparent class, etc. class given the properties of a child class instance. 
Maybe:

class Progenitor {
public $surname;
function __construct($surname) {
$this-> surname = $surname;
}
}
class Offspring extends Progenitor {}
$offspring = new Offspring('Schinkel');

$progenitor = clone $offspring asinstanceof Progenitor
echo get_class($progenitor);  // prints: Progenitor
echo $progenitor->surname;  // prints: Schinkel

2. Similarly it would be nice to be able to treat an object as an instance of 
its parent/grandparent/etc. where (parentof $instance) === $instance

$progenitor = $offspring asinstanceof Progenitor
echo get_class($progenitor);   // prints: Progenitor
echo $progenitor === $offspring ? 'frue' : 'false;  // prints: true

Note I have no idea if having two instances where references are equal but they 
are different classes would have unintended consequences, so this might not be 
a good idea, not sure.  But it would be nice to be able to treat an object as 
its parent from time to time, if it is possible.

3. It would also be nice to create a child class starting with an instance of a 
parent as its base.

See example for #5.  It should work the same.

4. Similarly it might be nice to be able to (somehow) assign a child class' 
identity and properties to an instance of its parent/grandparent/etc. where 
(childof $instance) === $instance although I have absolutely no idea how it 
this would work syntactically.

???

5. And probably the functionality I've wanted most in this area — which is 
admittedly only tangentially-related — is to be able to assign to $this so we 
could do something like clone an object to get an equivalent object. Or if case 
#1 or #2 above was possible, by cloning an instance of its 
parent/grandparent/etc. would initialize for that object.  For example:

class Foo {
public $value;
function __construct(int $value) {
$this->value = $value;
}
function fromFoo(Foo $foo) {
$this = clone $foo;   // <-- assigning $this replaces all state to be 
equal to the cloned instance
}
}
$f1 = new Foo(100);
$f2 = new Foo(0);
$f2->fromFoo($f1);
echo $f2->value;  // prints 100

> Scalar conversion I can see, but every time someone suggests adding siblings 
> to __toString(), there's major pushback.

Look ma, no magic methods!  :-)

-Mike

Re: [PHP-DEV] [VOTE] Deprecations for PHP 8.1

2021-07-08 Thread Mike Schinkel
> On Jul 8, 2021, at 1:26 PM, Rowan Tommins  wrote:
> 
> for the record, here is what I think:
> 
> * Removal of a deprecated feature can be at any point in the future, even the 
> indefinite future, just not "never".
> * Very short deprecation periods can be harmful, because they don't give 
> people enough time to change.
> * Very long deprecation periods can also be harmful, because people will put 
> off making changes, and end up with a large back log when things are finally 
> removed.
> * Specific plans are useful to users - "this will be removed in 2024" is easy 
> to base decisions on.
> * Failing that, any plan is better than no plan at all - it's easier to work 
> with "a decision on this will be made in 2023 based on an estimate of usage 
> at that point" than "at some point between 1 and 100 years from now, we'll 
> remove it without further notice".

That is a policy I can concur with.  _Definitely_ better than what was stated 
earlier in the thread.

Does anyone else disagree?  If no, could this get memorialized on the wiki 
somewhere to reference in future discussions, if needed? (Or does it need an 
RFC?)

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



Re: [PHP-DEV] [VOTE] Deprecations for PHP 8.1

2021-07-07 Thread Mike Schinkel
Replying to Rowan and commenting on Nikita's message.

> On Jul 6, 2021, at 4:24 AM, Rowan Tommins  wrote:
> 
>> Instead I replied because your email strongly implied (stated?) that 
>> "deprecation required removal"
> 
> I stand by that interpretation, which while not universal is very widely 
> used, and I think is more useful than a general hint at "bad practice".
> 
> You spend most of your e-mail seeming to argue against it, and then seem to 
> say that actually you do agree with it after all, and all you're saying is 
> that sometimes the deprecation period should be longer:


What I was disagreeing with is your assertion that "by definition" deprecation 
must be followed with near-term removal.


> I am not advocating that.  I am advocating we should consider making it:
>> 
>> "features that are strongly discouraged will*probably*  be removed in the 
>> next major version, but in some cases may be retained for one or more major 
>> versions."
> 
> I'm totally OK with that.
> 
> I do think that there should be a clear *plan* for removing each deprecated 
> feature, though. That plan might be "deprecate in 8.1, and examine prior to 
> 9.0 whether usage has dropped / the alternatives are mature / etc". It might 
> flat out be "deprecate in 8.1, but don't remove until 10.0".
> 
> Otherwise, the message becomes "this feature is kind of bad, and at some 
> point we might decide to drop it without further notice, but actually we 
> might not, so no hurry to remove it", which I just think isn't that helpful.


The "plan" that makes the most sense is one that takes into consideration the 
BC breakage that would occur at the time of removal, and that is not something 
you can project _in advance_.   IMO you cannot really know in advance how long 
a feature might continue to be used in the wild in some cases, you can only 
evaluate the current situation when the time comes.  

Or as they say "no battle plan survives first contact with the enemy" and 
"facts on the ground matter."


> On Jul 6, 2021, at 9:30 AM, Nikita Popov  wrote:
> 
> As far as this RFC is concerned (and this is the customary phrasing for all
> deprecation RFCs), all changes are for deprecation in PHP 8.1 and removal
> in PHP 9.0. That's the baseline.
> 
> However, nothing prevents you from starting an RFC prior to the PHP 9.0
> release that counters the prior decision and extends the deprecation period
> for another major version. However, the onus is now on you to argue that
> something previously deprecated should not be removed (or not be removed
> yet). If you cannot make a strong argument for that, then the default
> action is taken.
> 
> We do still carry a couple deprecations from PHP 5 times around, because
> actually removing the affected functionality has some technical issues.

And this is exactly how it should be. That deprecating a feature w/o near-term 
removal is a legitimate approach to have people vote on. IOW, that deprecation 
does not "by definition" require near-term removal.

Removal is determined when appropriate and by vote, and not any hard-and-fast 
"IF deprecated THEN must be removed soon."

Please note that I am fully respecting the ballot and voting outcomes here; if 
people always vote to remove a deprecated feature in next major version that so 
be it.  

But RFC authors should be allowed to propose a long time horizon for removal 
without being told they "are doing it wrong."

-Mike

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



Re: [PHP-DEV] [VOTE] Deprecations for PHP 8.1

2021-07-05 Thread Mike Schinkel
Replying in one long email to all three who replied to me:


> On Jul 5, 2021, at 8:03 AM, Guilliam Xavier  wrote:
> Hi Mike,
> 
> Your links speak *in general*. However this is *specifically for PHP*: 
> https://www.php.net/manual/en/errorfunc.constants.php#errorfunc.constants.errorlevels.e-deprecated-error
>  (*emphasis* mine)
> 
> E_DEPRECATED: Run-time notices. Enable this to receive warnings about 
> code that *will not work in future versions*.

1. In general (no pun intended), is it a good idea for PHP to take a general 
concept and redefine its meaning?  (Rhetorical question.)

2. That link you provided speaks of not working in future versions.  That 
future version could be 5 major versions from now, doesn't have to be next 
version.

3. And most importantly, the content on that page is not written in immutable 
stone. It could just as easily be updated to say the following, assuming that 
an agreement is made to do so: 

"Enable this to receive warnings about code constructs that are discouraged and 
MAY not work in future versions, so best for developers to no longer depend on 
it."


> As for "significant BC breakage", isn't that what major versions are for? 
> (and with the current release plan, 9.0 would be for end 2025, i.e. 4 years 
> after 8.1)

They can be, but AFAIK there is no immutable principle in software that 
deprecated versions must be removed in the next major version.  Doing so or not 
doing is simply a choice, a decision about what is in the best interest of the 
software and its user base. And unless I misunderstand, nothing about the PHP 
project is immutable that cannot be changed by consensus and/or an RFC vote. 

So I am simply making the argument that this restrictive idea that deprecations 
*must* result in removal in the next major version can do more harm than good 
in selected cases.  

Being restrictive in our view of deprecation means we create BC-breaked changes 
when we really don't have to, and more importantly it means we do not signal 
that certain practices are to be discouraged when we could.

Imagine if we decided to deprecated global variables and instead encourage DI 
and/or static variables in classes? IF we could deprecate global without 
removal, I would be 100% for deprecating global. But given the current 
restrictive interpretation promoted by some, we should all be 0% for 
deprecating global.

> On Jul 5, 2021, at 8:05 AM, G. P. B.  wrote:
> 
> For the PHP project deprecation means a future removal, I'm pretty sure this 
> is an agreed policy for the project.

Can you point me to where this has been definitely agreed in the past?  An RFC 
ideally?  (Honest question.)

There is this[1] but it only says functions will usually be completely removed 
"Later" and not "next major version."   "Later" could be 5 versions later.

There is this[2], but it makes no mention of when, nor was it ever voted on.

[1] https://wiki.php.net/rfc/deprecated-modifier
[2] https://wiki.php.net/rfc/deprecated_attribute

> E_STRICT was like Rowan said used for cases of "well you should probably not 
> do this but we'll accept it",
> and this category has been removed.

But the E_STRICT constant was not removed. (Ironically?)

The motivation was "to simplify our error model and resolve the currently 
unclear role of strict standards notices."  So as I read it[3] we are talking 
apples (policy) and oranges (simplify error model/improve clarity)

[3] https://wiki.php.net/rfc/reclassify_e_strict

> Now if you truly want this definition of "deprecation" can I bring forward 
> again to "deprecate" short tags, using 'var' for object properties, all of 
> the SPL data structures, a bunch of extensions, using locales, and maybe to 
> be fancy emit one when you don't use a visibility modifier on object 
> methods/properties/constants, heck why not even one for not using a typed 
> property now that we got mixed and union types.

I would be 1000% for ALL of those.  Bring them on, PLEASE.

But since you wrote that I assume you think that would be a bad idea.  Why?

> As you can see this opens the door to kinda everything being marked as 
> deprecated just to ensure another discussion needs to be held for a removal.

Yes, it opens the door for doing a lot of good for PHP, IMO.

> The policy of X being deprecated means it's going to be removed is very clear 
> for end users who don't need to scramble as to whether or not this 
> deprecation leads to a removal or not.

In all my years working with other developers, I have never witnessed anyone 
"scramble" to determine if deprecation means removal. Deprecation has a pretty 
clear meaning to most developers I know. It simply means "not recommended."  If 
a developer uses a deprecated feature, they are "doing it wrong."

BUT, the project owner who has existing code isn't doing it wrong to want to 
continue to run their software without having to invest new money into 
refactoring because of a function removal. Unless there is a 

Re: [PHP-DEV] [VOTE] Deprecations for PHP 8.1

2021-07-05 Thread Mike Schinkel
> On Jul 5, 2021, at 7:14 AM, Rowan Tommins  wrote:
> 
> On 05/07/2021 11:46, Patrick ALLAERT wrote:
>> Did we ever deprecated something without the immediate intention of
>> removing it?
> 
> 
> What would that even mean?

It would mean that although the functions are available and allowed, they are 
not recommended[1].


> Surely a deprecation, by definition, is a notice that something is going to 
> be removed.

I know that you, and others on this list, have chosen to define deprecation as 
including removal, but that is actually not the accepted definition on the web, 
nor is it in any way a requirement, it is just your preference.  

Indirectly from Wikipedia and voted as the top answer on StackOverflow here[2] 
(emphasis MINE):

"deprecation is a status applied to software features to indicate that they 
should be avoided, typically because they have been superseded. Although 
deprecated features remain in the software, their use may raise warning 
messages recommending alternative practices, and deprecation MAY indicate that 
the feature will be removed in the future."

So I am arguing for the legitimacy of retaining "deprecated" features if their 
removal would cause significant BC breakage, I'm not just trying to be a 
pendant.  

-Mike
[1] https://whatis.techtarget.com/definition/deprecated
[2] https://stackoverflow.com/questions/8111774/deprecated-meaning

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



Re: [PHP-DEV] [Proposal] call_user_func_map(): flexible named parameter mapping for call_user_func*

2021-07-01 Thread Mike Schinkel


> On Jul 2, 2021, at 12:30 AM, Hossein Baghayi  
> wrote:
> 
> Hello,
> 
> On Sun, 27 Jun 2021 at 19:09, Ralph Schindler 
> wrote:
> 
>> 
>> This proposes a method for a publisher/framework/producer (the caller of
>> the callback) to document all the parameters that are available as named
>> parameters, and subscribers/consumers (creator of the callback) could
>> subscribe to what they need by name.
>> 
> 
> Wouldn't it rather be nice if we had more detailed callable types instead?
> I mean instead of simply defining a parameter type as `callable` we could
> specifically define what the callable expects.
> 
> Something like this:
> ```
> function bar ((int, string):bool $callback) {...}
> ```
> 
> A more generic approach that could be more descriptive, maybe.
> 
> I have no clue if this was already discussed in other threads or not. And
> whether it is feasible to implement.


From 2015 which failed (not sure why): 

https://wiki.php.net/rfc/callable-types

But I believe that would be better to be part of a broader ability to define 
our own types, e.g.

type function(int, string):bool IntStrFunc;
function bar (intStrFunc $callback) {...}

I think a few have mentioned user-defined types in the recent past but I am not 
aware of it being a current RFC for it. 

-Mike

Re: [PHP-DEV] [RFC] Readonly properties

2021-06-30 Thread Mike Schinkel
> On Jun 29, 2021, at 9:08 AM, Nikita Popov  wrote:
> 
> In any case, I don't want to include changes to cloning in this proposal --
> the topic is related, but also orthogonal to readonly properties.
> Unfortunately, it will not be possible to get cloning changes into PHP 8.1
> anymore, due to feature freeze.
> 
> It's okay to vote against this if cloning is a deal breaker. In that case
> I'll probably either work on cloning before re-proposing this,

I while back I made a suggestion for cloning which seemed to resolve the 
cloning issue in a way that no other proposals do. 

However, no one acknowledged it, so maybe few if any people saw it?  
https://externals.io/message/114729#114747 


Anyway TL;DR, the approach is to allow specifying a closure on clone, binding 
$this to it, and then allow modifications to readonly properties while in that 
context and anything that it calls:

$clone_obj = clone $obj fn() => {
$this->foo = 'new value';
}

Would this not be a viable solution for cloning, for this RFC, or the only you 
work on if this one fails to pass?

-Mike

Re: [PHP-DEV] is_literal() is back

2021-06-26 Thread Mike Schinkel
> On Jun 26, 2021, at 10:03 AM, Craig Francis  wrote:
> 
> Just a quick reply at the moment, but what happens if a db library had a 
> method to set what was in the LIMIT part of a query, you did the MySQL thing 
> of “30, 10” to get paginated results, and then one day the library changed to 
> require the argument to be an integer?

You didn't provide enough details on your hypothetical for a definitive answer, 
so let's fill in some details so I can provide an answer (but if theses details 
do not fit the use-case you envision, you'll need to be more specific.)

This db library you speak of is a SQL query builder.  Using it would look like 
this (code examples derived from [1]):

$builder = new MySqlBuilder(); 
$query = $builder->select()->setTable('user')->limit('30,10'); 

The version where the above code works is version 2 and there are no type hint 
on method parameters.  Then they release version 3 is which they add an `int` 
type hint on the limit() method, and they introduce an offset() method.  This 
is the scenario I will use to answer your question.

-

I upgrade to version 3 and my code breaks. I inspect the error, figure out the 
problem and then I change my code to look like this:

$query = $builder->select()->setTable('user')->offset(30)->limit(10);  

Problem solved.

That said, please note the difference between your LIMIT scenario and the 
is_literal() scenario are three (3) fold:

1. If added to PHP is_literal() will be promoted as the panacea to solve all 
injection vulnerabilities in (almost?) all the "What's new in PHP" blog posts 
and then many of the PHP library developers who read these articles will rush 
to add is_literal() checks to their libraries without fully understanding and 
addressing the ramifications.  And that over-zealousness will take time to 
recognize and thus recover from.  

2. Your LIMIT scenario does not have a coincidental concurrent PR blitz that 
is_literal() will get meaning that even if some db libraries do constrain LIMIT 
it will only be a few at a time at most. So no more a problem than any other 
backward compatibility break in a library.

3. Finally and most importantly, there is an easy fix in userland for your 
LIMIT scenario as I illustrated.  For many use-cases where is_literal() may be 
added as a gatekeeper there would be no easy fix, except to use a technique 
that your RFC describes as "clearly the developer doing something wrong."

-Mike

[1] https://github.com/nilportugues/php-sql-query-builder



> On Sat, 26 Jun 2021 at 2:51 pm, Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> The idea behind is_literal() is of good intention, but as they say the road 
> to hell is paved with good intentions.
> 
> The RFC proposes to add an internal "literal" flag to a string, the 
> is_literal() function, and nothing else. 
> 
>  Further the RFC states a vision to get "libraries to start using 
> is_literal() to check their inputs."  Again, that comes from a great 
> intention.  
> 
> The problem lies with the fact that library developer who choose to disallow 
> non-literal strings will offer solutions when a use-case literally 
> (pun-intended) cannot produce a literal string. 
> 
> Sure, most leading library developers will offer a solution, but many of the 
> long-tail library developers will not either because it will add scope and/or 
> because those library developers don't have to skill and/or experience to do 
> so.
> 
> So what will those users of those libraries do when faced with a required to 
> only use literal strings?  They will find a workaround so they can get their 
> jobs done.  And that workaround is really simple:
> 
> function make_literal(string $non_literal):string {
> $literal = '';
> for( $i = 0; $i< strlen($non_literal); $i++ ){
> $literal .= chr(ord($non_literal[$i]));
> }
> return $literal;
> }
> 
> You can see it in action 3v4l.org <http://3v4l.org/> <http://3v4l.org/ 
> <http://3v4l.org/>> here[1] and for posterity on gist.github.com 
> <http://gist.github.com/> <http://gist.github.com/ <http://gist.github.com/>> 
> here[2]. 
> 
> Once developers start bypassing the is_literal() check then all those good 
> intentions will be moot, and many who think they are secure from injection 
> attacks will be vulnerable:
> 
> $sql = 'SELECT * FROM foo WHERE id=' . make_literal( $_GET['id']);
> $result = mysqli_query($conn, $sql);
> 
> So what am I suggesting we do?  
> 
> 1. We postpone passing this is_literal() RFC until we have collectively 
> addressed how userland developers will be able to handle non-literals in SQL, 
> HTML, etc. when their use-cases require non-literals.
> 
> 2. We could also go ahead and add the inte

Re: [PHP-DEV] is_literal() is back

2021-06-26 Thread Mike Schinkel
The idea behind is_literal() is of good intention, but as they say the road to 
hell is paved with good intentions.

The RFC proposes to add an internal "literal" flag to a string, the 
is_literal() function, and nothing else. 

 Further the RFC states a vision to get "libraries to start using is_literal() 
to check their inputs."  Again, that comes from a great intention.  

The problem lies with the fact that library developer who choose to disallow 
non-literal strings will offer solutions when a use-case literally 
(pun-intended) cannot produce a literal string. 

Sure, most leading library developers will offer a solution, but many of the 
long-tail library developers will not either because it will add scope and/or 
because those library developers don't have to skill and/or experience to do so.

So what will those users of those libraries do when faced with a required to 
only use literal strings?  They will find a workaround so they can get their 
jobs done.  And that workaround is really simple:

function make_literal(string $non_literal):string {
$literal = '';
for( $i = 0; $i< strlen($non_literal); $i++ ){
$literal .= chr(ord($non_literal[$i]));
}
return $literal;
}

You can see it in action 3v4l.org  here[1] and for posterity 
on gist.github.com  here[2]. 

Once developers start bypassing the is_literal() check then all those good 
intentions will be moot, and many who think they are secure from injection 
attacks will be vulnerable:

$sql = 'SELECT * FROM foo WHERE id=' . make_literal( $_GET['id']);
$result = mysqli_query($conn, $sql);

So what am I suggesting we do?  

1. We postpone passing this is_literal() RFC until we have collectively 
addressed how userland developers will be able to handle non-literals in SQL, 
HTML, etc. when their use-cases require non-literals.

2. We could also go ahead and add the internal "literal" flag to a string so 
that if someone wants to use it to write an extension to add an is_literal() 
function in the mean time it would be available, but not yet standardized into 
PHP.

Thank you in advance for your consideration.

-Mike

[1] https://3v4l.org/oCBp7#focus=rfc.literals 

[2] https://gist.github.com/mikeschinkel/b9abd4178db461568b813269bc936c18 
 

Re: [PHP-DEV] Introduce str_left/right In 8.1

2021-06-24 Thread Mike Schinkel
> On Jun 24, 2021, at 8:04 AM, G. P. B.  wrote:
> 
> Moreover, the fact that only a very restricted number of programming
> languages, which are some of the earliest languages ever, implement those
> functions should tell you something about programming language design
> as a whole, which is that many people came to the conclusion that a variant
> of substring is a better abstraction than "left/right".

It think the distinction is not so much that is earlier vs. later languages, 
but who the target market is for the languages. For languages that offer left() 
and right() function the average developer skill for developers proficient in 
those language tends to be lower than for languages that do not have those 
functions, compared on a absolute scale to the most highly-skilled professional 
developers, of course.

Erlang has left() and right() string methods, and it is not an earlier language.
R is not an early language and it has StrLeft() and StrRight() but R is a 
language targeting data scientists instead of hard core programmers.
Visual Basic is not earlier, but it is based on early Basic. That said it has 
always targeted more line-of-business programmers than professional programmers.
Excel, which is an end-users tool has LEFT() and RIGHT() functions.  
Wikipedia actual has a really nice comparison of languages on string handling:

- 
https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(string_functions)#left
 

- 
https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(string_functions)#right
 

 

So a question to ask about PHP we could collectively answer is: Who is the 
target market for PHP?  

If we collectively want to forsake lower-skilled developers then no, it would 
not make sense to include str_left()/str_right() because few programming 
languages targeting more advanced developers do.

OTOH if we do want to maintain approachability for lower-skilled developers and 
allow them easier success experiences then adding functions like 
str_left()/str_right() make a lot of sense.

Maybe it would make sense to have the community identify and define who PHP's 
target user is, and then put that as a stake in the ground?  If that were 
agreed and explicitly stated on PHP.net  for reference, it 
sure could help stop a lot of bikeshedding and heated debates among people with 
different visions for the future of PHP.  

#justsaying
  


That said, many newer languages use the indexing operator to extract substrings 
of length 2 or more, which PHP does not.  

Given your comment about early languages are you amenable to adding a substring 
indexing syntax to PHP for strings and arrays?

I quite like how Swift does it, but there are many others:

- Swift: https://stackoverflow.com/a/39677331/102699 
 
- Go:   https://www.dotnetperls.com/substring-go 

- Python: 
https://runestone.academy/runestone/books/published/thinkcspy/Strings/IndexOperatorWorkingwiththeCharactersofaString.html
 

 
- Ruby: https://stackoverflow.com/a/4528091/102699 

- F#: https://dotnetcodr.com/2017/02/18/creating-substrings-in-f/ 
 
- D: https://stackoverflow.com/a/20570677/102699 
 
- Mathematica: https://reference.wolfram.com/language/ref/StringTake.html 
 

-Mike






Re: [PHP-DEV] [RFC] Name issue - is_literal/is_trusted

2021-06-24 Thread Mike Schinkel

> On Jun 24, 2021, at 6:33 AM, Stephen Reay  wrote:
> 
>> On 24 Jun 2021, at 17:07, Kamil Tekiela  wrote:
>> 
>> Hi Stephen,
>> 
>> I believe the idea was for dynamically generate table names, or numbered 
>> tables/columns. E.g. 
>> 
>> function getTable(string $table){
>>// is_literal check here
>> }
>> 
>> $number = (int) $_GET['tableno'];
>> if($number < 0 || $number > 10) {
>>throw new Exception("Invalid number");
>> }
>> 
>> $tablename = 'table_'.$number;
>> getTable($tablename);
>> 
>> The number is concatenated to the table name. 
>> 
>> —Kamil
> 
> Hi Kamil,
> 
> Thanks for at least trying to answer this question.
> 
> I’m sure someone somewhere does that and thinks its a good idea. I 
> respectfully (to you; probably less respectfully to someone if they tell me 
> they do this) disagree. I don’t think PHP should necessarily shy away from 
> features because they’re potentially dangerous, but I also don’t think it 
> should be adding new features/functions that are more dangerous, just to make 
> some weird (IMO bad-practice) edge cases easier.

WordPress Multisite does exactly that.  

Whether or not them doing so is a "good idea" is irrelevant as there are a 
large number of website that use that mode of WordPress currently active on the 
web.


> I’d suggest if they insist on that bizarre naming pattern, _and_ want to use 
> a literal string check, they could define an array of string numbers that 
> represent their table names.
> 
> $tbls = [‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ...];
> 
> getTable(’table_’ . $tbls[$number]);

Some WP MS installations support millions of thousands sites. See WordPress.com 
.

But yes, I guess it could be possible for them to hack hack together 
'table_983761' out of literals via a Rube Goldbergian-function, if forced to.


> On Jun 24, 2021, at 6:35 AM, Stephen Reay  wrote:
> 
>> On 24 Jun 2021, at 17:16, Craig Francis  wrote:
>> 
>> On Thu, 24 Jun 2021 at 10:55, Stephen Reay  wrote:
>> 
>>> but still I have to keep asking: Why integers at all?
>>> 
>> 
>> While I'm not a fan of this approach, there is a lot of existing code and
>> tutorials that use:
>> 
>> $sql = 'WHERE id IN (' . implode(',', array_map('intval', $ids)) . ')';
>> 
>> $sql = sprintf('SELECT * FROM table WHERE id = %d;', intval($id));
>> 

And WordPress (and I am sure a lot of other legacy code) does not support 
parameterized queries in the DB object, at least not without jumping through 
tons of hoops.  Not to mention the 60k existing open-source plugins and the 
likely million custom plugins in the wild.

-Mike
P.S. Of course we could ignore the entirety of WordPress, but that just does 
not strike me as a prudent course of action.

Re: [PHP-DEV] [RFC] clamp

2021-06-24 Thread Mike Schinkel



> On Jun 24, 2021, at 7:59 AM, Pierre  wrote:
> 
> Le 24/06/2021 à 11:44, Michał Marcin Brzuchalski a écrit :
>> I get an impression that we constantly add things into standard library
>> which are from a language perspective irrelevant
>> and that all could be developed in userland with no harm.
>> 
>> Cheers,
>> --
>> Michał Marcin Brzuchalski
> 
> Hello,
> 
> I respectfully do not agree with this last statement. A simple method such as 
> this one entirely belong to the standard library. I wouldn't want to end-up 
> with a NPM-like ecosystem where I'd have to choose between clamp-php, 
> php-clamp, php-bound-int, int-php-bound, etc...

> 
> The more the standard library will be complete, the less projects will need 
> dependencies, which is better for your projects long term maintenance. You 
> often end-up in dependency resolution hell because library A use library B, 
> which use foo/clamp which is not compatible with another C library you use, 
> or because it doesn't support PHP core version X or Y.
> 
> A simple function such as clamp in standard library makes much sense, 
> anything like it must go into standard library, this way the userland 
> ecosystem can focus on domain related stuff, or more complex topics, without 
> worrying too much about this kind of detail. Having a great and complete 
> standard library lowers community fragmentation, and that's for the best !
> 
> Moreover, it also ensures that all developers speak the same language 
> regarding primitives provided by the standard library, and makes 
> communication more efficient within community.

This.  All of this.

-Mike

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



Re: [PHP-DEV] Introduce str_left/right In 8.1

2021-06-23 Thread Mike Schinkel
Replying to both Sara's and G.P.B.'s emails below:

> On Jun 23, 2021, at 12:48 PM, Sara Golemon  wrote:
> 
> Using some context, I would assume you mean this:
> 
> function str_left(string $str, int $len): string {
>  return substr($str, 0, $len);
> }
> 
> function str_right(string $str, int $len): string {
>  return substr($str, -$len);
> }
> 
> If that's the case, then why?  As you can see, the existing
> functionality available is trivial to write.  
> 
> Am I misunderstanding what these proposed functions should do, or am I
> underestimating the difficulty of typing a zero or negative sign on certain
> keyboards?

I can't speak for Hamza, but one reason I can see for why — at least for 
str_right() — is that using a negative index might not occur to many people. 
Hell, I even forgot substr() worked that way until you mentioned it.

But, since objective evidence is better than opinion, a non-trivial number of 
people have searched how to get the last 'n' characters from a string in PHP, 
found the answer, and then went to the effort to upvote it on StackOverflow.  
If the 90-9-1 rule holds, then that's about 6200 people who have been confused, 
searched and found the answer here:

https://stackoverflow.com/questions/10542310/how-can-i-get-the-last-7-characters-of-a-php-string
 


For future people to whom it does not occur that substr() accepts negative 
arguments, or for people who forget that fact, str_right() would provide an 
obvious solution that would be easy to find in IDE autocomplete or when 
scanning the list of functions on PHP.net.  

At which point it would make sense to also at str_left() for symmetry.  

That said, my world won't change if these functions are not added, but adding 
them would be nice a little improvement to daily PHP developer experience.

> On Jun 23, 2021, at 10:52 AM, G. P. B.  wrote:
> 
> All this to say that the burden of maintenance for such a specialized
> function makes it very unsuitable to be in core.

I have frequently heard the justification of maintenance burden mentioned as an 
objection to adding specific features.  And in many cases, it is easy to see 
why future maintenance burden would be a concern.

However, it *seems* in this case that these functions are so trivial to 
implement that once written and documented they would likely never need to be 
touched again. But as I do not yet know the internals of PHP I obviously do not 
know that to be a fact.

Honest question: Would you mind explaining the type of maintenance required for 
simple functions like this?  What is likely to change in the future that would 
require maintenance?  And would you mind giving a few or at least one example 
of a trivial function that did need to be maintained after it was written?  

Thank you in advance for taking the time and effort to answer.

-Mike

[PHP-DEV] Add mysqi_stmt->query? (Was Sql Object Model Parser & Sanitizer)

2021-06-22 Thread Mike Schinkel
> On Jun 22, 2021, at 12:54 PM, Kamil Tekiela  wrote:
> While it's true that a lot of the internet is using mysqli due to WordPress, 
> this doesn't change the fact that PHP already offers a solution to the 
> problem. Both PDO and mysqli support server-side prepared statements. 
> 

Hi Kamil,

Clearly for whatever reason your arguments and Larry's arguments are 
misunderstanding and thus misrepresenting what I was proposing.  But given how 
long our respective emails are getting I do not have confidence we will get to 
clarification if we continue, so I am going to suggest we bring the original 
point of this thread to a close.  

I will just have to implement a proof-of-concept so that what I have been 
proposing will not be so hard to misunderstand.

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



Re: [PHP-DEV] Sql Object Model Parser & Sanitizer (was [RFC] is_literal)

2021-06-22 Thread Mike Schinkel


> On Jun 22, 2021, at 11:41 AM, Larry Garfield  wrote:
> 
> On Tue, Jun 22, 2021, at 8:39 AM, Mike Schinkel wrote:
>>> On Jun 22, 2021, at 9:00 AM, Kamil Tekiela  wrote:
>>> 
>>> Hi Mike,
>>> 
>>> Please don't do this. We already have PDO with prepared statements. The 
>>> data must be bound. This is the secure way of writing SQL queries. 
>> 
>> The problem is that over 40% of the web currently runs on PHP code that 
>> using mysqli.  That CMS does not support PDO nor prepared statements, 
>> and is unlikely to switch to it anytime some in the foreseeable future. 
> 
> WordPress is not going to leverage anything we do here until and unless there 
> is a major change of leadership and culture at that project.  Please don't 
> waste any mental effort on it; they clearly waste no mental effort on what 
> the rest of the PHP community considers good, secure practices.  Anything 
> involving them is tilting at windmills.

You misunderstand.  What I am (likely) "wasting" my mental effort is to discuss 
features that I would be able to use WITHOUT WordPress having to make ANY 
changes.

HOWEVER, these would be beneficial beyond WordPress, since parameterized 
queries cannot parameterize table names nor field names. 

This is all trying to address the concerns that Craig Francis brought up off 
list when he said that you cannot escape or sanitize without knowing context 
when I was asking his to provide a make_literal() function, add support for a 
IsLiteral attribute, or support an IsLiteralInterface so that people don't 
latch on to using is_literal() and make certain edge cases impossible. 

When I am trying to address a problem, I come at it from many angles until I 
find a solution.  One potential solution then is to have a class built into PHP 
that can ensure the SQL returned is indeed safe. 

> Mike, speaking as someone who has written an SQL abstraction layer and query 
> builder with significant usage (Drupal 7-9), you are *grossly* 
> under-estimating the complexity of what you describe.  It might be possible 
> to hack together for SQL92, aka "what most PHP devs actually use because they 
> haven't noticed that it's not 1992 anymore", but that's already been done.  
> We have DBTNG in Drupal, we have Doctrine, problem solved.

I think what is happening here is you are making an assumption I am proposing a 
much larger scope than I am.

Think of the scope I am proposing being on par with $mysqli->prepare(), but a 
bit more to be able to handle more than just values.

> Modern SQL, though, is a stupidly complex and stupidly inconsistent beast.  
> Most of the syntax beyond the basics is different on every damned database.  
> The official spec *is not even publicly available*, and costs a lot of money 
> to access.  And no DB engine actually supports all of it; they all support 
> different subsets with their own different extensions that may or may not be 
> comparable.

Both Modern SQL and legacy SQL are both still text-based query languages  and 
they all have grammars that can be represented by BNF rules. 

https://github.com/ronsavage/SQL

Those rules could be abstracted into a form accessible via a "dialect" 
interface and that is how these would literally any version of SQL could be 
supported.

Could we finish all of a given dialect at once?  No.  Iteration based on what 
is found to be supported is how this could be approached.  Remember, these 
dialects could be implemented in userland. By any PHP developer. 

Could we ever get them to be perfect?  Probably not.  But they would be good at 
the start and then very good and there would like to be many people providing 
PRs to fix new edge cases for the dialects that get the most use.

> Building a tool that parses an arbitrary string to an AST for a spec that is 
> inconsistent, inaccessible, and not implemented correctly by anyone is a 
> fool's errand, and that's just the first part of it.  

That is not what I am proposing.  I am proposing to build a tool that knows how 
to parse based on a simplified grammar and then sanitize based on those rules.

There really are only a few contexts in a SQL query to be concerned about.  
Keywords, field names, table name, table aliases, and typed values (plus maybe 
a few other things I missed?) The grammars themselves can evolve independently 
as userland implementations of interfaces. This is not rocket science.

> That's not even getting into designing an API for people to modify it,

No API per se, an interface.  (Yes that is also an API, but not one that you 
call; instead it calls you.)

> or questions of performance,

Parsing a SQL query should not take nearly as long as executing the query 
itself, especially if the SqlObjectModel were written in C.

> or compiling the AST back into a DB-specific string


Re: [PHP-DEV] Sql Object Model Parser & Sanitizer (was [RFC] is_literal)

2021-06-22 Thread Mike Schinkel


> On Jun 22, 2021, at 11:56 AM, Pierre  wrote:
> 
> Le 22/06/2021 à 17:35, Mike Schinkel a écrit :
>> https://github.com/WordPress/WordPress/blob/master/wp-includes/wp-db.php#L2050
> Sorry for the discussion pollution here but, but ouch, plugins are still 
> using this unsafe form ? Reminds when I was a student, I learnt to 
> parametrize queries there, it was 20 years ago. I never understood people not 
> doing that in the first place.
>> But also because of much legacy code exists in the form of plugins and 
>> themes that do not support parameterized queries.
> Yes I agree, legacy is legacy, you have to deal with it. But all legacy code 
> cannot be fixed, and doing a highly complex SQL parsing / escaping / 
> vulnerability detection code that explicitly targets legacy code and not 
> modern code seems weird to me.
>> HOWEVER, whether mysqli supports parameterised queries or not is all a moot 
>> point because parameterised queries do not allow for parameterizing field 
>> names or table names.  And the point of this thread was to discuss how to 
>> mark SQL that has been composed at run-time to be "safe."  Without being 
>> able to parameterize field names and table names parameterised queries are 
>> not a sufficiently complete solution.
> 
> Not being able to parametrize table or field names is not only a problem for 
> mysqli, but it is for PDO and pgsql too. That's a place where userland 
> query-builders and others DBALs, even the most basic ones do shine, and 
> brings a real added-value.
> 
> But having anyone, writing SQL with user-given table names or column names, 
> and executing it using something like WP's _do_query() method seems like they 
> *WANT* to be hacked.

Are you not familiar with PHPMyAdmin[1] and/or Adminer[2]?  

Do they, or anyone else who has a similar use-case want to be hacked?

> I'm not sure how you will succeed in plugging the is_trusted() / is_literal() 
> / is_wathever() method correctly in an SQL Model Parser & Sanitizer anyway, 
> knowing that at this point, all you'll receive is a huge string issued by 
> some plugin API which has already done crazy dark (and probably bugguy as 
> well) magic.
> 
> I don't see how adding magic in PHP core will avoid the need to fix all those 
> legacy plugins, they probably would need themselves to use this new shiny API 
> to benefit from it ? In the opposite, if something alters the behavior of 
> mysqli implicitly for everyone in order to make it safe, it sounds like there 
> will be a lot of BC ? In both case, it seems that it will not do any shiny 
> magic to me.

It would not affect *any* of those plugins by itself.  They would be left to 
fend for their own.

What it *would* do is allow those developers writing new sites and/or plugins 
or maintaining old ones who proactively choose to sanitize their SQL to be able 
to do so before they pass their SQL to $wpdb->query(), especially if the RFC 
is_trusted() and/or is_literal() passes.

> But, I might be wrong, this thread becomes harder and harder to read, and I 
> may have missed a few points.

It just started!  Note I created a new thread from the 
is_literal()/is_trusted() thread to talk about SQL.

-Mike

[1] https://www.phpmyadmin.net/
[2] https://www.adminer.org/




Re: [PHP-DEV] Sql Object Model Parser & Sanitizer (was [RFC] is_literal)

2021-06-22 Thread Mike Schinkel
> On Jun 22, 2021, at 10:35 AM, Stephen Reay  wrote:
> 
>> On 22 Jun 2021, at 20:39, Mike Schinkel  wrote:
>> 
>>> On Jun 22, 2021, at 9:00 AM, Kamil Tekiela  wrote:
>>> 
>>> Hi Mike,
>>> 
>>> Please don't do this. We already have PDO with prepared statements. The 
>>> data must be bound. This is the secure way of writing SQL queries. 
>> 
>> The problem is that over 40% of the web currently runs on PHP code that 
>> using mysqli.  That CMS does not support PDO nor prepared statements, and is 
>> unlikely to switch to it anytime some in the foreseeable future.  
>> 
>> A SQL object model parser and sanitizer could more easily be used 
>> incrementally by that CMS since PDO does not share connections with mysqli 
>> (AFAIK, anyway.)
>> 
> 
> (Resending from on-list address)
> 
> Apparently you didn't know mysqli supports parameterised queries?
> Wordpress could have adopted parameterised queries when they grudgingly 
> switched to mysqli, years after both it and PDO were introduced.

Well, yes and no.  

I admit I had forgotten it because frankly the WordPress wp-db object wrapper 
used by 99.7%[1] of WordPress developers does not support it and given I had 
long ago realized I could not use them in WP I guess my memory blocked out the 
existence of prepared statements in mysqli.

But it is not relevant in WordPress. Here is where (almost?) all SQL queries go 
to run in WordPress:

https://github.com/WordPress/WordPress/blob/master/wp-includes/wp-db.php#L2050 

Note there are no bind_param() or execute() calls anywhere in that file.  Their 
is a prepare(), but WordPress rolled their own:

https://github.com/WordPress/WordPress/blob/master/wp-includes/wp-db.php#L1302 

So saying that parameterized query is a solution leaves out 40% of the web.  
Because some other guys are the intransigent ones here. 

But also because of much legacy code exists in the form of plugins and themes 
that do not support parameterized queries.

HOWEVER, whether mysqli supports parameterised queries or not is all a moot 
point because parameterised queries do not allow for parameterizing field names 
or table names.  And the point of this thread was to discuss how to mark SQL 
that has been composed at run-time to be "safe."  Without being able to 
parameterize field names and table names parameterised queries are not a 
sufficiently complete solution.  

At least not from an is_literal()/is_trusted() perspective.

> There’s zero reason to believe they would adopt this unless forced to.

Exactly! WordPress is not going to change, so that leaves it up to PHP 
developers using WordPress to protect themselves. 

Since I am *assuming* that everyone on this list wants to minimize the number 
of security issues in PHP applications across the web by whatever reasonable 
means necessary, I also assume that pointing at WordPress and saying "It's 
their fault not ours" does not help achieve those security goals?  So I am also 
assuming that finding a pragmatic solution that would allow PHP to be able to 
empower the developer in a way that WordPress won't might be worth considering.
 
But tell me if I am assuming wrongly here.

-Mike

[1] Yes, I made that up out of whole cloth. But honestly in 10+ years working 
with WP I have almost never seen anyone use anything but the $wpdb provided by 
WP — except for one single plugin — and $wpdb does not support parameterized 
queries.

Re: [PHP-DEV] Sql Object Model Parser & Sanitizer (was [RFC] is_literal)

2021-06-22 Thread Mike Schinkel
> On Jun 22, 2021, at 9:00 AM, Kamil Tekiela  wrote:
> 
> Hi Mike,
> 
> Please don't do this. We already have PDO with prepared statements. The data 
> must be bound. This is the secure way of writing SQL queries. 

The problem is that over 40% of the web currently runs on PHP code that using 
mysqli.  That CMS does not support PDO nor prepared statements, and is unlikely 
to switch to it anytime some in the foreseeable future.  

A SQL object model parser and sanitizer could more easily be used incrementally 
by that CMS since PDO does not share connections with mysqli (AFAIK, anyway.)

> The idea behind SQL builder is to generate SQL, not to allow the data to be 
> sanitized. 

That is why the title of this email said "Parse and Sanitizer" not "Builder."

> Every time I hear the word sanitize I get goose bumps. You can't remove any 
> characters from a string to make it safe. If you want to use escaping, then 
> you need to do it context aware and properly formatted. Don't sanitize 
> anything. Format the SQL properly instead. 

I believe you are latching onto the word sanitizing as you understand it and 
ignoring the context of the discussion.

What I believe I am proposing is to implement an object that would be 
SQL-syntax-aware and — to use your words — "format the SQL properly."  

But maybe I am wrong?  Can you explain how what I am proposing would not be:

- "Removing the characters" needed to make it safe?  
- Context aware?

Note that I did not specifically talk about removing characters, and I did talk 
about context. I talked about parsing the SQL so as to ensure it is safe.

> On a general note. Implementing SQL builder in PHP would be an enormous task, 
> which is not feasible.

Is it possible you just scanned the first email in this thread and did not 
fully read it?  

For the email to which you replied I literally wrote:

I think we are talking two different things here.  And I will admit I am 
probably the one that is not using exactly the right term.  I had envisioned 
something, and then Dan said "SQL Builder" I used that term (wrongly.)Let me 
clarify by giving what I am referring to a different name:  A SQL Object Model 
with parser and sanitizer functionality.

What I was discussing would not be the enormous task you are referring to.  I 
was not proposing creating anything at all like these first two Google results 
for "php sql query builder: [1] and [2].  I was proposing a SQL object model, 
parser and "safe SQL generator" (I changed the last word since you triggered on 
it.)

> There are so many dialects, so many options, and even then it won't ever be 
> accurate as you don't have the full context in PHP.

My email addressed how dialects and options would be handled.  Using dependency 
injection of objects that define each dialect and provide access to the schema.

> SQL is a very powerful language, and building a parser for it in PHP would 
> mean that we either limit it to a subset of valid SQL commands, or we try to 
> create a super tool that is more powerful than MySQL, Oracle, PostgreSQL, 
> etc. combined. 

That is a false binary. It would not be a huge undertaking to create a generic 
query parser that used an object implementing an interface to provide it with 
the information needed to correctly parse a query _*enough*_ to sanitize it.  

And classes defining any given SQL subset could, if not in PHP core, be written 
in userland. And the DB vendor is a likely candidate to write them too.

> There's absolutely nothing wrong with writing SQL in PHP and preparing it on 
> the server. For database servers that don't support prepared statements we 
> already have PDO which is an abstraction library that tries to escape and 
> format data within SQL. It works 99% of the time. 

"Nothing _wrong_ with"  (per se), is true.  

But for applications that have 15 years of legacy code using mysql(i), PDO is a 
non-starter.

> The example you suggested already has a simple syntax in PHP. 
> 
> $conn = mysqli_connect(...);
> $stmt = $conn->prepare($sql);
> $stmt->execute([$_GET['openings'], $_GET['limit']]);

If PHP were to add functionality to core to use prepared statements with the 
mysqli connection, this discussion _might) be different.

But, as I said, for the CMS that controls >40% of the web PDO is a non-starter.

OTOH, what about when a developer needs to parameterize field and table names 
in PDO[3]?  PDO does not address that aspect of assembling a known-safe SQL 
string and requires manual sanitization. What I am proposing _*would*_ address 
this.  

IOW, PDO is a tool for a different albeit overlapping use-case, and could even 
leverage PDO which as applicable to achieve its objectives.

-Mike

[1] https://github.com/nilportugues/php-sql-query-builder
[2] https://github.com/ClanCats/Hydrahon
[3] https://stackoverflow.com/a/182353/102699



[PHP-DEV] Sql Object Model Parser & Sanitizer (was [RFC] is_literal)

2021-06-22 Thread Mike Schinkel
> On Jun 22, 2021, at 6:45 AM, Pierre  wrote:
> 
> Le 22/06/2021 à 11:28, Dan Ackroyd a écrit :
>> On Tue, 22 Jun 2021 at 10:25, Mike Schinkel  wrote:
>>> Should(n't?) PHP add a basic SQL builder class that can be extended for 
>>> special cases, e.g. different flavors of SQL?
>>> 
>> No. Or at least not yet.
>> 
>> This type of thing is much better done in userland, where the api can
>> evolve at a fast rate, rather than being limited by the fixed release
>> schedule of PHP.
> 
> Agreed, PHP is probably not the right place for an SQL builder, there's too 
> many dialects, too many standard or non-standard features, in the end SQL 
> builders almost always end-up being opinionated by its designer's original 
> need, philosophy, or SQL usage habits, and tailored for users which use 
> certain paradigms.
> 
> An SQL query builder is already business domain tied, in some way. Of course 
> most are very generic, but often don't handle properly SQL advanced or modern 
> features, whereas some other where built for ORMs and such and may a reduced 
> advanced SQL features that fits the original need.
> 
> I don't wish to see an SQL query builder in PHP core, instead of favoring 
> usage of modern SQL, it'll in my opinion (of course, that's subjective) lower 
> the expectation of people and probably normalize SQL-92 being the only SQL 
> spoken by people writing PHP (just exaggerating a bit).


I think we are talking two different things here.  And I will admit I am 
probably the one that is not using exactly the right term.  I had envisioned 
something, and then Dan said "SQL Builder" I used that term.

Let me clarify by giving what I am referring to a different name:  A SQL Object 
Model with parser and sanitizer functionality.  One with a simple interface and 
one that would need not be tied to or limited by any specific dialect of SQL.

To illustrate what I mean I created the following straw man example.  It 
assumes a hypothetical SqlObjectModel classes that needs to be instantiated 
with an objects that implement hypothetical `SqlDialectInterface` and 
`SqlSchemaInterface` instances passed to its constructor.  The former defines 
the rules for the MySql dialect, and the latter accesses the schema to validate 
data and data types.  

Some "dialects" and "validators" for very well-known and widely used database 
servers such as MySQL could be implemented in PHP core, while others could be 
implemented in userland (the database vendors would be good candidate to 
implement them, actually.)  I don't yet know what those interfaces should look 
like but I am pretty sure that could be figured out.

So here is the example (I omitted error handling logic for brevity and clarity):

$sql = << {openings}
GROUP BY
c.company_name
LIMIT 
{limit}
SQL;

$conn = mysqli_connect(...);
$som = new SqlObjectModel(new MySqlDialect(), new MySqlSchema($conn));
$som->parse($sql);
$som->set( "limit", $_GET['limit'] );
$som->set( "openings", $_GET['openings'] );
$result = mysqli_query( $conn, $som->sql() );

The SQLObjectModel *could* potentially have additional features like the 
ability to get and set the table name, list of fields, joins, where clauses, 
etc. but the core value-add is not in building SQL but rather parsing and 
sanitizing with properly escaped and quoted arguments so that known-safe SQL 
could be generated.

Existing or new SQL builders could use this to take SqlObjectModel() and pass 
its generated SQL through to ensure their SQL they will output is safe, which 
by the way the string could now be tagged as "trusted" before the builder 
returns the SQL to its developer, assuming an is_trusted() RFC were to pass.

Similarly, any ORM could ensure its SQL is fully sanitized and then pass on to 
whatever functions are needed to execute the SQL.

So, absolutely nothing here would keep people from using "modern SQL," and/or 
cause people to lower the expectation to normalize SQL-92.  This could be a 
generic query parser and sanitizer that could be configured by the "dialect" 
and "schema" objects passed to it and its scope it small, simple and 
straightforward.

I hope that clarifies what I was thinking?

-Mike

Re: [PHP-DEV] [RFC] is_literal

2021-06-22 Thread Mike Schinkel
> On Jun 22, 2021, at 5:28 AM, Dan Ackroyd  wrote:
> 
> On Tue, 22 Jun 2021 at 10:25, Mike Schinkel  wrote:
>> 
>> Should(n't?) PHP add a basic SQL builder class that can be extended for 
>> special cases, e.g. different flavors of SQL?
>> 
> 
> No. Or at least not yet.
> 
> This type of thing is much better done in userland, where the api can
> evolve at a fast rate, rather than being limited by the fixed release
> schedule of PHP.
> 
> If, after people had settled on a good api, someone could make a
> strong argument for adding it to core, it could be evaluated then.


Sure.  But that is not inconsistent with what I was asking/proposing.  

There would be a benefit to collectively working towards to defect-standard 
solution rather than leave it to the chaos of userland to come up many 
different approache, even if initially in userland.

Even a PSR might be appropriate, but I tend to think the interface-centric 
approach only works well things there the benefit it interoperability and not 
when the benefit is implementation.

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



Re: [PHP-DEV] [RFC] is_literal

2021-06-22 Thread Mike Schinkel
> On Jun 22, 2021, at 4:53 AM, Dan Ackroyd  wrote:
> 
> The whole point of the idea of literal strings is to make it be easier
> to write some code that:
> 
> i) is safe.
> ii) can be reasoned about at scale.
> 
> Passing bare strings around is not so great for either of those
> things. You have to manually remember "this is a string that is
> intended to be used in a particular way. And doing that in a large
> code base, when your engineering department is large enough to work in
> separate teams is particularly difficult.
> 
> Instead of using bare strings, using a more specific type e.g.
> HtmlAttribute::fromString('#fff'); and then passing that around would
> be much easier to reason about.

THIS.

> Similarly for the thoughts about concatenating numbers into strings.
> Yeah, people might think they want that, but in practice using an SQL
> builder that allows you to put the number in the right place like:
> 
> $sqlBuilder->add('SELECT * FROM foo LIMIT %d', FIXED_LIMIT);
> 
> 
> And then predictable when the request comes in to allow users to set
> their own limit, changing it to:
> 
> $sqlBuilder->add('SELECT * FROM foo LIMIT %d', $_GET['limit']);
> 
> Doesn't take any time to refactor the code, because it's already using
> an appropriate library that handles variables correctly.

So, IMO this begs the question: 

Should(n't?) PHP add a basic SQL builder class that can be extended for special 
cases, e.g. different flavors of SQL?  

The problem with depending on userland to do this is that there will never be a 
single standard adopted.

If built into PHP it could:

1. Legitimize it across all PHP developers, 
2. To make sure its always available in the most basic PHP install, 
3. To allow implementing a performant SQL parser (which is not reasonably done 
in PHP),
4. To make creating a target for polyfills for prior versions possible, 
5. And to create a standard that all PHP projects that use SQL can adopt?

-Mike
P.S. PHP could also implement a sanitizing templating language for SQL as 
possibly a different or even additional approach.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] is_trusted - was is_literal

2021-06-22 Thread Mike Schinkel
> On Jun 21, 2021, at 7:18 PM, Benjamin Morel  wrote:
> 
> On Tue, 22 Jun 2021 at 01:06, Derick Rethans  wrote:
> 
>> On 21 June 2021 23:37:56 BST, Yasuo Ohgaki  wrote:
>>> 
>>> The name "is_trusted" is misleading.
>>> Literal is nothing but literal.
>> 
>> I agree with this. The name is_trusted is going to be the same naming
>> mistake as "safe mode" was. Developers will put their trust in it that it
>> is 100% guaranteed safe.
> 
> 
> FWIW, agreed, too. Trusted is vague and may imply some false sense of
> security. Literal is literally what it says on the tin.


I proposed the name change originally.

For my inspiration take a look at Trusted Types API in Javascript:

https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API 


And also Trusted Types API from the W3C

https://w3c.github.io/webappsec-trusted-types/dist/spec/ 


The reason is_trusted() would be better than is_literal() is so that the 
function could in the future handle other trusted types that are definitely not 
literal and allow most code that using is_trusted() to continue to work.  

So, for example, in the future we could add a new TrustedInterface and if an 
object implemented the trusted interface and a __ToString() method it could be 
considered trusted by code that uses the is_trusted() to guard against 
untrusted code.

Alternately if in the future PHP added a TrustedAttribute we could use on the 
__ToString() method to declare an object that could be used when a trusted 
string is required.

-

Conversely, I am *strongly* opposed to is_literal() as proposed.  The current 
RFC proposes half a solution without first envisioning what the other half of 
the solution will look like.

If an is_literal() RFC were passed I would envision the following things 
happening:

1. Bloggers would start blogging about how all PHP users should use 
is_literal() when accepting SQL and HTML code, but won't provide any of the 
nuances about special-cases because many won't understand them, they will just 
see a new PHP feature to hype.

2. PHP listing tools will jump on is_literal() and champion its use.  Just look 
at Psalm.

3. Coding standards teams in large organizations will see that the listing 
tools are flagging non-literals and wil start requiring all SQL and HTML etc. 
code to be literals. And since they already bar the use of eval() there will be 
no way to work around the requirement when you actually know what you are 
doing. 

And because they are in large organizations, they will be divorced from the 
developers in the trenches who 95% of the time will have no problem with the 
requirement, but 5% of the time will simply not be able to achieve their 
development needs. Unfortunately these trench developers will not have enough 
power in the organization to get the coding standards teams to even list to 
their issues, especially if they are an agency or contractor.

4. Library developers will similarly adopt is_literal() as a requirement to use 
their library.  While the most popular ones will likely be enlightened enough 
they will address edge cases. many in the long tail will not.  So lots of the 
long-tail PHP libraries out there — and especially the ones only needed by a 
small audience so there won't be alternatives — will not address exceptions. 
And for any of many reasons, many of those library developers will not be 
responsive to those who submit PRs to provide workarounds.

THIS is the future I do not want to see, and if is_trusted() is renamed back to 
is_literal() this is the future I predict. Maybe it won't happen, but I 
personally do not want to risk it.

The biggest problem with the RFC is it does not address how to bypass someone 
else's requirement for use of is_literal() when you *know* what you are doing 
and you absolutely need to.  Craig and I have had several long discussions 
about this, and he said he did not want to allow that because someone might 
misuse it (Craig, if I am paraphrasing incorrectly, please do correct me here.) 
 

And I completely understand Craig's misgivings, but then he would not address 
mine.  His only solution to get around the special-case needs that *will* exist 
is to use eval(). which is a lot like saying: "So you are in pain?  Why not try 
Meth?"  

Craig shared this talk from Google which inspired him:

https://www.youtube.com/watch?v=ccfEu-Jj0as 


I would highly recommend watching this before voting on Craig's RFC.

The speaker talks about how they used "CompileTimeConstants" to reduce security 
bugs, BUT:

1. They used a @CompileTimeConstant attribute and a static checker to guard 
against unsafe strings instead of a function baked into Java. So convention and 
process over language enforcement.

https://errorprone.info/bugpattern/CompileTimeConstant 

Re: [PHP-DEV] [PROPOSAL] Bare name array literals (again)

2021-06-22 Thread Mike Schinkel
> On Jun 21, 2021, at 1:34 PM, Rowan Tommins  wrote:
> 
> On 21/06/2021 17:54, tyson andre wrote:
>> In every place where `key` is a valid php identifier
>> (e.g. can be used in PHP 8.0's named parameters),
>> I propose to allow `[key: expr]` to be used instead of `['key' => expr]`.
> 
> This is an immediate "no" from me: it multiplies the ways to write the same 
> thing from 2 to 4, in order to save a few bytes, in a few instances.
> 
> I think this is something that Douglas Crockford got absolutely right when he 
> simplified JavaScript object syntax to formalise JSON: every valid key can be 
> represented as a quoted string, so if the quotes are always there,p ...

That is one way to look at it.  

Another way to look at it was Crockford's regrettable decision to optimize for 
the uncommon case by imposing tedium on developers and making reading of JSON 
files even harder for end-users than developers has created an unfortunate 
legacy that we can likely never correct given the ubiquity of JSON at this 
point. That decision was probably the initial impetus for JSON5, even, which 
unfortunately can't get widespread adoption because of JSON classic's ubiquity.

But I digress.  And the reason I digress is to contrast — as Tyson also did — 
the JSON the serialization form with the programming language form.  Javascript 
itself supports object initialization without having quotes around the 
identifiers.  And unless I remember wrongly, serializing the JSON object was 
the spark that turned into JSON.

Meanwhile back at PHP, one of the most annoying and poor developer experience 
aspects of working with PHP — because arrays are so ubiquitous in code in the 
wild — is the requirement for those damn quotes around array indexes, and 
especially that array indexes are not implemented as symbols so that we can get 
some "compile-time" checking of indexes in our IDEs and linters and even PHP 
itself.

> you don't need to remember a list of rules about reserved words, allowed 
> characters, etc.

Having to remember the same rules for symbol identifiers hardly seems to be a 
burden for a developer to me.

Also, you used etc. but I cannot think of anything else. Is there something you 
did not include?

> 
>> This is useful for shortening long arrays where the keys are known literals,
>> e.g.
>> 
>> ```php
>> return [success: true, data: $data, cursor: $cursor];
>> // is equivalent to the following, but shorter:
>> return ['success' => true, 'data' => $data, 'cursor' => $cursor];
>> ```
> 
> Although common, this is not a good use of arrays; if your keys are "known 
> literals", they should be fields of some object:
> 
> return new Result(success: true, data: $data, cursor: $cursor);

Except that arrays in PHP can do things objects cannot do in PHP.  So your 
assertion as an absolute is not valid.

To start with, and most important for the immutable-envious developer world is 
that arrays are passed by value.  Unless and until we have an object equivalent 
for passing by value you cannot authoritatively say "your fields should always 
be in an object."

Also, as noted by Kami and acknowledged by Larry, there are many things you can 
do with arrays you cannot do with objects such as destructuring.


> If you don't want to declare a class (yet), you can use an anonymous object. 
> Rather than yet another way to write arrays, it would be great to have some 
> more powerful syntax for those; currently you'd have something like this:
> 
> return new class(success: true, data: $data, cursor: $cursor) { public 
> function __construct(public bool $success, public array $data, public 
> CursorInterface $cursor) {} };

> 
> Brainstorming, we could perhaps extend property promotion into the "new 
> class" clause, so that you could write this:
> 
> return new class(public bool success: true, public array data: $data, public 
> CursorInterface cursor: $cursor) {};

Let's compare your suggestion with the following from a *readability* and also 
developer quality-of-life perspective:

return [ success: true, data: $data, cursor: $cursor ];

YES, there are benefits you get with the approach you mention, but readability 
and developer experience are definitely not in that set of benefits. 



NOW, all that said, I am not sure I will support this change to arrays proposed 
by Tyson.  

I might, but I would like to understand Tyson's use-cases first where he would 
prefer to need an array instead of an object if objects instantiation were made 
easier, and more importantly, why could objects not be used?


-Mike

P.S. While I wanted to close with a request for Tyson to explain, I also want 
to mention I would likely be a lot more interested in is innovation in the area 
of object initialization, implicit typing and implicit class declaration.

Consider if the following could create an instance of an anonymous class with 
an implicitly-typed public boolean property `success`, and array property 
`data` and a CursorInterface property 

Re: [PHP-DEV] [Vote] Partial Function Application

2021-06-19 Thread Mike Schinkel
> On Jun 18, 2021, at 7:41 PM, Benjamin Eberlei  wrote:
> 
> On Wed, Jun 16, 2021 at 6:17 PM Larry Garfield 
> wrote:
> 
>> Hi folks.  The vote for the Partial Function Application RFC is now open,
>> and will run until 30 June.
>> 
>> https://wiki.php.net/rfc/partial_function_application
> 
> I wanted to explain my no vote on this one.
> 
> The examples section shows how every use-case of partials can be done using
> short functions and while this is often a lot more to type (especially if
> you mirror the typehints), these extra symbols feel necessary from my POV
> to make the code clear that creates a partial.
> 
> Especially the ... as "additional" arguments and its various interactions
> with ? produce so many different ways of calling something, it feels
> unnecessary to me to introduce this complexity to newbies that might come
> across use of this functionality. Plus the additional edge cases of delayed
> execution, non-support for named parameters. Its a lot to know to fully
> understand this feature.
> 
> Given that the functional paradigm isn't widely spread in use across PHP
> developers, i am not convinced that we should add more features in this
> direction that increase the complexity of understanding the language by
> that much. While one could argue that functional paradigm isn't
> wide-spread, because these features are missing, it is my believe that the
> majority of PHP developers would still rather prefer imperative coding.
> 
> As a thought experiment I tried to think of code in our codebase that we
> could convert to PFA once we migrated to 8.1 and there just isn't that
> much. This is very different to short functions, nullabilty operator and
> other "glue" / sugar proposals that were added to the language lately,
> which a lot of existing code benefits from and existing code could be
> converted automatically to them using phpcs/phpcbf rules.
> 
> I also am wary of the future after this RFC, as it states it is the
> launching pad to another attempt at the Pipe Operator, which also proposes
> to do a thing (calling functions) in a completly new way that will be hard
> for beginners. 

Just to offer a counter perspective since the assertion was made that partial 
functions would be hard for beginners.

I believe beginners will have a harder time comprehending closures, and 
especially short closures, than partial functions. And especially for the 
use-cases which are likely to be more common, none of which are any more 
"functional" in nature than PHP already is. The use-cases I think will be more 
common? Calling any of the existing built-in PHP functions that accept a 
callable as a parameter.

I am no expert on beginners but I did teach beginning programmers in a 
classroom setting for a decade. One of the biggest stumbling blocks I have 
found for beginners is excessive syntax that looks complex. Many of the 
concepts themselves are less difficult for beginners to understand.  

So, in my experience it will be easier for newbies to understand this, for 
example:

array_map( $this->sanitize_value(?), $values );

Rather that this:

array_map( fn($value) => $this->sanitize_value($value), $values );

The latter just has more sigils to grok than the former, and from what I've 
seen with newbies when you throw too many sigils at them they quickly move into 
a learned helpless state and think that it will be too complicated for them to 
understand.

Bottom line though, what I am saying about newbies is just my opinion and 
probably biased by my own personal sensibilities. 

If we want to consider how beginners will grok new features we should probably 
find a way to solicit objective feedback from beginners to consider in RFCs. 
Otherwise I fear each of us may just be assuming that beginners have the same 
sensibilities as we do. 

-

And where most of us would be still using strings for function callables, the 
benefit of PFA for non-beginners is they let us use symbols to aid refactoring, 
static analysis, IDE functionality, etc.:

array_map( intval(?), $values );

Rather than:

array_map( 'intval', $values );

Of course we could use this, but seriously how many of us are using the 
following structure rather than just passing the function name as a string?

array_map( fn($value) => intval($value), $values );


> I also am wary of the future after this RFC, as it states it is the
> launching pad to another attempt at the Pipe Operator, which also proposes
> to do a thing (calling functions) in a completly new way that will be hard
> for beginners. I hope we don't add both these features to keep the language
> smaller in this aspect of how functions are called.

For the record, my gut tells me beginners will not grok the proposed pipe 
operator as easily as I think they will partial functions.  But who actually 
knows for sure how newbies will comprehend pipes?

-Mike
> 

--
PHP Internals - PHP Runtime Development Mailing List
To 

Re: [PHP-DEV] [RFC] is_literal

2021-06-18 Thread Mike Schinkel


> On Jun 18, 2021, at 8:30 AM, Mike Schinkel  wrote:
> 
> 
>> On Jun 18, 2021, at 7:22 AM, Craig Francis > <mailto:cr...@craigfrancis.co.uk>> wrote:
>> 
>> On Fri, 18 Jun 2021 at 11:45 am, Guilliam Xavier > <mailto:guilliam.xav...@gmail.com>>
>> wrote:
>> 
>>> IIUC, with the addition of integers, the function will return true for e.g.
>>> `'SELECT * FROM foo LIMIT ' . (int)$limit` even if $limit doesn't come from
>>> a "static" value (e.g. random_int() or even `$_GET['limit']`)
>> 
>> Yes, that’s correct.
>> 
>> Supporting integers from any source helps with adoption, and we cannot find
>> any security issues (it’s a fairly small change to the RFC, and that
>> prompted the new name, especially as the original is_literal wasn’t
>> perfect).
> 
> For the avoidance of doubt can you confirm that this $sql would indeed be 
> trusted?
> 
> $ids = array_map( 'intval', $_GET['ids'] ?? [] );

Sorry, that should have been:

$ids = array_map( 'intval', $_GET['ids'] ?? [0] );


-Mike



  1   2   3   4   5   >