=for advent_year 2010

=for advent_day 02

=for advent_title Setting the bar high with an array of unique gifts

=for advent_author Adam Russell   

Not every elf studies the theory and craft of toymaking at elf college.
Some elves study more abstract but less employable subjects and come
to toy making after making the sad realization that very few people care to,
say, discuss that shiny new Rubik's Cube that Santa dropped off in terms of
Galois Theory.N<note0> Of course, there are some happy intersections between
the abstract and the practical. M<Set::Array> is an example of one such useful
application of the abstract&mdash;Set Theory&mdash;towards cleaner and more
maintainable code. M<Set::Array> essentially wraps arrays in a class that
defines higher level functions on the internal data. Of course you can still
do the basics. The code below shows some of the classic array functions anyone
would expect. 

Running this:

=begin code

my $sa0=Set::Array->new(qw/b a yams tartes/);
$sa0->pop(); #methods that that throw pies aren't chainable
$sa0->unshift('cider')->delete('yams')->reverse();

=end code

Results in a C<$sa0> M<Set::Array> object with elements <code>(a, b, cider)</code>

But such functionality is simply the new pair of underwear under the tree when
what you really want is a train set! Let us direct our attention to the well
hidden and expertly wrapped gifts in the corner under the stairs.

M<Set::Array> comes with a variety of parent-approvedN<note1> Nerf weaponry
to attack our array-like objects with ammunition ranging from the canonical
C<union()> on line 36 for our sample script, to the sugary C<join()> on 38 and
esoteric C<bag()> on lines 35 and 53.

C<bag()> is a bit of a departure from "real" sets in that it does not exclude
duplicates. To ensure uniqueness to elements the module comes with a very
necessary C<unique()> function which is included presumably to, you know,
actually allow us to convincingly use the word "set". ho ho ho.

Given another array&hellip;

=begin code

my $sa1=Set::Array->new(0,1,'cider','eggnog');

=end code

&hellip;we can test some of the more set-like operations amongst the
thirty-odd methods available:

=begin code

print $sa0->difference($sa1)->join(', ');
#a, b

print $sa0->intersection($sa1)->join(', ');
#a, b, cider

print $sa0->symmetric_difference($sa1)->join(', ');
#1, a, 0, b, eggnog

=end code

In case you've forgotten your math, that last one returns the elements
that occur in either set but do not also occur in the intersection.

Finally, it should be mentioned that the proper set operations implemented by
M<Set::Array> also come with overloaded operator synonyms i.e;
C<+>, C<&>, C<->, C<*>, and C<%> They were left out of the examples since
overloaded operators bring back ghosts of C++ courses past.

=sourcedcode mod2.pl

=begin footnote note0

Hans Zassenhaus, Rubik's cube: A toy, a galois tool, group theory for everybody, Physica A: Statistical Mechanics and its Applications, Volume 114, Issues 1-3, August 1982, Pages 629-637, ISSN 0378-4371, DOI: A<http://www.sciencedirect.com/science/article/B6TVG-46J0R6R-5D/2/2a5c22348a33973c2dcad28f30d6ea41|10.1016/0378-4371(82)90362-4>

=end footnote

=begin footnote note1

The modification of the caller $sa0 is because of the void context.
If we had called the function in a list context&hellip;

=begin code

my @sack=$sa0->bag($sa1);

=end code

&hellip;then $sa0 is unmodified and the result of the operation is assigned
to @sack.

=end footnote

=cut