I was fooling around with the concept of generating constant scalars
in perl (with no code changes, can you believe it?) using the *foo = \$bar
trick. Turns out you can actually get a readonly global scalar with
simply:
*PI = \3.14159;
$PI can be used anywhere, but you can't modify it's value.
I went about in this vein for some time, until it struck me that this is
simply a type-specific aliasing operation. I went nuts thinking about
getting C++-like references with none of the dereferencing. At the end
of it all, the concept is quite workable and rather elegant, because
it gives you one less chance to use obfuscating typeglobs, and relief
from seeing a while lot of money $-) whenever you want to use references.
Socket/Fcntl/POSIX are obvious clients of this scheme.
Aliasing packages, is something that I haven't thought about before
sleep overcame.
Here's the result of one night's gallivanting with perl. I avidly welcome
your comments. (I hope this is one contribution to reducing "line noise",
and have true perl constants in the bargain).
- Sarathy.
gsar@engin.umich.edu
---------------------------------------8<-------------------------------------
package Alias;
=head1 NAME
Alias - declare aliases and constants
=head1 SYNOPSIS
use Alias qw(alias const);
alias TEN => $ten, Ten => \$ten, Ten => \&ten,
Ten => \@ten, Ten => \%ten, TeN => \*ten;
const pi => 3.14, ten => 10;
=head1 DESCRIPTION
Given a list of alias-symbol => value pairs, declares global aliases
in the caller's namespace. If the value supplied is a reference, the
alias is created for the underlying value instead of the reference
itself (since no one will use this package to alias references--they
are automatically "aliased" on assignment). This allows the user to
alias all of Perl's basic types.
If the value supplied is a compile-time constant, the aliases become
read-only. Any attempt to write to them will fail with a run time
error. A function-alias C<const> is aliased by this package (on demand)
for C<alias>, since this reads better for constant declarations.
=head1 EXAMPLE
use Alias qw(alias const);
$ten = 10;
alias TEN => $ten, Ten => \$ten, Ten => \&ten,
Ten => \@ten, Ten => \%ten;
alias TeN => \*ten; # same as *TeN = *ten
const _TEN_ => 10;
$ten = 20;
print "$TEN, $Ten, $ten\n";
sub ten { print "10\n"; }
@ten = (1..10);
%ten = (a..j);
&Ten;
print @Ten, %Ten;
$_TEN_ = 20;
=head1 NOTES
It is worth repeating that the aliases will be created in the
caller's namespace.
Aliases cannot be lexical, since, by necessity, they live on the
symbol table. They can be localized by first C<local>izing the
typeglob of the same name first, within the same block. However, this
will localize all the base types of the same name, and you will have
to deal with the consequences of that.
Remember that aliases are very much like references, only you
don't have to de-reference them as often.
It is possible to alias packages, but that might be construed as
abuse.
Using this package will lead to a much reduced urge to use typeglobs.
=head1 AUTHOR
Gurusamy Sarathy gsar@umich.edu
=cut
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(alias);
@EXPORT_OK = qw(const);
sub alias {
my($i) = scalar(@_) - 1 ;
my($j) = $i-1;
die "Need even number of args" if $j % 2;
my($pkg) = caller; # for namespace soundness
while ($j >= 0) {
if ('GLOB' eq ref $_[$i]) { eval "*$pkg\:\:$_[$j] = \${\$_[$i]}" }
elsif (ref $_[$i]) { eval "*$pkg\:\:$_[$j] = \$_[$i]" }
else { eval "*$pkg\:\:$_[$j] = \\\$_[$i]" }
$i--; $j--;
}
}
alias const => \&alias; # alias the alias :-)
1;
in perl (with no code changes, can you believe it?) using the *foo = \$bar
trick. Turns out you can actually get a readonly global scalar with
simply:
*PI = \3.14159;
$PI can be used anywhere, but you can't modify it's value.
I went about in this vein for some time, until it struck me that this is
simply a type-specific aliasing operation. I went nuts thinking about
getting C++-like references with none of the dereferencing. At the end
of it all, the concept is quite workable and rather elegant, because
it gives you one less chance to use obfuscating typeglobs, and relief
from seeing a while lot of money $-) whenever you want to use references.
Socket/Fcntl/POSIX are obvious clients of this scheme.
Aliasing packages, is something that I haven't thought about before
sleep overcame.
Here's the result of one night's gallivanting with perl. I avidly welcome
your comments. (I hope this is one contribution to reducing "line noise",
and have true perl constants in the bargain).
- Sarathy.
gsar@engin.umich.edu
---------------------------------------8<-------------------------------------
package Alias;
=head1 NAME
Alias - declare aliases and constants
=head1 SYNOPSIS
use Alias qw(alias const);
alias TEN => $ten, Ten => \$ten, Ten => \&ten,
Ten => \@ten, Ten => \%ten, TeN => \*ten;
const pi => 3.14, ten => 10;
=head1 DESCRIPTION
Given a list of alias-symbol => value pairs, declares global aliases
in the caller's namespace. If the value supplied is a reference, the
alias is created for the underlying value instead of the reference
itself (since no one will use this package to alias references--they
are automatically "aliased" on assignment). This allows the user to
alias all of Perl's basic types.
If the value supplied is a compile-time constant, the aliases become
read-only. Any attempt to write to them will fail with a run time
error. A function-alias C<const> is aliased by this package (on demand)
for C<alias>, since this reads better for constant declarations.
=head1 EXAMPLE
use Alias qw(alias const);
$ten = 10;
alias TEN => $ten, Ten => \$ten, Ten => \&ten,
Ten => \@ten, Ten => \%ten;
alias TeN => \*ten; # same as *TeN = *ten
const _TEN_ => 10;
$ten = 20;
print "$TEN, $Ten, $ten\n";
sub ten { print "10\n"; }
@ten = (1..10);
%ten = (a..j);
&Ten;
print @Ten, %Ten;
$_TEN_ = 20;
=head1 NOTES
It is worth repeating that the aliases will be created in the
caller's namespace.
Aliases cannot be lexical, since, by necessity, they live on the
symbol table. They can be localized by first C<local>izing the
typeglob of the same name first, within the same block. However, this
will localize all the base types of the same name, and you will have
to deal with the consequences of that.
Remember that aliases are very much like references, only you
don't have to de-reference them as often.
It is possible to alias packages, but that might be construed as
abuse.
Using this package will lead to a much reduced urge to use typeglobs.
=head1 AUTHOR
Gurusamy Sarathy gsar@umich.edu
=cut
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(alias);
@EXPORT_OK = qw(const);
sub alias {
my($i) = scalar(@_) - 1 ;
my($j) = $i-1;
die "Need even number of args" if $j % 2;
my($pkg) = caller; # for namespace soundness
while ($j >= 0) {
if ('GLOB' eq ref $_[$i]) { eval "*$pkg\:\:$_[$j] = \${\$_[$i]}" }
elsif (ref $_[$i]) { eval "*$pkg\:\:$_[$j] = \$_[$i]" }
else { eval "*$pkg\:\:$_[$j] = \\\$_[$i]" }
$i--; $j--;
}
}
alias const => \&alias; # alias the alias :-)
1;