On 14 May 2023 11:59:13 BST, Robert Landers <landers.rob...@gmail.com> wrote: >As someone who has had limited interaction with the engine code itself >but has been using PHP, daily, for nearly 15 years, I'm not sure this >technical distinction makes sense in the context of programming in >PHP. When using traits, I don't think of it as 'inserting code', but >rather I think of it as 'using code' -- you do use `use TraitName` >after all and it is very similar to the top-level using statement.
I don't think it's a technical distinction at all, it's part of the definition of traits in PHP, which are often described as "compiler assisted copy and paste". The methods from the trait are added to the definition of the class during compilation, and after that it is almost impossible to distinguish them from methods written directly in the class definition. Conversely, namespace imports are entirely local to the current file (or even a namespace{} block), and it's almost impossible for running code to see anything other than the expanded name. That doesn't mean that there aren't good reasons to have nameof() handle both things in the way proposed, I just think those reasons are probably different for the two cases. >> Can you give an example of such an error message that would want to expose >> the local alias? > >Which error message helps in resolving the error and would be written >by someone writing the code? To clear up any doubt, there was no sarcasm or aggression intended, I was genuinely requesting an example, which you have provided, so thank you. >use function \Path\To\Function\Serializer\to_json as json_serializer; > >// a bunch of code using json_serializer() >throw new Exception('json_serializer returned invalid json'); >// or >throw new Exception('\Path\To\Function\Serializer\to_json returned >invalid json'); I can see your reasoning now, but I can think of arguments both ways round: if you're trying to find out *why* the function returned invalid JSON, you need to know where the source code for that function is, so need its fully qualified name. My gut feel is still that it's more often useful to have the expansion done for you, but maybe others have different perspectives. >This would also be weird in the case of constants/functions in the >global space, because fully qualified names begin with a "\" which >feels unnatural when reading things meant for humans (such as error >messages). This seems to be a common sentiment indeed - people prefer long lists of "use function" to \ prefixes. It's not something I personally find unnatural, any more than "/images/logo.png" or "/etc/hosts", but I'm willing to concede I may be in a minority there. >> Not really, I'm afraid. If I have to write out the fully-qualified name, why >> would I bother with nameof() rather than just using a string? > >If you write it in a string you really will, actually, have to write >out the fully qualified name because an IDE won't know you're >referencing a language construct and be able to autocomplete it for >you. If you rename the function or remove it, you won't be able to use >static analysis to locate these strings, you'll have to manually >search-and-replace the codebase, which opens up space for human error. This makes some sense, although static analysis tools and IDEs already do a lot with pseudo-types in docblocks to understand the expected values of strings. The biggest weakness of a generic "nameof" is that it still doesn't hint what kind of thing you want to mention. >IMHO, this comment isn't constructive or helpful, how can I help you >understand? I'm more than happy to answer any and all questions, but >comments like this are pretty demoralizing when there are only a few >people discussing the feature in a community I'm relatively new to I'm genuinely sorry you felt this way, and it was absolutely not my intention to criticise you. If anything, it was meant to be an admission of my own failings, that I'd come into the discussion with the wrong preconceptions, because the use cases which immediately came into my head seemed to have contrasting requirements from the ones that you intended. To put things into a more productive context, then, I think a useful improvement to the RFC would be some examples of how you would use it with the different supported types, showing why the proposed semantics are useful for those scenarios. On a different note, you've talked about how errors would be handled for nonexistent constructs, but given PHP's dynamic nature, there's also a question of *when* they would need to exist. For instance, assuming we go with Warnings, if I use nameof(Foo::bar), and class Foo is defined in a different file, there's a few things that could happen: - the resolution happens while compiling a single file, in which case it will always give a Warning, because any symbol outside the file is unknown - the resolution happens at runtime, and causes class Foo to be autoloaded - the resolution happens at runtime but doesn't trigger autoloading, so whether it gives a Warning or not depends on whether other code happens to have loaded the definition of Foo - probably other options that I haven't considered With the "no error handling" version, this becomes moot, because it's just a string manipulation exercise. That's how ::class currently works, apart from a few specific cases like static::class and $someInstance::class Regards, -- Rowan Tommins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php