Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:111171 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 19424 invoked from network); 24 Jul 2020 15:03:26 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 24 Jul 2020 15:03:26 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 66EDE1804C8 for ; Fri, 24 Jul 2020 06:58:21 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 24 Jul 2020 06:58:21 -0700 (PDT) Received: by mail-pl1-f177.google.com with SMTP id x8so4451629plm.10 for ; Fri, 24 Jul 2020 06:58:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=FHbNiSC7aS7Ji1smOXJ80uDNvWv/gF95evoYpyXS7G0=; b=X228wK+fWCfnV4kBlKzR9Re/T5K2xXYcn73N24WQp6VfTAqYLNu05s+Kf36u9GPTzz B7kGNzjV+LRRuj5xwSrv++6qyelHmD9cC4mFedRZBojXGlFxkJGQTCnjaAJLp1JwQBj1 iFTMBFdwblKYXX52gkFnkRQME7f3/JRrOheC8M7mB2cAMh2JW90EkzJTlhqf2GqWYCWg leL04PhtALK/XhcIbbPI3HJBEbZ3mGJdbF6/jzhwgTtMYEu8HW4QAdYq4wauKbG3V7RK WfKcSmbbV6RzuxoB2vk1Dod9uJ2gK8VPx9jzVSXMFJx13S15fCAejCF/Apli83ULIxbF DOWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=FHbNiSC7aS7Ji1smOXJ80uDNvWv/gF95evoYpyXS7G0=; b=lkGdGZK+04n7e7P7BJYcijOEDIVm2bcmm/+FZ/jdERN8WCyoMGLuff8fv0ojaAN0Tn oN8HXbb19uxgfYaWyH1hVMaZTBIw7wljFERYRK2VV4xckadZpxAbsHJdoA4vB7RNXQtb PRjLUZvTR396grhDo8hc3M3i1J3r08KnI+jJIY1vrJMgkLnH45ASxEkR3U1rGrjX9RZ5 jtXK0p4jQmI3piKoYgR5EPzUgI0CPsT/o0qyo31djZMCfMdxr4zRaxrjszKTiUEi7/Xv skUFhfyQ5ZYEnn1hE/SrNUOpyZTnq1UnB1wTUeKTv73JQGOdhX2hUu9+8bixPquz0nBN pqFg== X-Gm-Message-State: AOAM533mVqS7rwpASY544gYF/x713BlsywZI8NwtK1OhbhSfIjv0R3xJ m+CNo+r3HumVL1XRX8RYlZlyZsRZZ4zFdp1mb2+qM2kGwGA= X-Google-Smtp-Source: ABdhPJz5bJzv01GPuD23zlIu9K2jGaYGFXyZnEO/wnPIZjY3EZA3li0jB8RhgQGkGAm1sJUNP0n7ClFMQIvsL+S4+eE= X-Received: by 2002:a17:90a:1345:: with SMTP id y5mr5682838pjf.68.1595599095883; Fri, 24 Jul 2020 06:58:15 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 24 Jul 2020 14:58:03 +0100 Message-ID: To: Benjamin Eberlei Cc: PHP internals Content-Type: multipart/alternative; boundary="000000000000506b5205ab305da7" Subject: Re: [PHP-DEV] [RFC][Proposal] Renamed parameters From: t.carnage@gmail.com (Chris Riley) --000000000000506b5205ab305da7 Content-Type: text/plain; charset="UTF-8" On Fri, 24 Jul 2020 at 14:43, Benjamin Eberlei wrote: > > > On Fri, Jul 24, 2020 at 3:15 PM Chris Riley wrote: > >> On Fri, 24 Jul 2020 at 14:01, Benjamin Eberlei >> wrote: >> >>> >>> >>> On Fri, Jul 24, 2020 at 1:13 PM Chris Riley wrote: >>> >>>> Hi all, >>>> >>>> The named parameters RFC has been accepted, despite significant >>>> objections >>>> from maintainers of larger OSS projects due to the overhead it adds to >>>> maintaining backwards compatibility as it has now made method/function >>>> parameter names part of the API; a change to them would cause a BC break >>>> for any library users who decide to use the new feature. >>>> >>> >>> Hi Chris, >>> >>> I had something similar in mind, but using an attribute. Here is a patch >>> that already allows this: >>> >>> >>> https://github.com/beberlei/php-src/commit/4b0a02f9c6ba579f93ec57c754fa3794a96c696b >>> >>> Idea: Have a @@NameAlias attribute, where you can provide a second name >>> for the attribute. This would allow to refactor parameter names by adding >>> the attribute with the old name as an alias. >>> >>> >>>> >>>> It is likely that the way this will shake out is that some maintainers >>>> will >>>> accept the additional overhead of including parameter names in their BC >>>> guidelines and others will not, this leaves users unsure if they can use >>>> the new feature without storing up issues in potentially minor/security >>>> releases of the libraries they use. This is not really an ideal >>>> situation. >>>> >>>> More pressing a point is that the current implementation breaks object >>>> polymorphism. Consider this example (simplified from one of my >>>> codebases) >>>> >>>> interface Handler { >>>> public function handle($message); >>>> } >>>> >>>> class RegistrationHandler implements Handler { >>>> public function handle($registraionCommand); >>>> } >>>> >>>> class ForgottenPasswordHandler implements Handler { >>>> public function handle($forgottenPasswordCommand); >>>> } >>>> >>>> class MessageBus { >>>> //... >>>> public function addHandler(string $message, Handler $handler) { >>>> //... } >>>> public function getHandler(string $messageType): Handler { //... } >>>> public function dispatch($message) >>>> { >>>> $this->getHandler(get_class($message))->handle(message: >>>> $message); >>>> } >>>> } >>>> >>>> This code breaks at run time. >>>> >>>> Proposals were made for resolutions to this issue however all of them >>>> require trade offs and could potentially break existing code. >>>> >>>> My proposal to resolve these two issues is to add the ability to rename >>>> parameters with a new syntax as follows. >>>> >>>> function callBar(Foo $internalName:externalName) { >>>> $internalName->bar(); >>>> } >>>> >>>> $x = new Foo(); >>>> callBar(externalName: $x); >>>> >>>> This allows both the above problems to be resolved, by renaming the >>>> internal parameter and keeping the external signature the same. >>>> >>>> I propose that the RFC would have two voting options. >>>> >>>> The first would be to implement it as proposed above, this would allow >>>> any >>>> parameter to be called by name regardless of the intentions of the >>>> author >>>> of the method/function and is closest to the current behaviour. >>>> >>>> The second option would be to use this syntax to make named parameters >>>> in >>>> userland code explicitly opt in. As such an additional shortcut syntax >>>> would be implemented: $: to designate a named parameter. eg >>>> >>>> function callBar($:externalName) { >>>> $externalName->bar(); >>>> } >>>> >>>> $x = new Foo(); >>>> callBar(externalName: $x); >>>> >>>> If a parameter is not opted in, a compile time error is raised: >>>> >>>> function callBar($externalName) { >>>> $externalName->bar(); >>>> } >>>> >>>> $x = new Foo(); >>>> callBar(externalName: $x); // Error: cannot call parameter >>>> $externalName by >>>> name. >>>> >>>> There are pros and cons to this second approach, on the one hand it >>>> reduces >>>> the usefulness of the named parameter syntax by requiring changes to old >>>> code to enable it (although this could probably be automated fairly >>>> easily) >>>> however it does provide a neater solution to the second problem in >>>> that, to >>>> prevent the runtime errors in the second issue example, every child >>>> class >>>> would need to use the rename syntax on it's parameter to prevent errors, >>>> whereas if we went down this route, the parent class could just not opt >>>> into the named parameter syntax and the code would function as expected. >>>> >>>> Another advantage is that with the ability to rename parameters using >>>> the >>>> opt in, we gain some flexibility to tighten up the LSP rules relating to >>>> named parameter inheritance. >>>> >>>> class Foo { >>>> public function bar($:param) { //... } >>>> public function baz($internal:external) { //... } >>>> } >>>> >>>> // OK >>>> class Bar { >>>> public function bar($renamed:param) { //... } >>>> public function baz($renamed:external) { //... } >>>> } >>>> >>>> // Compile time error cannot rename named parameter $:param (renamed to >>>> $:renamedParam) >>>> class Baz { >>>> public function bar($:renamedParam) { //... } >>>> } >>>> >>>> // Compile time error cannot rename named parameter $:external (renamed >>>> to >>>> $:renamed) >>>> class Baz { >>>> public function baz($internal:renamed) { //... } >>>> } >>>> >>>> While this would be technically possible with the first option (no opt >>>> in) >>>> it would break any existing code which renames a parameter as every >>>> parameter would be subject to these rules. >>>> >>>> I don't have Wiki karma so can't post this yet; but I want to get the >>>> ball >>>> rolling on discussion as feature freeze is coming up fast and if we >>>> want to >>>> go for the second option, that must hit before the named parameter >>>> syntax >>>> is in a tagged version of PHP. >>>> >>>> Regards, >>>> Chris >>>> >>> >> Hi, >> >> While the attribute idea does solve the BC problems, I'm not seeing how >> it really solves the polymorphism issue - could you provide an example of >> how this would work? >> >> In either case; as a personal preference I'd rather stick to syntax that >> affects the parameter as part of it's definition instead of tweaking it's >> behaviour with an attribute. It just feels easier to grasp what is going on. >> > > Attributes are part of the declaration from PHP 8 on, and make them prime > implementation device for this kind of functionality, because they don't > require new keywords (same goes for ReadOnly and many other proposals that > were shot down leading up to PHP 8). > > You are right about poloymorphism, that would "only" work when every > implementation adds @@NameAlias("message"). You could devise another > attribute for this that gets inherited: @@InheritName or something (with > probably a better name needing to be found). > Do you have an implementation example of using attributes that can be added to the RFC: https://wiki.php.net/rfc/renamed_parameters Thanks, Chris --000000000000506b5205ab305da7--