bob_dobalina has asked for the wisdom of the Perl Monks concerning the following question:

is there a way to pipe one function into another - like i want to split, and then inline uppercase the output of split here's what I'm trying to do
my $info = "one:two:three:four"; my @arr = split(/:/, $info); my $iLength = scalar @arr; for(my $i=0; $i<$iLength; $i++) { $arr[$i] = uc($arr[$i]); } # @arr = ONE, TWO, THREE, FOUR
but I'd like to do it somehow like the following psuedo-code
my $info = "one:two:three:four"; my @arr = uc split(/:/, $info);

Replies are listed 'Best First'.
Re: pipe one function output to another
by FunkyMonk (Bishop) on Aug 14, 2009 at 15:29 UTC
    map is the way to do it:
    my @arr = map uc, split(/:/, $info);

    BTW,

    for(my $i=0; $i<$iLength; $i++) { $arr[$i] = uc($arr[$i]); }

    isn't very Perlish. The Perl way (other than using map) would be

    for (@arr) { $_ = uc; }

    or even

    $_ = uc for @arr

      for (@arr) { $_ = uc; }
      That may be the "Perl way", but according to the Damian Conway-authored Perl Best Practices, a better way would be:
      for my $index (@arr) { $index = uc $index; }
Re: pipe one function output to another
by derby (Abbot) on Aug 14, 2009 at 15:23 UTC

    my @arr = map { uc( $_ ) } split(/:/, $info );

    -derby
Re: pipe one function output to another
by Fletch (Bishop) on Aug 14, 2009 at 15:22 UTC

    map?

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: pipe one function output to another
by jwkrahn (Abbot) on Aug 14, 2009 at 16:34 UTC
    my $info = "one:two:three:four"; my @arr = split /:/, uc $info;
      I like that even more. Run uc on the text before splitting it.
Re: pipe one function output to another
by ssandv (Hermit) on Aug 14, 2009 at 17:45 UTC
    There's actually a general answer to this question, and that answer is yes. If you have two functions, func1 and func2 (forgive my startlingly clever and original naming convention) and func2 returns a list, and func1 operates on a list, Perl will work from right to left, and func1 will operate on the list you get from func2. Mostly. It'll violate your intuitive expectations a lot, though:
    my @stuff=qw(foo bar baz); print join "\n",@stuff,"\n"; print "test!\n"; ------------ foo bar baz test!
    because it joined (@stuff,"\n") (a perfectly legal list) using "\n" instead of joining @stuff and then putting one last \n on the end.
      print join "\n",@stuff,"\n";

      Your code results in a double newline at the end of the string being printed, which might not fit the requirement. Why not use parentheses so that join only operates on @stuff? Or why not make the last item being joined an empty string? Another way would be to modify the default list separator (see $LIST_SEPARATOR or $" in perlvar).

      $ perl -e ' > my @stuff = qw{ foo bar baz }; > > print join qq{\n}, @stuff, qq{\n}; > print qq{Tail of test 1\n}; > > print join( qq{\n}, @stuff ), qq{\n}; > print qq{Tail of test 2\n}; > > print join qq{\n}, @stuff, q{}; > print qq{Tail of test 3\n}; > > print do{ local $" = qq{\n}; qq{@stuff\n} }; > print qq{Tail of test 4\n};' foo bar baz Tail of test 1 foo bar baz Tail of test 2 foo bar baz Tail of test 3 foo bar baz Tail of test 4 $

      I hope this is of interest.

      Cheers,

      JohnGG

        Exactly. There are many ways to fix that, my point wasn't to fix it, my point was to show that it takes a bit of practice to train your intuition to operate on lists that way.
Re: pipe one function output to another
by Marshall (Canon) on Aug 15, 2009 at 02:02 UTC
    You should just uppercase the string to start with as this is a very efficient operation in Perl.
    #!/usr/bin/perl -w use strict; my $info = "one:two:three:four"; $info = uc($info); my @arr = split(/:/, $info); print "@arr\n"; __END__ Prints: ONE TWO THREE FOUR
    This is the SAME thing:
    my $info = "one:two:three:four"; my @arr = split(/:/, uc($info) );
    In Perl uc($var), upper case works on the entire string of $var.
Re: pipe one function output to another
by spx2 (Deacon) on Aug 15, 2009 at 04:08 UTC

    It's natural that you want to use uc like that.

    First method - Call some methods on native types

    You can use autobox for this in the following manner:

    2 package MyArray; 3 use base qw(autobox); 4 sub uc { return map { uc } @{$_[0]}; }; 5 6 7 package MyString; 8 use base qw(autobox); 9 10 sub split { [ split $_[1], $_[0] ] ; }; 11 12 13 package main; 14 15 16 use autobox ARRAY => 'MyArray'; 17 use autobox STRING => 'MyString'; 18 use feature 'say'; 19 20 say "one:two:three:four"->split(':')->uc();

    or shorter:

    1 2 use feature 'say'; 3 use autobox ; 4 5 sub ARRAY::uc { return map { uc } @{$_[0]}; }; 6 sub SCALAR::split { [ split $_[1], $_[0] ] ; }; 7 8 9 say "one:two:three:four"->split(':')->uc();

    Second method - Overriding the CORE method uc

    This is simple , you just make up your own new method and you replace the one from CORE with your own in the BEGIN block

    1 2 3 use feature 'say'; 4 5 sub new_uc { 6 @_ > 1 7 ? map { uc } @_ 8 : uc $_[0] ; 9 } 10 11 BEGIN { 12 *CORE::GLOBAL::uc = *new_uc; 13 } 14 15 say uc split(':',"one:two:three:four"); 16 17 my $w = uc "a"; 18 say $w;

    By writing new_uc like that you assure that it will work as the old uc for scalars and in the new way for arrays

    P.S. : There would be a third method .. to get into the Perl C sources in file pp.c at line 3620 and modify PP(pp_uc) so that it will behave as it should. Unfortunately that would require also reading av.c to understand how the arrays work , and reading or guessing what all of the macros do. Btw , has anyone else tried this before ? How in God's name do you start understanding those sources ?