Re: 'use' inside or outside of package declaration?
by BrowserUk (Patriarch) on May 11, 2011 at 06:41 UTC
|
#! perl -slw
use strict;
package fred;
...
But that's because I often end my modules with:
return 1 if caller;
package main;
fred->import;
## code that tests the package above goes here.
In this way, running the module as a perl fred.pm runs the test.
This keeps the tests with the tested code, ensures it is kept up to date with that code and acts as documentation for its use. To my mind, this is a 3 way win.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
If the -l switch is not lexically scoped (I don't think it could be), then print statements will behave differently when running testing than when run as a module, if the consumer using your code isn’t using such a switch.
| [reply] |
|
|
then print statements will behave differently when running testing than when run as a module, if the consumer using your code isn’t using such a switch.
Only if the module uses print. And I consider this to be exactly as I want it.
If modules want to use $\, or any other global variable, then they *must* localise and set it. The main program *always* own the globals. So if modules want predictable behaviour from their use of globals, they must localise and set to their requirements.
If my modules need to print to a predefined (global) filehandle, and I want $\ = "\n", then I will localise and set it so either on a case by case basis, or more likely, for (say) debug purposes, I define a private debug function that does so and call that rather than print.
But, most modules don't print directly to STDOUT or STDERR. We'd mostly be pissed off if they did.
Test scripts frequently do print stuff, and when the module is run as a script for testing, the -l is in force.
As for -s, I frequently use runtime configuration in my test scripts like our $MAX //= 1e6;. Then if I want to run a quick test, I can use
perl fred.pm -MAX=1e3
Silly eg: #! perl -slw
use strict;
package fred;
sub new {
my $class = shift;
return bless { @_ }, $class;
}
sub method {
my $self = shift;
return keys %{ $self };
}
return 1 if caller;
package main;
our $MAX //= 10;
print 'Max: ', $MAX;
my $o = fred->new( 'a' .. 'z' );
print for $o->method;
__END__
C:\test>perl -s fred.pm -MAX=123
Max: 123
w
e
a
m
s
y
u
c
k
q
g
i
o
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
It is very important that package be the first non-comment token in a module.
| [reply] [d/l] |
|
|
| [reply] |
|
|
|
|
|
Re: 'use' inside or outside of package declaration?
by JavaFan (Canon) on May 11, 2011 at 06:55 UTC
|
I would not put 'use warnings;' on top. But that has nothing to do with package. There's a difference between:
use Module;
use warnings;
and
use warnings;
use Module;
If Module has user defined warnings, the first one enables them, the second doesn't. | [reply] [d/l] [select] |
|
|
So, putting use warnings as far down as possible (after the module includes) can enable the most warnings?
But Moose and 5.12 both enable warnings so we don't need to say it again... maybe that's not strictly true? Checking perldelta, it says 5.12 turns on strict. But I thought Moose and various "modern" boilerplates turn on warnings, and would do so fairly early.
It would be more awkward to have multiple packages defined in one file, if they used different modules and thus had different custom warnings available to them, since warnings pragma isn't scoped to the package. Normally I would not have multiple packages except for one-offs or an internal object that's very simple, but needs to be blessed.
| [reply] [d/l] |
|
|
| [reply] [d/l] [select] |
|
|
|
|
But Moose and 5.12 both enable warnings
No, 5.12 most assuredly does not. I guarantee this.
And that Moose continues to do so is a design flaw so serious that it really cannot be considered anything less than a genuine bug.
Modules that act like Acme:: modules without being in that namespace are a problem.
| [reply] [d/l] |
Re: inside or outside?
by wind (Priest) on May 11, 2011 at 04:10 UTC
|
I treat the use strict; and use warnings; declarations as a way to document the beginning of the actual code. I therefore put them immediately after all my other use statements and obviously after the package statement as well.
use MyTest qw(mysub);
use strict;
use warnings;
my $foo = 'bar';
mysub($foo);
This serves no purpose. The code would work the same if the strictures requirement was placed sooner.
I believe sometimes people put them later because they are lazy about their @EXPORT declarations, and don't always use our. | [reply] [d/l] |
Re: 'use' inside or outside of package declaration?
by toolic (Bishop) on May 11, 2011 at 15:27 UTC
|
| [reply] |
|
|
Wow, ten years later and I'm still looking for an answer.
| [reply] |
Re: 'use' inside or outside of package declaration?
by chrestomanci (Priest) on May 11, 2011 at 15:16 UTC
|
I think you should put the package declaration on the first non comment line of the file, and before any use statements. Two reasons:
Firstly if you use a modlue that exports symbols into the caller's namespace, then those symbols will only visable in the package that used the module. eg:
package foo;
use File::Copy;
# Code here.
package bar;
# Won't work, as File::Copy was not used in this package.
copy('source','dest');
If you put the use line before the package line, then you are importing into the default package (main), if you then change packages then your imports will not be visable.
I don't know if the situation is different with pragmas such as strict, but I would say it is a poor habit to get into.
Secondly, in the Perl 6 specification it says in Synopsis 10: Packages that:
As a special exception, if a braceless package declaration occurs as the first executable statement in a file, then it's taken to mean that the rest of the file is Perl 5 code.
In other words, If you write your perl 5 packages and classes so that the package statement comes first, the they are less likey to break when run by a perl 6 aware interpreter.
| [reply] [d/l] |
|
|
Firstly if you use a modlue that exports symbols into the caller's namespace, then those symbols will only visable in the package that used the module.
Eh, no.
Global symbols, whether exported or not, are just that. Global. Visible from everywhere. Sure, if you import something in package A, then switch to package B, you may need to use a fully qualified name, but both the exported and imported name are visible.
use File::Copy;
package Foo;
::copy($from, $to); # Not a problem.
Believing that the package statement should come first is equivalent of saying no meaningful code can be written that has more than one package statement in a file.
CPAN begs to differ. | [reply] [d/l] |
Re: 'use' inside or outside of package declaration?
by tchrist (Pilgrim) on May 12, 2011 at 11:01 UTC
|
I would think that if the package line itself used syntax that did not work in older perls, then the use or feature would certainly have to come first!
That’s an interesting point. As of 5.14, you can do this:
package NAMESPACE VERSION;
That sets the appropriate version number in that namespace, at compile time, and in a declarative fashion so that the toolchain doesn’t have to run (or simulate running) the code just to ascertain the package’s version number. It is also superior in that it puts the version number right at the top where it belongs, guaranteeing that it won’t drift down in the module as time goes by, as so often seems to occur.
And that’s not all.
You can also do this:
package NAMESPACE BLOCK
To create a lexical scope smaller than that of the rest of the file scope for the package declaration to govern. And of course you may combine these:
package NAMESPACE VERSION BLOCK
If you’re going to do this, it does make some sense to put a use 5.014 before that in your code. With all the myriad differences in Perl that have come about in the 5.10, 5.12, and 5.14 releases, I’ve for some time now taken to prominently placing a use 5.012 (or whatever) as the first thing in the file. It’s a way of declaring the version of Perl that I developed and tested the code under, and an indication that I have no intention of backporting and testing and maintaining it on Perls older than that. | [reply] [d/l] [select] |
|
|
use 5.10.1;
use utf8;
as the very first things. I'm not afraid of very old perls not liking the dotted syntax since the installer already checked the version once. I agree, this documents the version I wrote it under and tested it under, and can ensure some backward compatibility if even newer ones changed things.
The meaning of utf8 in modern versions is simply to state that the source file is UTF-8. That really really affects the entire file, not a block, not a package.
Based on what I learned on this thread, I'll put other stuff after the module's package line. I'm trying autodie for example, and I had supposed that to be more global and not per-package, but it was on your list.
As for the referenced ranteditorial concerning warnings in production servers, I think that ought to be fixed once and for all in the logging system. Just piping stderr to a file and archiving that file is rather brute simple. I've worked on systems where logging was more engineered. At the very least it has quotas with purging so it won't fill up the disk!
| [reply] [d/l] [select] |
|
|
My current semi-working boilerplate for new programs tends to look like this:
#!/usr/bin/env perl
use 5.012; # want unicode strings!
use utf8;
use strict;
use autodie;
use warnings; # defer FATAL till runtime
use open qw< :std :utf8 >;
use charnames qw< :full >;
use File::Basename qw< basename >;
use Carp qw< carp croak confess cluck >;
$0 = basename($0); # shorter messages
$| = 1;
binmode(DATA, ":utf8");
# give a full stack dump on any untrapped exceptions
$SIG{__DIE__} = sub {
confess "Uncaught exception: $@" unless $^S;
};
# now promote run-time warnings into stackdumped exceptions
# *unless* we're in an try block, in which
# case just generate a clucking stackdump instead
$SIG{__WARN__} = sub {
if ($^S) { cluck "Trapped warning: @_" }
else { confess "Deadly warning: @_" }
};
But that suffers form a couple of bugs. There is a bug in the implementation of autodie that screws up the layers imposed by use open. Witness:
% perl -e 'use open qw(:std :utf8); open(F, ">/tmp/out"); print F "\xD
+F"'; wc /tmp/out
0 1 2 /tmp/out
% perl -e 'use autodie; use open qw(:std :utf8); open(F, ">/tmp/out");
+ print F "\xDF"' ; wc /tmp/out
0 1 1 /tmp/out
% perl -e ' use open qw(:std :utf8); use autodie; open(F, ">/tmp/out")
+; print F "\xDF"' ; wc /tmp/out
0 1 1 /tmp/out
The other problem is that use utf8 doesn’t really work well on globals, because there are issues with how the package symbol tables are accessed as byte strings. There is also an issue of what to do about something like:
use Weather::El_Niño;
That has to map to the filesystem, and now what do you do?
Just use the bytes as they are? Normalize to UTF‑8? Downgrade
to Latin1 (which it might have already been)?
Did you
know that (for very good reasons) the Darwin HSF+ filesystem always converts filenames into NFD, their canonically decomposed form? So be careful when checking filenames!! You can’t just say:
@files = grep { /Niñ/ } glob("{El,La}_*");
Because if you input it in the normal way, your pattern is going to have a U+00F1 LATIN SMALL LETTER N WITH TILDE there (which is the NFC form) but the results from the filesystem will have an "n" followed by U+0303 COMBINING TILDE (the NFD version), which is suddenly two separate code points, not one.
There is a Google Summer of Code project for cleaning up Perl’s tokenizer vis‐à‐vis 8‑bit names, including for UTF‑8. I am convinced that this can and shall be fixed.
I see my stalker is back. Yawn! | [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
|
|
|
it does make some sense to put a use 5.014 before that [the package line] in your code.
Now you see, that is rational thinking. I knew you were capable of it.
It does make sense to use some pragmas before the package statement in a module.
They may be few and far between, and require you to test that the positioning works as you'd want and expect it to, but such pragmas do exist.
And strict is one of them. Chosen through a process of applied rationality, in direct contrast with blanket imposition of dogma every bit as bad as that which you (rightly) rail against.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |