Declarations and Scope followup on Chromatic's post

potyl on 2009-10-18T08:44:50

Chromatic as a good post on Declarations and Scope. I'm glad to see that I'm not the only one that follows this best practice. Which by the way I was surprised to not see in Damian Conway's Perl Best Practices.

What I find the most strange is that I get constantly asked why I'm wrapping all my scripts into functions and that I don't have just plain executable code from the beginning. One of my posts in StackOverflow raised a lot of critics just by following this simple best practice: Scope bashing.

I think that all conscious perl programmers always employ use strict; and use warnigns. So I find that localizing all our code in scoped blocks (let it be a do {};, a function or even a simple code block {}) is just too practical to be overlooked. I don't think that doing this adds too much noise nor distractions to the original source code. Yet the benefits gain are huge!

Not only does this technique protects your variables from becoming global but it also helps when the code needs to be refactored. There's nothing more annoying that having a monolithic script without functions that can't be refactored easily because the code assumes each single variable to be a global!


Scope bashing?

oylenshpeegul on 2009-10-18T17:57:13

Calling my comment on SO "scope bashing" is unfair. I'm all in favor of scoping everything as tightly as possible. Indeed, I agree with everything in chromatic's post. But I still think the practice of wrapping a Perl script in a main subroutine is not "best" or even good. I maintain it's an antipattern that indicates the author is a C programmer, not a Perl programmer.

In chromatic's example, $sth has tighter scope than the other variables, but in the first case, it's declared along with the rest. Wrapping the whole thing in a subroutine doesn't change that. You still have to do everything he talked about.

Re:Scope bashing?

potyl on 2009-10-19T05:18:00

You're right that I haven't chosen my words properly. I should have said scope discussion.

Please accept my apologies.

global bad, lexical good

n1vux on 2009-10-19T16:49:45

This certainly is covered in Damian Conway's PBP:

"5.1. Lexical Variables
Avoid using non-lexical variables."

And preferred use of my (or local for certain built-ins) is repeated in a dozen or more specific contexts like filehandeles, builtin vars, ....

Re:global bad, lexical good

potyl on 2009-10-19T17:27:22

This certainly is covered in Damian Conway's PBP: "5.1. Lexical Variables Avoid using non-lexical variables."

I'm not referring to lexical variables (my), as you pointed out that part is covered by the best practices. I was referring to writing a single script from the top to the bottom with out localizing all variables. Remember that my only declares the variable for the life time of the current block. If the variable is not declared in a block then the file is the block scope, making the variable global. This is no matter if the variable is written in all caps or in lower case

I think that we have learned that declaring all variables as global is a bad programming practice. We are lucky with Perl that we don't need to do so. We can even declare our variables just before we need to. Other languages, C for instance, are not that lucky and are trying to address this in some way or another (C99 is doing it, a bit too late).

I like wrapping all my code inside a function, it limits the scope of the variables and doesn't allow me to cut corners. If I need something global it has to be pulled out manually from the block. Moving bits of code from the main function to another function is easier because if I forget a variable use strict; will spot it right away. Without this refactoring code that omits a variable will pass unseen as all variables are global.

Re:global bad, lexical good

Hercynium on 2009-10-19T18:48:39

hear hear!

Whenever I encounter a substantial (>100 lines) perl script with no main sub I get nervous.

A quick, one-off script may not require the extra structure and discipline, but we all know how easily a one-off can become mission-critical... and quickly grow in size scope and function.

In my opinion, file-scoped vars are nearly as bad as true globals, and packaged-scoped vars less-so, but still best to avoid, unless the alternative is sufficiently more complicated code somewhere else.

By using a main block/sub you make it much clearer each time a file, package, or global var is declared/defined, plus code that is intended to execute only once is also clearer.

In the end, the maintenance programmer will thank you for confining as much code as possible to lexical blocks. Always think of the maintenance programmer... remember, it may be YOU... or a violent psychopath who knows where you live.

Overall, the only reason I can think of to *not* use a main sub (and therefore minimize file/package/globals) is in the interest of the bad kind of laziness, the kind that saves a second now because of not caring for later.