Variable as argument when it, itself, requires a variable argument

OK, I got great input from @etardiff and @tw-FRed for “sub-problems” to the following (here and here).

Below is the full problem, but here is first a little “symbolic illustration” to give an immediate sense of the problems essence (disregard the colors):

<$wikify name=X
  text=<$transclude $variable=foo arg=<<currentTiddler>>/> 
> ...

(I know why the above doesn’t work, I don’t know how to avoid it)

OK, the real problem is as follows:

Here’s a dictionary titled dic:

tiddler1: pending
tiddler2: resolved
tiddler3: pending
...

Tiddlers are tagged such that they form a branching tree; i.e every tiddler has an arbitrary number of children tagged with the parent title.

The following procedure lists all children and grandchildren that are not resolved:

\function resolved() [[dic]indexes[]enlist-input[]] :map[[dic]getindex<currentTiddler>match[resolved]then<currentTiddler>] +[format:titlelist[]join[ ]]

\procedure unresolved(tid)
<$list filter="""[tag<tid>]""">
{{{ [<currentTiddler>] -[enlist<resolved>] }}}
<$transclude $variable="unresolved" tid=<<currentTiddler>> />
</$list>
\end

Problem
How many unresolved children/grandchildren do tiddlers tagged “foo” have?

<$list filter="[tag[foo]]">
somehow count the output form the procedure
but the procedure needs the current tiddler as input 
</$list>

Thank you!

1 Like

Am I perhaps doing something wrong to get into this situation to begin with?

I had trouble following what you were trying to achieve, which part of the code worked as intended and which did not, and what exactly the desired output of each part of the code was.

Suggest setting up a small test wiki with some sample data and a mock up of the desired outcome.

OK, this shows the problem: https://issue-varg.tiddlyhost.com/ - How do I count the seen titles?

Thanks!

Your recursive procedure does not need the unresolved function, which will make it very slow, if there are many indices / tiddlers.

It should look like this:

\procedure getState(tid, state:pending)
<$list filter="[tag<tid>]">
  <% if [[dic]getindex<currentTiddler>match<state>] %>
    <$link/>, 
  <%endif%>
  <$transclude $variable="getState" tid=<<currentTiddler>><
 state=<<state>> />
</$list>
\end

Then you can use it for both “resolved” and “pending” states. Eg: <<getState top>> and <<getState top resolved>>

Counting will look as follows.

<$wikify name=x text="""<<getState top>>""">
<$text text={{{ [<x>split[, ]count[]subtract[1]] }}}/>
</$wikify>

The count value is only reliable, if there is no comma-space ", " combination in the title.
For a reliable counter the getState procedure would need to be modified.

hope that helps
-m

Here is the getState procedure for a reliable count value

\procedure getState(tid, state:pending, count)
<$list filter="[tag<tid>]">
  <% if [[dic]getindex<currentTiddler>match<state>] %>
    <% if [<count>match[yes]] %>
      X,
    <%else%>
      <$link/>, 
    <%endif%>
  <%endif%>
  <$transclude $variable="getState" tid=<<currentTiddler>> state=<<state>> count=<<count>> />
</$list>
\end

Counting will look like this

<$wikify name=x text="""<<getState top count:"yes">>""">
<$text text={{{ [<x>split[,]count[]subtract[1]] }}}/>
</$wikify>

This is my test-data

test-mats-problem.json (2.1 KB)

Much appreciated - but your solution doesn’t actually count the “unresolved ones” as requested, but instead specifically the pending ones (or some other specific state). This is my fault, I should have been clearer arbout this; in the really real case there is actually a third state (processing). I have now updated the wiki to reflect this.

What would work - if it for some reason is better - is to count all pending+processing ones. That will always equal the unresolved ones in numbers.

\procedure getState(tid, state:pending, count)
<$list filter="[tag<tid>]">
  <% if [[dic]getindex<currentTiddler>match<state>] %>
    <% if [<count>match[yes]] %>
      X,
    <%else%>
      <$link/>, 
    <%endif%>
  <%endif%>
  <$transclude $variable="getState" tid=<<currentTiddler>> state=<<state>> count=<<count>> />
</$list>
\end

<<getState top>>
<<getState top state:processing>>

<$wikify name=x text="""<<getState top count:yes>><<getState top state:processing count:yes>>
""">
<$text text={{{ [<x>split[,]count[]subtract[1]] }}}/>
</$wikify>

text="""<<getState top count:yes>><<getState top state:processing count:yes>>"""

Hahaa! That works, excellent! Thanks @pmario !

The important thing for counting is the “count” parameter. Otherwise a tiddler eg: a,a will count as 2 tiddlers.

You could also make the hardcoded dictionary title a parameter of getState(). So it would be more generic.

The important thing for counting is the “count” parameter. Otherwise a tiddler eg: a,a will count as 2 tiddlers.

Good point, thanks.

You could also make the hardcoded dictionary title a parameter of getState(). So it would be more generic.

No need for that just now but, right, good.

Personally I would avoid recursion via procedures in such a situation and do everything via functions, that way getting the count is as simple as adding count[] at the end of a filter expression without any need for wikifying:

\function get.children(t) [<t>] [get.tree<t>]

\function get.tree(top) [all[tiddlers]tag<top>] :map:flat[get.children<currentTiddler>]

\function get.resolved(top) [get.tree<top>] :filter[[dic]getindex<currentTiddler>match[resolved]]

\function get.unresolved(top) [get.tree<top>] :filter[[dic]getindex<currentTiddler>!match[resolved]]



Tree:

{{{ [get.tree[top]] }}}

---


Resolved:

{{{ [get.resolved[top]] }}}


---

Unresolved:

{{{ [get.unresolved[top]] }}}

Unresolved count:

<$text text={{{ [get.unresolved[top]count[]] }}} />


2 Likes

Beautiful! That code is a complete lesson. Even your naming conventions gives insights. Thank you Saq!

1 Like

But be aware, that both algorithms have a recursion problem. Eg: if

  • tiddler1.1 is tagged: tiddler1 and
  • tiddler1 is tagged: tiddler1.1

That’s the reason, why the TOC-macors needed some extra logic, which tracks titles, that have already been visited.

1 Like

Thanks, good to keep in mind. For my particular use case, recursion should not be an issue.