Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • Just add can_any() in a patch to UNIVERSAL::can, and use Test::MockObject and you're set. ;-)
    • Personally, I think if anyone wants generic functionality like this they should put it in something like a My::UNIVERSAL class and have all objects inherit from that instead. That way, you don't risk breaking CPAN classes which, by default, inherit from UNIVERSAL.

  • But amusing and too easy to write down. Well, my first implementation only did the scalar context case. The second left me hanging between a do-it-all implementation which was not very clear to read and another with auxiliary methods can_oneof and can_someof. The third implementation prevented me of using my @a; for ( @_ ) { ...; push @a, ... }; return @a instead of a proper map. This is it.

    package USUAL;

    sub can_any {
        return wantarray ? goto &can_someof : goto &can_oneof;

    sub can_one

  • The right way to do this would be Replace Conditional With Polymorphism… that is, if feasible/sensible, wrap the objects in other objects which all have a stringify method that delegates to the right method in the wrapped object.

    But doing it for just this one instance, of course, is way too much effort.

    And I find that can is often the wrong tool when I’m just trying to do something, regardless of how it gets done. Usually, eval is better suited to that job, although in this case it is so unw

    • You know, that might make an interesting generic class. Something which, given a list of classes, can automatically set up common delegate methods to allow the language to work out the logic rather than the programmer. It reminds me of a few programmers I've spoken with who don't seem to understand the value of how many OO languages can properly dispatch on signature to identically named methods. Pushing conditional logic into the language's hands rather than the programmer's is definitely the way to go.

      • And matching on the signature alone is pretty rudimentary. Real magic happens when you do actual structural matching, à la Haskell f.ex.

    • Courtesy of Matt Trout here is an evil trick to enables a different kind of syntax…

      sub try::method {
          my $self = shift;
          for my $method ( @_ ) {
              return \sub { $self->$method( @_ ) } if $self->can( $method );
          my $class = ref( $self ) || $self;
          croak qq{Can't locate any of the object methods "@$methods" via package "$class"};

      return [
          map  { $_->${try::method qw(string heredoc)}() }

      • When I wrote App::Pgrep, I chose a different route. I have a hash which resembles this (there are other keys in the hash which I've removed for clarity):

        %HANDLER_FOR = (
            quote   => { stringify => sub { shift->string } },
            heredoc => {
                stringify => sub {

                    # heredoc lines are terminated with newlines
                    my @strings = shift->heredoc;

        • Hmm, I seem to remember muttering something to do with polymorphism on this thread…

          sub TokenHandler::quote::stringify { shift->string }

          sub TokenHandler::heredoc::stringify {
              # heredoc lines are terminated with newlines
              my @strings = shift->heredoc;
              return join '' => @strings;

          sub TokenHandler::pod::stringify {
              # pod lines lines are *not* terminated with newlines
              my @strings = shift->lines;
              return join "\n" =

          • I was going to change the code when I remembered why I didn't go this route: I didn't want to add code directly to the classes. What if Adam adds a stringify method? What if I forget one and there's some crazy AUTOLOAD method? What if at some point in the future I wanted to swap in a class with an identical interface? By adding just a tiny bit of infrastructure, I can sidestep these issues. I wasn't terribly worried about them in the specific case of PPI, but in the general case, I'm extremely gun shy

            • What if Adam adds a stringify method?

              Huh? What does that have to do with the code I wrote?

              • Again, it's probably not an issue with the particular example in hand, but if I add methods directly to a class and someone else comes along and adds identically named methods, I have no guarantee that my method will behave the same way their method does. When their other methods try to call the method and get mine, who knows what happens?

                Thus, I really don't feel comfortable reaching directly into another package (though traits are OK because you (mostly) get the compile-time safety).

                • I’m trying to follow what you are talking about. Who else than you would be adding methods to your own classes?

                  • Ah, sheesh. Now I see the disconnect. I skimmed your code (thinking that I had already seen stuff like this before) and I had read TokenHandler::pod::stringify as PPI::Token::Pod::stringify. Just shoot me now, will you? I was surprised that you had suggested this. Now I know why :)

                    • Ah, now it makes sense.

                      Yeah, I definitely would not suggest that! (Considering how much I lambast the Ruby crowd for making a mindless habit of it…)

                      I just thought that, well, you need a dispatch at that point, and your table is static, so why not let Perl do the job? I find the resulting code a good deal less ugly too, although that is certainly debatable.