function within qq{}

Discussion in 'Perl Misc' started by cate, Feb 2, 2010.

  1. cate

    cate Guest

    I know you can do this, I just can't find it.
    How do you call a sub within a qq{} construct

    qq{The common term for H2O is chem("H2O").}

    Thank you

    (As soon is this post is complete... I'll find it) :)
     
    cate, Feb 2, 2010
    #1
    1. Advertising

  2. cate wrote:
    > I know you can do this, I just can't find it.
    > How do you call a sub within a qq{} construct
    >
    > qq{The common term for H2O is chem("H2O").}


    perldoc -q "How do I expand function calls in a string"



    John
    --
    The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway
     
    John W. Krahn, Feb 2, 2010
    #2
    1. Advertising

  3. cate

    cate Guest

    On Feb 2, 10:18 am, "John W. Krahn" <> wrote:
    > cate wrote:
    > > I know you can do this, I just can't find it.
    > > How do you call a sub within a qq{} construct

    >
    > > qq{The common term for H2O is chem("H2O").}

    >
    > perldoc -q "How do I expand function calls in a string"
    >
    > John
    > --
    > The programmer is fighting against the two most
    > destructive forces in the universe: entropy and
    > human stupidity.               -- Damian Conway


    @{[mysub(1,2,3)]}
    good grief. Thanks
     
    cate, Feb 2, 2010
    #3
  4. cate

    Uri Guttman Guest

    >>>>> "c" == cate <> writes:

    c> On Feb 2, 10:18 am, "John W. Krahn" <> wrote:
    >> cate wrote:
    >> > I know you can do this, I just can't find it.
    >> > How do you call a sub within a qq{} construct

    >>
    >> > qq{The common term for H2O is chem("H2O").}

    >>
    >> perldoc -q "How do I expand function calls in a string"
    >>

    c> @{[mysub(1,2,3)]}
    c> good grief. Thanks

    and that is considered a poor construct. i never use it (or its scalar
    cousin) nor do i recommend it. when i review code, i downgrade when i
    see that used. it is simpler and better to just assign to a variable
    before the string and then interpolate it. also it will likely be faster
    as you don't need the reference/dereference. also it will only call your
    code in a list context (even the scalar form!) which may be a
    problem. assigning to your own variable allows you to control the
    context as well.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Feb 2, 2010
    #4
  5. cate

    John Bokma Guest

    cate <> writes:

    > I know you can do this, I just can't find it.
    > How do you call a sub within a qq{} construct
    >
    > qq{The common term for H2O is chem("H2O").}
    >
    > Thank you
    >
    > (As soon is this post is complete... I'll find it) :)


    perl -e '
    sub chem {
    my $term = shift;
    return "*$term*";
    }
    print qq{The common term for H2O is ${\( chem("H2O") ) }};
    '

    use @{...} for list expressions, ${...} for scalar.

    See perldoc perlref section Using References, item 4.

    --
    John Bokma j3b

    Hacking & Hiking in Mexico - http://johnbokma.com/
    http://castleamber.com/ - Perl & Python Development
     
    John Bokma, Feb 2, 2010
    #5
  6. cate

    Uri Guttman Guest

    >>>>> "JB" == John Bokma <> writes:

    JB> cate <> writes:
    >> I know you can do this, I just can't find it.
    >> How do you call a sub within a qq{} construct
    >>
    >> qq{The common term for H2O is chem("H2O").}
    >>
    >> Thank you
    >>
    >> (As soon is this post is complete... I'll find it) :)


    JB> perl -e '
    JB> sub chem {
    JB> my $term = shift;
    JB> return "*$term*";
    JB> }
    JB> print qq{The common term for H2O is ${\( chem("H2O") ) }};
    JB> '

    JB> use @{...} for list expressions, ${...} for scalar.

    partly incorrect.

    perl -le 'sub context {return "array" if wantarray} ; print "scalar ${\context()}"'
    scalar array

    that is an obscure bug that has been around a long time. the scalar form
    still calls the sub in list context. this is one of the reasons i don't
    recommend using this trick. and a trick it is. it isn't really meant to
    be used like that but perl's syntax supports interpolating of
    dereferenced expressions. the interpolate module supports this in a
    better way and so does perl6.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Feb 2, 2010
    #6
  7. cate

    Uri Guttman Guest

    >>>>> "BM" == Ben Morrow <> writes:

    BM> Quoth "Uri Guttman" <>:
    >> >>>>> "JB" == John Bokma <> writes:

    >>

    JB> cate <> writes:
    >> >> I know you can do this, I just can't find it.
    >> >> How do you call a sub within a qq{} construct
    >> >>
    >> >> qq{The common term for H2O is chem("H2O").}
    >> >>
    >> >> Thank you
    >> >>
    >> >> (As soon is this post is complete... I'll find it) :)

    >>

    JB> perl -e '
    JB> sub chem {
    JB> my $term = shift;
    JB> return "*$term*";
    JB> }
    JB> print qq{The common term for H2O is ${\( chem("H2O") ) }};
    JB> '
    >>

    JB> use @{...} for list expressions, ${...} for scalar.
    >>
    >> partly incorrect.
    >>
    >> perl -le 'sub context {return "array" if wantarray} ; print "scalar
    >> ${\context()}"'
    >> scalar array
    >>
    >> that is an obscure bug that has been around a long time. the scalar form
    >> still calls the sub in list context.


    BM> It's not a bug. \($x, $y, $z) is perfectly valid, and returns a list of
    BM> refs. (This also means that \(@a) is not the same as \@a: one of the few
    BM> cases where parens *are* necessary to denote a list.)

    yes, but the "${\foo()}" idiom looks like it will be in scalar
    context. that is the issue. you need to put a scalar() in there. whether
    it is a true bug or not, i say this is one reason to not use this
    trick. using a variable is simpler, probably faster and safer.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Feb 2, 2010
    #7
  8. cate

    Uri Guttman Guest

    >>>>> "BM" == Ben Morrow <> writes:

    BM> Quoth "Uri Guttman" <>:
    >> >>>>> "BM" == Ben Morrow <> writes:

    >>

    BM> It's not a bug. \($x, $y, $z) is perfectly valid, and returns a list of
    BM> refs. (This also means that \(@a) is not the same as \@a: one of the few
    BM> cases where parens *are* necessary to denote a list.)
    >>
    >> yes, but the "${\foo()}" idiom looks like it will be in scalar
    >> context. that is the issue. you need to put a scalar() in there. whether
    >> it is a true bug or not, i say this is one reason to not use this
    >> trick. using a variable is simpler, probably faster and safer.


    BM> Oh, I agree there. The right answer is of course some sort of template
    BM> system: sprintf will do for starters, and there are plenty on CPAN.

    and what is wrong with my suggestio of a simple variable assignment
    before the string is built? that is all the OP needs.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Feb 2, 2010
    #8
  9. cate

    John Bokma Guest

    "Uri Guttman" <> writes:

    >>>>>> "JB" == John Bokma <> writes:

    >
    > JB> cate <> writes:
    > >> I know you can do this, I just can't find it.
    > >> How do you call a sub within a qq{} construct
    > >>
    > >> qq{The common term for H2O is chem("H2O").}
    > >>
    > >> Thank you
    > >>
    > >> (As soon is this post is complete... I'll find it) :)

    >
    > JB> perl -e '
    > JB> sub chem {
    > JB> my $term = shift;
    > JB> return "*$term*";
    > JB> }
    > JB> print qq{The common term for H2O is ${\( chem("H2O") ) }};
    > JB> '
    >
    > JB> use @{...} for list expressions, ${...} for scalar.
    >
    > partly incorrect.


    I stand corrected, thanks (Ben too). I haven't used this construct for
    ages, don't really like it.

    --
    John Bokma j3b

    Hacking & Hiking in Mexico - http://johnbokma.com/
    http://castleamber.com/ - Perl & Python Development
     
    John Bokma, Feb 3, 2010
    #9
  10. with <> Uri Guttman wrote:
    *SKIP*
    > yes, but the "${\foo()}" idiom looks like it will be in scalar
    > context. that is the issue. you need to put a scalar() in there. whether
    > it is a true bug or not, i say this is one reason to not use this
    > trick. using a variable is simpler, probably faster and safer.


    s/probably/definetely/

    #!/usr/bin/perl

    use strict;
    use warnings;
    use Benchmark qw{ cmpthese timethese };

    sub abc {
    return "abc";
    }
    sub def {
    my $t = "def";
    return "*$t";
    }
    my( $x, $y );

    cmpthese timethese -5, {
    code00 => sub { $x = "@{[ abc ]}"; },
    code01 => sub { $x = "${\( def )}"; },
    code02 => sub { $y = abc; $x = "$y"; },
    };

    __END__
    Benchmark: running code00, code01, code02 for at least 5 CPU seconds...
    code00: 6 wallclock secs ( 5.17 usr + 0.00 sys = 5.17 CPU) @ 559916.63/s (n=2894769)
    code01: 7 wallclock secs ( 5.09 usr + 0.00 sys = 5.09 CPU) @ 667528.49/s (n=3397720)
    code02: 7 wallclock secs ( 5.27 usr + 0.00 sys = 5.27 CPU) @ 941641.56/s (n=4962451)
    Rate code00 code01 code02
    code00 559917/s -- -16% -41%
    code01 667528/s 19% -- -29%
    code02 941642/s 68% 41% --

    p.s. "faster" is strawman, anyway


    --
    Torvalds' goal for Linux is very simple: World Domination
    Stallman's goal for GNU is even simpler: Freedom
     
    Eric Pozharski, Feb 3, 2010
    #10
  11. cate

    Marc Girod Guest

    On Feb 2, 4:50 pm, John Bokma <> wrote:

    > sub chem {
    >     my $term = shift;
    >     return "*$term*";}


    I think the common name for H2O is 'water'.

    Marc
     
    Marc Girod, Feb 3, 2010
    #11
  12. cate

    Marc Girod Guest

    On Feb 2, 10:19 pm, "Uri Guttman" <> wrote:

    > and what is wrong with my suggestio of a simple variable assignment
    > before the string is built? that is all the OP needs.


    It requires a block around it when used with 'for'?
    I.e. one might consider it as needless verbosity, in a context where
    compacity would enhance readability...

    print qq{The common term for $_ is ${ \chem($_) }} for @molecule;

    Suppose you have 10 such lines...

    Marc
     
    Marc Girod, Feb 3, 2010
    #12
  13. Marc Girod wrote:
    > On Feb 2, 10:19 pm, "Uri Guttman" <> wrote:
    >
    >> and what is wrong with my suggestio of a simple variable assignment
    >> before the string is built? that is all the OP needs.

    >
    > It requires a block around it when used with 'for'?
    > I.e. one might consider it as needless verbosity, in a context where
    > compacity would enhance readability...
    >
    > print qq{The common term for $_ is ${ \chem($_) }} for @molecule;
    >
    > Suppose you have 10 such lines...


    Use printf.

    printf "The common term for %s is %s\n", $_, chem($_) for @molecule;

    I never do a function call in a qq string because I consider that bad style.

    - Wolf
     
    Wolf Behrenhoff, Feb 3, 2010
    #13
  14. cate

    Uri Guttman Guest

    >>>>> "WB" == Wolf Behrenhoff <> writes:

    WB> Marc Girod wrote:
    >> On Feb 2, 10:19 pm, "Uri Guttman" <> wrote:
    >>
    >>> and what is wrong with my suggestio of a simple variable assignment
    >>> before the string is built? that is all the OP needs.

    >>
    >> It requires a block around it when used with 'for'?
    >> I.e. one might consider it as needless verbosity, in a context where
    >> compacity would enhance readability...
    >>
    >> print qq{The common term for $_ is ${ \chem($_) }} for @molecule;
    >>
    >> Suppose you have 10 such lines...


    WB> Use printf.

    and that was mentioned by ben iirc. i would use sprintf instead as my
    rule is print rarely, print late. i can't recall ever using printf
    directly, whereas i use sprintf when i need too.

    WB> I never do a function call in a qq string because I consider that
    WB> bad style.

    and we have another true believer! :)

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Feb 3, 2010
    #14
  15. cate

    Marc Girod Guest

    On Feb 3, 2:07 pm, Wolf Behrenhoff
    <> wrote:

    > Use printf.


    This was Ben's answer, and... I agree, at least in that case
    (and I cannot make another one now).

    But I was replying to Uri's challenge.

    Marc
     
    Marc Girod, Feb 3, 2010
    #15
  16. cate

    John Bokma Guest

    Marc Girod <> writes:

    > On Feb 2, 4:50 pm, John Bokma <> wrote:
    >
    >> sub chem {
    >>     my $term = shift;
    >>     return "*$term*";}

    >
    > I think the common name for H2O is 'water'.


    LMAO!

    --
    John Bokma j3b

    Hacking & Hiking in Mexico - http://johnbokma.com/
    http://castleamber.com/ - Perl & Python Development
     
    John Bokma, Feb 3, 2010
    #16
  17. cate

    Guest

    On Tue, 2 Feb 2010 08:01:14 -0800 (PST), cate <> wrote:

    >I know you can do this, I just can't find it.
    >How do you call a sub within a qq{} construct
    >
    >qq{The common term for H2O is chem("H2O").}
    >
    >Thank you
    >
    >(As soon is this post is complete... I'll find it) :)


    Its a little like the tail wagging the dog.
    -> "The common term for %s is %s."
    This doesen't change, so a sprintf is all you need.
    Sometimes its a problem if you need to print the same thing
    at different places in the program.

    Taking your theme of qq(), you can split a message format string
    from the data and consistently call a message formatter that puts
    it all together.

    This is just for example purposes. Should you need a full
    blown formatter, there are probably dozens of safe ones on
    Cpan.

    -sln

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


    my $common_msg = qq{"The common term for '%s' is '%s'."};
    my $chem_msg = qq{"'%s' is the common term for '%s'."};
    my %chemterms = (
    'H20' => 'water',
    'C02' => 'carbon dioxide',
    '02' => 'oxygen',
    'NaCL' => 'sodium chloride',
    );
    my %commonterms = reverse %chemterms;

    ##
    for (sort keys %chemterms) {
    print getMsg($common_msg, $_, chem($_)), "\n";
    }
    for (sort keys %commonterms) {
    print getMsg($chem_msg, '\u'.$_, chem(-$_)), "\n";
    }
    exit 0;
    ##

    sub chem {
    my ($key) = @_;
    return $commonterms{$key} || 'undefined' if $key =~ s/^-//;
    return $chemterms{$key} || 'undefined'
    }
    sub getMsg {
    my ($msg, @data) = @_;
    my $retval = '';
    my $evstr = "\$retval = sprintf ($msg, ". "@{[map {qq(\"$_\",)} @data]}" .");";
    eval $evstr;
    return $retval;
    }
    __END__

    The common term for '02' is 'oxygen'.
    The common term for 'C02' is 'carbon dioxide'.
    The common term for 'H20' is 'water'.
    The common term for 'NaCL' is 'sodium chloride'.
    'Carbon dioxide' is the common term for 'C02'.
    'Oxygen' is the common term for '02'.
    'Sodium chloride' is the common term for 'NaCL'.
    'Water' is the common term for 'H20'.
     
    , Feb 3, 2010
    #17
  18. cate

    Guest

    On Wed, 03 Feb 2010 12:00:47 -0800, wrote:

    >This is just for example purposes. Should you need a full
    >blown formatter, there are probably dozens of safe ones on
    >Cpan.
    >
    > my $evstr = "\$retval = sprintf ($msg, ". "@{[map {qq(\"$_\",)} @data]}" .");";


    Shorter:
    my $evstr = "\$retval = sprintf ($msg, @{[map {qq(\"$_\",)} @data]} );";
    or
    my $evstr = "\$retval = sprintf ($msg, @{[map {qq('$_',)} @data]} );";

    if you don't want to interpolate @data's elements during eval.

    -sln
     
    , Feb 3, 2010
    #18
  19. cate

    Ted Zlatanov Guest

    On Wed, 03 Feb 2010 12:48:01 -0800 wrote:

    s> On Wed, 03 Feb 2010 12:00:47 -0800, wrote:
    >> This is just for example purposes. Should you need a full
    >> blown formatter, there are probably dozens of safe ones on
    >> Cpan.
    >>
    >> my $evstr = "\$retval = sprintf ($msg, ". "@{[map {qq(\"$_\",)} @data]}" .");";


    s> Shorter:
    s> my $evstr = "\$retval = sprintf ($msg, @{[map {qq(\"$_\",)} @data]} );";
    s> or
    s> my $evstr = "\$retval = sprintf ($msg, @{[map {qq('$_',)} @data]} );";

    s> if you don't want to interpolate @data's elements during eval.

    That's like putting a band-aid on someone who's being electrocuted.
    Yeah, it might help with the skin burns, but...

    Ted
     
    Ted Zlatanov, Feb 4, 2010
    #19
  20. cate

    Guest

    On Thu, 04 Feb 2010 09:33:24 -0600, Ted Zlatanov <> wrote:

    >On Wed, 03 Feb 2010 12:48:01 -0800 wrote:
    >
    >s> On Wed, 03 Feb 2010 12:00:47 -0800, wrote:
    >>> This is just for example purposes. Should you need a full
    >>> blown formatter, there are probably dozens of safe ones on
    >>> Cpan.
    >>>
    >>> my $evstr = "\$retval = sprintf ($msg, ". "@{[map {qq(\"$_\",)} @data]}" .");";

    >
    >s> Shorter:
    >s> my $evstr = "\$retval = sprintf ($msg, @{[map {qq(\"$_\",)} @data]} );";
    >s> or
    >s> my $evstr = "\$retval = sprintf ($msg, @{[map {qq('$_',)} @data]} );";
    >
    >s> if you don't want to interpolate @data's elements during eval.
    >
    >That's like putting a band-aid on someone who's being electrocuted.
    >Yeah, it might help with the skin burns, but...
    >
    >Ted


    You lost me. Something wrong with this?
    Whats a better way?

    -sln
     
    , Feb 4, 2010
    #20
    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. uli
    Replies:
    3
    Views:
    525
  2. TheDustbustr
    Replies:
    1
    Views:
    464
    Sami Hangaslammi
    Jul 25, 2003
  3. Fernando Rodriguez
    Replies:
    6
    Views:
    320
    Michele Simionato
    Nov 3, 2003
  4. Peter Moscatt
    Replies:
    4
    Views:
    328
    Peter Moscatt
    Apr 18, 2005
  5. Christopher J. Bottaro

    how to get name of function from within function?

    Christopher J. Bottaro, Jun 3, 2005, in forum: Python
    Replies:
    16
    Views:
    560
    Christopher J. Bottaro
    Jun 6, 2005
Loading...

Share This Page