--- /dev/null
+use 5.014000;
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ NAME => 'Data::SExpression::Util',
+ VERSION_FROM => 'lib/Data/SExpression/Util.pm',
+ ABSTRACT_FROM => 'lib/Data/SExpression/Util.pm',
+ AUTHOR => 'Marius Gavrilescu <marius@ieval.ro>',
+ MIN_PERL_VERSION => '5.14.0',
+ LICENSE => 'perl',
+ SIGN => 1,
+ PREREQ_PM => {
+ qw/Data::SExpression 0.41/,
+ },
+ TEST_REQUIRES => {
+ qw/Data::Dump::Sexp 0/,
+ },
+ META_ADD => {
+ dynamic_config => 0,
+ resources => {
+ repository => 'https://git.ieval.ro/?p=data-sexpression-util.git',
+ },
+ }
+);
--- /dev/null
+Data-SExpression-Util version 0.000_001
+=======================================
+
+Data::SExpression::Util contains several routines for processing
+linked lists (represented Data::SExpression::Cons objects). These are
+analogous to Lisp functions with the same names.
+
+INSTALLATION
+
+To install this module type the following:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+DEPENDENCIES
+
+This module requires these other modules and libraries:
+
+* Data::SExpression
+
+COPYRIGHT AND LICENCE
+
+Copyright (C) 2018 by Marius Gavrilescu
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.24.1 or,
+at your option, any later version of Perl 5 you may have available.
+
+
--- /dev/null
+package Data::SExpression::Util;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+
+our %EXPORT_TAGS = ( 'all' => [
+ qw/cons
+ append
+ mapcar
+ rev
+ position
+ /]);
+
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+
+our $VERSION = '0.000_001';
+
+use Data::SExpression::Cons;
+
+sub cons {
+ my ($car, $cdr) = @_;
+ Data::SExpression::Cons->new($car, $cdr);
+}
+
+sub append {
+ my ($expr, $rest) = @_;
+ if (defined $expr) {
+ cons $expr->car, append($expr->cdr, $rest)
+ } else {
+ $rest
+ }
+}
+
+sub mapcar (&@);
+
+sub mapcar (&@) {
+ my ($block, $expr) = @_;
+ if (defined $expr) {
+ my $result;
+ do {
+ local $_ = $expr->car;
+ $result = $block->()
+ };
+ cons $result, mapcar { $block->($_) } $expr->cdr
+ } else {
+ undef
+ }
+}
+
+sub revacc {
+ my ($expr, $acc) = @_;
+ if (defined $expr) {
+ revacc ($expr->cdr, cons($expr->car, $acc))
+ } else {
+ $acc
+ }
+}
+
+sub rev {
+ my ($expr) = @_;
+ revacc $expr, undef;
+}
+
+sub positionacc {
+ my ($expr, $list, $acc) = @_;
+ if (!defined $list) {
+ undef
+ } elsif ($list->car eq $expr) {
+ $acc
+ } else {
+ positionacc($expr, $list->cdr, $acc + 1)
+ }
+}
+
+sub position {
+ my ($expr, $list) = @_;
+ positionacc $expr, $list, 0
+}
+
+1;
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+Data::SExpression::Util - routines for processing linked lists
+
+=head1 SYNOPSIS
+
+ use Data::SExpression::Util qw/:all/;
+ my $list = cons 1, cons 2, cons 3, undef; # (1 2 3)
+ my $other_list = cons 4, cons 5, undef; # (4 5)
+
+ $list = append $list, $other_list; # $list is now (1 2 3 4 5)
+
+ say position 1, $list; # 0
+ say position 4, $list; # 3
+ say 'undef' unless defined position 0, $list; # undef
+
+ $list = rev $list; # (5 4 3 2 1)
+ $list = mapcar { $_ + 1 } $list; # (6 5 4 3 2)
+
+ say position 2, $list; # 4
+
+=head1 DESCRIPTION
+
+Data::SExpression::Util contains several routines for processing
+linked lists (represented L<Data::SExpression::Cons> objects). These
+are analogous to Lisp functions with the same names.
+
+Right now very few functions are implemented, more will come in the
+next version.
+
+The list of functions is:
+
+=over
+
+=item B<append>(I<$list>, I<$other_list>)
+
+Appends the list I<$other_list> at the end of the list I<$list>.
+
+=item B<mapcar> { I<block> } I<$list>
+
+Analogous to Perl's map function. Runs I<block> with each element of
+the list I<$list> as $_, and then returns a containing all of the
+result.
+
+=item B<rev>(I<$list>)
+
+Reverses a list
+
+=item B<position>(I<$elt>, I<$list>)
+
+Searches for I<$elt> in I<$list> and returns the first matching
+element (comparison is done via eq).
+
+=back
+
+=head1 AUTHOR
+
+Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2018 by Marius Gavrilescu
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.24.1 or,
+at your option, any later version of Perl 5 you may have available.
+
+
+=cut
--- /dev/null
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 6;
+use Data::Dump::Sexp qw/dump_sexp/;
+BEGIN { use_ok('Data::SExpression::Util', ':all') };
+
+my $list = cons 1, cons 2, cons 3, undef; # (1 2 3)
+my $other_list = cons 4, cons 5, undef; # (4 5)
+
+$list = append $list, $other_list; # $list is now (1 2 3 4 5)
+
+is position(1, $list), 0;
+is position(4, $list), 3;
+ok !defined(position 0, $list);
+
+$list = rev $list;
+is dump_sexp($list), '(5 4 3 2 1)';
+
+$list = mapcar { $_ + 1 } $list; # (6 5 4 3 2)
+is dump_sexp($list), '(6 5 4 3 2)';