An old trick that save me TONES of code


G

George Mpouras

# the following trick to create and write dynamic files save me a lot of
code, thans perl !


my %file = ();


foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or die
"oups $^E\n" } }

print {$file{john} {white}[0]} "i am in john white\n";
print {$file{george}{blue} [0]} "I am in george blue\n";

foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
close $file{$user}{$color}->[0] or die "oups $^E\n" } }
 
Ad

Advertisements

T

Tim McDaniel

# the following trick to create and write dynamic files save me a lot of
code, thans perl !


my %file = ();


foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or die
"oups $^E\n" } }

print {$file{john} {white}[0]} "i am in john white\n";
print {$file{george}{blue} [0]} "I am in george blue\n";

foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
close $file{$user}{$color}->[0] or die "oups $^E\n" } }

The thing that's new to me is having a little array to associate the
filehandle and the filename. That's neat -- thank you. Is that what
you mean by "trick"?

I haven't tried running the code. I notice
open $file{$user}{$color}->[0] but
print {$file{john} {white}[0]} "i am in john white\n";
Do you need the "->" in the first one? I don't think so, but I don't
usually elide "->".

Does
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or ...

work, or does the first element of the [...] have to be a reference
like "\(my $fh)"?

I do see a possible drawback of this. Some systems have a constraint
on the number of files that can be open at one time. But I think that
any system I've used in the past 20 years can handle 9 files, as shown
in this example.

(Oh, and a minor misfeature: I think qw/george john jim/ should have
been qw/george john paul ringo/.)
 
J

J. Gleixner

# the following trick to create and write dynamic files save me a lot of
code, thans perl !


my %file = ();


foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or die
"oups $^E\n" } }

To simplify it a bit, use a hash for everything. That way you have
a nice label for the data and avoid having to remember what's in [0]
vs [1] months later.

# not really needed, but to keep it similar to your example..
$file{ $user }{ $color }{ 'filename' } = "$user.$color.txt";

open ( $file{ $user }{ $color }{ 'fh' },
'>' , $file{ $user }{ $color }{ 'filename' } ) or die "...";
 
R

Rainer Weikusat

J. Gleixner said:
# the following trick to create and write dynamic files save me a lot of
code, thans perl !


my %file = ();


foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or die
"oups $^E\n" } }

To simplify it a bit, use a hash for everything. That way you have
a nice label for the data and avoid having to remember what's in [0]
vs [1] months later.

'Having a nice label for the data' can also be achieved by declaring
symbolic constants mapping names to the index values, eg

use constant => {
FH => 0,
FN => 1
};

or

use constant FH => 0;
use constant FN => 1;
# not really needed, but to keep it similar to your example..
$file{ $user }{ $color }{ 'filename' } = "$user.$color.txt";

The {} in a hash lookup still autoquote everything which 'looks'
like a simple name (matched ^\w+$, according to Ben Morrow).
 
C

Charles DeRykus

# the following trick to create and write dynamic files save me a lot of
code, thans perl !


my %file = ();


foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or die
"oups $^E\n" } }

print {$file{john} {white}[0]} "i am in john white\n";
print {$file{george}{blue} [0]} "I am in george blue\n";

foreach my $user (qw/george john jim/) {
foreach my $color (qw/green blue white/) {
close $file{$user}{$color}->[0] or die "oups $^E\n" } }

The thing that's new to me is having a little array to associate the
filehandle and the filename. That's neat -- thank you. Is that what
you mean by "trick"?

I haven't tried running the code. I notice
open $file{$user}{$color}->[0] but
print {$file{john} {white}[0]} "i am in john white\n";
Do you need the "->" in the first one? I don't think so, but I don't
usually elide "->".

Does
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or ...

work, or does the first element of the [...] have to be a reference
like "\(my $fh)"?

I do see a possible drawback of this. Some systems have a constraint
on the number of files that can be open at one time. But I think that
any system I've used in the past 20 years can handle 9 files, as shown
in this example.

The allowable no. of open files on the Unix OS's I'm familiar with is
always more than a thousand...although a particular host can be and
often is more restrictive via setrlimit.

If that limit is exceeded, you'll get an EMFILE ("Too many open files").
although the core module FileCache can sometimes be used to get around
the limit...sort of.
 
Ad

Advertisements

R

Rainer Weikusat

[...]

open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or die
"oups $^E\n" } }

print {$file{john} {white}[0]} "i am in john white\n";
[...]

I haven't tried running the code. I notice
open $file{$user}{$color}->[0] but
print {$file{john} {white}[0]} "i am in john white\n";
Do you need the "->" in the first one? I don't think so, but I don't
usually elide "->".

According to perlref(1)

The arrow is optional between brackets subscripts

This makes sense because Perl 'container objects' cannot contain
anything except scalars which means that

$blah{7}[0]{33}

is unambigious: It must 'mean' $blah{7}->[0]->{33}.

Does
$file{$user}{$color} = [ my $fh, "$user.$color.txt" ];
open $file{$user}{$color}->[0] , '>' , $file{$user}{$color}->[1] or ...

work, or does the first element of the [...] have to be a reference
like "\(my $fh)"?

Why would it need to be a reference to a scalar? Or anything, for that
matter? An uninitialized array element is as good a scalar whose value
is undef than any other scalar.

------------
my @a;

open($a[0], '<', '/etc/services');
print while defined($_ = readline($a[0]));
------------

NB: Using <> for I/O doesn't work here, cf

If what's within the angle brackets is neither a filehandle
nor a simple scalar variable containing a filehandle name,
typeglob, or typeglob reference, it is interpreted
as a filename pattern to be globbed
[perlop(1)]

In the given context, I regard this as a misfeature.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top