Skip Menu |

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

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

People
Owner: perl [...] toby.ink
Requestors: al [...] iamalnewkirk.com
Cc:
AdminCc:

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



Subject: Add NumberLike to Types::TypeTiny
Date: Sun, 17 Mar 2019 10:55:22 -0400
To: bug-Type-Tiny [...] rt.cpan.org
From: Al Newkirk <al [...] iamalnewkirk.com>
I've had occasions where having a NumberLike type would have been useful. Seems simple enough to implement and I think makes sense for the Types::TypeTiny library. Maybe this could be as simple as: (parent => 'StringLike', constraint => sub { looks_like_number("$_") }). Thanks, Al Newkirk (alnk) awncorp@cpan.org
On Sun Mar 17 10:57:17 2019, al@iamalnewkirk.com wrote: Show quoted text
> I've had occasions where having a NumberLike type would have been useful. > Seems simple enough to implement and I think makes sense for the > Types::TypeTiny library. > > Maybe this could be as simple as: > (parent => 'StringLike', constraint => sub { looks_like_number("$_") }). > > Thanks, > > Al Newkirk (alnk) > awncorp@cpan.org
This is LaxNum from Types::Standard.
Subject: Re: [rt.cpan.org #128867] Add NumberLike to Types::TypeTiny
Date: Wed, 20 Mar 2019 06:21:10 -0400
To: bug-Type-Tiny [...] rt.cpan.org
From: Al Newkirk <al [...] iamalnewkirk.com>
Not exactly. LaxNum is derived from Str which doesn't allow refs, so a blessed object wouldn't pass validation. StingLike, on the other hand, is specifically designed to validate blessed objects with an overloaded string conversion operation. I'm asking to take that one step further by having a type, ideally NumberLike, whose parent is StringLike and look_like_number(). On Wed, Mar 20, 2019 at 4:40 AM Graham Knop via RT < bug-Type-Tiny@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=128867 > > > On Sun Mar 17 10:57:17 2019, al@iamalnewkirk.com wrote:
> > I've had occasions where having a NumberLike type would have been useful. > > Seems simple enough to implement and I think makes sense for the > > Types::TypeTiny library. > > > > Maybe this could be as simple as: > > (parent => 'StringLike', constraint => sub { looks_like_number("$_") }). > > > > Thanks, > > > > Al Newkirk (alnk) > > awncorp@cpan.org
> > This is LaxNum from Types::Standard. >
On 2019-03-17T14:57:17Z, al@iamalnewkirk.com wrote: Show quoted text
> I've had occasions where having a NumberLike type would have been useful. > (parent => 'StringLike', constraint => sub { looks_like_number("$_") }).
What if you've got a blessed object (or dualvar!) which overloads stringification to return something non-numeric, but overloads numification to return a number? It's pretty easy to add a constraint like this in your own code: has room_number => ( is => 'ro', isa => StringLike->where(q{ Scalar::Util::looks_like_number("$_") }), ); That said, I have been thinking of something like "stringifies_to", "numifies_to", etc methods. Like this: has room_number => ( is => 'ro', isa => StringLike->stringifies_to(PositiveInt), ); This is probably more useful than a NumberLike type because it allows you to constrain the number (in this example to a positive integer).
Subject: Re: [rt.cpan.org #128867] Add NumberLike to Types::TypeTiny
Date: Wed, 20 Mar 2019 08:30:11 -0400
To: bug-Type-Tiny [...] rt.cpan.org
From: Al Newkirk <al [...] iamalnewkirk.com>
Thanks for the tip! I already have added something similar to my own code. I only brought it up here as I thought it would be a nice addition to Types::TypeTiny, if even only a slight convenience. i.e. NumberLike = StringLike->numifies_to(Number) Please let me know if I can help in any way, or even kickoff the implementation of stringifies_to and numifies_to. On Wed, Mar 20, 2019 at 8:15 AM Toby Inkster via RT < bug-Type-Tiny@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=128867 > > > On 2019-03-17T14:57:17Z, al@iamalnewkirk.com wrote:
> > I've had occasions where having a NumberLike type would have been useful. > > (parent => 'StringLike', constraint => sub { looks_like_number("$_") }).
> > What if you've got a blessed object (or dualvar!) which overloads > stringification to return something non-numeric, but overloads numification > to return a number? > > It's pretty easy to add a constraint like this in your own code: > > has room_number => ( > is => 'ro', > isa => StringLike->where(q{ Scalar::Util::looks_like_number("$_") > }), > ); > > That said, I have been thinking of something like "stringifies_to", > "numifies_to", etc methods. Like this: > > has room_number => ( > is => 'ro', > isa => StringLike->stringifies_to(PositiveInt), > ); > > This is probably more useful than a NumberLike type because it allows you > to constrain the number (in this example to a positive integer). >
I've already got an initial implementation (attached), but haven't checked it into the repo because I haven't done tests. If you wanted to do some test cases, that would certainly help. It allows things like: StringLike->stringifies_as(Int) Any->numifies_as(PositiveInt) And: Object->attributes_as({ name => Str, age => Int }) (The above will check $_ is a blessed object, check $_->name returns a Str, and check $_->age returns an Int.)
Subject: stringifies-as.patch
diff -r 3a2b99d513c2 lib/Type/Tiny.pm --- a/lib/Type/Tiny.pm Tue Feb 26 16:45:49 2019 +0000 +++ b/lib/Type/Tiny.pm Wed Mar 20 20:01:15 2019 +0000 @@ -1271,6 +1271,68 @@ sub of { shift->parameterize(@_) } sub where { shift->create_child_type(constraint => @_) } +{ + my $i = 0; + my $_where_expressions = sub { + my $self = shift; + my $name = shift; + $name ||= "where expression check"; + my (%env, @codes); + while (@_) { + my $expr = shift; + my $constraint = shift; + if (!ref $constraint) { + push @codes, sprintf('do { local $_ = %s; %s }', $expr, $constraint); + } + else { + my $type = Types::TypeTiny::to_TypeTiny($constraint); + if ($type->can_be_inlined) { + push @codes, sprintf('do { my $tmp = %s; %s }', $expr, $type->inline_check('$tmp')); + } + else { + ++$i; + $env{'$chk'.$i} = do { my $chk = $type->compiled_check; \$chk }; + push @codes, sprintf('$chk%d->(%s)', $i, $expr); + } + } + } + + if (keys %env) { + # cannot inline + my $sub = Eval::TypeTiny::eval_closure( + source => sprintf('sub ($) { local $_ = shift; %s }', join(q( and ), @codes)), + description => sprintf('%s for %s', $name, $self->name), + environment => \%env, + ); + return $self->where($sub); + } + else { + return $self->where(join(q( and ), @codes)); + } + }; + + sub stringifies_as { + my $self = shift; + my ($constraint) = @_; + $self->$_where_expressions("stringification check", q{"$_"}, $constraint); + } + + sub numifies_as { + my $self = shift; + my ($constraint) = @_; + $self->$_where_expressions("numification check", q{0+$_}, $constraint); + } + + sub attributes_as { + my $self = shift; + my ($constraint) = @_; + $self->$_where_expressions( + "attributes check", + map { my $attr = $_; qq{\$_->$attr} => $constraint->{$attr} } sort keys %$constraint + ); + } +} + # fill out Moose-compatible API sub inline_environment { +{} } sub _inline_check { shift->inline_check(@_) }
Subject: Re: [rt.cpan.org #128867] Add NumberLike to Types::TypeTiny
Date: Fri, 22 Mar 2019 19:05:06 -0400
To: bug-Type-Tiny [...] rt.cpan.org
From: Al Newkirk <al [...] iamalnewkirk.com>
I sat down to work with the patch given and found a few interesting things: #1: I modified the behavior of attributes_as to inline as "$_->can($attr) ? $_->$attr : $_->{$attr}" because otherwise the validation blows up if given an object without that subroutine attribute and doesn't produce an error message. I added the "$_->{$attr}" bit because I don't think "attributes" should necessarily have to be subroutines. Let me know if that's okay! #2 I don't know whether to call this a feature or a bug because, at-present, "Str->numifies_as(Number)" passes validation, given that the validation, which is something like do { my $tmp = 0+"me"; (defined($tmp) && !ref($tmp) && Scalar::Util::looks_like_number($tmp)) }, returns truthy given that 0+"me" returns 0 which looks_like_number. Note: I discovered that a string is defined as a value that when referenced produces a SCALAR -- this is brilliant! On Wed, Mar 20, 2019 at 4:08 PM Toby Inkster via RT < bug-Type-Tiny@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=128867 > > > I've already got an initial implementation (attached), but haven't checked > it into the repo because I haven't done tests. If you wanted to do some > test cases, that would certainly help. > > It allows things like: > > StringLike->stringifies_as(Int) > Any->numifies_as(PositiveInt) > > And: > > Object->attributes_as({ name => Str, age => Int }) > > (The above will check $_ is a blessed object, check $_->name returns a > Str, and check $_->age returns an Int.) >
Types::TypeTiny is really for type constraints that are needed internally by Type::Tiny, so not adding stuff by request. Type::Tiny has no need for a NumberLike type. I will be adding `stringifies_to`, `numifies_to`, and `with_attribute_values` methods in Type::Tiny 1.008000 though. There's an implementation in the repo now.