Tinderbox Forum

Using links() with item|group value of $Prototype="x"

Note A (source) is linked to Note B (destination). Note B has a prototype of “Reference”.

I would like to create a Rule for Note A, that checks if Note B has a prototype of ‘Reference’, and if so then populates a User-defined attribute of $citation (instead of Rule which checks for link type citation) for Note A with the $Name of Note B.

Is this possible? I have tried the following two rules, but they return nothing.

$citation=links($Prototype="Reference").outbound..$Name;
$citation=links($Prototype(destination)="Reference").outbound..$Name;

I thought this should be possible, because according to this TB Ref page, the item|group argument may be an unquoted attribute holding an appropriate string value.

I think you’re referring to these examples in the linked article:

links(find(descendedFrom("Some note")).inbound.my_link.$SomeAttribute 
links(find(descendedFrom("Some note")&$MyDate==$StartDate).outbound..$Width 
links($MySet).outbound.example.$Name 
links($MyList).inbound.note.$WordCount 

Note that in the first two, they use a query within find(). The query terms are essentially true/false tests. It is the find that returns a list of paths which are a valid group input to links().

That said I think you may also be confusing scope. For each $Rule you want—for this note—to report the $Name of all notes that are linked to from this note. But you also want to add a query into defining the group of linked-to notes. Your code above, even if it returned what you expect would make each notes’s rule apply to the group of all notes for all sources which is not what you want. So, you’re not misunderstanding the notes on links() but rather you’re trying to do something for which links() wasn’t designed. The only filter as to which linked notes are sampled is an optional filter on link type(s)

A more useful approach here is to use collect() with a find()-based query. In pseudo-code terms:

$citation = collect(find(_query_),$Name);

where the _query_ is something like

$Prototype="Reference" the tested note has $Prototype value set to “Reference”
& => AND
linkedFrom(that) => is the currently tested note linked to by the note calling the find

The query now tests every note in the document. First returns the path of those with right prototype setting; it then further filters that list retaining those with a link inbound from the calling note (i.e. the note running the find).

Now to test that…

Yes, this seems to find your desired data:

$MyList=collect(find($Prototype=="Reference"&linkedFrom(that)),$Name);

In my test, the rule was run in note ‘aa’. There are three notes with the ‘Reference’ prototype (bb, cc, dd) but only _two (bb, dd) are also linked from ‘aa’. In the code, for a rule running in ‘aa’ the ‘that’ designator refers to ‘aa’.

Note how the testing for links is reversed within the query. Although we want to test fro those notes linked to from the current note, within the query we’re testing other notes and so have to test for an inbound link, thus use of linkedFrom where you might have assumed linkedTo(0 would be appropriate.

This worked perfectly. And thank you for the explanation, Mark. I now understand the mechanisms a bit better.