aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes6
-rw-r--r--MANIFEST6
-rw-r--r--Makefile.PL13
-rw-r--r--README69
-rw-r--r--lib/List/Gather/Simple.pm129
-rw-r--r--t/List-Gather-Simple.t27
6 files changed, 250 insertions, 0 deletions
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 <john@ankarstrom.se>',
+ 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, <john+spam@ankarstrom.se> (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<gather>/C<take> construct in Perl 6/Raku. It differs from other
+implementations in that it is, as the name suggests, very simple.
+
+C<gather> and C<take> are implemented as normal subroutines, operating
+on a localized variable called C<@gathered>. All three of these
+are imported when List::Gather::Simple is C<use>d.
+
+The benefit of exporting C<@gathered> as a variable (rather than a
+subroutine called C<gathered>) is that C<@gathered> is very clearly
+a normal Perl array, which can be used as an lvalue too, unlike the
+C<gathered> 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<use warnings 'void'> is active and
+C<gather> is called in void context.
+
+Note that the warning will be associated with the line on which
+C<gather> is called. This can lead to the following unintuitive
+behavior: If you return the results of C<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 C<gather>
+call inside the subroutine.
+
+=item Exception: Call to 'take' outside of 'gather'
+
+This exception is raised if C<take> is called outside of a C<gather>
+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<List::Gather>
+
+=item *
+L<Perl6::Gather>
+
+=item *
+L<Perl6::Take>
+
+=item *
+L<Syntax::Keyword::Gather>
+
+=back
+
+=head1 AUTHOR
+
+John Ankarström, E<lt>john+spam@ankarstrom.seE<gt> (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;