moving a match into a subroutine

Discussion in 'Perl Misc' started by Stefan Ram, Jul 16, 2009.

  1. Stefan Ram

    Stefan Ram Guest

    I want to have the match »something =~ /(.)/g« to be kept in a
    separate subroutine, because then, I can keep this at the
    start of my script. (I like to collect those parts of my
    script that I change often there.)

    However, as one can see from the script below, my first attempt
    (exhibit 0) does not work, it only prints empty lines.

    When I do not use a subroutine (exhibit 1), the behavior is as
    wanted: it prints lines with »a«, »b«, and »c«.

    Can I put the match »something =~ /(.)/g« in a separate
    source code entity that can be moved to the top of my script
    (like a subroutine) and still get the behavior of exhibit 1?

    #!/usr/bin/perl
    #perl 5.8.3

    use strict;
    use warnings;

    my $text = "abc";

    # exhibit 0
    sub match($){ $_[0] =~ /(.)/g }
    while( match( $text ))
    { print $1, "\n"; }

    # exhibit 1
    while( $text =~ /(.)/g )
    { print $1, "\n"; }
     
    Stefan Ram, Jul 16, 2009
    #1
    1. Advertising

  2. Stefan Ram

    C.DeRykus Guest

    On Jul 16, 4:15 am, -berlin.de (Stefan Ram) wrote:
    >   I want to have the match »something =~ /(.)/g« to be kept in a
    >   separate subroutine, because then, I can keep this at the
    >   start of my script. (I like to collect those parts of my
    >   script that I change often there.)
    >
    >   However, as one can see from the script below, my first attempt
    >   (exhibit 0) does not work, it only prints empty lines.



    >
    >   When I do not use a subroutine (exhibit 1), the behavior is as
    >   wanted: it prints lines with »a«, »b«, and »c«.
    >
    >   Can I put the match »something =~ /(.)/g« in a separate
    >   source code entity that can be moved to the top of my script
    >   (like a subroutine) and still get the behavior of exhibit 1?
    >
    > #!/usr/bin/perl
    > #perl 5.8.3
    >
    > use strict;
    > use warnings;
    >
    > my $text = "abc";
    >
    > # exhibit 0
    > sub match($){ $_[0] =~ /(.)/g }
    > while( match( $text ))
    > { print $1, "\n"; }



    Backreferences are dynamically scoped within the local block
    so, in this case, $1 is undefined outside your subroutine
    block. You should also see the helpful warning:

    Use of uninitialized value $1 in concatenation (.) ...

    One way to correct the problem:

    sub match { return $_[0] =~ /(.)/g ? $1 : undef; }
    while( my $matched = match( $text )){ print "$matched\n"; }

    > ...


    --
    Charles DeRykus
     
    C.DeRykus, Jul 16, 2009
    #2
    1. Advertising

  3. On 2009-07-16, Stefan Ram <-berlin.de> wrote:
    *SKIP*
    > However, as one can see from the script below, my first attempt
    > (exhibit 0) does not work, it only prints empty lines.


    Did you run it? Besides you didn't copy-paste.

    *SKIP*

    > #!/usr/bin/perl
    > #perl 5.8.3
    >
    > use strict;
    > use warnings;
    >
    > my $text = "abc";
    >
    > # exhibit 0
    > sub match($){ $_[0] =~ /(.)/g }
    > while( match( $text ))
    > { print $1, "\n"; }


    print "$_\n" for match $text;

    That's your fish.

    > # exhibit 1
    > while( $text =~ /(.)/g )
    > { print $1, "\n"; }
    >



    --
    Torvalds' goal for Linux is very simple: World Domination
    Stallman's goal for GNU is even simpler: Freedom
     
    Eric Pozharski, Jul 17, 2009
    #3
  4. Stefan Ram

    Guest

    On 16 Jul 2009 11:15:56 GMT, -berlin.de (Stefan Ram) wrote:

    > I want to have the match »something =~ /(.)/g« to be kept in a
    > separate subroutine, because then, I can keep this at the
    > start of my script. (I like to collect those parts of my
    > script that I change often there.)
    >
    > However, as one can see from the script below, my first attempt
    > (exhibit 0) does not work, it only prints empty lines.
    >
    > When I do not use a subroutine (exhibit 1), the behavior is as
    > wanted: it prints lines with »a«, »b«, and »c«.
    >
    > Can I put the match »something =~ /(.)/g« in a separate
    > source code entity that can be moved to the top of my script
    > (like a subroutine) and still get the behavior of exhibit 1?
    >
    >#!/usr/bin/perl
    >#perl 5.8.3
    >
    >use strict;
    >use warnings;
    >
    >my $text = "abc";
    >
    ># exhibit 0
    >sub match($){ $_[0] =~ /(.)/g }
    >while( match( $text ))
    >{ print $1, "\n"; }
    >
    ># exhibit 1
    >while( $text =~ /(.)/g )
    >{ print $1, "\n"; }


    The other posters pointed out your problem.
    Probably thier two solutions can be combined into 1.

    ------------------------------
    use strict;
    use warnings;

    my $text = "abc";
    my $val;

    sub match($) {
    return $_[0] =~ /./g if wantarray;
    $_[0] =~ /(.)/g;
    $1; # <-- goes out of scope here, just return its value
    }

    # Scalar context, multiple match() calls
    print "$val\n" while ( $val = match( $text ));

    print '-' x 20, "\n"; # pos($text) is reset after failed match (unless \G)

    # List context, single match() call
    print "$_\n" for ( match( $text ));

    ---------------------------------

    -sln
     
    , Jul 24, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. linkswanted
    Replies:
    0
    Views:
    1,270
    linkswanted
    Dec 21, 2007
  2. linkswanted
    Replies:
    0
    Views:
    1,601
    linkswanted
    Jan 6, 2008
  3. linkswanted
    Replies:
    0
    Views:
    469
    linkswanted
    Jan 23, 2008
  4. linkswanted
    Replies:
    0
    Views:
    660
    linkswanted
    Jan 24, 2008
  5. king
    Replies:
    5
    Views:
    210
Loading...

Share This Page