Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109558 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 32370 invoked from network); 7 Apr 2020 19:16:07 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 7 Apr 2020 19:16:07 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id BA54F1804F2 for ; Tue, 7 Apr 2020 10:44:04 -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=-0.7 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (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 ; Tue, 7 Apr 2020 10:44:04 -0700 (PDT) Received: by mail-wm1-f52.google.com with SMTP id f20so2747002wmh.3 for ; Tue, 07 Apr 2020 10:44:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-transfer-encoding:content-language; bh=PONcghEa4EMxrm//qVd0zqVRNAFMiB41KPTWipRlAoY=; b=W+dYPVze/W6HdF5IECQ8H2a9SWKIq0lwhO5B1FW4WOECOg5iz1v/YHAkxjJdvEGcmV kDk8HrsmWe0nGhi3NMzO546+r9l3b3QI+z1MUN8dBKu1SAJ8KgXC6F4TmKTQce7xo88T m0daNSNhnp6HR+QVfTO4KrpUwtLvMzmEQ5lpqihK0XYTWO2PDsXczH2rI+i/W8lpxWvs Ot5fsh4H8YVxneg/ViozH7fQjJDGI/M0m9OZh0cYox3GXYUpqjwxkkiGrvLKR+vOqffY Sn3+4Ah4jK6quREuMOuA+s2BdDFyehLwsuP9R7KpGbZu/P5nTvp3Wif26UtIF/h1dwj9 LMsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=PONcghEa4EMxrm//qVd0zqVRNAFMiB41KPTWipRlAoY=; b=qD1PbJI9LAm9vwFN5KP8/lVKhsb0sU8pm21lGYrDJWTr62VgOofFwddxpcN4j/BdcY oTrU2aHresktzcZ/HWxrvATezAiopApBzwkHBZ84rSVhy0EvK8+6u/+1m+v3KP0UEK6j z/SY+rKNPYaQAP/pU2cziivKOlYFgi5/0UzaSbi02dME+4+EcvdqhFAbLdV+p8E2Peb8 nDNu8pzdImW2l0uSbV1+ykTTk9iUGMex9Xk/IYtzz/YVsL4wptVa/PbrFxuldbZtDrDY 7BMlzkFqX5OmeYutHBcrOEd3xuCIhZEn51wk1B8G8JjmwwEF4OvPB9tCzqjRGS//rN5d Kyug== X-Gm-Message-State: AGi0PubJVaNxWstKqDOBel7/K7swoHZAw2j/PryoHWmnxso5FBFwPxN8 AS+J5pizAju03MckjaCGlDqPdTd8 X-Google-Smtp-Source: APiQypJqPfWFv2zDTVdEROkBcc764B58IAiZq7fnypFjR0GGL0t/uosCqflM0EJbRPDXrv1ClLgK9A== X-Received: by 2002:a05:600c:291d:: with SMTP id i29mr356629wmd.135.1586281442444; Tue, 07 Apr 2020 10:44:02 -0700 (PDT) Received: from [192.168.0.14] (cpc84253-brig22-2-0-cust114.3-3.cable.virginm.net. [81.108.141.115]) by smtp.googlemail.com with ESMTPSA id i2sm32097008wrx.22.2020.04.07.10.44.01 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 07 Apr 2020 10:44:01 -0700 (PDT) To: internals@lists.php.net References: Message-ID: <49588112-bfd9-35c6-4580-e40a10e42ea6@gmail.com> Date: Tue, 7 Apr 2020 18:43:59 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-GB Subject: Re: [PHP-DEV] Resurrecting named parameters From: rowan.collins@gmail.com (Rowan Tommins) On 07/04/2020 13:44, Nikita Popov wrote: > Make named-parameter opt-in in some fashion, so that parameter names > only need to be preserved for methods that have the opt-in marker. I'm not > a fan of this, as it greatly diminishes the practical usefulness of named > parameters. I generally prefer the idea of named parameters requiring some sort of opt-in at the definition site. I feel like this would solve a whole bunch of problems: - LSP violations could be stricter errors, because they would show up once the parent class opted in, not as soon as you upgraded your PHP version. - Similarly, library authors would have a chance to tidy up their parameter naming, knowing that it was going to be a part of the compatibility contract for future versions. Without an opt-in, they might find themselves unable to fix poor or inconsistent names without declaring a BC break. - Internal functions could also be "opted in" gradually, giving core devs and extension authors time to sort out any that do odd things with ZPP or ZEND_NUM_ARGS. - Variadic functions could be automatically "opted out" without needing a particular special case (they could just give a generic "function doesn't support named params" error). The biggest downside I can see is that there's no obvious way of library code opting in to named parameters when run under PHP 8 (or whenever we add them) but also compiling successfully under earlier versions. That would certainly slow the spread of the feature rather drastically, which would be a shame. I wonder if there's a clever syntax we could adopt that would avoid this. In some ways, it would be nice to go one step further, and separate the names presented to callers from the names used inside the function body. Since parameters become ordinary mutable variables for the rest of the function, it can be tempting to think of them as part of the implementation, not part of the signature. This can lead to them naturally changing both over time, and in inheritance hierarchies. For instance, an interface might define a parameter as "$id", but a concrete class want to label it as "$requestedFoobarId" to make the implementation clearer. It would be nice to be able to (optionally) define both. Straw man example syntax, using ":$foo" as opt-in, and "foo: $bar" as aliasing: function get( int id: $requestedFoobarId, boolean :$deep ) That would essentially be sugar for: <> function get( int $id, boolean $deep ) {     $requestedFoobarId = $id;     unset($id);     // ... } In the same way, normal positional parameters could be (and in some languages are) seen as sugar for this: function get( int $1, boolean $2 ) {     $requestedFoobarId = $1;     $deep = $2;     // ... } It would also give another option for the LSP problem - if the parent class or interface opts into named parameters, the child class gets implicit aliases if it doesn't specify any: interface Foo { function thing( :$id ); } // named parameter "id" class Bar implements Foo { function thing( id: $barId ) {} } // explicit alias matches interface, $bar->thing(id: 42) will set $barId=42 class Baz implements Foo { function thing( $bazId ) {} } // implicitly aliased, $baz->thing(id: 42) will set $bazId=42 based on the name in the interface class Wrong implements Foo { function thing( :$wrongName ) {} } // Error: tries to accept named parameter "wrongName", but interface requires it to accept named parameter "id" instead Regards, -- Rowan Tommins (né Collins) [IMSoP]