Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:124632 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 9CD7B1A00B7 for ; Sat, 27 Jul 2024 00:04:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1722038764; bh=qcU+wLfRkslqsnMrCeZ7CkWQIHryAkLd7V3p9DFGb4g=; h=Subject:From:In-Reply-To:Date:Cc:References:To:From; b=g7Pb2719Q1peVAjsaNM7G2F4GhYm9J7s3J7V8CrvR+t8kvn6AAsdwCa1ENxFKitt/ CdtiNg9I5aRbh2W4hdsXWNtGT8cLnZL/3kSw6BmVilHI4eG6HQeBM0+DCZ0ep7cvnT ciuDasPk7wv0cusrvGlR/tUbfv6LKt/wxKRdu0A1iomV9m4eCfy9aKMdK37l4IeIOf 6SPH5dxADYI4c0xpfnqUa9xlL1i1mZus/HCkuggB5JG+EA2DIQJ7VwC0U6LsrdbOVH GRaukUBnpH++esdPnwsCKuS9DxHYzrkaNo6KCUXABd9sBPZOGtzINxr8Omh18QsmMx 17JdThb7s95Ow== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 22148180048 for ; Sat, 27 Jul 2024 00:06:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yw1-f181.google.com (mail-yw1-f181.google.com [209.85.128.181]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sat, 27 Jul 2024 00:06:03 +0000 (UTC) Received: by mail-yw1-f181.google.com with SMTP id 00721157ae682-65f9708c50dso2102577b3.2 for ; Fri, 26 Jul 2024 17:04:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20230601.gappssmtp.com; s=20230601; t=1722038667; x=1722643467; darn=lists.php.net; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=xFikSn9ScBNqHxciSd3bNT7O8W9o1xuJ5UFLECBPqew=; b=WINmk4m8/35qmawCJNjRmpYYbISl2oQtCfkZjLrBfBXwOuKxMg6vJHNm7AkFJ6VXq0 ft2DfM/7BlpAgw4WuLjZvKabiTwmQgdnWh6g5feDchDpJwwL3oygnc2UqrV8H2VlAfmZ ju/fMFLG6Z2yNONuPHW3BMDEyq6mcvBMDJ+Pq0y9G4xarM9rjYrzURr3ibN8zxji5Tsm A7b2QtG9JnhSqWwlbbGgbG0HZFP5uGdTG7wQvcM39b+7uBuqfdDYO79BqCG9VYVkF+Z/ 4WnvxsM9vP9XwbUEEHi372fXOD8S1IFgE/KEtjkjeUnfdCRWx83lvPQ8kpipo+wkTzm0 l/fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722038667; x=1722643467; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xFikSn9ScBNqHxciSd3bNT7O8W9o1xuJ5UFLECBPqew=; b=ExAUCK5hM+vn5qt+iv41b8VPe8U1mMCGFG/NnMKcX+Yl4r8mZ6wK/OrjP9LYQGOzEn PwBqfoPoomQE4Y+qNQb77pokkeAGuKGawM7kto7l2UrTupGn/Rc8ev+4umDnEXDHuBFB hTIFM4HcnL02Q4bczBR9Z7/A6FSusQDNBOX1tQazUlCFXFGZ7bnCaSndq0QbxDqwZ4aC dq7Vc4phuZjpKkifXJXw7eWS/BKzMY6tz+upjlI0i/THCR2wl9gGNRQkJQNzS30/wdao knBMhMqNl11+lOGaBNUGdbZWvr1UAo3Ol22aXhVRa7dpvmYW4bStbPmERiZBjNb2hh2p Gt7g== X-Forwarded-Encrypted: i=1; AJvYcCUzPZOvZAO0xT3mpL3oxvNYM4h6ASAutCffm1PBlDrBVgRuhNdt74r/vpiQtLEQy4yKUY1rerJxgJI2ExBzyZyd+Ro9WsaWAw== X-Gm-Message-State: AOJu0YxQ8lqDVavypBisZz0y5mhwfZm606htIVEG7phEbTxZcvFStVwD bbtClXJFlQIcz5W4LaGDd+TJu4CwFb6EpsBZTTTCRHGgE9lKttcdkYDw8+d9Ew8= X-Google-Smtp-Source: AGHT+IGZ7cOTjGbC7EjDtHGzdMm4ZaHItpSGLkFcsPNprurhfiqhcLKAwDPMNmvjJ+YI390v/2d4wg== X-Received: by 2002:a0d:f587:0:b0:653:ffe7:d62f with SMTP id 00721157ae682-67a06cf03femr14520807b3.20.1722038667185; Fri, 26 Jul 2024 17:04:27 -0700 (PDT) Received: from smtpclient.apple (c-98-252-216-111.hsd1.ga.comcast.net. [98.252.216.111]) by smtp.gmail.com with ESMTPSA id 00721157ae682-67566dd904esm10828987b3.3.2024.07.26.17.04.26 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 26 Jul 2024 17:04:26 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.8\)) Subject: Re: [PHP-DEV] Explicit callee defaults In-Reply-To: <8ac3f087-a739-4759-891c-3dd19260ef5e@gmx.de> Date: Fri, 26 Jul 2024 20:04:25 -0400 Cc: Bilge , internals@lists.php.net Content-Transfer-Encoding: quoted-printable Message-ID: <34BF3A40-592C-41D7-8C35-5A9F3934E919@newclarity.net> References: <8ac3f087-a739-4759-891c-3dd19260ef5e@gmx.de> To: "Christoph M. Becker" X-Mailer: Apple Mail (2.3696.120.41.1.8) From: mike@newclarity.net (Mike Schinkel) > On Jul 26, 2024, at 6:42 PM, Christoph M. Becker = wrote: >=20 > I have only skimmed your suggestion, but it sounds quite similar to > . I would really love to hear from some of those who voted "no" ~9 years = why they did so, and if they still feel the same. > On Jul 26, 2024, at 5:54 PM, Bilge wrote: > When writing a function, we can specify defaults for its parameters, = and when calling a function we can leverage those defaults implicitly by = not specifying those arguments or by "jumping over" some of them using = named parameters. However, we cannot explicitly use the defaults. But = why would we want to? >=20 > Sometimes we want to effectively inherit the defaults of a function = we're essentially just proxying. One way to do that is copy and paste = the entire method signature, but if the defaults of the proxied method = change, we're now overriding them with our own, which is not what we = wanted to do. It is possible, in a roundabout way, to avoid specifying = the optional parameters by filtering them out (as shown in the next = example). The final possibility is to use reflection and literally query = the default value for each optional parameter, which is the most awkward = and verbose way to inherit defaults. >=20 > Let's use a concrete example for clarity. >=20 > function query(string $sql, int $limit =3D PHP_INT_MAX, int $offset =3D = 0); >=20 > function myQuery(string $sql, ?int $limit =3D null, ?int $offset =3D = null) { > query(...array_filter(func_get_args(), fn ($arg) =3D> $arg !=3D=3D = null)); > } >=20 Yes, I run into that issue all the time. So much so that I adopted an = "optional args" pattern which itself has many downsides but in my code = it has had fewer downsides than doing it other ways. So for your example I would write it like this (though I hate having to = double-quote the names of the optional args): function query(string $sql, array $args =3D []); function myQuery(string $sql, array $args =3D []) { query($sql, $args); } myQuery("SELECT * FROM table;", ["offset" =3D> 100])); This is very flexible and a pattern that served me well for 10+ years.=20= But of course this has none of the type safety nor code-completion = benefits of named parameters, which I would sorely like to have. > In this way we are able to filter out the null arguments to inherit = the callee defaults, but this code is quite ugly. Moreover, it makes the = (sometimes invalid) assumption that we're able to use `null` for all the = optional arguments. >=20 > In my new proposal for explicit callee defaults, it would be possible = to use the `default` keyword to expressly use the default value of the = callee in that argument position. For example, the above implementation = for myQuery() could be simplified to the following. >=20 > function myQuery(string $sql, ?int $limit =3D null, ?int $offset =3D = null) { > query($sql, $limit ?? default, $offset ?? default); > } >=20 > Furthermore, it would also be possible to "jump over" optional = parameters without using named parameters. >=20 To me, while nice I feel it is very much like only a quarter step in the = right direction. I do not meaning to highjack your thread; feel free to ignore this if = you feel committed to pursing only your stated approach and are not = interested in what I would like to see. But I mention in hopes you and = others see value in a more complete approach: To begin, we can already currently do this (although I do not see many = people doing it in PHP; fyi this approach is the norm for many Go = programmers): class QueryArgs { public function __construct( public ?int $limit =3D 100, public ?int $offset =3D 0, ){} } function myQuery(string $sql, QueryArgs $args =3D new QueryArgs()) { query($sql, $args); } myQuery("SELECT * FROM table;", new QueryArgs(offset:100)); I can only give my reasons for not doing it myself in PHP and speculate = that others may have similar reasons and/or have never even considered = it: 1. Not having an easy and consistent way to declare the "args" class in = the same file where the functions that use it are declared which keeps = it out-of-sight and makes it harder to keep updated than it needs to be. 2. Having lots of visually annoying boilerplate that obscures a clear = use-case. What would be great IMO would be if PHP could elevate this concept to = first class and add syntax and features to streamline and empower its = use. Imagine if we could instead: 1. Define an "args" type which would be based on a class like enum is = based on a class: args QueryArgs { public ?int $limit =3D 100; public ?int $offset =3D 0; } 2. Declare a function to use those args, using your `default` keyword = when they are optional: function myQuery(string $sql, QueryArgs $args =3D default) { query($sql, $args); } 3. And finally, allow a streamlined syntax to pass args: myQuery("SELECT * FROM table;", {offset:100}); (I do not think we can or even should try to tackle the PSR-4 "every = symbol in its own file" problem here, so I am going to leave that for = other potential RFCs.) -Mike