[PHP-DEV] Custom object equality
Hi internals, There is often a need to compare whether two objects are equal. For example, a popular [brick/money](https://packagist.org/packages/brick/money) library has a `Money` class, which has an `equals()` method. However, this becomes tedious to implement such methods, when multiple nested objects are involved. For instance, Money has an amount and a currency. There were already suggestions on the mailing list to allow "overloading" existing `==` operator, and some suggestions went even as far as overloading `<`, `>=` etc operators. However, overloading existing operators may lead to a BC break between the PHP version which does support the functionality, and which doesn't. It won't result in a BC break in case it's an entirely new syntax, because a library or a project won't be able to write code which overloads `==` in say PHP 8.4, but with code which still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is implemented as a magic method, then `==` will work differently for 8.3 and 8.4. I suggest thinking about introducing a new operator `~=`, which signifies that custom equality is requested. In such a case, `==` will work as it works now, and by default `~=` will work also like `==`, unless its behavior is overwritten via a magic method. If a magic method is not present in a class being compared, `~=` will compare two objects field by field, but using `~=` comparison rather than `==` comparison, recursively. For instance, a Money object may consist of Amount and Currency. If two Moneys are compared using `~=`, and Money does not implement a magic method, Amount also doesn't implement it, but Currency does, then Amounts are compared using `~=` which is equal to `==` comparison in this case, but Currencies are compared using their custom comparison logic. This approach allows combining - no BC break - `~=` is a new syntax which is unavailable in older PHP versions - explicitly showing an intent that objects are compared using a custom comparison, rather than standard PHP one - allow to skip writing boilerplate equals() methods which just forward equals() to the nested objects - standardize such comparisons on the language level Of course how exactly this operator looks may be changed, `~=` is just an example. WDYT? Regards, Illia / someniatko
Re: [PHP-DEV] RFC Proposal: Readonly Structs in PHP
Hi internals! I think it can be useful for structured data obtained from decoding JSONs or from a relational database. However, maybe there is an even better idea, which combines the best of two worlds: the world of your structs RFC, and native PHP arrays - something like "array shapes". For instance, taking the syntax from your proposed RFC (but perhaps the keyword changed to `shape`, or perhaps `array class` to reuse keywords - let's not bikeshed here) to define a shape, and adding a function like `array_shape_coerce($array, $shapeType)` which internally marks an array to be of a defined shape if it matches its definition (throws an exception otherwise, or perhaps returns true/false value or an enum for success/failure) and allows it to be passed where a certain shape type is expected. I think this could be a better approach than pure structs because it leaves all array-based PHP machinery available to such "structs", like `array_map()`, `array_filter()` etc. There is an open question of whether array coerced to shapes can be modified, and if yes, how to react to modifications. Perhaps the easiest solution is to have another function along the lines `array_shape_seal($array, $shapeType)` which not only marks array to be of shape (if the given array matches given shape), but also permits only such modifications which keep the array to be of this shape. And if the regular `array_shape_coerce` is used, then any modifications are permitted, but the array "loses" its shape. Regards, Illia / someniatko
Re: [PHP-DEV] pipes, scalar objects and on?
I am glad this topic arose! I was also planning to write on this topic to the internals mailing list, but have abandoned this idea, because I feel it might be inconvenient for the real active PHP developers on the list to receive too many emails from the people which don't actively participate in the development itself. My interest in the pipe operator might seem a little non-standard - basically what I'd really want to see is a **nullable** pipe operator! There is a popular library github.com/schmittjoh/php-option, which has 250 MILLION installations. Basically what it provides is a class-wrapper of a value of lack thereof: it's either `Some` or `None`. I also maintain a similar library https://packagist.org/packages/someniatko/result-type which fixes some shortcomings of the original one related to the static analysis, but this is another story. Basically what the stats tell us is that such stuff is popular among the PHP community. In my eyes, it is actually semantically equivalent to the nullable PHP types: `?Type`. And some operations provided by the lib, are actually covered by PHP itself, which has multiple null-friendly operators: `$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal` `$option->isEmpty()` --> `$nullable === null` `$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw new \Exception('blah')` I'd like to use the arguably "more idiomatic" native PHP nullables, rather than a foreign-feeling userspace construct, if they were more convenient. But there is a very important operation, `map()`, which is unfortunately not covered by the native PHP, which is `Option::map()`, and here is a real-world example: ``` return $repository->getById($idFromHttpRequest) ->map($serializer->serializeToJson(...)) // only executes when the Option is Some, not None ->map(fn (string $json) => new Response(status: 200, content: $json)) ->getOrElse(new Response(status: 404)); ``` I'd really like to write such code in a native way: ``` return $repository->getById($idFromHttpRequest) ?|> $serializer->serializeToJson($$) ?|> new Response(status: 200, content: $$) ?? new Response(status: 404); ``` Notice I use the old syntax here, using `$$` as a "piped" intermediate result variable, mostly because I'd like to use arbitrary PHP expressions, instead of piping functions only. I feel this is more natural for the PHP than the more functional-oriented way. I am okay with using functions too like this: ``` return $repository->getById($idFromHttpRequest) ?|> $serializer->serializeToJson(...) ?|> fn (string $json) => new Response(status: 200, content: $json) ?? new Response(status: 404); ``` but that feels less "clean", and also note the inconsistency with `?? new Response(status: 404)` part. Regards, Illia / someniatko
Re: [PHP-DEV] [VOTE] Use exceptions by default in SQLite3 extension
Got it, thank you for explaining. Regards, Illia / someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [VOTE] Use exceptions by default in SQLite3 extension
Hi! It says in the RFC: > PDO is using exceptions, like everyone else. and > Create a new exception class SQLite3Exception, which extends the Exception > class The `PDOException` class is actually extending the `RuntimeException`, not just `Exception`. I am sure it is better to do this for `SQLite3Exception` as well. Regards, Illia / someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Class Re-implementation Mechanism
> > >> So it's mostly a syntactic sugar that allows defining an interface for > the current class that is already implemented by the current class. > Yeah, while answering to you, I've actually came to the same conclusion. > > The interface name is the same as the class name and based on the context, > you either use one or the other. > I think we should distinguish this thing from an interface though. There are some places where this could get in conflict like (new > ReflectionClass(A::class))->isInterface(). But also internally things might > be difficult to sort out to know what to use one or the other. > Yeah, I also thought about reflection, exactly about this method. I believe it's better not to lie, and make isInterface() return false. However, another method should be added, e.g. isClassInterface() - which will return true only in case of `class interface`, or, maybe a more general one like isImplementable(), which will also return true for interfaces. > To have a perfect syntax-sugar, why not also allow the interface name to > be specified? > Something like: > final class interface(ServiceInterface) Service { > public function method1() {} > protected function method2() {} > } > > that would generate: > interface ServiceInterface { > public function method1(); > } > final class Service implements ServiceInterface { > public function method1() {} > protected function method2() {} > } > Well that goes against my initial concern of not introducing additional entities to the system. However it indeed reduces the amount of code to write and is more "transparent" type of syntaxic sugar, like the promoted properties in constructors - this feature also translates to PHP code. If my suggestion ever becomes an RFC, this way of implementing it may become a separate vote I suppose. Regards, Illia / someniatko
Re: [PHP-DEV] Class Re-implementation Mechanism
> This sounds interesting but it breaks some expectations. > > Interesting because you can have any class act as an interface for other > classes with the interface being built up of any public properties or method > that exists on that class. In my original suggestion, it's not like any class, but only those you specifically mark as `class interface`, not just `class`. Closer to the end of my idea I also suggest that maybe it's worth it to allow implementing, like interfaces, ANY classes, not only those specifically marked with the new syntax, but this indeed brings up some issues. > Ok, maybe not any class but just a final class. I see no issue there of allowing to reimplement the interface of a non-final class. This still is better than extending from it IMO. But we _probably_ should prohibit it from abstract classes. > And also maybe just a final class that doesn't yet implement an interface. Also, here is no conflict as well. When reimplementing the interface of the class, you can treat it as a normal interface - which can extend from other interfaces. > The expectation it breaks is that if you have a final class, whenever you use > it, you expect some specific implementation exists on it. > And this would break the expectation and in real life someone might pass a > totally different implementation. > Will not break generic LSP but still will break some expectations. That's why a new syntax is brought up. This expectation might indeed break if we allow to reimplement any existing final class, instead of requiring a manual opt-in. (sorry, this email is sent to you the second time, Alexandru, because I forgot to reply to the maillist as well) Regards, Illia / somenitko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
[PHP-DEV] Class Re-implementation Mechanism
Hi again, internals My marathon of some crazy ideas continues :D, with less crazy one this time. ## Idea Allow "reimplementing" the non-static public API (that is public properties and methods, excluding constructor) of a class by other classes like this: ```php final class interface A { public string $s; public function __construct(string $s) { $this->s = $s; } public static function fromInt(int $i): self { return new self((string) $i); } public function foo(): int { return 42; } } final class B implements A { public string $s = 'hello'; public function foo(): int { return 69; } } function usesA(A $param): void {} usesA(new B); // this works ``` ## Explanation Consider there is a class like this: ```php final class Service { public function __construct(private SomeDependency $dependency) {} // ... } final class SomeDependency { // ... } ``` We want to write some tests for the Service class, but we don't want to use a real SomeDependency instance during tests. A common approach is to either extract an interface (JUST to make it testable), or to drop the `final` keyword and allow extending the class. Both approaches have their flaws: - extracting an interface unnecessarily complicates the system, where only one "real" implementation of an interface is assumed. - dropping the `final` keyword allows for the rabbit-hole of inheritance abuse, like greatly described in this article: https://front-line-php.com/object-oriented I believe I came up with a better idea: what if we could leave both benefits of prohibiting the inheritance abuse and also allow not to clutter our namespace with excess entities like interfaces? I hereby suggest to combine the responsibilities of a class and an interface into one thing like that: ```php final class interface C {} final class D implements C {} ``` Now other classes can "implement" this class as well. Introduction of the new syntax (`class interface`) also solves BC problem - if you want to forbid your classes to be reimplemented whatsoever, you can still stick to the `final class` syntax. Although it is also possible to allow "reimplementing" ANY class, then new syntax is not needed - but some library writers like Marco Pivetta could be sad about that I suppose. Soo..., what do you think? Could this be a valuable addition to the language? Regards, Illia / someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] RFC Proposal - Types for Inline Variables
Hi there, I am not a core PHP language developer, just a regular PHP programmer, and cannot speak for the whole community, so I'll just share my opinion. I believe a new language feature suggestion should contain not only its description, but also motivation: i.e. what are we trying to achieve with it. Will the development experience be worse without it, or maybe it disallows some sneaky bugs to appear in your code, or maybe it acts as a native documentation for your code etc. Personally it's hard for me to see what kind of improvement will restricting a type of a variable bring. It may prevent repurposing the variable with the same name for a different use somewhere down the function, which can lead to bugs if a function is large enough. However, for such cases I think better idea would be to introduce `const` variables like in JavaScript - which can only be set once and cannot be reassigned later. This way you'll also guarantee the type of the variable will be preserved. > We can add types in a lot of places, but we still don't have a way to add types to inline variables. > int $value = 10; > $value = 'foo'; // TypeError Can you describe some use cases where this feature will be useful? I see it's coming from statically typed / compiled languages like C++, but in such languages compiler must know variable type in order to manage memory properly. As PHP is an interpreted language, it doesn't have this problem. Regards, Illia / someniatko
Re: [PHP-DEV] Re: Official Preprocessor
Hi, These all are valid concerns! I cannot speak about management and cost issues though, as I am not an active PHP dev team member. > 3. What's the MVP? How do we measure usefulness, adoption and maintenance > complexity? As a shot in the dark, the first step could be implementation of typed lists in my opinion. Do not implement full-blown static analyser nor the type checker for each possible case, just only check the usage of typed lists within the pre-processed files. Assume that whatever comes from the non-preprocessed ones is correct. Make only simple naive assumptions for all internal array_ functions as well as basic array operations. If there is some runtime magic going on with constructing the list, just fallback to infering the type as a simple array. For such cases, allow a special attribute which will tell the type checker this variable / property etc will indeed contain the typed list, like a @var annotation for IDEs / static analysers nowadays. The preprocessor / type checker **should not aim to 100% guarantee the correct types will be in the runtime**: TypeScript does this neither. Rowan has mentioned Dart language in a parallel thread, which makes most of the checks statically, but for some cases the compiler still adds runtime checks. Rowan warned that PHP might have a lot of such cases possible though. But I still think this also might be a good idea for MVP. > 4. Is it an aborttable idea? If things go south and can't be supported > anymore, how bad for PHP adopters would it be? I don't think any of PHP new features that go live are abortable. This affects not only my suggestion, but also everything what has been done for PHP in past. Once a feature is in the language and released to the public, you cannot revert it. There must be a long multi-year process preceded with a deprecation at least. A concept of experimental features was suggested earlier, but this is completely different topic, so I believe we should not go into that rabbit hole here. Overall, I consider this question orthogonal (or irrelevant if you prefer) to the original topic, let's take as an axiom that there is no way back. > 5. How would voting on the spec be like? Complete years-work-hours spec or > small incremental functionalities? Small incremental functionalities. Gradually more stuff could be proven statically, more complex cases covered, and while they are not, an attribute / static assertion could be used. Maybe some of such assertions could be allowed to be preserved in runtime, at the cost of some performance penalty, IDK. But I believe we should leave such choice to developers, whether they want the checks in runtime as well. > 6. Is versioning tightly coupled with PHP version or does it have its own > version support system targeting multiple php versions at the same time? I strongly believe it must go hand in hand with the PHP version, and not as a separate tool, because I see it as a feature of a PHP language itself. > Overall, I think PHP has been constantly losing popularity in favor of > Typescript and a transpiler could create an exciting solution for some of > PHP's problems, but it does not seem like a pet project. Sure, it should be considered seriously and requires some upfront planning. Though, well, PHP itself started as a pet project :D -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
[PHP-DEV] Re: Official Preprocessor
I'd like to also emphasize that the concept of compilation and static type-checking / analysis is not foreign to the PHP community. Major frameworks like Symfony already have a concept of compiling e.g. a DI container, and static analyzers like Psalm, PHPStan and others are actively used. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
[PHP-DEV] Official Preprocessor
Hi Internals The main gist: -- I suggest to introduce an official type-checker / static analyser / preprocessor / transpiler for PHP, somewhat similar to TypeScript in the JavaScript world, which will allow to introduce the features otherwise impossible for the PHP world, at the cost of including an additional transpilation step. The reasoning: -- You all know there are a lot of problems with the language, especially large gaps with the current type system, which have large community demand to overcome, but still cannot be solved due to the paradigm chosen by PHP. And the paradigm is to be statically typed (to some extent), but dynamically checked language, which limits the number of available options due to performance reasons. The introduction of static types have gradually eliminated the need of using external means of communicating the types (phpdoc @param and @return annotations), replacing them with native language constructs, making the language more expressive and enterprise-ready. However, there are a lot of things still missing, like types of arrays, including lists, hash-maps and structure-like arrays, and of course generic classes and functions. These are still covered nowadays with external means like phpdoc annotations and static analysers / type checkers to validate them. This leaves PHP in the odd mixture of native types and externally validated annotations via comments. Paradigm of a dynamically checked language also leaves out the problem of type-checking before running the code. Even though the types are defined statically, you still have to physically run the code, with all possible execution paths, to catch a type error. To avoid that you still would have to use an external typechecker / static analyser, even if PHP could cover 100% of type demand natively. Python solves this problem nicely I think. It is dynamically typed, but it allows a special syntax for static types and also has a separate static type checker. I think this is really a good approach and it would be great if PHP followed this path for the beginning, but we have what we have already. There were attempts to create preprocessors for PHP (like PHP++ IIRC), which allowed features like generics, but they did not gain enough popularity, weren't baked by large enough companies, didn't make their way to major IDEs support. I believe the only solution is to make an official one. Therefore, I suggest the following thing: 1. Introduce a new #declare directive which will mark the file as requiring pre-processing. 2. Let PHP introduce special features that only work in such "pre-processing required" files, such as typed lists and generics. 3. Implement a static type-checker in PHP that will verify those typed lists and generics are indeed used in a valid way. 4. Make the PHP preprocessor output the "normal" PHP file somewhere, which has list types and generics erased. I think something like that was suggested earlier many times. As an alternative to a new #declare feature + validation + transpilation in "plain old PHP", the Python way of just ignoring statically checked stuff could be applied. This approach though looks odd to me in PHP world, because having some stuff checked in runtime, and some only statically may confuse developers a lot. Basically, this will split PHP in two languages, one being superset of other, but checked statically. I realize this might be much of a paradigm shift, it may require lots of work if accepted (I can only dream of it though), but still I want to share my thoughts with you and propose something for consideration. Regards, Illia / someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC][Dynamic class constant fetch]
> What's convenient about `Foo::{$bar}` vs `constant(Foo::class . '::' . > $bar)`? I'm a bit confused by this :| > > Is it the few keystrokes added? Even if ignoring syntax / convenience bikeshedding, I find it a really valuable addition to the language self-consistency. It's symmetrical to the already existing syntax of dynamic property fetch and dynamic method calls. One could argue that it's dynamic, too much magic and bad, but then we should either deprecate those features, or if not, have this symmetry. The Principle of Least Amusement and human pattern recognition overall with thank you. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] ARRAY_UNIQUE_IDENTICAL option
> To solve this, I propose adding an ARRAY_UNIQUE_IDENTICAL option that > can be passed to array_uniques $flags which uses identical operator > (===) semantics. Internally it uses a new hashmap that allows using > arbitrary PHP values as keys to efficiently remove duplicates. This is > slightly over-engineered for this use case. However, this data > structure will be required for implementing ADTs to deduplicate > instances with the same values. This hashmap is a heavily minimized > version of the teds extensions StrictHashMap [1]. As a regular developer, I look from the usage side, not from the implementation side. >From such perspective, remembering that filtering unique enums requires this exact flag is somewhat "dirty": on the surface, nothing tells that enums are non-comparable. You will have to memorize yet another PHP quirk, or be able to build a logical chain: - enums are non-comparable by default - enums have no default string value (if not baked by a string) - array_unique internally sorts an array - default flag for array_unique compares the string representations of its items - thus it won't work for enums in a general case This requires deeper knowledge of PHP, which is for sure a valuable skill, but not as wide-spread as we would like to. Most of the devs will first try to use array_unique() with the default flag, perhaps not even knowing about flags existence. Each usage of such a flag will not reveal intent by itself and at least will require a comment for readable codebases. Perhaps an alternative idea is to provide a default string value for enums which are not baked, Nikolas had already brought up this idea earlier. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] is_literal
Nevertheless, I am sure even without a dedicated type it is still a valuable addition to the engine. Just to clarify, I understand that if this would require too much additional work to implement the type, IMO it's okay to ship the feature without it for now. I was just replying to other arguments, which are not related to the work amount :P Thank you for your work! Regards, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] is_literal
> And I agree, there would be value in having a `literal-string` type, > especially when working with IDE's and Static Analysers; but it brings a > couple of issues that the is_literal() function solves: Yeah, those are valid arguments why we should have a dedicated `is_literal()` function, and in fact we could have both the type and the function at the same time, the same as we have `string` type and `is_string()` function. My worry is, if type is not added in the present RFC, adding it later may look as "too low value" and probably will have a lower chance of being accepted. > 1) Libraries need to support older versions of PHP, so they wouldn't be able > to use the `literal-string` for many years; whereas they can use > `function_exists('is_literal')` today, probably to provide their own function > that simply returns true on pre PHP 8.1. If the type is added in say 8.2, they wouldn't be able to use it even longer. Of course this can be re-modelled using a value object which performs the is_literal() check in the constructor, however I think a native PHP type would be better, for example in the case of variance checks (being a subtype of "string"). > 2) The is_literal() function gives the libraries a choice on how to handle > the situation. At the moment they just receive a string of unknown origin, so > they can trigger a warning, while also supporting legacy projects who want to > switch off the warnings. And some developers might want to use a library that > has an option that can raise exceptions (so they can be certain there are no > issues). If we have both the fn and the type, libraries would still have that choice, either enforce it solidly and throw TypeError (PHP 8.1), or polyfill the `is_literal()` function to always return `true` and be able to both take advantage of PHP 8.1 and work on the earlier versions. I hope these points will be really considered, and PHP's type system will evolve into more robust and strong one. (offtopic: hoping we will have typed vector and dict types someday too) > Craig Regards, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] is_literal
Hi! >From what I understood reading the RFC, this looks like a new type, "literal string", specifically a subtype of "string". Have you considered instead of forcing library authors to use `is_literal()` check everywhere on their input boundary and making sure no place where input is passed, is forgotten, to let them type their whole codebase, including internal, against the new `literal-string` type, which would be enforced by PHP all the time? From my perspective as a PHP developer, it would serve clearer intent than only checking in a few places which presumably may take user input, i.e. you could explicitly state "this function does only work with literal strings". Regards, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Re: [RFC] Short functions, take 2
> Unless there is any significant feedback, I'll be calling a vote for this RFC > sometime late this week (Thursday/Friday-ish). Hi! As a regular PHP developer, I am very interested in having this quality-of-life feature: it allows code whose intent is more functional-ish (mapping input arguments to an output expression), than imperative-ish (do this then do that), to look more appropriate. Is it planned to be voted or it's just forgotten :P? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] A little syntactic sugar on array_* function calls?
> The proposed syntax > > $array |> array_map($fn1, ?) |> array_filter(?, $fn2) > > When I compare to: > > $array->map($fn1)->filter($fn2) > > 1. It's longer. Much longer. > 2. It still requires knowing where the array goes. That's legacy which we > could sidestep with the arrow notation. > 3. Admittedly, the pipe is much more powerful. While the argument No. 2. is completely valid, the 1st one is not so. If you remove whitespaces around the `|>` and also if you alias these functions to `map` and `filter` respectively (or if, for instance, some future RFC moves them into a special `PHP\Array` namespace, which would probably never happen, but it's allowed to dream), it could look like this: ```php $array|>map($fn1, ?)|>filter(?, $fn2); $array->map($fn1)->filter($fn2); ``` A bit longer (due to 2.), but not that much, actually. Best wishes, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] A little syntactic sugar on array_* function calls?
> The pipe operator feels like a poor solution while `->` would do exactly what > people want. Could you elaborate? Adding method-like array access functions with only few predefined functions, and only for arrays looks very limited in scope, while the pipe operator would allow applying any existing function, be it internal or userland one, to any type of variable, not limited by arrays, having the same "fluent api" feel. Also it clearly distincts between object method calls and function application, which is a plus for clarity, IMO. I am also not sure who the "people" you refer to are, because, well, I am among the people using PHP daily, and I would personally prefer a more generic solution, which the Pipe Operator currently is. Best wishes, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] A little syntactic sugar on array_* function calls?
Sorry, I made a typo here. In combination with the proposed Partial Function Application RFC (https://wiki.php.net/rfc/partial_function_application), which is however is under active discussion, and changes will probably be made to it, it would look roughly like this: ```php $array |> array_map($somefunction, ?); ``` Best wishes, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] A little syntactic sugar on array_* function calls?
> I was wondering whether $array->map($somefunction) would be possible. There is Pipe Operator RFC existing already, which most probably would suit your needs. The code you want will look like this: https://wiki.php.net/rfc/pipe-operator-v2 ```php $array |> array_map($somefunction). ``` Best wishes, someniatko -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Partial function application
> The GitHub PR supports this, and there is even a comment there saying > we should show this in the RFC. We'll get that updated. Thank you for the quick reaction and for your work! -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Partial function application
> Greetings, Internalians! > > I would like to offer for your consideration another RFC, specifically syntax > for partial function application. > > https://wiki.php.net/rfc/partial_function_application Thank you again for one more wonderful language change! I am sure this is a huge step into the correct direction for the language. One of the nice side effects of this proposal is that it is great for reducing visual clutter when being used in functions like `array_map()`, `array_filter()` etc. However, I have a small nitpick, which may probably be a bit hard to implement: what about partially applied constructors? They are sort of functions as well. For instance: ```php $strings = [ 'value-1', 'value-2' ]; $objects = array_map( fn (string $s) => new ValueObject($s), $strings ``` to be turned into ```php $strings = [ 'value-1', 'value-2' ]; $objects = array_map(new ValueObject(?), $strings); ``` There is unfortunately no mention of partially applied constructors in the RFC. If it is not implemented as above, could you please consider adding it to the Future Scope probably? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Pure intersection types
> Should we be planning ahead for some future where union and intersection > types can be mixed and design the reflection API accordingly? I worry that > if we have a ReflectionIntersectionType, and a ReflectionUnionType, that > ReflectionIntersectionAndUnionType is just going to make both implementers > and users table-flip. As far as I understood, there is no need for any new "combination" `ReflectionType`-s. For e.g. "A|(B)". There should be a structure like this: ``` ReflectionUnionType#getTypes(): |-- ReflectionType |-- ReflectionIntersectionType#getTypes(): |-- ReflectionType |-- ReflectionType ``` -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
RE: [PHP-DEV] [RFC] Short-match
`match` is an expression, where as if-else construction is not. This allows for combining it with a potential future feature of single line functions and methods. For example (hypothetical syntax is used): ``` function getNumberKind(int $number) => match { $number > 0 => NumberKind::POSITIVE, $number == 0 => NumberKind::ZERO, $number < 0 => NumberKind::NEGATIVE, } ``` See how natural it looks and reads. Another improvement is that it reduces the amount of visual clutter (`if` and `return` keywords). Yet another distinction between “if” and “match” is their intent. `If` is more appropriate for the procedural flow. However, when we operate with pure functions, `match` is a good sign of such function. It shows that different input values turn into different output values, instead of different branches of procedural code being executed. Therefore, if code is intended to be more FP-ish, IMO, `match` is preferred. For the procedural code patterns, including early returns / throws, `if` is clearly a better choice. So, `match` is better suited for functional-ish parts of code, which do not pose behavior, but only convert one value to another ones. In the FP world, pattern matching is a widely used feature, allowing to split computations of output value for different kinds of input value. The closest thing available in PHP these days is `match (true)`. The `(true)` part looks ugly and artificial, and removing it is a matter of a cosmetic change. Of course, it is possible to use `match` instead of `switch` or `if`s for procedural code, and vice versa, which is still syntaxically correct, but bad from an intent expression perspective. This is a downside of `match` expression as a whole and, IMO, is irrelevant for this small improvement. So, - `match` allows writing clearer code when used with FP-ish intent; it is also an expression, therefore irreplaceable with if/switch in some cases. - pattern matching is a widely used feature in FP, and `match (true)` is the current way to achieve the most similar thing in PHP. - improving `match` will not hurt the language allowing to write the same thing two ways – because it is already done by accepting `match` RFC itself -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] [Discussion] Shorter Attribute Syntax Change
Hello Internals, Here is a small comparison table based on current feedback, maybe it will bring some objective clarity to the discussion: (markdown below) Impact|`@@`|`#[]` ---|---|--- BC break|virtualy nonexistent|slightly broader: `##[` comments are now broken. Parser|no technical problems by now|no technical problems by now Extendability|less future-proof, arguably|more future-proof, arguably Grepability|harder, arguably|easier, arguably (however, consider an Attribute taking an array `[]` parameter.) Perception|similar to PHPDoc annotations, more familiar to PHP devs|more familiar to Rust devs Other issues are either speculative or insignificant (as for me): - causing future parsing issues: no evidence - "backfilling": there is, arguably, no use case for it. Code using PHP 8 features will target PHP 8 anyway. Code, compatible with both PHP 7 and PHP 8 would most probably use classic PHPDoc annotations. - "syntax no other language uses": this is probably insignificant. - "possibility of @@ moving to @ is near to 0": i am not sure anyone planned to move @@ to @, and if so, it would be an unnecessary BC break. I am personally in favor of `@@`, but just because it looks visually nicer to me. I see no strong objective reason to favor one over the other. If you want an ending token, maybe consider `@@Attribute@@`, personally I like those round-ish shapes :P. On Tue, Jul 28, 2020 at 5:47 PM Joe Ferguson wrote: > > Hello Internals, > > I've been working with Derick Rethans and others (thanks all!) on a Shorter > Attribute Syntax Change RFC which outlines reasons why the "#[]" syntax > would be preferred over the currently agreed upon "@@" syntax for Shorter > Attribute Syntax. > > An important part of the research that went into this proposal demonstrates > how "@@" will make handling attributes more difficult for PHP_CodeSniffer > (and similar tools) and shows how the alternative "#[]" syntax is more > friendly for these tools. > > You can find the RFC > https://wiki.php.net/rfc/shorter_attribute_syntax_change and I'm happy to > answer any questions as best I can. > > -- > - Joe Ferguson > JoeFerguson.me > osmihelp.org -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Re: [RFC] [VOTE] Make constructors and destructors return void
> I think going from forbidding > return types on ctors to requiring them to be void is one step to far. I am afraid you've slightly misunderstood the intention of this RFC. It is proposed that it is impossible to return anything from the constructor, not that you have to add ": void" to it. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Re: [RFC] Nullsafe operator
> I've reworded some things and added more information on short > circuiting. Functionality wise the RFC has remained the same. > > Since there was little negative feedback I'd like to put this feature > to a vote in ~1 week. If you have any concerns or criticism please let > me know in time. Just curious, do you plan on putting this to a vote in near time? The feature freeze is coming soon. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Proposal: A way for classes to define a response to any primitive type cast
> This would seem to fit your use case with Shoop quite well: > rather than Shoop::array($array)->first()->unfold(), you would just call > $array->first(). It's fairly high on a lot of people's wish lists, but > there's a lot of details to get right in both design and implementation, > so I strongly recommend searching for previous discussions and proofs of > concept before diving in. We don't need methods on non-scalar objects, if we have [pipe operator](https://wiki.php.net/rfc/pipe-operator-v2): sth like `$array |> array_first(?)`. This would allow much greater flexibility. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property write visibility
I do agree with Marco that this is a step in a wrong direction. Our goal should be not ensuring that a prop is not rewritten outside, but rather that it is not re-written at all. It makes no sense to rewrite a property in majority of cases: 1. fields of an DTO - nay. Should be immutable instead. You never change DTO, don't you? 2. injected services (like DB connection or an HTTP client) - nay. Shouldn't ever be overwritten once an object containing them is instantiated. Write-once / immutable is preferred. 3. data fields of an Entity-like object - looks like the only reasonable case. However adding dedicated syntax for this is arguably not much better that what we have now. It is already solvable with standard getX() pattern, or with a single method returning a required chunk of state as DTO. So for me this does only solve the problem of having getters (or dedicated methods) in #3, which is rare enough compared to other code, and is already solvable with syntax existing nowadays already. Introducing the new syntax, however, will have the following downsides: - adding proper immutable / write-once properties to the language will be met with much more resistance: "Why adding immutable if we have private set already!" - this will encourage using them in places where immutability (e.g. via static analysis tool like Psalm) should be used instead (see #1 and #2). - adding more advanced property accessors feature will be also likely met with more resistance. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php