+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