Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128820 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 lists.php.net (Postfix) with ESMTPS id 818DA1A00BC for ; Sun, 12 Oct 2025 18:35:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1760294131; bh=w1WIOhYXyuJx7LV6Y+m4KDlGS3upNk7MSx1IcBSAEpk=; h=Date:Subject:To:References:From:In-Reply-To:From; b=QMQyum8oziJHgx4Lu0hB+DURMeCczHfaOqfArXlpi44EAPJbl5GLmle1mwgywhqBe GP9Yn2AzleZ/nspC1o1GUJYXV27ghhyQAEW3XIK4tO+zcncTHcZ+hQycfvQN+R84TQ PSYyXdqNZ9TIacDclWlnbad1KKNsDZl9YRUlX8fELkVBoj936qc1x632Kzjr7HMr9V mEzu6TdyprbLZLgjfrv3X4jQhcDfIONdVHSBhbSacHGYYTi51JNEiGTbkUX4U4tAx3 whw+Xh7MqtmHE2gUe6/l+oWmQJee8Tz9jU9c7pXrn9dSniHYdf1IhTpodtlN0Iy2u1 0dFk+mOsZw/+A== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 052A8180056 for ; Sun, 12 Oct 2025 18:35:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) 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,DMARC_PASS,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from chrono.xqk7.com (chrono.xqk7.com [176.9.45.72]) (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 ; Sun, 12 Oct 2025 18:35:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bastelstu.be; s=mail20171119; t=1760294113; bh=XKOtQsutP4E8DFzIJ2FS++pucT8fg7lt5lBJ8KTrKH8=; h=Message-ID:Date:MIME-Version:Subject:To:References:From: In-Reply-To:Content-Type:from:to:cc:subject:message-id; b=gNXIrQae8S/ySst0X2DZmOu63fEnV4wog0UWBDW/QQ5quS6PiYWw6Je6ZQXmVKNdb 7jOorvv+674eVHu9aVAA3STw+PpH1/4L7LkbNkOJJORkgoJ7737oCfZryx2e1WX3q8 AxpOEv7CGlma+IioqQXgEcms/tFU04H+uXBE10lMPjyqrIjiMF9EzBFQUQ21YebGQM zpVHoAWxhk2ErdmZMGwWvfD/+mo9Dj9apQ0hG+prGlfGDA4H6IQV2+Vxy5GZlGJ31K +b1wRKLPF2uLjzX+fGQqNNnPp04E1qAIfGj4uxDtsXY6AkjyyPSriemUF35sXD2F/v 8D9vHgVPe+/+w== Message-ID: Date: Sun, 12 Oct 2025 20:35:11 +0200 Precedence: list list-help: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 Subject: Re: [PHP-DEV] [RFC] Partial Function Application v2 To: Larry Garfield , php internals References: <13830641-0fb9-4de9-94ed-8873045ef820@app.fastmail.com> Content-Language: en-US In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: tim@bastelstu.be (=?UTF-8?Q?Tim_D=C3=BCsterhus?=) Hi On 10/10/25 17:26, Larry Garfield wrote: >> What will happen if the original function already has a parameter named >> $args0? > > It will skip over existing names. I've updated the text accordingly. Okay. Looking at all the examples, I think it would be nice if it would not use the generic `arg` prefix, but use the original name as the prefix. For the function foo(int $a = 5, int $b = 1, string ...$c) { } example, the 3rd and following parameters could be `$c_1`, `$c_2`, … (still skipping over duplicates). >>> Prefill all parameters, making a "delayed call" or "thunk" >> >> The example desugaring is inconsistent with the previously explained >> semantics: Here an arbitrary number of arguments is accepted, but >> previously it says "will result in a Closure with no parameters". > > Hm, I think that should probably read "no required parameters". It would only make a difference if the underlying function had an optional variadic AND you called the thunk with extra, extraneous args. Okay. Now looking at the examples: $c = stuff(?, ?, f3: 3.5, p4: $point, ...); $c = fn(int $i1, string $s2, int $m5 = 0): string => stuff($i1, $s2, 3.5, $point, $m5); and $c = stuff(1, 'hi', 3.4, $point, 5, ...); $c = fn(...$args): string => stuff(1, 'hi', 3.4, $point, 5, ...$args); seem to be inconsistent with each other with regard to whether or not "superfluous" arguments are passed through. This might (or might not?) be explained in the “func_get_args() and friends” section, but is unexplained at the point the example appears. Also within the func_get_args() section, there is no explicit `...$args` in the resulting signature, but instead the desugaring uses array_slice() + func_get_args(). >> - Are PFAs legal in constant expressions? e.g. does the following work: >> `const Foo = intval(?, 10);`? > > At the moment no, though Arnaud says that should be doable, with some reasonable restrictions. (No variables, no variable callable name, etc.) Yes, restrictions go without saying. The support for FCC in const-expr also doesn't support variable names and Closures in const-expr may also not capture the scope. > I've asked Arnaud to generate one for the RFC. Thank you, I'm seeing you added an example. I've a small request to hopefully make the example more useful: It currently uses only “placeholder” parameters. It would be useful to also add one pre-filled parameter to it. I would assume that this pre-filled parameter does not appear within the Closure frame, but appears with the frame for the actual function? Relatedly to the stack trace example and also to the “Evaluation order” I'd be curious how pre-filled parameters are implemented technically. For pre-filled variables, the regular variable capturing logic would work, but it doesn't for function returns. Is it effectively creating a temporary variable under the hood? Meaning is: $partial = speak(?, getArg()); desugared into: $pfa_tmp_2 = getArg(); $partial = fn (string $who) => speak($who, $pfa_tmp2); ? - How does it interact with `compact()`, specifically: $partial = compact(someValue(), ?); Would the `?` be able to capture a variable containing the return value of `someValue()`? - How does it interact with `ReflectionFunctionAbstract::getClosureUsedVariables()`? - Same question for other scope introspection functionality (e.g. Xdebug). Best regards Tim Düsterhus