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

Re^8: Quote and Quote-like Operators (here-docs break)

by tye (Sage)
on Dec 16, 2011 at 23:09 UTC ( [id://944027]=note: print w/replies, xml ) Need Help??


in reply to Re^7: Quote and Quote-like Operators (heredocs break)
in thread Quote and Quote-like Operators

I much prefer join over sprintf (as well as over here-docs or multi-line quoted strings or concatenation). That preference took a lot of years to form but has now lasted almost as many years. Other techniques don't scale nearly so well, IME, in the face of on-going maintenance and growing size and complexity of the string and programmers' potential for simple mistakes.

In the rare case of using a Perl here-doc as a quick solution, I also move it to be top-level. I also have a somewhat unusual editor configuration that includes showing trailing whitespace (something a significant percentage of my coworkers don't appear to have -- based on them seeming oblivious to the trailing whitespace that they sometimes commit). And even those here-docs rarely last very long.

Heck, even in the short term I'd likely just replace it with a multi-line quoted string:

( my $string= q{ ... } ) =~ s/(?=^|(\n))\n[^\S\n]+/defined $1 ? "\n" : ''/ge;

(Clever undenting regex included just to show how easy it is to eliminate the opening newline that this adds -- not because I find myself actually using such.)

Having here-docs at the top level is also annoying. Not as annoying as not being able to re-indent code w/o breaking it, of course.

SQL seems to be one of the most common examples of the use of a here-doc. I particular dislike using here-docs for SQL. By using join, I don't have to suffer due to SQL not allowing trailing commas, here-docs not supporting comments nor excluding lines conditionally, or lots of other things.

But most SQL I write ends up looking more like:

$db->select( [ "this", "that", "theother", "COUNT(*) as things" ], join( ' ', "foo", "LEFT JOIN bar USING( id )", ), [ "? <= stamp", "stamp < ?", @exclude ? "this NOT IN ( ?? )" : (), ], "GROUP BY this, that, theother", "ORDER BY that, this", "LIMIT $size OFFSET $skip", "HAVING 1 < count(*)", );

Which just boils down to this slightly longer code that I write when I don't have such trivial wrappers handy:

$db->prepare( join ' ', "SELECT", join( ', ', "this", "that", "theother", "COUNT(*) as things", ), "FROM", join( ' ', "foo", "LEFT JOIN bar USING( id )", ), "WHERE", join( ' AND ', "? <= stamp", "stamp < ?", @exclude ? "this NOT IN ( ?? )" : (), ), "GROUP BY this, that, theother", "ORDER BY that, this", "LIMIT $size OFFSET $skip", "HAVING 1 < count(*)", );

(Except that I like to build the SQL first rather than pass it directly to prepare(), so that I can easily get literal SQL in case I need to play with it interactively in a simple SQL tool. This includes replacing the placeholders with quote()d values.)

I find that scales much better as maintenance takes its toll.

I've also repeatedly suffered due to multi-line SQL dripping with whitespace, especially leading whitespace, tripping up perhaps somewhat naive DB tools I've needed to use to diagnose DB problems.

So I still feel quite justified in discouraging others from just running off and using here-docs, especially when I'm not planning on going on for thousands of words on how to avoid the many pitfalls.

- tye        

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (7)
As of 2024-03-28 11:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found