Perl TM Tutorial: As Low as it Gets (Part II)

(Followup to part I)

Compared to toplets, assertions are more complicated. They are also more interesting as they carry the connections between toplets and between toplets and literal values.


To express, for instance, that my cat Sacklpicka is an instance of a cat, the following would create a stand-alone assertion:

my $a = Assertion->new (kind    => TM->ASSOC,
                        type    => 'isa',
                        roles   => [ 'instance', 'class' ],
                        players => [ 'sacklpicka', 'cat' ]);

This by itself does only create the assertion, not add it to the map. For that a separate step is necessary:

$tm->assert ($a);

If you would care how this eventually pans out in the map you would see

bless( [
      ], 'Assertion' ),

Not only have the identifiers for cat and sacklpicka been made absolute using the base URI; also the scope component has defaulted to us, (the universal scope).

Additionally the infrastructure has reordered the role/player lists to adhere to a certain sorting. This is done in order to uniquely compute an MD5 fingerprint over the assertion. That MD5 is actually used as value for the internal identifier. Two assertions are equal if their internal identifiers are.

Associations of other predefined types, such as is-subclass-of (supertype-subtype in TMDM) can be added just as above and are recognized as long as the correct roles are used:

type           | role1        role2
isa            | instance     class
is-subclass-of | subclass     superclass

You can use different combinations, but you cannot expect the package to recognize them.

Names and Occurrences

Also names and occurrences are captured as assertions, whereby the values are created as literals:

use TM::Literal;
my $name = new TM::Literal ('Der Sacklpicka');
my $url  = new TM::Literal ('',

By default, values will be strings, but the package TM::Literal defines other useful data types. To attach these values to a toplet, assertions of a special kind are used:

$tm->assert (
    # add a name
    Assertion->new (kind    => TM->NAME,
                    type    => 'name',
                    scope   => 'de-AT',
                    roles   => [ 'thing', 'value' ],
                    players => [ 'sacklpicka', $name ]),
    # add an occurrence
    Assertion->new (kind    => TM->OCC,
                    type    => 'homepage',
                    scope   => 'us',
                    roles   => [ 'thing', 'value' ],
                    players => [ 'sacklpicka', $url ])

In both assertions the value plays a well-defined role (cleverly called value), and so does the toplet (thing) to which it is attached.

Any name or occurrence type, such as homepage can be added, as can any special scope, such as de-AT above.

Finding Assertions (generic)

Slightly unintuitive perhaps, the whole mechanics concerned with searching is concentrating on assertions, not on toplets.

The central work horse here is the function match_forall which returns matching assertions, i.e. those which follow certain search criteria given by a template all matching assertions are supposed to follow.

To find all instances of cat we can use:

my @cats = $tm->match_forall (
                    type    => 'isa',
                    roles   => [ 'instance', 'class' ],
                    players => [ undef,      'cat' ]

Hereby we constrained only the type of the assertion, all the roles and some of the players. Where you keep undef as player (or as role) you signal a dont-care intention. The scope or the kind of assertion we kept open altogether.

Now, since this actually returns assertions, we have to dig deeper to find the instances themselves in a further step:

map { $tm->get_players ($_, 'instance') } @cats

That will take each assertion and will use the method get_players to find all players for the role instance.

Finding Assertions (special purpose)

Looking for specific assertions with templates is flexible, but the algorithm to do that is also quite slow. For some search needs highly specialized query handlers have been provided. These are documented in TM::Axes.

To find all our cats you would use accordingly

@cats = $tm->match_forall (type => 'isa',
                           class => $tm->tids ('cat'));

Note that these handlers expect you to provide fully expanded local identifiers to work.

These specialized handlers also make it a bit easier to find names and occurrences (subsumed as characteristics), say, for our beloved cat:

$tm->match_forall ('topic' => $tm->tids ('sacklpicka'),
                   'char' => '1')

To access the values themselves we again have to project them out

map { $tm->get_players ($_, 'value') }
$tm->match_forall (....)

and to get to the pure values (without the data type information) we have to project even further from the literals:

map { $_->[0] }
map { $tm->get_players ($_, 'value') }
$tm->match_forall (....)

If we were only interested in, say, occurrences, then the simplest is to filter the result list for the appropriate kind:

map  { $_->[0] }
map  { $tm->get_players ($_, 'value') }
grep { $_->[TM->KIND] == TM->OCC }
$tm->match_forall (....)

You might also run into a situation where you have a value and want to know which toplet it is associated with. Also for this a specialized handler exists:

map { $tm->get_x_players ($_, 'thing') }
$tm->match_forall ('value' => new TM::Literal ('Der Sacklpicka'),
                   'char'  => '1')

That handler does not make a distinction how the value is used - as occurrence or as name; so you might have to filter for TM->OCC or TM->NAME in case.

Work supported by the Austrian Research Centers.

Posted In