Skip to content

Instantly share code, notes, and snippets.

@maddingue
Created January 18, 2013 21:42
Show Gist options
  • Save maddingue/4568886 to your computer and use it in GitHub Desktop.
Save maddingue/4568886 to your computer and use it in GitHub Desktop.
use strict;
use constant_tiny;
use constant pi => 4 * atan2(1, 1);
use constant ponies => qw<
Twilight_Sparkle Fluttershy Pinkie_Pie AppleJack Rainbow_Dash Rarity
>;
use constant {
host => "mail.whatever.com",
port => 25,
user => "maddingue",
pass => "s3Kret",
};
print "pi = ", pi, $/;
print "host = ", host, $/;
print "ponies: ", join(", ", ponies), $/;
package constant_tiny;
$INC{"constant.pm"} = $INC{+__FILE__};
package constant;
use strict;
require 5.010;
my %forbidden = map +($_, 1), qw<
BEGIN INIT CHECK END DESTROY AUTOLOAD UNITCHECK
STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG
>;
my $normal_constant_name = qr/^_?[^\W_0-9]\w*\z/;
sub import {
my $class = shift;
return unless @_; # ignore "use constant;"
if (not defined $_[0]) {
require Carp;
Carp::croak("Can't use undef as constant name");
}
my $multiple = ref $_[0];
if ($multiple and $multiple ne "HASH") {
require Carp;
Carp::croak("Invalid reference type '$multiple'");
}
my $constants = $multiple ? shift : { shift() => undef };
my $flush_mro;
my $pkg = caller();
my $symtab;
{ no strict 'refs'; $symtab = \%{$pkg . '::'} }
foreach my $name (keys %$constants) {
if ($name !~ $normal_constant_name or $forbidden{$name}) {
require Carp;
Carp::croak("Invalid name '$name'");
}
no strict 'refs';
my $full_name = "${pkg}::$name";
if ($multiple || @_ == 1) {
my $scalar = $multiple ? $constants->{$name} : $_[0];
if ($symtab && !exists $symtab->{$name}) {
Internals::SvREADONLY($scalar, 1);
$symtab->{$name} = \$scalar;
++$flush_mro;
} else {
*$full_name = sub () { $scalar };
}
} elsif (@_) {
my @list = @_;
*$full_name = sub () { @list };
} else {
*$full_name = sub () { };
}
}
mro::method_changed_in($pkg) if $flush_mro;
}
__PACKAGE__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment