From bdc020126a6b59f3a7b866ba72f6ca22a52f8e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Wed, 5 May 2021 20:02:23 +0200 Subject: First commit --- Changes | 6 +++ MANIFEST | 6 +++ Makefile.PL | 13 +++++ README | 69 +++++++++++++++++++++++++ lib/List/Gather/Simple.pm | 129 ++++++++++++++++++++++++++++++++++++++++++++++ t/List-Gather-Simple.t | 27 ++++++++++ 6 files changed, 250 insertions(+) create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 Makefile.PL create mode 100644 README create mode 100644 lib/List/Gather/Simple.pm create mode 100644 t/List-Gather-Simple.t diff --git a/Changes b/Changes new file mode 100644 index 0000000..3fa9d72 --- /dev/null +++ b/Changes @@ -0,0 +1,6 @@ +Revision history for Perl extension List::Gather::Simple. + +0.01 Wed May 5 19:38:12 2021 + - original version; created by h2xs 1.23 with options + -AX --skip-exporter --use-new-tests -n List::Gather::Simple + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..e83b383 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,6 @@ +Changes +Makefile.PL +MANIFEST +README +t/List-Gather-Simple.t +lib/List/Gather/Simple.pm diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..ec081a9 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,13 @@ +use 5.006; +use ExtUtils::MakeMaker; +WriteMakefile( + NAME => 'List::Gather::Simple', + VERSION_FROM => 'lib/List/Gather/Simple.pm', + PREREQ_PM => {}, + ABSTRACT_FROM => 'lib/List/Gather/Simple.pm', + AUTHOR => 'John Ankarström ', + LICENSE => 'perl', + dist => { + PREOP => 'pod2text lib/List/Gather/Simple.pm > $(DISTVNAME)/README', + }, +); diff --git a/README b/README new file mode 100644 index 0000000..46cb38b --- /dev/null +++ b/README @@ -0,0 +1,69 @@ +NAME + List::Gather::Simple - Simple implementation of gather/take + +SYNOPSIS + use List::Gather::Simple; + print gather { + take for gather { + take 'Hello ', 'world!'; + }; + unshift @gathered, 'Test message: '; + }, "\n"; + # -> Test message: Hello world! + +DESCRIPTION + List::Gather::Simple is yet another Perl 5 implementation of the + "gather"/"take" construct in Perl 6/Raku. It differs from other + implementations in that it is, as the name suggests, very simple. + + "gather" and "take" are implemented as normal subroutines, operating on + a localized variable called @gathered. All three of these are imported + when List::Gather::Simple is "use"d. + + The benefit of exporting @gathered as a variable (rather than a + subroutine called "gathered") is that @gathered is very clearly a normal + Perl array, which can be used as an lvalue too, unlike the "gathered" + subroutine of other implementations. That means that the following is + valid: + + gather { @gathered = merge(@gathered, @x) while @x } + +DIAGNOSTICS + Warning: Useless use of 'gather' in void context + This warning is issued if "use warnings 'void'" is active and + "gather" is called in void context. + + Note that the warning will be associated with the line on which + "gather" is called. This can lead to the following unintuitive + behavior: If you return the results of "gather" from a subroutine + and then call that subroutine in void context, the warning will + still be issued, but it will refer to the line of the "gather" call + inside the subroutine. + + Exception: Call to 'take' outside of 'gather' + This exception is raised if "take" is called outside of a "gather" + block. + + Note that this is a runtime error. + +SEE ALSO + All of the following modules have inspired List::Gather::Simple: + + * List::Gather + + * Perl6::Gather + + * Perl6::Take + + * Syntax::Keyword::Gather + +AUTHOR + John Ankarström, (remove +spam) + +COPYRIGHT AND LICENSE + Copyright (C) 2021 by John Ankarström + + This library is free software; you can redistribute it and/or modify it + under the same terms as Perl itself, either Perl version 5.32.1 or, at + your option, any later version of Perl 5 you may have available. + diff --git a/lib/List/Gather/Simple.pm b/lib/List/Gather/Simple.pm new file mode 100644 index 0000000..bf14952 --- /dev/null +++ b/lib/List/Gather/Simple.pm @@ -0,0 +1,129 @@ +package List::Gather::Simple; + +use 5.006; + +use warnings; +use strict; +no strict 'refs'; + +use Carp; +use Exporter qw/import/; + +our $VERSION = '0.01'; +our @EXPORT = qw/gather take @gathered/; +our $gathering; + +sub gather (&) { + my ($code, $pkg) = (shift, caller); + local @{"${pkg}::gathered"}; + local $gathering = 1; + &$code; + warnings::warnif 'void', "Useless use of 'gather' in void context" + if not defined wantarray; + return @{"${pkg}::gathered"}; +} + +sub take (@) { + croak "Call to 'take' outside of 'gather'" if not $gathering; + @_ = $_ if not @_; + my $pkg = caller; + push @{"${pkg}::gathered"}, @_; + return @_; +} + +1; +__END__ +=encoding utf8 + +=head1 NAME + +List::Gather::Simple - Simple implementation of gather/take + +=head1 SYNOPSIS + + use List::Gather::Simple; + print gather { + take for gather { + take 'Hello ', 'world!'; + }; + unshift @gathered, 'Test message: '; + }, "\n"; + # -> Test message: Hello world! + +=head1 DESCRIPTION + +List::Gather::Simple is yet another Perl 5 implementation of the +C/C construct in Perl 6/Raku. It differs from other +implementations in that it is, as the name suggests, very simple. + +C and C are implemented as normal subroutines, operating +on a localized variable called C<@gathered>. All three of these +are imported when List::Gather::Simple is Cd. + +The benefit of exporting C<@gathered> as a variable (rather than a +subroutine called C) is that C<@gathered> is very clearly +a normal Perl array, which can be used as an lvalue too, unlike the +C subroutine of other implementations. That means that +the following is valid: + + gather { @gathered = merge(@gathered, @x) while @x } + +=head1 DIAGNOSTICS + +=over + +=item Warning: Useless use of 'gather' in void context + +This warning is issued if C is active and +C is called in void context. + +Note that the warning will be associated with the line on which +C is called. This can lead to the following unintuitive +behavior: If you return the results of C from a subroutine +and then call that subroutine in void context, the warning will +still be issued, but it will refer to the line of the C +call inside the subroutine. + +=item Exception: Call to 'take' outside of 'gather' + +This exception is raised if C is called outside of a C +block. + +Note that this is a runtime error. + +=back + +=head1 SEE ALSO + +All of the following modules have inspired List::Gather::Simple: + +=over + +=item * +L + +=item * +L + +=item * +L + +=item * +L + +=back + +=head1 AUTHOR + +John Ankarström, Ejohn+spam@ankarstrom.seE (remove +spam) + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2021 by John Ankarström + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.32.1 +or, at your option, any later version of Perl 5 you may have +available. + +=cut diff --git a/t/List-Gather-Simple.t b/t/List-Gather-Simple.t new file mode 100644 index 0000000..5ed72d6 --- /dev/null +++ b/t/List-Gather-Simple.t @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More; +BEGIN { use_ok('List::Gather::Simple') }; + +is_deeply [gather { take 1; take 2 }], [1,2], "double take"; +is_deeply [gather { take for (1,2) }], [1,2], "take implicit argument"; +is_deeply [gather { take for gather { take 1 } }], [1], "nested gather"; +is_deeply [gather { + @gathered = (1); + take 2; + push @gathered, 3; +}], [1,2,3], "@gathered"; +is_deeply [gather { + @gathered = (1); + take gather { + @gathered = (0); + }; + take 2; + push @gathered, 3; +}], [1,0,2,3], "nested @gathered"; +is_deeply [gather { take 1 }, @gathered], [1], "localized @gathered"; + +done_testing; -- cgit v1.2.3