Skip Menu |

This queue is for tickets about the Type-Tiny CPAN distribution.

Report information
The Basics
Id: 94286
Status: rejected
Priority: 0/
Queue: Type-Tiny

People
Owner: Nobody in particular
Requestors: SJM [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Type::Tiny and when()
Considering the somewhat murky future of when() I don't know if this is even reasonable to suggest, but a particular use-case for me with Type::Tiny types is to create a type library related to Exception objects for use in a Try::Tiny catch block along with when(). For example, consider that I have an exception class named Exception::FileOpen and a Type::Tiny class_type restraint pointing to it named FileOpenError. I want to be able to do this: try { ... } catch { when(FileOpenError) { ...handle file open exception... } default { ...all other exceptions... } }; This seems like, to me, a particularly elegant way to handle this sort of exception catching. The problem is, given the way that when() works (as of 5.18.2), since FileOpenError is a subroutine, when() evaluates the return value in boolean context (which Type::Tiny overloads to always be true), when what I want is for it to apply a smartmatch and thus perform a ->check() operation against $_. The last time I heard, I believe the standing proposal by rjbs was to make when() always perform a smartmatch, which would solve this issue, but I don't really know the status of those changes. In the meantime the easiest way to achieve this behavior would be to have boolean context overload to calling a check on $_ but I don't know how desirable that is. Either way, I figured it wouldn't hurt to explain my use case. A non-ideal workaround would simply to do something like this: when (my $e = FileOpenError) { } So that when() operates on a scalar and thus uses smartmatch, but I'm somewhat concerned about false positives when (not if) people on my team forget to do this.
I think this is something that worked once, but got broken along the way. The trick is to get Perl to think the type name FileOpenError is a constant rather than a coderef. This can never work for parameterizable types like ArrayRef, but should work for others like Int, Num, Str, etc.
On 2014-03-31T13:44:20+01:00, TOBYINK wrote: Show quoted text
> I think this is something that worked once, but > got broken along the way.
I believe it got broken when I added the `-declare` bit to Type::Library. `-declare` means that type constraint subs get redefined half-way through setting up the type library. So when you declare `Str`, it creates a sub like: sub Str () { "Str" } But once the type constraint actually gets defined, that sub gets redefined as something like: sub Str () { $constraint_object } Perl gets very angry when you redefine a constant, so I had to make sure that Perl never considered the subs to be constants. So I don't think I can fix this. It probably needs to be fixed in Perl. For what it's worth, https://metacpan.org/pod/Switcheroo#HINTS
Also, this ought to work: when ( \&is_FileOpenError ) { ... }
Thanks for digging into it a bit more. I guess it never occurred to me that perl would see constants different than subroutine calls. Knowing that allows for a pretty simple workaround where I define the types in one module and just have a module that imports those types and creates constants for export based on them. It's a bit circuitous but it works and gets the syntax look/feel I wanted. Also thanks for the heads up on Switcheroo. Useful.
I'm cleaning up the queue for Type::Tiny. I don't think this is a problem that can realistically be solved within Type::Tiny. The do-what-I-didn't-mean problem of `when` needs to be solved in Perl 5 itself.