Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Re^4: Quote and Quote-like Operators

by jmcnamara (Monsignor)
on Dec 16, 2011 at 10:26 UTC ( #943927=note: print w/replies, xml ) Need Help??

in reply to Re^3: Quote and Quote-like Operators
in thread Quote and Quote-like Operators

Yes, but in that case printing the contents of the heredoc will print the indentation as well.

A better solution would be if perl removed whatever leading whitepsace came before the heredoc (or the end token) from the text of the heredoc. Then the heredoc could be indented to match the surrounding code. In that case I would use it more often.

I'm not saying that heredocs aren't useful. Just that they break indentation.


Replies are listed 'Best First'.
Re^5: Quote and Quote-like Operators
by tchrist (Pilgrim) on Dec 16, 2011 at 14:14 UTC
    I'm not saying that heredocs aren't useful. Just that they break indentation.
    Then you’re just doing them wrong. :)
    sub compile_filter() { my @criteria; for my $i ( 0 .. $#ARGV ) { my $snippet = $ARGV[$i]; $snippet =~ s/^\s+//; # prime the autoloader on allcappish barewords if (my @capwords = $snippet =~ /\b (?=[A-Z]) ([A-Z0-9]+) \b/xg +) { eval deQQ<<"EO_AUTOLOADED_SUBS"; |QQ| |QQ| use subs qw(@capwords); |QQ| EO_AUTOLOADED_SUBS } # args starting with a backslash or which are a bracketed # espression are interpreted as pattern matches if ($snippet =~ m{ ^ \\ | ^ \[ .* \] $ }x) { $snippet = "/$snippet/"; } my $test_compile = deQ <<'START_TEST'; |Q| use warnings qw[FATAL all]; |Q| my $ignore = START_TEST $test_compile .= deQQ(<<"END_TEST"); |QQ| sub { $snippet }; |QQ| |QQ| # so eval returns true |QQ| 1; |QQ| END_TEST # debug("test compile:\n$test_compile"); eval($test_compile) || die "$0: invalid criterion in '$snippet': $@\n"; $criteria[$i] = "do { $snippet }"; } my $real_code = deQ(<<'START_CODE') . "\t"; |Q| use warnings; |Q| #use warnings qw[FATAL all]; |Q| #no warnings qw[deprecated]; |Q| |Q| sub filter { |Q| |Q| debug(sprintf("testing code point %X", ord())) +; |Q| |Q| my $result = |Q| START_CODE $real_code .= join("\n &&\n\t" => @criteria) . deQ(<<'END_CODE'); |Q| |Q| ; |Q| |Q| debug("result of " . join(" && ",@criteria) . +" is $result"); |Q| return $result; |Q| } |Q| |Q| # so eval returns true |Q| 1; END_CODE debug("CRITERIA are\n$real_code"); eval($real_code) || die; }
    As you see, heredocs certainly don’t have to “break indentation”; it just takes a bit of creative processing to make ’em look purdy. The deQ and deQQ functions are trivial:
    sub dequeue($$) { my($leader, $body) = @_; $body =~ s/^\s*\Q$leader\E ?//gm; return $body; } sub deQ($) { my $text = $_[0]; return dequeue q<|Q|>, $text; } sub deQQ($) { my $text = $_[0]; return dequeue qq<|QQ|>, $text; }
    See how that all works?


      Even with all of that clever work, go ahead a 'shift' any of those blocks of code over and watch your heredoc break. Your heredocs above break indentation (your terminators aren't indented). And (re)indentation breaks your heredocs.

      Perhaps worse, trailing whitespace can break a Perl heredoc. Plenty of reason to avoid using them in code I plan to maintain.

      - tye        

        It's even worse than that. I recently discovered that an incorrect closing quote in a string will break it. So I insist on not using strings in code I plan to maintain.

        <but class="seriously">I don't disagree that acrobatics to make heredocs appear as normal code flow edges toward egregious.</but>

        Many of the developers @my_work use the 'clever':
        .... my $here_doc = '....END'; stuff here ....END

        Along with clever trim leading whitespace code...which I I use heredocs, but ONLY on the left margin. I've become fond of syntax highlighting, so any incorrect trailing marker is (usually) obvious. I've also taken to using some vim heredoc highlighting tips and always use the terminators SQL, XML, and HTML when appropriate.

        If I have a heredoc in a sub, I move it out of the sub, e.g.

        my $sql = <<SQL; SELECT * FROM TABLE SQL sub do_stuff { ... $dbh->execute($sql); }
        If the $sql needs to be dynamic, I'll probably change it to a sprintf template, and call sprintf in the sub.

        I totally agree with you. Heredocs, as implemented in Perl5 are a maintenance problem waiting to happen. I frankly cant stand it when I indent a chunk of code and breaks in all kinds of bizarro ways because it has stupid here docs in it.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://943927]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2020-10-20 14:50 GMT
Find Nodes?
    Voting Booth?
    My favourite web site is:

    Results (210 votes). Check out past polls.