use utf8;
use open ':std', ':utf8';
use feature 'unicode_strings';
...
for my $file ( @files ) {
open my $FH, '<', $file or die "Cannot open '$file' because: $!";
my $size = read $FH, my $data, -s $FH or die "Cannot read from '$f
+ile' because: $!";
$size == length( $data ) or die "Error reading from '$file'\n";
close $FH;
...
This will always result (if $data contains Unicode characters) in dieing with the message "Error reading from '$file'\n".
The solution is to use this instead:
$size == $data =~ y///c or die "Error reading from '$file'\n";
Hope this helps.
Please correct me if I am wrong.
Naked blocks are fun!
-- Randal L. Schwartz, Perl hacker
|
use Foo;
use Foo ':modern';
Some methods behave slightly differently depending on the package-scoped lexical boolean flag. When it is not too cumbersome or performance critical, the flag is checked inside a method, perhaps in a few places. Otherwise, methods are redefined, which, sadly, leads to code duplication. Additionally, in modern mode some constants are exported to the user, so they can use them. "Classic" users don't know nor care about these constants. Here is my implementation, is it OK or can be done better?
package Foo;
use strict;
use warnings;
use feature 'say';
use parent 'Exporter';
my $MODE = 0;
my %const;
BEGIN {
%const = (
ABC => 'abc',
XYZ => 'xyz',
# etc.
# longer list
)
}
use constant \%const;
our @EXPORT_OK = keys %const;
sub import {
my ( $self, $flag ) = @_;
if ( defined $flag and $flag eq ':modern' ) {
$MODE = 1;
Foo-> export_to_level( 1, 'Foo', keys %const );
no warnings 'redefine';
*Foo::m2 = \&Foo::Modern::m2;
# etc.
# longer list
}
}
sub new { my $class = shift; bless {}, $class }
sub m1 { say $MODE ? 'modern 1' : 'classic 1' }
sub m2 { say 'classic 2' }
package Foo::Modern {
sub m2 { say 'modern 2' }
};
1;
And a user does:
use strict;
use warnings;
use feature 'say';
use lib '.';
use Foo ':modern';
my $obj = Foo->new;
$obj->m1;
$obj->m2;
say ABC;
|
Praised monks,
I have experienced an unexpected behavior of 'local'.
I am trying to attach the scope of the value of a global variable to the current lexical block (e.g. a function),
meaning that upon exit of that block, the previous value is restored.
I think this is exactly the intended use case for local.
The reason why I am doing this is to create a module with subroutines for selective debugging output.
Kind of like this:
#!/usr/bin/env perl
use v5.20;
use warnings;
use feature 'signatures';
no warnings 'experimental::signatures';
# ------ Debugging function definition:
our %debug;
our $d_area = "(default)";
sub dsay( @args ) {
return
unless $debug{ uc $d_area }
|| $debug{'ALL'};
my $prefix =
$d_area ne "(default)"
? "DEBUG $d_area: "
: "DEBUG: ";
say $prefix, @args;
}
# ------ Application program:
sub common_sub {
say "call to common sub (d_area is $d_area)";
dsay "debugging output from common_sub";
}
sub one {
say "call to one:";
local $d_area = "one";
dsay "debugging output from one";
common_sub;
dsay "more debugging output from one";
}
sub two {
say "call to two:";
local $d_area = "two";
dsay "debugging output from two";
common_sub;
dsay "more debugging output from two";
}
# Switch on debugging for area 'two'
# (I'll use command line switches with Getopt::Long later).
$debug{TWO} = 1;
say "hello from main";
dsay "debugging output from main";
one;
two;
which creates this output:
hello from main
call to one:
call to common sub (d_area is one)
call to two:
DEBUG two: debugging output from two
call to common sub (d_area is two)
DEBUG two: debugging output from common_sub
DEBUG two: more debugging output from two
This works perfectly.
Note that the debugging output of common_sub depends on the localized value of the $d_area variable.
But now I want to put the debugging output function and variables into a module, export everything correctly, like this:
#
# Dsay.pm
#
package Dsay;
use parent 'Exporter';
our @EXPORT = qw( %debug $d_area dsay );
our %debug;
our $d_area = "(default)";
sub dsay( @args ) {
return
unless $debug{ uc $d_area }
|| $debug{'ALL'};
my $prefix =
$d_area ne "(default)"
? "DEBUG $d_area: "
: "DEBUG: ";
say $prefix, @args;
}
1;
and replace the definitions in the main program by a simple
use Dsay;
The result is that I don't get any debugging output anymore.
I understand that importing $d_area
creates an entry in the symbol table of the importing module (here: main),
which references the variable in the Dsay module.
And after a long while of contemplating (and debugging, and reading, and experimenting)
I think I also understand that local $d_area = "..."; creates a new temporary variable to hold the new value,
and — also temporarily — changes the $d_area symbol
to be a reference to that new variable (and value).
The symbol that is changed is the one in the current package's symbol table, because $d_area is unqualified.
Which means that the symbol — and the value! — in the Dsay module is completely unaffected,
and not substituted!
This explains the unexpected behavior.
Surely, to remedy this, I could use
local $Dsay::d_area = '...';
in all places, but I would have liked to avoid to use the fully qualified name, for easier typing and faster debugging.
After all, the unqualified $d_area refers to the variable within the Dsay module,
which menas that any change done here is seen there, and any change done there is seen here.
But local cuts that correspondence!
Do the monks know of any incantation (or magic spell?) so that local $d_area modifies the original imported variable,
not only the local one?
Could there be any benefit in adding an explicit import function to the Dsay module,
and/or playing around with explicit variable references like \$Dsay::d_area to that effect?
Thank you for your enlightenment!
|