—package
Set::Scalar;
use
strict;
local
$^W = 1;
$VERSION
=
'1.13'
;
@ISA
=
qw(Set::Scalar::Real Set::Scalar::Null Set::Scalar::Base)
;
use
Set::Scalar::Real;
use
Set::Scalar::Null;
sub
ELEMENT_SEPARATOR {
" "
}
sub
SET_FORMAT {
"(%s)"
}
sub
_insert_hook {
my
$self
=
shift
;
if
(
@_
) {
my
$elements
=
shift
;
$self
->universe->_extend(
$elements
);
$self
->_insert_elements(
$elements
);
}
}
sub
_new_hook {
my
$self
=
shift
;
my
$elements
=
shift
;
$self
->{ universe } = Set::Scalar::Universe->universe;
$self
->_insert( { _make_elements(
@$elements
) } );
}
=pod
=head1 NAME
Set::Scalar - basic set operations
=head1 SYNOPSIS
use Set::Scalar;
$s = Set::Scalar->new;
$s->insert('a', 'b');
$s->delete('b');
$t = Set::Scalar->new('x', 'y', $z);
=head1 DESCRIPTION
=head2 Creating
$s = Set::Scalar->new;
$s = Set::Scalar->new(@members);
$t = $s->clone;
$t = $s->copy; # clone of clone
=head2 Modifying
$s->insert(@members);
$s->delete(@members);
$s->invert(@members); # insert if hasn't, delete if has
$s->clear; # removes all the elements
=head2 Displaying
print $s, "\n";
The display format of a set is the members of the set separated by
spaces and enclosed in parentheses ().
You can even display recursive sets.
=head2 Querying
@members = $s->members;
@elements = $s->elements; # alias for members
$size = $s->size; # the number of members
$s->has($m) # return true if has that member
$s->contains($m) # alias for has
if ($s->has($member)) { ... }
$s->member($m) # returns the member if has that member
$s->element($m) # alias for member
$s->is_null # returns true if the set is empty
$s->is_universal # returns true if the set is universal
$s->null # the null set
$s->universe # the universe of the set
=head2 Deriving
$u = $s->union($t);
$i = $s->intersection($t);
$d = $s->difference($t);
$e = $s->symmetric_difference($t);
$v = $s->unique($t);
$c = $s->complement;
These methods have operator overloads:
$u = $s + $t; # union
$i = $s * $t; # intersection
$d = $s - $t; # difference
$e = $s % $t; # symmetric_difference
$v = $s / $t; # unique
$c = -$s; # complement
Both the C<symmetric_difference> and C<unique> are symmetric on all
their arguments. For two sets they are identical but for more than
two sets beware: C<symmetric_difference> returns true for elements
that are in an odd number (1, 3, 5, ...) of sets, C<unique> returns
true for elements that are in one set.
Some examples of the various set differences:
set or difference value
$a (a b c d e)
$b (c d e f g)
$c (e f g h i)
$a->difference($b) (a b)
$a->symmetric_difference($b) (a b f g)
$a->unique($b) (a b f g)
$b->difference($a) (f g)
$b->symmetric_difference($a) (a b f g)
$b->unique($a) (a b f g)
$a->difference($b, $c) (a b)
$a->symmetric_difference($b, $c) (a b e h i)
$a->unique($b, $c) (a b h i)
=head2 Comparing
$eq = $s->is_equal($t);
$dj = $s->is_disjoint($t);
$pi = $s->is_properly_intersecting($t);
$ps = $s->is_proper_subset($t);
$pS = $s->is_proper_superset($t);
$is = $s->is_subset($t);
$iS = $s->is_superset($t);
$cmp = $s->compare($t);
The C<compare> method returns a string from the following list:
"equal", "disjoint", "proper subset", "proper superset", "proper
intersect", and in future (once I get around implementing it),
"disjoint universes".
These methods have operator overloads:
$eq = $s == $t; # is_equal
$dj = $s != $t; # is_disjoint
# No operator overload for is_properly_intersecting.
$ps = $s < $t; # is_proper_subset
$pS = $s > $t; # is_proper_superset
$is = $s <= $t; # is_subset
$iS = $s >= $t; # is_superset
$cmp = $s <=> $t;
=head2 Boolean contexts
In Boolean contexts such as
if ($set) { ... }
while ($set1 && $set2) { ... }
the size of the C<$set> is tested, so empty sets test as false,
and non-empty sets as true.
=head2 Iterating
while (defined(my $e = $s->each)) { ... }
This is more memory-friendly than
for my $e ($s->elements) { ... }
which would first construct the full list of elements and then
walk through it: the C<$s->each> handles one element at a time.
Analogously to using normal C<each(%hash)> in scalar context,
using C<$s->each> has the following caveats:
=over 4
=item *
The elements are returned in (apparently) random order.
So don't expect any particular order.
=item *
When no more elements remain C<undef> is returned. Since you may one
day have elements named C<"0"> don't test just like this
while (my $e = $s->each) { ... } # WRONG
but instead like this
while (defined(my $e = $s->each)) { ... } # right
=item *
There is one iterator per one set which is shared by many
element-accessing interfaces-- using the following will reset the
iterator: elements(), insert(), members(), size(), unique(). insert()
causes the iterator of the set being inserted (not the set being the
target of insertion) becoming reset. unique() causes the iterators of
all the participant sets becoming reset. B<The iterator getting reset
most probably causes an endless loop.> So avoid doing that.
=item *
Modifying the set during the iteration may cause elements to be missed
or duplicated, or in the worst case, an endless loop; so don't do
that, either.
=back
=head1 AUTHOR
Jarkko Hietaniemi <jhi@iki.fi>
=head1 COPYRIGHT AND LICENSE
Copyright 2001 by Jarkko Hietaniemi
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
1;