Stories
Slash Boxes
Comments
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.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Unfortunately, there's quite a bit to criticize about it.

    You are such a tease!

    I myself don't really have a lot of complaints about the language, except that it sure would be nice to have a spiffy IDE sometimes... and it mostly doesn't because it is so dynamic as to make that difficult.

    But, I am interested in hearing what you *would* consider a "legitimate" complaint. (Would I be correct in assuming most lie in the OO area?)
    • by Ovid (2709) on 2005.10.05 15:08 (#43715) Homepage Journal

      In addition to Dom's comments, I would also add a complaint that, ironically, I also have with Java: mixing objects and primitives (Perl's less of a pain, but still a pain).

      Lately I've been thinking a lot about allomorphism (think "duck typing" in Ruby) and how it relates to programming. Consider the following snippet:

      foreach my $method (@methods) {
        foreach my $object (@objects) {
          next unless $object->can($method);
          $object->$method( $args_for{$method} );
        }
      }

      That's powerful. Dangerous, but powerful. Many languages would force you to jump through a lot of hoops to replicate this behavior (if it's even possible).

      Where does @objects come from, though? If the programmer supplies them, what happens when she does this?

      process($object1, $object2, [ qw/foo bar baz/ ]);

      The call to $object->can blows up. There's no reason it has to but now we're forced to rewrite our code to do something like this:

      use Scalar::Util 'blessed';

      foreach my $method (@methods) {
        foreach my $object (@objects) {
          next unless blessed $object && $object->can($method);
          $object->$method( $args_for{$method} );
        }
      }

      That seems like a contrived example, but I've found this biting me more than once. Here's an example I recently had to write.

      sub _attributes {
          my ( $self, $attrs ) = @_;
          return '' unless $attrs;
          if ( ref $attrs && UNIVERSAL::isa( $attrs, 'SCALAR' ) ) {
              return ' ' . $$attrs;
          }
          my @attributes = UNIVERSAL::isa( $attrs, 'HASH' ) ? %$attrs : @$attrs;
          return '' unless @attributes;
          # more code here
      }

      Because it's the person using this module who controls what is getting passed in (from a function at a higher level, not this one directly), I've no control over whether or not they're passing in a normal reference. As a rule of thumb, having to check isa() indicates a design flaw. Theoretically, I should just be able to do something like this:

      sub _attributes {
        my ($self, $attrs) = @_;

        # the following line is for illustration purposes only.  The
        # higher level code would probably call this method directly
        return $attrs->_build_attributes;
      }

      I could do that now, but that means blessing the references passed in and that means that I've modified the calling variables and that's bad. Of course, I could clone them and then bless them, but that gets annoying, too. Instead, I'd like to be able to have a _build_attributes method exist internally for scalar, array, and hash references and only make it visible to trusted classes. That would simplify the logic quite a bit and allow Perl to handle dispatching rather than the programmer handling dispatching.

      There are also some annoying bugs with typeglobs. One irritation occurs when one has a CODE slot defined in a glob with no corresponding subroutine. This breaks inheritance and causes weird "not a code reference" messages. Unfortunately, the best fix seems to either be deleting the entire glob or create a subroutine which dispatches up the inheritance heirarchy or dies with a "no such method" error message :(

      Fortunately, I think all of these complaints go away in Perl 6. Not sure about trusted methods, though.

      • As a rule of thumb, having to check isa() indicates a design flaw.

        There is Scalar::Util::reftype(), which would make the code slightly less ugly and broken, but your theoretical alternative would be nice also.