Front page | perl.perl5.porters |
Postings from February 2018
[perl #132902] Blead Breaks CPAN: Class::Std
From: Father Chrysostomos via RT
February 25, 2018 06:24
[perl #132902] Blead Breaks CPAN: Class::Std
Message ID: firstname.lastname@example.org
On Sat, 24 Feb 2018 18:42:22 -0800, demerphq wrote:
> On 25 February 2018 at 02:40, Father Chrysostomos via RT
> <email@example.com> wrote:
> > On Sat, 24 Feb 2018 15:51:03 -0800, demerphq wrote:
> > The text that follows was meant to be the explanation. can and
> > AUTOLOAD go together. Since overloading does not use AUTOLOAD, using
> > can to detect overloading can be problematic.
> Yeah I read that text, but I am still not seeing the connection the
> way you do.
> So, it makes sense to override can if you use AUTOLOAD.
> And overload's dont trigger AUTOLOAD. That is clear.
> But, it doesnt seem to obvious to me that that means that we shouldnt
> use can() for finding inheritable methods. Overload is *designed* so
> this works. That is why the methods are registered the way they are.
> (At least that is what the comments in overload indicate to me.)
> It seems like you are saying something like: "Because the main reason
> to override can() is to work properly with AUTOLOAD, people often
> implement their can overrides without accounting for overload subs,
> and thus most of them are buggy, thus we shouldn't use can()".
> Which doesn't seem logical to me, even if perhaps it is practical.
> Why not simply say "We should document that can() overrides need to be
> robust to overload calls"? I mean, i would consider any can() that
> doesn't handle overload subs buggy, why don't you? It seems a strange
> basis to argue we shouldn't use the one thing we have available to use
> (Zefram mentions there is internal code that exactly what we want but
> it is not exposed).
> To me that there are buggy can() implementations out there is a
> problem for those buggy can() implementations, and maybe an indication
> we need better docs on this, not an argument to avoid can() for this
> type of purpose.
The way I see it, the fact that overloading uses weird-named subs is just an artefact of the implementation. Overloading can be inherited, but it does not consist of method calls (though they may trigger methods), as shown by the fact that AUTOLOAD is not respected, and by the fact that the fallback value (a scalar) is also inherited. In fact, overloading originally did not share internal code with method calls at all; that was just the most convenient way to get inheritance to work.
I don’t think we should blur this distinction and call ‘can’, because it puts the burden on too many programmers to ensure that their ‘can’ methods behave a way that ‘can’ was not designed for to begin with.
I do *not* consider what you call ‘buggy can() implementations’ to be buggy.
> > Not just recursion. Look at the test I added in e6bb0a40852.
> Thanks, i will look.
Based on your explanation above, it has a ‘buggy can() implementation’.
> > Well, since Carp is used *everywhere*, I believe it should remain as
> > lightweight as possible.
> Overload is widely used as well. I also am not that sympathetic to the
> lightweight argument, i don't see a single module used for this kind
> of purpose as a problem, especially when you consider how much code we
> have in Carp to deal with these types of issues.
I’m not entirely opposed to loading overload.pm unconditionally. I just want it to be justified, and not just convenient because it saves two lines of code. In this instance, it is justifiable.
> I totally agree. No argument there at all. See
> 02c84d7f0f97e083f5d8ea9856488f3ede09364f for an example of me patching
> for this objective. ;-)
> > That said, I’m still on the fence about it. I know Zefram cares
> > about this sort of thing, too, so I would ask him which is the best
> > approach:
> > • Go ahead and load overload.pm unconditionally. It’s already much
> > smaller than Carp.
> > • Copy & paste mycan into Carp. It’s just seven lines or so (but we
> > need two versions depending on the perl version).
> Isnt mycan slow compared to the internals version? Maybe in modern
> perls we should expose the internals function Zefram mentioned:
> (05:57:51) Zefram: annoyingly, the exact thing you want is available
> as a Perl op, method_named, but you can't get at that op in isolation
> through Perl source code
It already exists. It is called UNIVERSAL::can (which we can use, since we control it; even though it was designed for methods, it happens to work for this case). Unfortunately, there are (buggy) CPAN modules that diddle with it. Fortunately, Carp already has (partial) code to detect whether that has happened.
(Note: There is a comment in overload.pm about ‘real’ can() leaving stubs. I think we need to get to the bottom of that before trying UNIVERSAL::can. Leaving a "()" stub behind may break things, since that’s where the fallback value is stored.)
via perlbug: queue: perl5 status: open