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

Reply via email to