Hi,
I was hoping to understand how can i create a recursive macro
I am thinking if i have
TiddlerA Field1 = “2” tag = “test”
TiddlerB Field1 = “2” tag = “test”
TiddlerC Field1 = “2” tag = “test”
How can i create a macro that would go through all tiddlers tagged test that has a field1 value greater than “1” one by one , and set their field value to “2”
I realize i can just list all of them and put a button with an action set field widget to set all the tiddlers field1 value to “2”
but i was wondering how can i do the process sequentially ,
so this filter brings the first tiddler
[tag[test]]:filter[get[field1]compare:number:gt[1]]+[first[]]
then i set the field to “1”
<$action-setfield $field="field1" $value="1" />
then now this makes only 2 tiddlers remaining that are matching the filter criteria
how do run the same process again , 2 more times until there are no tiddlers matching the criteria for which the process would terminate
Thank you
To discuss recursion, I find it much easier with a practical reference use case.
See if the following (try it at TiddlyWiki.com) makes sense:
\define tagged(this total_levels processed_levels:0)
<$list filter="[[$processed_levels$]match[0]]">$this$</$list>
<$let new_processed_levels={{{ [[$processed_levels$]add[1]] }}}
padding={{{ [[>]pad<new_processed_levels>,[>]] }}}>
<$list filter="[tag[$this$]]">
<br><<padding>> {{!!title}}
<$list variable="another_level" filter="[<new_processed_levels>compare:integer:lt[$total_levels$]]">
<$macrocall $name="tagged" this={{!!title}} total_levels=$total_levels$ processed_levels=<<new_processed_levels>>/>
</$list>
</$list>
</$let>
\end
<<tagged "Reference" 3>>
Give this a try:
\define forAll(tids)
<$list filter="[enlist<__tids__>first[]]">
<$action-setfield field1="1" />
<$macrocall $name="forAll" tids={{{ [enlist<__tids__>rest[]format:titlelist[]join[ ]] }}}/>
</$list>
\end
Notes:
- The
<<forAll>> macro is passed a space-separated, bracketed list of tiddler titles to be processed.
- The
$list widget gets the first tiddler from the list and sets <<currentTiddler>>. If <__tids__> is empty, the macro does nothing
- The
$action-setfield sets the desired field (field1) to a value of 1
- The
$macrocall then enlists the tiddler titles and rest[] removes the first item. Then, the remaining items are re-formatted as a single text value containing a space-separated, bracketed list of tiddler titles. The resulting text value is then passed into the forAll macro to perform the recursion on the remaining items.
To invoke the forAll macro:
<$button> go
<$set name="tids" filter="[tag[test]] :filter[get[field1]compare:number:gt[1]]">
<$macrocall $name="forAll" tids=<<tids>>/>
</$set>
</$button>
Notes:
- The $button widget triggers the processing.
- The
$set widget gets the initial list of “target” tiddlers to be processed. Note that, by default, $set will create a variable (named “tids”), that is automatically formatted as a space-separated, bracketed list of tiddler titles.
- The
$macrocall is then invoked with the initial list of tiddler to be processed.
enjoy,
-e
Thank you very much, i found eric’s example easier to follow