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 look at it:

    msg = ' spacey string ';
    msg.replace(r'^\s+', '');
    msg.replace(r'\s+$', '');

    That’s clearly orders of magnitude easier to read than the Perl version.

    • Oh wait, it has to be this:

      msg = ' spacey string ';
      msg = msg.replace(r'^\s+', '');
      msg = msg.replace(r'\s+$', '');

      Or possibly chain the methods.

      msg = ' spacey string ';
      msg = msg.replace(r'^\s+', '').replace(r'\s+$', '');

      Perl can’t hold a candle to any of that.

      • Perl can’t hold a candle to any of that.

        But perl6 might... [] []

        In Python that can be written as:
        msg = msg.strip()
        • I expected that. Of course, until I read the documentation, I don’t actually have any idea about what strip does.

          • The Python version removes spaces from both sides of the text. Just create that in a sub{} in Perl and be done with it. : )
            • I know. I’m saying that if I see msg.strip() in a random piece of Python code, and I’ve never seen the documentation of strip, then I don’t know what it does, any more than I know what the Perl code does if I’ve never read the documentation.

        • In Python that can be written as:
          msg = msg.strip()
          Hey, but that's nearly impossible to write in Perl. Let me see:

          # in-place version
          sub strip { s/^\s+//; s/\s+$//; }
          # which would be used as
          • That won’t quite work. Make it

            sub strip { $_[0] =~ s/^\s+//; $_[0] =~ s/\s+$//; }

            or maybe

            sub strip { s/^\s+//, s/\s+$// for $_[0] }
            • use strict;
              use warnings;

              my $string = " This is the test ";

              sub trim {
                      my $a = $_[0];
                      $a = join(" ", split(" ", $a));
                      return $a;

              my $nstring = trim($string);

              print "$string\n";
              print "$nstring\n";

              I don't think it takes every case...but it works with the "test" string.
            • The latter version can be generalized to:

              sub strip { s/^\s+//, s/\s+$// for @_ }

              However I don't like the idea of modifying arguments in place. Functions that do that violate my expectations. Instead I'd make a copy and return the copy. Like this:

              sub strip {
                  return map strip($_), @_ unless 1 == @_;

                  my $x = shift;
                  $x =~ s/^\s+//;
                  $x =~ s/\s+$//;
                  return $x;
              • The latter took me a while to read. I’m not used to recursion so casually… and it seems to me that deliberately creating opportunities to get the termination condition wrong is an unnecessary source of bugs.

                I agree though that returning a copy is better; I wrote my code that way only because was correcting the example code.

                Personally I’d write it like this:

                sub strip {
                    my @stripped = @_;
                    s/^\s+//, s/\s+$// for @stripped;
                    return @stripped;

                On a

                • There is a subtle but significant difference between the two versions that shows up if someone writes my $bar = strip($foo); Your code will return 1 in that case, while mine returns $foo stripped appropriately.

                  To fix that you would need to check wantarray. Or you could return @_[0..$#_] instead.

                  Personally I have a lot of utility functions that usually accept one value, but sometimes accepts a list and returns a list. I find it annoying to add the loop and the wantarray check to each one. And I find

                  • I see the points, but I still don’t like the idiom. It has several moving parts that have to be arranged just so, and you have to read carefully to trace its self-interaction to understand what is really going on.

                    I prefer to write simpleton code. I also prefer to avoid conditionals for the same reason, so I’d use @_[0..$#_] over wantarray. All told, for a general-case idiom I’d settle on this:

                    sub foo {
                        for ( @_ = @_ ) {
                            # ...

                    • I'm too dumb to remember what the difference between @_ and @_[0..$#_] is (and I'd guess others are also), so MHO is that wantarray would be preferable. I like btilly's way also, though it does make more function calls when run on a list. And on a side note, I also find the title of this thread amusing :-)
                    • A lot of this is personal taste. All solutions are ugly. Yours involves an extra level of indentation, assignment in the for loop declaration (normally a red flag), and the subtle return construct.

                      I'll note that efficiency depends on your use case. My approach is more efficient for the single argument case. Yours is more efficient for the list case. (More efficient than either of our versions is to make your return depend on a call to wantarray.)

                      Anyways there was a period where I had to write a bunch o
                    • Well, I’ve actually written a module to deal with that sort of thing [], so…