Subtleties of the collect() command


(James Fallows) #1

I have a file in which I use the following Rule, for a parent container:
$Text=collect(descendants,$ItemDetails).format("\n"))

This means that in the parent container, the $Text field is a sequential list of the $ItemDetails attributes of child items.

I am trying to make the collect() operator work, but with two attributes. I would like the $Text field of the parent note to show for each item the $StartDate, and then the $ItemDetails. As in:
July 1, 2017 Finish presentation notes

What’s the trick to having a Collect operation apply to two attributes? If I try
$Text=collect(descendants,$StartDate + " " + $ItemDetails).format("\n")
the results aren’t what I’m looking for. Sample of how the $Text field looks with that syntax:
1482727440
1482777060
1483056000
1483142400
1483142400
1483207200
1483236420

What is the trick to specifying collection of two attributes? Thanks.


(Galen Menzel) #2

There’s no trick to using more than one attribute — Tinderbox will accept an arbitrary expression as the second operator to collect. The issue is that there are two + operators in Tinderbox: one for string concatenation and one for numeric addition. Tinderbox tries to choose the best one depending on context, and it’s choosing numeric addition here.

In the expression $StartDate + " " + $ItemDetails, the left-hand-most argument to + is a Date, which Tinderbox interprets as a number, since Tinderbox represents Dates as numbers internally. This makes Tinderbox decide to use numeric addition here, which (from what I can tell) simply ignores the strings. The result is the numeric representation of the $StartDates of the descendant notes.

(My guess is that Tinderbox uses the Unix time convention of representing dates as the number of seconds since midnight UTC of 1 January 1970. Note that, for example, 1482727440/(606024*365) = 47.02 years, making the first descendent’s $StartDate close to new year of 2017, if I’m not mistaken).

The solution is to format the $StartDate to a string so that the concatenation operator is used. This should work:

$Text=collect(descendants,$StartDate.format("MM d, y") + " " + $ItemDetails).format("\n"))

If you don’t want to bother with formatting, a quick-and-dirty way to ensure that string concatenation is used is to start the expression off with a blank string, which forces the expression into a string context:

$Text=collect(descendants, "" + $StartDate + " " + $ItemDetails).format("\n"))


(Paul Walters) #3

A different approach is to have an attribute and a rule in each note that concatenates the text at that level, e.g.:

$collectText=$StartDate.format("M d, y")+ ": "+$ItemDetails

and then at the container level have

$Text=collect(descendants,$ItemDetails).format("\n")

Doing the concatenation at the note level makes it easier to have alternatives for calculating $collectText depending on conditions in that note. For example at the note level a rule that could include the value of attributes such as $DueDate or $Context, etc., into $collectText if those other attributes had valid values, else ignore the attribute(s).


(James Fallows) #4

Paul, Galen, thanks for your tips. I understand the principles you’re explaining and the practicalities for putting them into effect. Obvious once you point it out, but I hadn’t stopped to think that + had two possible internal meanings to Tinderbox, and that the program would use contextual clues to figure out which meaning to apply.

Update tried the approach of specifying a string format for $StartDate, and works like a charm. Thanks.


(Galen Menzel) #5

It’s confusing behavior, especially since dates act like strings in many contexts. @mwra perhaps this gotcha could be added to the date-datatype atbref page?


(Mark Anderson) #6

Good point. Just heading off to Hypertext’17 but I’ve made a note.