Recurssive macro question

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>>
2 Likes

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

2 Likes

Thank you very much, i found eric’s example easier to follow