NAME
Set::Relation - Relation data type for Perl
VERSION
This document describes Set::Relation version 0.0.2 for Perl 5.
SYNOPSIS
use Set::Relation;
my $r1 = Set::Relation->new( members => [ [ 'x', 'y' ], [
[ 4, 7 ],
[ 3, 2 ],
] ] );
my $r2 = Set::Relation->new( members => [
{ 'y' => 5, 'z' => 6 },
{ 'y' => 2, 'z' => 1 },
{ 'y' => 2, 'z' => 4 },
] );
my $r3 = $r1->join( $r2 );
my $r3_as_nfmt_perl = $r3->members();
my $r3_as_ofmt_perl = $r3->members( 1 );
# Then $r3_as_nfmt_perl contains:
# [
# { 'x' => 3, 'y' => 2, 'z' => 1 },
# { 'x' => 3, 'y' => 2, 'z' => 4 },
# ]
# And $r3_as_ofmt_perl contains:
# [ [ 'x', 'y', 'z' ], [
# [ 3, 2, 1 ],
# [ 3, 2, 4 ],
# ] ]
This documentation is pending.
DESCRIPTION
Set::Relation provides a simple Perl-native facility for an application to organize and process information using the relational model of data, without having to employ a separate DBMS, and without having to employ a whole separate sub-language (such as Muldis Rosetta does). Rather, it is integrated a lot more into the Perl way of doing things, and you use it much like a Perl array or hash, or like some other third-party Set:: modules available for Perl. This is a standalone Perl 5 object class that represents a Muldis D quasi-relation value, and its methods implement all the Muldis D relational operators.
WARNING: This module is still experimental and may change in incompatible ways between releases. It is also under construction and about a third of the planned short term features are yet missing. However, those features that are present have complete code and documentation. While the existing features should be fully useable now and a review of their code makes them look correct, most features have in fact not yet been tested in running code and so might actually be broken. This module might in fact work for you now, but it is officially pre-alpha quality. Please treat it mainly as a developer preview, to experiment possible future use.
If you want to help out with this module's development, generally the most helpful thing you can do to start out is to flesh out the test suite. I suggest looking at the test suites of other Set:: modules as well as various database related modules as inspiration or a source for copying.
Loosely speaking, a Set::Relation object is a wrapper over a set of hash refs, where all the hash refs in the set have the same number of elements and the same set of hash keys; so in this context, a Perl hash ref and a Set::Relation object correspond to the relational model concepts of a tuple and a relation, respectively. A relation is analogous to a SQL row-set but that the columns and rows are not ordered, and there are no duplicate column names or duplicate rows. Set::Relation provides all the normal operators of other Set:: classes, such as 'is_subset', 'union', 'difference' etc, but it also provides operators like 'join', 'quotient', 'projection', 'group', 'summary', 'semijoin', 'restriction', 'semidifference', 'transitive_closure', 'outer_join' etc.
Note, you can model a whole relational database by having a hash ref whose keys are akin to SQL table names and whose values are Set::Relation objects.
The name Set::Relation was chosen because it seems the most descriptive. A 'relation' is a value, same as an integer or an array is a value, and a relation can do everything a generic set can do plus more. The Set:: namespace is used to reduce confusion amongst other concepts of the word 'relation', as some people think it means 'compare'; Set:: illustrates that this class' objects are functionally set-like collection values.
This documentation is pending.
Matters of Value Identity
The relational model of data fundamentally involves values as being immutable and distinct values having distinct identities, and the type of a value is part of its identity.
The relational model has 3 kinds of types and values, called scalar types/values, tuple types/values, and relation types/values; the 3 are all mutually disjoint and no value in one kind can be identical to a value in another. This Set::Relation module treats its own objects as relation values, it treats ordinary un-blessed Perl hash-refs as tuple values, and it treats all other Perl values (and Perl undef) as scalar values.
Or strictly speaking, a Set::Relation object doesn't just represent a relation as its allowed structure is more liberal than a true relation; rather, a Set::Relation object directly represents the concept of a "quasi-relation" value as defined by the Muldis D language, which is more natural for integration with Perl's liberal way of doing things and is also simpler to implement. But if your use of the module is appropriately more restricted than what the module itself allows, then you can be working with just true relation values. For simplicity, the rest of this documentation will refer to the concept of "quasi-relation" less formally as just "relation".
This documentation section outlines how Set::Relation considers every kind of Perl value in regards to its value identity, which has a large role to play in the semantics of Set::Relation's routines. Since a tuple is a set of zero or more distinctly named attribute values and a relation is a set of zero or more distinct-valued tuples having the same set of attribute names, matters of whether 2 Perl values are considered duplicates or not depends on this concept of identity.
A tuple/relation attribute name is exactly the same as a Perl Hash key; it is a defined non-reference case/everything-sensitive character string of zero or more characters.
Two tuples/Perl-Hashes are considered identical iff they are of the same degree (same number of elements), have the same keys, and have corresponding values that individually are considered identical.
Two relation/Set::Relation objects are considered identical iff they are of the same degree (same number of attributes), have the same attribute names, are of the same cardinality (same number of tuples), and every tuple in one corresponds to a distinct tuple in the other, individually considered identical. Other object attributes of a Set::Relation object such as keys/key-constraints or member identity caches have no bearing on the value identity of a Set::Relation.
Two Perl undefined values are considered identical to each other, and distinct from all defined values.
Two defined non-reference Perl values are considered identical iff their string representations are identical; either is distinct from Perl undef and from all reference/blessed Perl values.
Two non-blessed reference non-Hash Perl values are considered identical to each other iff they stringify to the same string representations, meaning essentially if they are the very same reference / have the same memory address; either is distinct from any blessed reference or non-reference or Hash-ref Perl value.
Two blessed reference / Perl object non-Set::Relation Perl values are considered identical to each other iff they both are blessed into the same Perl class and they both stringify to the same string representations, meaning generally that either they are the very same reference or their class overloads stringification (in which case we treat their class as a value type); either is distinct from any non-blessed Perl value or Set::Relation object.
Loosely speaking, Set::Relation treats its own objects and Perl Hash-refs and non-reference or undefined Perl values as being of value types, that compare on their actual values, while treating all other Perl reference or blessed values as being reference types, that compare on their memory addresses. Value types can't be mutated while the containers that the reference values point to can be mutated. If you want some other class' object treated as a value type, make it overload stringification (or an alternate/additional convention can be devised like Set::Relation's own 'which' convention). If you want a Hash-ref/tuple or Set::Relation object to be treated as a reference type, then pass it around using another layer of reference indirection, such as by adding a scalar-ref up front.
Note: Were this Perl 6, we would basically just use the standard WHICH
method or ===
comparison operator to determine identity; but Perl 5 doesn't have that so we do the aforementioned instead.
Now, while a relation value is conceptually immutable, the Set::Relation class allows you to mutate a Set::Relation object under some circumstances as a convenience to users, in a similar manner to how you can mutate a Perl Hash or Array by inserting or deleting its elements. By default, a newly created Set::Relation object is mutable, that is its identity is said to not be frozen; but when you perform certain operations with one, it will become immutable, gaining a frozen identity, and this change can not be reversed, though you can clone said object to get an un-frozen duplicate.
There are 3 main ways to make a Set::Relation object immutable. The first is explicitly, by invoking its freeze_identity
method. The second is implicitly, by invoking its which
method (this one may be reconsidered on users' request). The third is if another Set::Relation object is constructed that is given the first object as a tuple attribute value; this was done rather than cloning the input object under the assumption that most of the time you wouldn't want to mutate the input object afterwards, for efficiency.
Matters of Performance
Set::Relation by itself is strictly an in-memory data structure, same as Perl's built-in arrays and hashes. Its design focuses on providing correct-behaving features in a relatively simple manner.
Performance is made as good as possible, using multiple design techniques, while not becoming too complicated. Set::Relation keeps a variety of indexes automatically and makes a trade-off of being willing to use more RAM (by storing multiple copies of data in hashed form, at least 3 copies total) in order to get better CPU performance.
Loosely speaking, each Set::Relation object is a Perl hash-ref with one element per tuple, where the hash value is the tuple itself as a Perl hash-ref and the key is a unique hash / serialization of the entire deep value of said tuple.
This basic structure means that fundamental operations of taking a whole arbitrary tuple and querying whether or not it is in the relation is an O(1) / constant-time operation, same as testing the existence of a key in a Perl hash; likewise, inserting a tuple into or deleting a tuple from a relation is also an O(1) / constant-time operation.
All basic set operations, like relational union or difference, are all O(N) / linear-time due to that basic structure alone. When comparing 2 input relations for a set operation, only the smaller one needs to be fully (at the worst) or partially scanned, and the other does not; the scan produces a list of tuples to search for, and each search for a tuple in the second relation is O(1). Similarly, many basic relational operations like projection and extension are 0(N). No such operations are in polynomial-time such as O(N^2); that would simply be unacceptable.
Set::Relation also automatically generates more indexes to help with the general cases of relational joins or semijoins where the arguments have some but not all attributes in common (the common ones only providing the join criteria). Without the extra indexes, a generic join would be in polynomial time since it would have to pair up every tuple of one argument with every one of another to see if parts of each tuple match. However, this is changed to linear time by first creating (or reusing) an index on each argument that is a hash of just the portion of the tuple attributes that overlap with the other argument. Creating each index is also linear time. So then using those indexes, doing an ordinary join or semijoin then has the same performance characteristics as relational union or difference.
Now to be more accurate concerning relational join operations, finding out what set of tuples in each input match each other is always a linear time operation like relational intersection (what is actually happening on the indexes), but producing the result set of tuples is an O(N*M) operation. Now if the attributes overlapped between both inputs are superkeys of each input, then producing the result set reduces to linear / O(N) time; otherwise it is appropriately slower since the then multiple tuples on each side of a match are then cartesian joined. If the main operation is a semijoin, that is always O(N) since we are actually just filtering one input by the other, not joining them for a result.
Of course, a regular cartesian product, a join between 2 relations having no attributes in common, can't be helped by an index (and generates none), and so does have O(N*M) performance all the time. This can't be helped since we know that the result will always have a cardinality that is the multiplication of input relations' cardinalities.
For the various few more complicated operators provided by Set::Relation, which are conceptually defined in terms of simpler operators, their performance is generally based on what they are defined in terms of.
To keep things simple, creation of indexes (besides the single fundemental one) is strictly automatic and you can not explicitly add or remove an index on a Set::Relation object. Creation is just done the first time the indexes would be used, so they only happen say if you do a regular join or such operation. Once an index is created, it is automatically kept up to date by any Set::Relation mutator methods; the design of said indexes also makes it such that keeping them up to date during tuple inserts or deletes is also O(1) per index.
To keep things simple, when new Set::Relation objects are generated from relational operations, that new object starts out with no indexes (other than the fundamental), even if conceivably the parent's could be copied.
The various Set::Relation operators know about and look for certain special cases of inputs which allow them to short-circuit the operation. In some cases they may return certain constant values, or they may just return one of their input objects directly. They may also use a cheaper operation than you requested which for example doesn't involve creating or using indexes. For example, if you use join
on 2 input relations that have all the same attributes, it will short circuit to intersection
. Or for example if you do union
and one input relation has zero tuples, it will simply return the other input object.
Now in the general relational model where relations are immutable, that makes no semantical difference, but it is important to know if you plan to mutate the result object of a relational operation, as you might then be mutating an argument too. So take appropriate precautions and do appropriate tests where necessary so that you don't have undesired side-effects in your program.
INTERFACE
The interface of Set::Relation is entirely object-oriented; you use it by creating Set::Relation objects by invoking the new()
submethod on the Set::Relation class name, and then invoking methods on those objects. All of their attributes are private, so you must use accessor methods.
The usual way that Set::Relation indicates a failure is to throw an exception; most often this is due to invalid input. If an invoked routine simply returns, you can assume that it has succeeded, even if the return value is undefined.
Constructor Submethods
This is currently the only routine declared by Set::Relation that you invoke off of the class name; currently you invoke all other routines off of a Set::Relation object.
submethod new of Set::Relation (Array|Hash|Set::Relation :$members?)
-
This constructor submethod creates and returns a new
Set::Relation
object, representing a single relation value, that is initialized primarily using the multi-dimensional Perl data structure given in its$members
argument, which defines the member attributes and tuples of the new relation. The allowed formats of a$members
argument mostly are those defined by the Muldis D language dialect HDMD_Perl5_Tiny for aQRelation
(orRelation
) value literal node payload, except that attribute values are just ordinary Perl values and not HDMD_Perl5_Tiny value literal nodes. Examples are:# Zero attrs + zero tuples. my $r1 = Set::Relation->new( members => [] ); # 3 attrs + zero tuples. my $r2 = Set::Relation->new( members => [ 'x', 'y', 'z' ] ); # Zero attrs + 1 tuple my $r3 = Set::Relation->new( members => [ {} ] ); # Named attributes format: 3 attrs + 1 tuple. my $r4 = Set::Relation->new( members => [ { 'login_name' => 'hartmark', 'login_pass' => 'letmein', 'is_special' => 1, }, ] ); # Ordered attributes format: 2 attrs + 1 tuple. my $r5 = Set::Relation->new( members => [ [ 'name', 'age' ], [ [ 'Michelle', 17 ], ] ] );
However, Set::Relation also supports a few additional, trivial formats for
$members
, as illustrated here:# The default value of a Set::Relation has zero attrs + zero tuples. my $r6 = Set::Relation->new(); # How to wrap any single tuple in a relation. my $r7 = Set::Relation->new( members => { 'login_name' => 'hartmark', 'login_pass' => 'letmein', 'is_special' => 1, } ); # One way to clone a relation object. my $r8 = Set::Relation->new( members => $r5 );
The new Set::Relation is initially a mutable object; its identity is not frozen.
Accessor Methods
These Set::Relation object methods are mainly about extracting object attributes, essentially the reverse process of an object constructor; but some of these will mutate aspects of objects besides what relation attributes and tuples they have, and some do other misc things.
method clone of Set::Relation ($self:)
-
This method results in a new Set::Relation object that has an exact clone of its invocant's attributes and tuples. The new Set::Relation is initially a mutable object; its value identity is not frozen, regardless of whether the invocant is frozen or not.
method export_for_new of Hash ($self: Bool|Array $want_ord_attrs?)
-
This method results in a Perl Hash value whose Hash keys and values you can give as argument names and values to
new
such that the latter would result in a clone of this method's invocant, as if you had usedclone
. In other words,export_for_new
is the inverse function tonew
. If this method's$want_ord_attrs
argument is missing or false, then the exported attributes and tuples are in named attributes format; if that argument is true, they are in ordered attributes format. If$want_ord_attrs
is a Perl Array then it is assumed to contain a list of attribute names matching those of the invocant, and so it is specifying what order the attributes should be in the result; otherwise if$want_ord_attrs
is the Perl string value1
, then the result will have its attributes ordered alphabetically by attribute name (see theheading
method docs for why that is the case). method freeze_identity ($self:)
-
This mutator method causes the invocant to become immutable when invoked; it freezes the invocant's value identity. This change is not reversible (an immutable Set::Relation object can't be made mutable again), however invoking
clone
on said object will give you a mutable duplicate. method which of Str ($self:)
-
This mutator method results in a character string representation of the invocant's value identity, and when invoked it has the side-effect of making the invocant immutable (as per
freeze_identity
) if it isn't already. The identity value result of this method is essentially a serialization of all the invocant's attribute names and tuple values, all of which are encoded and sorted in such a way that any 2 Set::Relation values having the same attributes and tuples are guaranteed to have the same value identity, and any 2 with different attributes or tuples are guaranteed to have different ones. This method is analagous to the specialWHICH
method of Perl 6 and lets you treat Set::Relation as a "value type". method members of Array ($self: Bool|Array $want_ord_attrs?)
-
This method results in a Perl Array value as per the 'members' element of the Hash that
export_for_new
would result in with the same invocant and with the same arguments. method heading of Array ($self:)
-
This method results in a Perl Array value whose elements are the attribute names of the invocant. The attribute names are sorted alphabetically so that if this method's result is used together with the result of invoking
body
on the same invocant with a non-Array but true valued$want_ord_attrs
then the default order of the ordered attributes resulting frombody
matches the default order resulting fromheading
; in contrast, ifbody
was invoked to return attributes in named format, it doesn't matter what orderheading
returns their names in. method body of Array ($self: Bool|Array $want_ord_attrs?)
-
This method results in a Perl Array value whose elements are the tuples of the invocant. Each tuple is either a Perl Hash or a Perl Array depending on the value of the
$want_ord_attrs
, like with themembers
method.
Mutator Methods
Invocations of these Set::Relation object methods will cause their invocants to mutate. But they do not mutate any of their non-invocant arguments. These methods also result in their invocants post-mutation, for the convenience of users that like to chain method calls.
method evacuate of Set::Relation ($topic:)
-
This mutator method deletes all of the tuples in its invocant relation. For a non-mutating equivalent, see the
empty
functional method. method insert of Set::Relation ($r: Array|Hash $t)
-
This mutator method inserts its tuples argument into its invocant relation. For a non-mutating equivalent, see the
insertion
functional method. method delete of Set::Relation ($r: Array|Hash $t)
-
This mutator method deletes its tuples argument from its invocant relation. For a non-mutating equivalent, see the
deletion
functional method.
Single Input Relation Functional Methods
These Set::Relation object methods are pure functional, each one whose execution results in a value and each one not mutating anything or having any side-effects; the sole exception to the latter is that some may mutate certain internals of some existing Set::Relation objects in ways that don't affect their value identity, such as by creating indexes to speed up current and future operations with said objects.
These methods each have a single Set::Relation object as input, which is the invocant. Some of them also result in a Set::Relation object while others do not.
method degree of UInt ($topic:)
-
This functional method results in the degree of its invocant (that is, the count of attributes it has).
method is_nullary of Bool ($topic:)
-
This functional method results in true iff its invocant has a degree of zero (that is, it has zero attributes), and false otherwise.
method cardinality of UInt ($topic:)
-
This functional method results in the cardinality of its invocant (that is, the count of tuples its body has).
method is_empty of Bool ($topic:)
-
This functional method results in true iff its invocant has a cardinality of zero (that is, it has zero tuples), and false otherwise.
method is_member of Bool ($r: Array|Hash $t)
-
This functional method results in true iff all of the tuples of its
$t
argument match tuples of its invocant (that is, iff conceptually$t
is a member of$r
), and false otherwise. This method is likeis_subset
except that the tuples being looked for don't have to be wrapped in a relation. method empty of Set::Relation ($topic:)
-
This functional method results in the empty relation of the same heading of its invocant, that is having the same degree and attribute names; it has zero tuples.
method insertion of Set::Relation ($r: Array|Hash $t)
-
This functional method results in a relation that is the relational union of
$r
and a relation whose tuples are$t
; that is, conceptually the result is$t
inserted into$r
. As a trivial case, if all of$t
already exist in$r
, then the result is just$r
. method deletion of Set::Relation ($r: Array|Hash $t)
-
This functional method results in a relation that is the relational difference from
$r
of a relation whose tuples are$t
; that is, conceptually the result is$t
deleted from$r
. As a trivial case, if all of$t
already doesn't exist in$r
, then the result is just$r
. method rename of Set::Relation ($topic: Hash $map)
-
This functional method results in a relation value that is the same as its
$topic
invocant but that some of its attributes have different names. Each element of the Hash argument$map
specifies how to rename one$topic
attribute, with the element's Hash key and Hash value representing the old and new names of a$topic
attribute, respectively. As a trivial case, this method's result is$topic
if$map
has no elements. This method supports renaming attributes to each others' names. This method will fail if$map
specifies any old names that$topic
doesn't have, or any new names that are the same as$topic
attributes that aren't being renamed. method projection of Set::Relation ($topic: Array $attrs)
-
This functional method results in the relational projection of its
$topic
invocant that has just the subset of attributes of$topic
which are named in its$attrs
argument. As a trivial case, this method's result is$topic
if$attrs
lists all attributes of$topic
; or, it is a nullary relation if$attrs
is empty. This method will fail if$attrs
specifies any attribute names that$topic
doesn't have. method cmpl_projection of Set::Relation ($topic: Array $attrs)
-
This functional method is the same as
projection
but that it results in the complementary subset of attributes of its invocant when given the same argument. method restriction of Set::Relation ($topic: Code $func, Any $assuming?)
-
This functional method results in the relational restriction of its
$topic
invocant as determined by applying the Bool-resulting Perl subroutine reference (having signatureof Bool (Hash $topic, Any $assuming?)
) given in its$func
argument when said subroutine is curried by its$assuming
argument. The result relation has the same heading as$topic
, and its body contains the subset of$topic
tuples where, for each tuple, the subroutine given in$func
results in true when passed the tuple as its$topic
argument and$assuming
as its$assuming
argument. As a trivial case, if$func
is defined to unconditionally result in true, then this method results simply in$topic
; or, for an unconditional false, this method results in the empty relation with the same heading. Note that this operation is also legitimately known as where. See also thesemijoin
method, which is a simpler-syntax alternative forrestriction
in its typical usage where restrictions are composed simply of anded or ored tests for attribute value equality. method cmpl_restriction of Set::Relation ($topic: Code $func, Any $assuming?)
-
This functional method is the same as
restriction
but that it results in the complementary subset of tuples of$topic
when given the same arguments. See also thesemidifference
method. method extension of Set::Relation ($topic: Array $attrs, Code $func, Any $assuming?)
-
This functional method results in the relational extension of its
topic
invocant as determined by applying the tuple-resulting Perl subroutine reference (having signatureof Hash (Hash $topic, Any $assuming?)
) given in its$func
argument when said subroutine is curried by its$assuming
argument. The result relation has a heading that is a superset of that of$topic
, and its body contains the same number of tuples, with all attribute values of$topic
retained, and possibly extra present, determined as follows; for each$topic
tuple, the subroutine given in$func
results in a second tuple when passed the first tuple as its$topic
argument and$assuming
as its$assuming
argument; the first and second tuples must have no attribute names in common, and the result tuple is derived by joining (cross-product) the tuples together. As a trivial case, if$func
is defined to unconditionally result in the degree-zero tuple, then this function results simply in$topic
. Now,extension
requires the extra$attrs
argument to prevent ambiguity in the general case where$topic
might have zero tuples, because in that situation,$func
would never be invoked, and the names of the attributes to add to$topic
are not known (we don't generally assume thatextension
can reverse-engineer$func
to see what attributes it would have resulted in). This function will fail if$topic
has at least 1 tuple and the result of$func
does not have matching attribute names to those named by$attrs
. method static_extension of Set::Relation ($topic: Hash $attrs)
-
This functional method is a simpler-syntax alternative to both
extension
andproduct
in the typical scenario of extending a relation, given in the$topic
invocant, such that every tuple has mutually identical values for each of the new attributes; the new attribute names and common values are given in the$attrs
argument. method map of Set::Relation ($topic: Array $result_attrs, Code $func, Any $assuming?)
-
This functional method provides a convenient one-place generalization of per-tuple transformations that otherwise might require the chaining of up to a half-dozen other operators like restriction, extension, and rename. This method results in a relation each of whose tuples is the result of applying, to each of the tuples of its
$topic
invocant, the tuple-resulting Perl subroutine reference (having signatureof Hash (Hash $topic, Any $assuming?)
) given in its$func
argument when said subroutine is curried by its$assuming
argument. There is no restriction on what attributes the result tuple of$func
may have (except that all tuples from$func
must have compatible headings); this tuple from$func
would completely replace the original tuple from$topic
. The result relation has a cardinality that is the same as that of$topic
, unless the result of$func
was redundant tuples, in which case the result has appropriately fewer tuples. As a trivial case, if$func
is defined to unconditionally result in the same tuple as its own$topic
argument, then this function results simply in$topic
; or, if$func
is defined to have a static result, then this function's result will have just 0..1 tuples. Now,map
requires the extra$result_attrs
argument to prevent ambiguity in the general case where$topic
might have zero tuples, because in that situation,$func
would never be invoked, and the names of the attributes of the result are not known (we don't generally assume thatmap
can reverse-engineer$func
to see what attributes it would have resulted in). This method will fail if$topic
has at least 1 tuple and the result of$func
does not have matching attribute names to those named by$result_attrs
.
Multiple Input Relation Functional Methods
These Set::Relation object methods are pure functional, each one whose execution results in a value and each one not mutating anything or having any side-effects; the sole exception to the latter is that some may mutate certain internals of some existing Set::Relation objects in ways that don't affect their value identity, such as by creating indexes to speed up current and future operations with said objects.
These methods each have at least 2 Set::Relation objects as input, one of which is the invocant and the other of which is an additional argument. Some of them also result in a Set::Relation object while others do not.
method is_identical of Bool ($topic: Set::Relation $other)
-
This functional method results in true iff its (mutually commutative) invocant and argument are exactly the same value (that is, Set::Relation considers them to have the same value identity), and false otherwise.
method is_subset of Bool ($look_in: Set::Relation $look_for)
-
This functional method results in true iff the set of tuples comprising
$look_for
is a subset of the set of tuples comprising$look_in
(both must have the same heading regardless), and false otherwise. method is_proper_subset of Bool ($look_in: Set::Relation $look_for)
-
This functional method is exactly the same as
is_subset
except that it results in false if$look_in
and$look_for
are identical. method is_disjoint of Bool ($topic: Set::Relation $other)
-
This functional method results in true iff the set of tuples comprising each of its same-heading mutually commutative invocant and argument are mutually disjoint, that is, iff the intersection of the invocant and argument is empty; it results in false otherwise.
method union of Set::Relation ($topic: Set::Relation $other)
-
This functional method results in the relational union/inclusive-or of its same-heading invocant and argument. The result relation has the same heading as the input relations, and its body contains every tuple that is in either of the inputs. Relational union is both a commutative and associative operation, and its identity value is the same-heading empty relation value (having zero tuples).
method exclusion of Set::Relation ($topic: Set::Relation $other)
-
This functional method results in the relational exclusion/exclusive-or of its same-heading invocant and argument. The result relation has the same heading as the input relations, and its body contains every tuple that is in just one of the two inputs. Relational exclusion is both a commutative and associative operation, and its identity value is the same as for
union
. Note that this operation is also legitimately known as symmetric difference. method intersection of Set::Relation ($topic: Set::Relation $other)
-
This functional method results in the relational intersection/and of its same-heading invocant and argument. The result relation has the same heading as the input relations, and its body contains only the tuples that are in both of the inputs. Relational intersection is both a commutative and associative operation, and its identity value is the same-heading universal relation value (having all the tuples that could possible exist together in a common relation value with that heading; this is impossibly large to represent in the general case, except perhaps lazily).
method difference of Set::Relation ($source: Set::Relation $filter)
-
This functional method results in the relational difference when its
$filter
argument is subtracted from its same-heading$source
invocant. The result relation has the same heading as the input relations, and its body contains only the tuples that are in$source
and are not in$filter
. Note that this difference operator is conceptually a special case of semidifference, applicable when the headings of the inputs are the same. method semidifference of Set::Relation ($source: Set::Relation $filter)
-
This functional method is the same as
semijoin
but that it results in the complementary subset of tuples of$source
when given the same arguments. Note that this operation is also legitimately known as antijoin or anti-semijoin. method semijoin of Set::Relation ($source: Set::Relation $filter)
-
This functional method results in the relational semijoin of its invocant and argument. The result relation has the same heading as
$source
, and its body contains the subset of$source
tuples that match those of$filter
as perjoin
. Note that relational semijoin is conceptually a short-hand for first doing an ordinary relational join between$source
and$filter
, and then performing a relational projection on all of the attributes that just$source
has. method join of Set::Relation ($topic: Set::Relation $other)
-
This functional method results in the relational join (natural inner join) of its invocant and argument. The result relation has a heading that is a union of the headings of the input relations, and its body is the result of first pairwise-matching every tuple of the input relations, then where each member of a tuple pair has attribute names in common, eliminating pairs where the values of those attributes differ and unioning the remaining said tuple pairs, then eliminating any result tuples that duplicate others. Relational join is both a commutative and associative operation, and its identity value is the relation value having zero attributes and a single tuple. As a trivial case, if either input relation has zero tuples, then the method's result will too; or, if either input is the nullary relation with one tuple, the result is the other input (see identity value); or, if the inputs have no attribute names in common, then the join of those is a cartesian product; or, if the inputs have all attribute names in common, then the join of those is an intersection; or, if one input's set of attribute names is a proper subset of the other's, then the join of just those two is a semijoin with the former filtering the latter.
method product of Set::Relation ($topic: Set::Relation $other)
-
This functional method results in the relational cartesian/cross product of its invocant and argument; it is conceptually a special case of
join
where the input relations have mutually distinct attribute names; unlikejoin
,product
will fail if any inputs have attribute names in common. method quotient of Set::Relation ($dividend: Set::Relation $divisor)
-
This functional method results in the quotient when its
$dividend
invocant is divided by its$divisor
argument using relational division. Speaking informally, say the relations$dividend
and$divisor
are calledA
andB
, and their attribute sets are respectively named{X,Y}
and{Y}
, then the result relation has a heading composed of attributes{X}
(so the result and$divisor
headings are both complementary subsets of the$dividend
heading); the result has all tuples{X}
such that a tuple{X,Y}
appears inA
for all tuples{Y}
appearing inB
; that is,A / B
is shorthand forA{X} - ((A{X} * B) - A){X}
. method composition of Set::Relation ($topic: Set::Relation $other)
-
This functional method results in the relational composition of its mutually commutative invocant and argument. It is conceptually a short-hand for first doing an ordinary relational join between the input relations, and then performing a relational projection on all of the attributes that only one of the arguments has; that is, the result has all of and just the attributes that were not involved in matching the tuples of the inputs.
DIAGNOSTICS
This documentation is pending.
CONFIGURATION AND ENVIRONMENT
This documentation is pending.
DEPENDENCIES
This file requires any version of Perl 5.x.y that is at least 5.8.1, and recommends one that is at least 5.10.0.
It also requires these Perl 5 packages that are bundled with any version of Perl 5.x.y that is at least 5.10.0, and are also on CPAN for separate installation by users of earlier Perl versions: version-ver(0.74..*).
It also requires these Perl 5 packages that are on CPAN: Moose-ver(0.65..*).
INCOMPATIBILITIES
None reported.
SEE ALSO
The separate all-documentation distribution Muldis::D is the formal definition of the Muldis D language, a portion of which Set::Relation is mainly based on. The Muldis D language in turn has as a primary influence the work of Christopher J. Date and Hugh Darwen whose home website is http://www.thethirdmanifesto.com/.
These other Perl 6 packages: Muldis::Rosetta, Set.
These other Perl 5 packages: Muldis::Rosetta, Set::Object, Set::Scalar.
BUGS AND LIMITATIONS
The Set::Relation library for Perl 5 does not make explicit attempts in code to enforce privacy of the library's internals, besides not documenting them as part of the public API. (The Set::Relation library for Perl 6 is different.) That said, you should still respect that privacy and just use the public API that Set::Relation provides. If you bypass the public API anyway, as Perl 5 allows, you do so at your own peril.
This documentation is pending.
AUTHOR
Darren Duncan (perl@DarrenDuncan.net
)
LICENSE AND COPYRIGHT
Set::Relation is Copyright © 2006-2009, Darren Duncan. All rights reserved.
Set::Relation is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation (http://www.fsf.org/); either version 3 of the License, or (at your option) any later version. You should have received a copy of the LGPL as part of the Set::Relation distribution, in the files named "LICENSE/LGPL" and "LICENSE/GPL" (the LGPLv3 is defined as the terms of the GPLv3 plus extra permissions); if not, see http://www.gnu.org/licenses/.
If it is not feasible for you to employ Set::Relation subject to the terms of the LGPL, then the copyright holder of Set::Relation can provide you a customized proprietary license, often at no cost, so that it is still possible for you to employ Set::Relation to meet your needs.
Any versions of Set::Relation that you modify and distribute must carry prominent notices stating that you changed the files and the date of any changes, in addition to preserving this original copyright notice and other credits. Set::Relation is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. However, for an additional fee, the copyright holders of Set::Relation can sell you a warranty for it.
While it is by no means required, the copyright holder of Set::Relation would appreciate being informed any time you create a modified version of Set::Relation that you are willing to distribute, because that is a practical way of suggesting improvements to the standard version.
ACKNOWLEDGEMENTS
- Todd Hepler (
thepler@employees.org
) -
Thanks for providing files for the test suite, module bug fixes, and other constructive input.
FORUMS
Several public email-based forums exist whose main topic is all implementations of the Muldis D language, especially the Muldis Rosetta reference implementation, but also the Set::Relation module. All of these you can reach via http://mm.DarrenDuncan.net/mailman/listinfo; go there to manage your subscriptions to, or view the archives of, the following:
muldis-db-announce@mm.DarrenDuncan.net
-
This low-volume list is mainly for official announcements from the Muldis Rosetta developers, though developers of Muldis Rosetta extensions can also post their announcements here. This is not a discussion list.
muldis-db-users@mm.DarrenDuncan.net
-
This list is for general discussion among people who are using Muldis Rosetta, which is not concerned with the implementation of Muldis Rosetta itself. This is the best place to ask for basic help in getting Muldis Rosetta installed on your machine or to make it do what you want. You could also submit feature requests or report perceived bugs here, if you don't want to use CPAN's RT system.
muldis-db-devel@mm.DarrenDuncan.net
-
This list is for discussion among people who are designing or implementing the Muldis Rosetta core API (including Muldis D language design), or who are implementing Muldis Rosetta Engines, or who are writing core documentation, tests, or examples. It is not the place for non-implementers to get help in using said.
An official IRC channel for Muldis D and its implementations is also intended, but not yet started.
Alternately, you can purchase more advanced commercial support for various Muldis D implementations, particularly Muldis Rosetta, from its author by way of Muldis Data Systems; see (http://www.muldis.com/) for details.