Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:110499 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 83162 invoked from network); 12 Jun 2020 15:26:38 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 12 Jun 2020 15:26:38 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 5EB611804D3 for ; Fri, 12 Jun 2020 07:11:02 -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_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-lf1-f48.google.com (mail-lf1-f48.google.com [209.85.167.48]) (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, 12 Jun 2020 07:11:01 -0700 (PDT) Received: by mail-lf1-f48.google.com with SMTP id a26so1103436lfj.13 for ; Fri, 12 Jun 2020 07:11:01 -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=C69yc8ZeJNKDvEyEm+BKoLVwmYTBflnM3HpkY1FoZlU=; b=u1BtQrHrDEfhJmCDGH9RlAmaXutIItQvyOdNkTrbreXJ4r7tkvgS3MKl9eb9UDOIcS CUXjbtv87YmzHiUSqZ8vYpTPEzz8rwSIJ/FG09nGwRlzVgfkzwWFJEjO6b59UU9zBZ9D lDb2k7901dYHsOO38joz3cf8zPYSz4Dfw5Y0E0EwwkmCs9pb1jHq4W0BhZnSO03p/o19 q18PrezRdM3U5dAlRmnuIXfmMos6YjLHs1XcOMTVvtq2UQH6cV0m/TPbU9+g+8Cc47yc ojm1+/c9e0sn1HCpJ6CxqLWu0xQbhh/ncSr4QznuysVCbCRdqWgjFXJSAPslBMnBmKwX Zrqg== 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=C69yc8ZeJNKDvEyEm+BKoLVwmYTBflnM3HpkY1FoZlU=; b=nVOzs9d1u4NaY64CKviSWcW7hSDtlh2Za8lVew7m2YQxcS/9mRCsm8EnGlSAn+Em5W UxjRv2tlKCxD3jO7PMER+3M/02nANhHGoiwT+shzvt4bXSih5O0AfNKMEI6YsYiA7WuL 8tmPckeszurWRxpjnOOsUBNLOSFQ9ibEZr5lSRg3Z2rmR+xXhthvykl0vi2aKtmDY9zd Jk5jYfAR1+9gLGtYSZgaax5q8XETBU/mBaXdEPBuwgYUczSPNU7OHPPsSJBOpRsN7Ifs tyxjVxK0QEcCkJ5qkX8FduXAY2bR9ouYJIdeVOlS/qLmLFEF1zxb4DgksjQZ494reCmc OGyQ== X-Gm-Message-State: AOAM531KoIV+dZkv4wEL3sst6IvHJRMwXfjvZRGS+8Iu+A97xDGjCWht J36w0ZOOsePsZpPa2CKKBfF0zAgxjFcRqjJ+iHE= X-Google-Smtp-Source: ABdhPJxv9kLo3oZS8OHyyl734SeGA89U2XFZEX9MgM1kkcQJCnNwjogdvKHHu122shj1BzSb4JkZ1XqzQHKqPyLGBag= X-Received: by 2002:a19:c016:: with SMTP id q22mr7037868lff.191.1591971058133; Fri, 12 Jun 2020 07:10:58 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 12 Jun 2020 16:10:41 +0200 Message-ID: To: Troy McCabe Cc: PHP internals Content-Type: multipart/alternative; boundary="00000000000069b6f305a7e3a545" Subject: Re: [PHP-DEV] Revisiting proposal for addition of `get_class_constants()` From: nikita.ppv@gmail.com (Nikita Popov) --00000000000069b6f305a7e3a545 Content-Type: text/plain; charset="UTF-8" On Fri, Jun 12, 2020 at 6:32 AM Troy McCabe wrote: > Hey Nikita, > > Thanks for the thoughts. > > > Could you please explain in more detail *why* we should duplicate > existing reflection functionality into free-standing functions? > > In terms of the *why*, there were three main reasons: > 1. It aligns with the addition of the functions referenced in the > original post (`str_[contains|starts_with|ends_with]()`), and one > their stated reasons of simplifying the API for userland developers. > While `(new \ReflectionClass(MyClass::class))->getConstants()` isn't > the most difficult thing to grasp, it's not immediately clear to new > developers, and is more verbose than > `get_class_constants(MyClass::class)` > I don't think this comparison makes a lot of sense. str_contains() etc were very much about providing a more convenient way to perform an extremely common operation. It makes sense to make common operations more concise. get_class_constants() is on the complete other side of the spectrum: It would be a very niche API. It's okay to have niche APIs (Reflection as a whole is pretty niche), but there's no point in optimizing them for concise calls. 2. `get_class_[methods|vars]()` existing as built-in functions, > creates a gap to retrieving class constants in the same way. If I > start down the path of class inspection using `get_class_*()`, but > find I can't retrieve constants in the same way, this is an > inconsistency. > That's correct, but I think it's acceptable as long as we consider those to be historical artifacts. > 3. When using Reflection, accessibility is not respected as it is with > the `get_class` family of functions. In the event that a developer is > looking for constants which are accessible to the current context, > there's no way (that I'm seeing, anyway) to retrieve _only_ constants > accessible in the current context. > This is a good point. I think the right way to address this would be to expand the reflection API though. It's a bit odd that visibility-based filtering exists here, but is not available in the reflection extension (it can filter by public/protected/private, but not by "visible in this scope"). Having methods like ReflectionMethod::isAccessible(?string $scope = null): bool would be a good addition, I think. > > I believe the existence of functions like get_class_methods() is a > historical artifact, because they were introduced before Reflection was a > thing. Unless there is a strong reason to the contrary, I would prefer > reflection functionality to stay inside Reflection... > > This is good background that I wasn't aware of (I knew the Reflection > API was newer than the built-in functions, but not that the > `get_class_*` functions were generally frowned upon). > > It does bring up 2 questions: > 1. Obviously this is a much larger discussion, but is there any > appetite to deprecate & remove the existing functions in favor of the > Reflection API? > I don't think there's a particularly strong reason to remove those functions. They're there and they don't hurt anyone :) I think there's a middle ground between "these must be removed" and "these must be extended further". > 2. An alternative to adding `get_class_constants()` would be to > introduce `ReflectionConstant` as a return type from > `ReflectionClass::getConstants` to match `ReflectionMethod` & > `ReflectionProperty`, which would solve point 3 above. Would this be a > preferable approach? > As you mention in your next mail, this already exists :) > > You do mention performance as a benefit, but it's not immediately > obvious to me which use-cases are bottlenecked by class constant reflection. > > Enum implementations are the big case for this. While the libs I've > looked at use an internal cache, these caches are per-request, so > reflection will need to be used as many times as there are enums in a > given system. Depending on the scale, this could be an appreciable > amount. Obviously external caches could be leveraged, but that then > requires additional development lift, instead of using battle-tested > enum libs. > I think the per-request cache here is the right approach. Reflection isn't so slow that hitting it once per request would be problematic. At the same time, no matter how this is implemented, you will still want to have that cache, because fetching the class constants is still going to be slower than not fetching them, regardless of how you do it. Having this as a free function may be two times faster than doing it via reflection, but not doing it at all is #INF times faster :) Regards, Nikita --00000000000069b6f305a7e3a545--