Why macro called list field breaks, but once wikified it works?

78 views
Skip to first unread message

S. S.

unread,
Feb 26, 2019, 2:18:49 AM2/26/19
to TiddlyWiki
I'm having a problem understanding WHY example 2. BREAKS down.
I did not even know how to give this post an appropriate title!
I would appreciate if someone could explain it to me.

Fields
title : Headache
list : [[A B]] [[C D]] E
tidd : Headache

\define get-related-tiddlers() <$view tiddler=$(tid)$ field="list" mode="block"/>

\define test(list-tids)
list
-tids= $list-tids$
<$list filter="[enlist<__list-tids__>]">

</$list>
\end

<$set name=tid value={{!!tidd}}>

tid= <<tid>>

get-related-tiddlers= <<get-related-tiddlers>>

1. WORKS: <$macrocall $name="test" list-tids={{!!list}} field="list" /
>

2. BREAKS: <$macrocall $name="test" list-tids=<<get-related-tiddlers>> field="list" />

<$wikify name="GOT-related-tiddlers" text=<<get-related-tiddlers>>>

3. WORKS!: <$macrocall $name="test" list-tids=<<GOT-related-tiddlers>> field="list" />

</$wikify>
</
$set>

Also, I wonder if this use case was the primary reason for making the $wikify widget? If not, what was?

Thanks!

Eric Shulman

unread,
Feb 26, 2019, 3:01:52 AM2/26/19
to TiddlyWiki
On Monday, February 25, 2019 at 11:18:49 PM UTC-8, S. S. wrote:
I'm having a problem understanding WHY example 2. BREAKS down.
I did not even know how to give this post an appropriate title!
I would appreciate if someone could explain it to me.

OK... Let's see if this helps:

TiddlyWiki macro definitions are NOT functions in the traditional programming sense.  Although input "parameters" can be passed to them, and they "return" something as a result, they don't actually "run" any of the "code" they contain.  When a macro is invoked, it does two things (and ONLY two things):

1) replace all occurrences of $paramname$ with the corresponding value that was passed as an input parameter
2) replace all occurrences of $(variablename)$ with the current value of the variable (assuming it is defined in the context of the "caller" of the macro)

That is ALL it does.  After doing the replacements, the resulting content is "returned".  If the macro call is being used as a widget parameter, then the result is simply passed along to the widget for further processing.  However, if the macro call is embedded directly in wiki content, then it is rendered.

In light of the above, when you invoke the following:
2. BREAKS: <$macrocall $name="test" list-tids=<<get-related-tiddlers>> field="list" />
the value of the "list-tids" parameter is simply passed along to the widget and will NOT be the contents of the list field, but rather will literally be:
<$view tiddler=SomeTiddlerName field="list" mode="block"/>

In contrast, when you use <$wikify> on the macro, you are forcing it to be rendered and then capturing that result in the variable "GOT-related-tiddlers".  Thus, the <$view> widget contained in the macro DOES get processed, and the result is then available to pass along to the "list-tids" param.

Also, I wonder if this use case was the primary reason for making the $wikify widget? If not, what was?

I would say it was a convincing reason, though perhaps not the only one.

hope this helps,
-e

Mohammad

unread,
Feb 26, 2019, 3:28:29 AM2/26/19
to TiddlyWiki
Hello S.S,
I had the same problem and encountered this many times and it is really a headache.
I always think, list is a for-loop and macro is a function! BUT they are not!

I think as Eric explained, there is a huge difference in programming concepts here and in other language like C++ or
Python! As you are preparing the TW documentation, it is of great value to clear this differences!

Among all these difficulties, TW is still very desirable to script in it!


--Mohammad

Mohammad

unread,
Feb 26, 2019, 3:30:18 AM2/26/19
to TiddlyWiki
Added to TW-Scripts.

S. S.

unread,
Feb 26, 2019, 6:12:05 AM2/26/19
to TiddlyWiki

Thank you Eric, both for taking the time to explain, and explaining it SO CLEARLY!
In over 2 years of using TiddlyWiki, I don't believe I ever properly understood this behaviour of macro definitions.
It was like a "hit or miss" game --- so happy when it worked --- back to the drawing board when it didn't, without knowing why.
By knowing this concept, it quickly becomes clear WHY a certain $macrocall is NOT to right way to proceed.
It also makes me immediately see a better solution, like below:

\define test(list-tids)
list
-tids= $list-tids$
<$list filter="[enlist<__list-tids__>]">

<
/$list>

\end

<$set name=tid value={{!!tidd}}>
tid= <<tid>>
<$set name="SET-related-tiddlers" tiddler=<<tid>> field="list">

SET-related-tiddlers= <<SET-related-tiddlers>>

4. WORKS!: <$macrocall $name="test" list-tids=<<SET-related-tiddlers>> field="list" /
>
</$set></$set>

There is still a little confusion about "parsing" and "rendering."

From what I (probably mistakenly) understand, a <<macro>> that is used as parameter in a <$widget parameter=<<macro>>/> - the macro is "parsed" but not "rendered."
From what I understand (in a limited way & paraphrasing from Jeremy) of parsing, is that, - this is the basic scanning of a block of text to find bits of wikitext syntax - (e.g. finding the {{!!tidd}} transclusion). The result of parsing is a tree that we then use to construct the render tree.

Now the <<macro>> as the $widget parameter simply gives to the $widget a parameter of replaced text for its $param$ & $(var)$ etc. values. That's it.

The widget's "parsed" code sits on the "render tree." Parsing here means the WikiText for expanding has been kind of "flagged" - awaiting a refresh signal - when it will then be "rendered"?

 When its time for "refreshing," this is the time all those "flagged" parts are "rendered" - which I believe is turning it into the appropriate HTML/CSS - and assigning it to the proper place in the DOM (Document Object Model -- html elements & their properties etc.) nodes ( a cancerous growth of html injected by javascript into existing html elements).

The << macro>> that sits as a parameter in a $widget has been parsed (flagged for expanding on a refresh) but still is not expanded (rendered into html). Thus when another $widget2 accesses $widget, it gets this unexpanded (unrendered - un-refreshed) value - that leaves so many confused and frustrated!

When there is some change that affects a part of the "render tree" where all the "parsed" stuff is patiently waiting - it's time for a "rendering." The affected parts of the "render tree" are refreshed (values found and turned into html etc.).

This happens quite often when editing a tiddler with the view pane switched on - but until something is typed that affects the "render tree" - for example that <<macro>> that sits in the open WikiText (in the text field of a tiddler?), those affected patiently waiting widgets etc. on the "render tree" -  get "rendered" - since as soon as typing that WikiText macro completed, a signal that some change has happened affecting the "render tree" calls for the selective refresh (selective rendering of the parts of the "render tree" affected by the recent change).

Now that I have made a complete mish-mash of trying to explain how I understand what is happening - I hope I can entice you to enlighten me!
Reply all
Reply to author
Forward
0 new messages