Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Coerce or transform with Types::Param

by tobyink (Canon)
on Mar 21, 2021 at 11:00 UTC ( #11130030=note: print w/replies, xml ) Need Help??


in reply to Coerce or transform with Types::Param

Something like this?

use Types::Standard qw( Str Maybe ); use Types::Common::String qw( StrLength ); my $Caption = StrLength[ 1, 2780 ]; my $EmptyStr = Str->where( q{ $_ eq '' } ); my $MaybeCaption = Maybe->of( $Caption )->plus_coercions( $EmptyStr => + q{ undef } ); use Test::More; ok( $MaybeCaption->check( 'My pic' ), 'Good caption passes type constr +aint' ); ok( $MaybeCaption->check( undef ), 'Undef passes type constraint' ); ok( ! $MaybeCaption->check( [] ), 'Arrayref fails type constraint' ); is( $MaybeCaption->coerce( '' ), undef, 'Empty string coerced to undef +' );

Basically, add the coercion to the Maybe[Caption], not to Caption.

But the important thing is to make sure that the empty string isn't considered a valid Caption. Because if a value is valid, it is never coerced.

Replies are listed 'Best First'.
Re^2: Coerce or transform with Types::Param
by 1nickt (Abbot) on Mar 21, 2021 at 12:41 UTC

    I was hoping you'd reply Toby, thank you.

    I made a couple of changes to the code so it compiles, and added a test to see that one can pass in the empty string and it will pass validation by being coerced to undef. But the syntax to do this must be wrong:

    ok( $Caption->check( $Caption->coerce('') ), 'Empty string passes' );
    ... I feel sure that there's a way to avoid calling coerce manually.

    Here's the revised test script:

    use Types::Standard qw( Maybe Str ); use Types::Common::String qw( StrLength ); my $NonEmptyCaption = StrLength[ 1, 10 ]; my $EmptyStr = Str->where( q{ $_ eq '' } ); my $Caption = (Maybe[$NonEmptyCaption])->plus_coercions( $EmptyStr => 'undef', ); use Test::More; ok( $Caption->check('My pic'), 'Good caption passes' ); ok( ! $Caption->check('This is too long'), 'Bad caption fails' ); ok( $Caption->check(undef), 'Undef passes' ); ok( ! $Caption->check([]), 'Arrayref fails' ); is( $Caption->coerce(''), undef, 'Empty string coerced to +undef' ); ok( $Caption->check( $Caption->coerce('') ), 'Empty string passes' ); done_testing;
    Outputs:
    perl 11130005-3.pl ok 1 - Good caption passes ok 2 - Bad caption fails ok 3 - Undef passes ok 4 - Arrayref fails ok 5 - Empty string coerced to undef ok 6 - Empty string passes 1..6

    Wonder if there is a more idiomatic way to do the check when a coercion is used. Thanks!


    The way forward always starts with a minimal test.
      ... I feel sure that there's a way to avoid calling coerce manually.

      That was why I used Types::Params because the POD says: ...it will check the arguments passed to it conform to the spec (coercing them if appropriate)

      Otherwise I've had to reply on has_coercions before attempting to call coerce

      If there is another way though, I would love to know about it.

      Dermot
Re^2: Coerce or transform with Types::Param
by tomred (Novice) on Mar 21, 2021 at 15:25 UTC
    I too hoped you'd reply.

    Your code is far less verbose than mine too.

    There are a couple of concepts that are new to me there, I've not come across of before and I haven't see a Type modified with where in that way either. I only considered where in the constructor so that is really useful.

    ...
    my $MaybeCaption = Maybe ->of( $LongCaption ) ->plus_coercions( $EmptyStr => q{ undef } );
    Really appreciate the help.
    Dermot

      of is a shorthand for parameterizing a type. If you do something like this, it will fail:

      if ( ArrayRef[Int]->check( \@numbers ) ) { ...; }

      And you need to add some parentheses which look pretty ugly:

      if ( ( ArrayRef[Int] )->check( \@numbers ) ) { ...; }

      The of method look a little nicer:

      if ( ArrayRef->of( Int )->check( \@numbers ) ) { ...; }

      And where is a shorthand for creating a child type with an additional restriction.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11130030]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2021-10-17 20:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (72 votes). Check out past polls.

    Notices?