Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Moose::Util::TypeConstraints - Querying subtype() Caveat

by kcott (Abbot)
on Jul 20, 2012 at 09:59 UTC ( #982783=perlquestion: print w/ replies, xml ) Need Help??
kcott has asked for the wisdom of the Perl Monks concerning the following question:

G'day Monks,

In Moose::Util::TypeConstraints, under Slightly Less Important Caveat, this is shown as silently failing:

use DateTime; subtype DateTime => as Object => where { $_->isa('DateTime') };

The recommended solution is given as:

use DateTime; subtype 'DateTime', as 'Object', where { $_->isa('DateTime') };

This didn't look right to me, especially as the quoting mechanism of => is supposed to be implicit and ignoring precedence (see perlop - Comma Operator).

I ran both forms through B::Deparse and got the same results:

$ perl -MO=Deparse,-p -e ' use Moose; use Moose::Util::TypeConstraints; use DateTime; subtype DateTime => as Object => where { $_->isa(q{DateTime}) }; ' use Moose; use Moose::Util::TypeConstraints; use DateTime; use warnings; use strict 'refs'; subtype('DateTime', as('Object', where(sub { $_->isa('DateTime'); } ))); -e syntax OK
$ perl -MO=Deparse,-p -e ' use Moose; use Moose::Util::TypeConstraints; use DateTime; subtype q{DateTime}, as Object => where { $_->isa(q{DateTime}) }; ' use Moose; use Moose::Util::TypeConstraints; use DateTime; use warnings; use strict 'refs'; subtype('DateTime', as('Object', where(sub { $_->isa('DateTime'); } ))); -e syntax OK

I ran diff on both outputs: they're identical.

The versions of Moose and Moose::Util::TypeConstraints that I'm using are both 2.0603 and I'm using Perl 5.14.2.

Two thoughts occurred to me regarding this:

  1. Moose source has use 5.008;. Perhaps the quoting mechanism of => worked differently under an earlier version of Perl than I'm using: while the wording has changed between versions, I don't see anything indicating delayed quoting. For reference, here's perlop - Comma Operator for 5.8.8, 5.14.2 and latest (5.16.0).
  2. Perhaps this is a documentation error. If the type name is not quoted (explicitly or implicitly), the syntax is still fine but the output is quite different:
    $ perl -MO=Deparse,-p -e ' use Moose; use Moose::Util::TypeConstraints; use DateTime; subtype DateTime, as Object => where { $_->isa(q{DateTime}) }; ' use Moose; use Moose::Util::TypeConstraints; use DateTime; use warnings; use strict 'refs'; ('DateTime'->subtype, as('Object', where(sub { $_->isa('DateTime'); } ))); -e syntax OK

Can anyone shed any light on this? Thanks in advance.

Update: I added use DateTime; to both of the first two statements to avoid ambiguity with similar code in the linked documentation.

-- Ken

Comment on Moose::Util::TypeConstraints - Querying subtype() Caveat
Select or Download Code
Re: Moose::Util::TypeConstraints - Querying subtype() Caveat
by Anonymous Monk on Jul 20, 2012 at 10:25 UTC

      Thanks for your response.

      It sounds like you also think this could be a documentation error. Thanks for digging up the original doco: I wouldn't necessarily assume a misunderstanding, it could simply be a typo.

      Re "See 2001 ...": unless you're merely indicating that indirect object syntax has been misunderstood for a long time, the significance of the 2001 links eludes me. (The 3rd link is actually 2000, if that's important.) The eariest version of Moose on CPAN (Moose 0.10), referenced in your second paragraph, is dated 05 Jul 2006.

      -- Ken

        Re "See 2001 ..." ... the significance of the 2001 links eludes me.

        Well, it was just link to explain about indirect object pitfall for anyone interested, the "2001" isn't important, I just found it curious, and it slipped into my post :)

Re: Moose::Util::TypeConstraints - Querying subtype() Caveat
by Khen1950fx (Canon) on Jul 20, 2012 at 11:50 UTC
    The recommended solution is the right solution. I got a bareword warning if I didn't quote. Here's the test that I ran:
    #!/usr/bin/perl; use Moose; use Moose::Util::TypeConstraints; use DateTime; use Test::More tests => 1; subtype 'DateTime', => as 'Object', => where { $_->isa('DateTime') }; has 'datetime' => (is => 'ro', isa => 'DateTime', required => 1); my $type = find_type_constraint('DateTime'); ok( $type, 'made a DateTime constraint' ); done_testing();
      Interestingly, the only thing really needed to be quoted is DateTime, and only if the line ends after it.

      Thanks for your reply, Khen1950fx.

      I wasn't suggesting not quoting. Rather, I was saying that I thought subtype DateTime => ... should perform the same quoting as subtype 'DateTime', ...: the B::Deparse tests, showing subtype('DateTime', ... for both forms, suggest this is correct.

      My subsequent example without quoting (in "Perhaps this is a documentation error. ...") was intended to show what would actually fail silently. With this form, B::Deparse gives 'DateTime'->subtype, ....

      In your test code, I note you've doubled up on the commas (i.e. 'XXX', => ...) in two places. With your code as is, I get

      1..1 ok 1 - made a DateTime constraint

      Removing the quotes around DateTime (i.e. subtype DateTime,\n  => ...), I get

      1..1 Can't locate object method "subtype" via package "DateTime" at pm_moos +e_quote.pl line 9. # Looks like your test exited with 255 before it could output anything +.

      Then removing the comma after DateTime (i.e. subtype DateTime\n  => ...), I get

      1..1 ok 1 - made a DateTime constraint

      The fat comma is now quoting DateTime.

      -- Ken

Re: Moose::Util::TypeConstraints - Querying subtype() Caveat
by tobyink (Abbot) on Jul 20, 2012 at 12:24 UTC

    Let's reduce that to the simpler:

    subtype DateTime => as 'Object';

    ... because that's all that's necessary to see what's going on. The problem is that Perl parses this in two different ways depending on whether DateTime has been loaded. (Or more formally, depending on whether there exists a stash called DateTime::.) If DateTime is not loaded, it gets parsed effectively as:

    subtype('DateTime', as('Object'));

    But if DateTime is loaded, it can (at least potentially - these things are tricky to predict) be parsed as an indirect method call, i.e. like this:

    DateTime::->subtype( as('Object') );

    This is in fact one of the reasons why it recommends picking a name like "MyDateTime" for your datetime datatype. Differentiating between the Moose type constraint name and the Perl package name.

    FWIW, MooseX::Types gives you a much more sugary syntax for types.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

      Thanks tobyink. I was only referring to instances with DateTime loaded.

      The documentation states that this fails silently:

      use DateTime; subtype DateTime => as Object => where { $_->isa('DateTime') };

      I am unable to reproduce this failure.

      One idea was that if the behaviour of the fat comma quoting mechanism had changed since Perl 5.8, then maybe the failure only happens with earlier versions of Perl. If this wasn't the case, my only other thought was that this was a documentation error - I provided an example of what would fail silently:

      use DateTime; subtype DateTime, as Object => where { $_->isa(q{DateTime}) };

      -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://982783]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (13)
As of 2014-11-28 13:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (197 votes), past polls