Acme-constant-0.1.3000755001750000144 012221545552 14343 5ustar00glitchmrusers000000000000README100644001750000144 35212221545552 15264 0ustar00glitchmrusers000000000000Acme-constant-0.1.3 This archive contains the distribution Acme-constant, version 0.1.3: Like constant, except actually not. This software is Copyright (c) 2013 by Konrad Borowski. This is free software, licensed under: The MIT (X11) License LICENSE100644001750000144 221212221545552 15426 0ustar00glitchmrusers000000000000Acme-constant-0.1.3This software is Copyright (c) 2013 by Konrad Borowski. This is free software, licensed under: The MIT (X11) License The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CHANGES100644001750000144 440012221545552 15415 0ustar00glitchmrusers000000000000Acme-constant-0.1.3================================================== Changes from 2012-09-28 00:00:00 +0000 to present. ================================================== ------------------------------------------ version 0.1.3 at 2013-09-28 12:28:26 +0000 ------------------------------------------ Change: fd789bce43df3bade8f01da74e30f015be536128 Author: Konrad Borowski Date : 2013-09-28 14:28:21 +0000 Release Acme-constant 0.1.3. Change: 4cc72556880ae14eaaf622bcf00aa1c22f17475b Author: Konrad Borowski Date : 2013-09-28 14:26:44 +0000 Force Perl v5.14. Until I find out "Bizarre copy of ARRAY in aassign", don't support lower Perl versions. Change: 96ad1d77ddf6cfc5f3be53e08eb5b61adc49b339 Author: Konrad Borowski Date : 2013-09-22 08:37:44 +0000 Release Acme-constant 0.1.2. Change: 35e6edcbd8e45fa03d0b6e05ae93c77c424b690d Author: Konrad Borowski Date : 2013-09-22 08:37:25 +0000 Fix old Perl versions properly. Change: 0d546f48b16280c1abbcfc046f760d5a9c2f353c Author: Konrad Borowski Date : 2013-09-21 10:10:19 +0000 Release Acme-constant 0.1.1. Change: 4a9266d9edc838e7337fae90828514978df91dbb Author: Konrad Borowski Date : 2013-09-21 10:09:45 +0000 Change error messages to be in Perl-style, and add diagnostics. Change: 0eb944c3f28b22ed4a1686e563df41e6cb4772fa Author: Konrad Borowski Date : 2013-09-21 09:41:41 +0000 Support OLD Perl versions by returning value after croak. Perl isn't clever enough to notice croak throws exception and thinks it has to return a value. Now fake value is returned as lvalue - the only way to access it however is modifying `Carp::croak` to not throw an exception - however, it's not supported. Change: a7e6cc7c742b3e713ea8258304e8c0e9f3ddd3ca Author: Konrad Borowski Date : 2013-09-21 09:26:43 +0000 Make interpolation work in Perls below 5.18. Change: 1a10863ec5c706a1c58a9b03c892a19599cd4b25 Author: Konrad Borowski Date : 2013-09-15 15:45:39 +0000 Acme::constant 0.1.0 ================ End of releases. ================ dist.ini100644001750000144 42212221545552 16046 0ustar00glitchmrusers000000000000Acme-constant-0.1.3name = Acme-constant author = Konrad Borowski license = MIT copyright_holder = Konrad Borowski copyright_year = 2013 version = 0.1.3 [@Git] [@Basic] [AutoPrereqs] [PkgVersion] [ExtraTests] [PodCoverageTests] [PodSyntaxTests] [ChangelogFromGit] META.yml100644001750000144 76112221545552 15661 0ustar00glitchmrusers000000000000Acme-constant-0.1.3--- abstract: 'Like constant, except actually not.' author: - 'Konrad Borowski ' build_requires: Test::More: 0 utf8: 0 configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 4.300038, CPAN::Meta::Converter version 2.120921' license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Acme-constant requires: Carp: 0 perl: 5.014 strict: 0 strictures: 1 version: 0.1.3 MANIFEST100644001750000144 21512221545552 15533 0ustar00glitchmrusers000000000000Acme-constant-0.1.3CHANGES LICENSE MANIFEST META.yml Makefile.PL README dist.ini lib/Acme/constant.pm t/release-pod-coverage.t t/release-pod-syntax.t t/tests.t t000755001750000144 012221545552 14527 5ustar00glitchmrusers000000000000Acme-constant-0.1.3tests.t100644001750000144 331712221545552 16222 0ustar00glitchmrusers000000000000Acme-constant-0.1.3/tuse strictures 1; use Test::More tests => 27; use utf8; BEGIN { require_ok 'Acme::constant'; use_ok 'Acme::constant', A => 'B'; use_ok 'Acme::constant', B => 1, 2, 3; use_ok 'if', 1, 'Acme::constant', C => 8; use_ok 'if', 0, 'Acme::constant', D => 16; # π needs to be quoted in order to not confuse PPI. use_ok 'Acme::constant', "π", 4 * atan2 1, 1; use_ok 'Acme::constant', "\0" => "NULL"; use_ok 'Acme::constant', STRUCTURE => [1, {2 => 3}] } is A, 'B', 'Scalar is properly declared'; is_deeply [B], [1, 2, 3], 'Array is properly declared'; is((B)[0], 1, 'Can access single element in declared array'); A = 42; is A, 42, 'Scalar is properly redeclared'; (B) = (4, 5, 6); is_deeply [B], [4, 5, 6], 'Array is properly redeclared'; is((B)[2], 6, 'Can access single element in redeclared array'); ok defined &C, 'C is defined'; is C, 8, 'Constant can be declared dynamically'; ok !defined &D, 'D is not defined'; (A) = (1, 2); is_deeply [A], [1, 2], 'Can change scalar into array'; (A) = 3; is_deeply A, 3, 'Can change array into scalar'; is substr("π"->(), 0, 7), '3.14159', 'Can use funny names for constants'; is "\0"->(), 'NULL', 'Can use non-word names for constants'; "\0"->() = 20; is "\0"->(), 20, 'Can assign to non-word names'; is_deeply STRUCTURE, [1, {2 => 3}], 'Can put complex structures as references'; STRUCTURE->[0] = 4; is_deeply STRUCTURE, [4, {2 => 3}], 'Can modify array references'; STRUCTURE->[1]{2} = 7; is_deeply STRUCTURE, [4, {2 => 7}], 'Can modify hash references'; push @{(STRUCTURE)}, 'hello'; is_deeply STRUCTURE, [4, {2 => 7}, 'hello'], 'Can push to arrays'; $#{(STRUCTURE)} = 0; is_deeply STRUCTURE, [4], 'Can change length of array reference in structure'; Makefile.PL100644001750000144 266112221545552 16403 0ustar00glitchmrusers000000000000Acme-constant-0.1.3 use strict; use warnings; use 5.014; use ExtUtils::MakeMaker 6.30; my %WriteMakefileArgs = ( "ABSTRACT" => "Like constant, except actually not.", "AUTHOR" => "Konrad Borowski ", "BUILD_REQUIRES" => {}, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "6.30" }, "DISTNAME" => "Acme-constant", "EXE_FILES" => [], "LICENSE" => "mit", "NAME" => "Acme::constant", "PREREQ_PM" => { "Carp" => 0, "strict" => 0, "strictures" => 1 }, "TEST_REQUIRES" => { "Test::More" => 0, "utf8" => 0 }, "VERSION" => "0.1.3", "test" => { "TESTS" => "t/*.t" } ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { my $tr = delete $WriteMakefileArgs{TEST_REQUIRES}; my $br = $WriteMakefileArgs{BUILD_REQUIRES}; for my $mod ( keys %$tr ) { if ( exists $br->{$mod} ) { $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod}; } else { $br->{$mod} = $tr->{$mod}; } } } unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) { my $br = delete $WriteMakefileArgs{BUILD_REQUIRES}; my $pp = $WriteMakefileArgs{PREREQ_PM}; for my $mod ( keys %$br ) { if ( exists $pp->{$mod} ) { $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod}; } else { $pp->{$mod} = $br->{$mod}; } } } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Acme000755001750000144 012221545552 15677 5ustar00glitchmrusers000000000000Acme-constant-0.1.3/libconstant.pm100644001750000144 2514112221545552 20251 0ustar00glitchmrusers000000000000Acme-constant-0.1.3/lib/Acmepackage Acme::constant; { $Acme::constant::VERSION = '0.1.3'; } use 5.014; use strictures 1; use Carp (); sub generate_constant { my ($package, $name, @values) = @_; # Prototype is used to make it work like a constant (constants # shouldn't take arguments). While anonymous subroutines don't use # prototypes, the prototype gets meaning when this subroutine is # assigned to type glob. my $constant = sub () : lvalue { # When constant used as array, it's very simple to understand # user wants an array. The !defined wantarray check is intended # to detect use of wantarray() in void context. if (wantarray || !defined wantarray) { @values; } # When constant has one element, writing to it in scalar # context is fine. elsif (@values == 1) { $values[0]; } # This shows an error, as otherwise, this could cause a strange # situation where scalar A shows (A)[0], when A has one # element, and 2 when A has two elements. The behavior of Array # constructor in ECMAScript is already confusing enough (new # Array(3) is [,,,], but new Array(3, 3) is [3, 3]). else { Carp::croak "Can't call ${package}::$name in scalar context"; # Return lvalue in order to make older versions of Perl # happy, even when it's not going to be used. @values; } }; # Make a block, to make a scope for strict "refs". { # Because of symbol table modifications, I have to allow # symbolic references. no strict qw(refs); *{"${package}::$name"} = $constant; } } sub import { my $package = caller; # The first argument is this package name my $name = shift; # Without arguments, simply fail. if (@_ == 0) { Carp::carp qq[Useless use of "$name" pragma]; } # When called with one argument, this argument would be hash # reference. elsif (@_ == 1) { my %hash = %{shift()}; # each is safe here, as %hash is lexical variable. while (my ($name, $value) = each %hash) { generate_constant $package, $name, $value; } } # Otherwise, assume one constant, that possibly could return a list # of values. else { my $name = shift; generate_constant $package, $name, @_; } return; } # Return positive value to make Perl happy. 'Acme!'; __END__ =head1 NAME Acme::constant - Like constant, except actually not. =head1 SYNOPSIS use Acme::constant ACME => 42; print "ACME is now ", ACME, ".\n"; ACME = 84; print "But now, ACME is ", ACME, "\n"; use Acme::constant LIST => 1, 2, 3; print "Second element of list is ", (LIST)[1], ".\n"; (LIST) = (4, 5, 6); print "But now, the second element is ", (LIST)[1], "\n"; =head1 DESCRIPTION This pragma lets you make inconstant constants, just like the constants the users of Ruby or Opera (before Opera 14, that is) already enjoyed. Unlike Perl constants, that are replaced at compile time, Acme constants, in true dynamic programming language style, can be modified even after declaration. Just like constants generated with standard C pragma, the constants declared with C don't have any sigils. This makes using constants easier, as you don't have to remember what sigil do constants use. =head1 NOTES As the Perl compiler needs to know about which barewords are keywords, constants have to defined in C section. Usually, this is not a problem, as C statement is automatically put in implicit C section, but that also means you cannot dynamically create constants. For example, in the example below, the C constant is always created, with value 1, as C is processed when Perl parser sees it. if ($ENV{DEBUG}) { use Acme::constant DEBUG => 1; # WRONG! } It's possible to dynamically use this module using L module, however, this is likely to cause problems when trying to use constant that doesn't exist. use if $ENV{DEBUG}, Acme::constant => DEBUG => 1; You can also use directly use C method, in order to conditionally load constant. BEGIN { require Acme::constant; Acme::constant->import(DEBUG => 1) if $ENV{DEBUG}; } Howver, usually the good idea to declare constant anyway, as using undefined constants in strict mode causes Perl errors (and sometimes could be parsed incorrectly). use Acme::constant DEBUG => $ENV{DEBUG}; Constants belong to the package they were defined in. When you declare constant in some module, the constant is subroutine declared in it. However, it's possible to export constants with module such as L, just as you would export standard subroutine. package Some::Package; use Acme::constant MAGIC => "Hello, world!\n"; package Some::Other::Package; print Some::Package::MAGIC; # MAGIC directly won't work. =head2 List constants Just like standard L module, you can use lists with this module. However, there are few catches you should be aware of. To begin with, you cannot use list constants in scalar context. While L module lets you do this, I believe allowing something like this can open can of worms, because constant with one element is just as valid constant (that wouldn't return 1). Something like this won't work. use Acme::constant NUMBERS => 1..6; print 'Found ', scalar NUMBERS, " numbers in NUMBERS.\n"; # WRONG! Instead, to count number of elements in the constant, you can use the C<() => trick, that lets you count elements in any sort of list. use Acme::constant NUMBERS => 1..6; print 'Found ', scalar(() = NUMBERS), " numbers in NUMBERS.\n"; Also, as C statement arguments are always parsed in the list context, sometimes you could be surprised with argument being executed in list context, instead of scalar context. use Acme::constant TIMESTAMP => localtime; # WRONG! Usually, when this happens, it's possible to use C operator in order to force interpretation of code in scalar context. use Acme::constant TIMESTAMP => scalar localtime; Constants return lists, not arrays (you don't use C<@> syntax, do you?), so in order to get single element, you will need to put a constant in parenthesis. use Acme::constant NUMBERS => 1..6; print join(" ", (NUMBERS)[2..4]), "\n"; =head2 Assignments The assignments are done using standard C<=> operator. use Acme::constant SOMETHING => 1; SOMETHING = 2; print "Something is ", SOMETHING, ".\n"; use Acme::constant ARRAY => 1, 2, 3; my $four = 7; ($four, ARRAY) = (4, 5, 6); print "Something is ", join(", ", ARRAY), ", and four is $four.\n"; There are also catches about assignments. Perl normally runs the part after C<=> operator in scalar context, unless leftside argument is a list or array. As inconstant constant is neither a list or array, the argument on right side is ran in scalar context. For example, following code will only save 2, as comma operator is ran in scalar context. use Acme::constant SOMETHING => 0; SOMETHING = (1, 2); # WRONG! print "Something is ", join(", ", SOMETHING), ".\n"; In order to force list interpretation, you need to put constant in the parenthesis. use Acme::constant SOMETHING => 0; (SOMETHING) = (1, 2); print "Something is ", join(", ", SOMETHING), ".\n"; Similarly, you cannot modify list constant in scalar context, as Perl expects you put a list, not a single value. use Acme::constant SOMETHING => (1, 2); SOMETHING = 3; # WRONG! print "Something is ", SOMETHING, ".\n"; To fix that, you need to put constant in parenthesis. This is only needed when constant has different number of elements than one, so after such assignment, you can use normal assignment, without parenthesis. use Acme::constant SOMETHING => (1, 2); (SOMETHING) = 3; print "Something is ", SOMETHING, ".\n"; SOMETHING = 4; print "Something is now ", SOMETHING, ".\n"; Also, the localization of Acme constants is broken, and while it will change the value, it won't change value back after leaving the block. This is related to that you cannot localize lexicals and references in Perl 5. use Acme::constant PI => 4 * atan2 1, 1; { local PI = 3; print "PI = ", PI, "\n"; } print "PI = ", PI, "\n"; =head1 CAVEATS Other than caveats mentioned here, general caveats about constants also exist. Unlike standard L module, constants with names like C can be used outside C package, because of different method of generating constants. The constants can be problematic to use in context that automatically stringifies the barewords. For example, the following code is wrong. use Acme::constant KEY => "acme"; my %hash; $hash{KEY} = 42; # Works like $hash{"KEY"} = 42; Instead, you should use following code. use Acme::constant KEY => "acme"; my %hash; $hash{(KEY)} = 42; =head1 DIAGNOSTICS =over 4 =item Can't call %s in scalar context (F) You tried to call constant containing constant containing different numbers than one in scalar context. As it's hard to determine what you mean, you have to disambiguate your call. If you want to get count of elements, you may want to assign it to C<()>, like C<() = CONSTANT>. If you want to get last element, use C<(CONSTANT)[-1]>. =item Can't modify non-lvalue subroutine call (F) You tried to assign single value to constant containing an array. This won't work, as Perl expects a list to be assigned. If you really want to assign an single element, use C<(CONSTANT) = $value> syntax. This error is provided by Perl, and as such, it could be confusing, as constant actually is lvalue, just assigned in wrong context. =item Useless localization of subroutine entry (W syntax) You tried to localize constant with C operator. This is legal, but currently has no effect. This may change in some future version of Perl, but in the meantime such code is discouraged. =item Useless use of "Acme::constant" pragma (W) You did C without any arguments. This isn't very useful. If this is what you mean, write C instead. =back =head1 SEE ALSO L - Builtin constant module. L - Constant scalars, arrays, and hashes. =head1 BUGS Please L to report bugs. =head1 SOURCE The source code for Acme::constant is available can be found L. =head1 COPYRIGHT Copyright 2013 by Konrad Borowski . release-pod-syntax.t100644001750000144 45012221545552 20557 0ustar00glitchmrusers000000000000Acme-constant-0.1.3/t#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use Test::More; eval "use Test::Pod 1.41"; plan skip_all => "Test::Pod 1.41 required for testing POD" if $@; all_pod_files_ok(); release-pod-coverage.t100644001750000144 76512221545552 21035 0ustar00glitchmrusers000000000000Acme-constant-0.1.3/t#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use Test::More; eval "use Test::Pod::Coverage 1.08"; plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage" if $@; eval "use Pod::Coverage::TrustPod"; plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage" if $@; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });