Reveal/list widget, performance and alternatives

I’m actually working with some $reveal widgets right now, and something like an $else would not only be super helpful, but it would be much more efficient.

Instead of having two $reveals back to back which perform the same check, but complementary of each other, just do the check once and then have an else widget after.

But the real savings would be <$list>…</$list><$else>…</$else> if we could allow it. the “emptyMessage” attribute is both clunky, and as I learned writing Uglify, super inefficient. It spins up an entirely new Wikitext parser, just like $wikify does. $else would get around this.

4 Likes

Agreed. I guess Evan didn’t think of that possibility.

But yes, this (for most programmers) is much more readable:

<$if value=<somevar>>>
  <span> somevar is truthy </span>
</$if><$else>
  <span> somevar is not truthy </span>
</$else>

<$if value={{!!name}} not match="Flibbles">
  <span>You're not Flibbles!</span>
</$if><$else>
  <span>Hello Flibbles!</span>
</$else>

It looks reliable but Evan’s implementation of the conditional widgets, is very brittle. Only add a newline in between an "end </$if>" and the next <$else> element. The whole thing breaks.

IMO that’s the main reason, why this implementation at the moment wouldn’t be merged into the core.

As soon as something needs a “state”, that “state” variable has to be a tiddler. I personally want to be able to have an “<$if>” statement at the start of the tiddler and an “<$elseIf>” at the end of the tiddler, where both of them can work with the same state.

IMO that would be efficient, flexible and stable.

2 Likes

It’s both readable and very reliable over many thousands of invocations. As for “brittleness”, he prints an error message right at the site of the problem, explaining what is wrong. I wouldn’t call that “broken”, I’d call it mitigated. Really, brittle implies something might break unexpectedly “out of the blue”. Never happens.

I guess it’s horses for courses.

Has anyone dreamed of something like a $switch widget or something similar?

I did. But when I was thinking on how it will have a easy use, I only saw the solution that in each case it invoke a different macro (used as template). But creating a widget is beyond my knowledge.

Not as “pretty” as actual “if” and “else”, but how about this:

<$vars tiddlerCount={{{ [all[tiddlers]count[]] }}} >
<$macrocall $name=SetSessionStorageItem k="tiddlerCount" v=<<tiddlerCount>>/>
</$vars>

<$list filter={{{ [<GetSessionStorageItem k:"tiddlerCount">compare:number:lt[12]] }}}>
<<currentTiddler>> is less than 12
</$list>
<$list filter={{{ [<GetSessionStorageItem k:"tiddlerCount">compare:number:gt[12]] }}}>
<<currentTiddler>> is greater than 12
</$list>

This is a ridiculous example, but it showcases this point: A slow/complicated filter happens just once.

The value is stored in session storage.

The subsequent “if” and “else” list widgets then have quick filters to evaluate, taking advantage of the temporary value in session storage.

To try that code, create a new tiddler in this TiddlyWiki which has the SetSessionStorageItem and GetSessionStorageItem macros.

Aside: take a moment to study the “Fibonacci Series” tiddler. This is all about using session storage to mimic true “variables” as we would have in a programming language.

EDIT: For that referenced TiddlyWiki instance:

Even more savings when a “costly” filter would normally be evaluated three times, here just evaluated once. SetSessionStorageItem and GetSessionStorageItem are so fast that, I think, they don’t matter.

<$vars tiddlerCount={{{ [all[tiddlers]count[]] }}} >
<$macrocall $name=SetSessionStorageItem k="tiddlerCount" v=<<tiddlerCount>>/>
</$vars>

<$list filter={{{ [<GetSessionStorageItem k:"tiddlerCount">compare:number:lt[24]] }}}>
<<currentTiddler>> is less than 24
</$list>
<$list filter={{{ [<GetSessionStorageItem k:"tiddlerCount">compare:number:gt[24]] }}}>
<<currentTiddler>> is greater than 24
</$list>
<$list filter={{{ [<GetSessionStorageItem k:"tiddlerCount">compare:number:eq[24]] }}}>
<<currentTiddler>> is equal to 24
</$list>

(I don’t know what’s up with the funky syntax highlighting)

One could also wrap that code above in a “little” <$list></$list>.

Such that the “big” filter only happens if the “little” filter indicates the “big” filter needs to be re-evaluated.

Rock’n roll !!!

Maybe what I’m about to say is just “a totally different thing”, I can’t tell:

It would be nice if such if and else type widgets could somehow also be prepended or appended to other widgets to generically test if the other widget gives some output or not. Specifically, I’m thinking of the problem with the ListWidget and the case where you want a headline to show only if a non-empty list is generated.

In effect the widgets would mean something like “If the succeeding widget has output then do X” - and - “If the preceding widget had output then do Y”

Yeah, that’s not out of the ballpark, but it is right by the fence.

That’s a deal in which you put the title within the <$list> and </$list> block.

But you set it up to only show once, just before the first item. (Using the list widget “counter”; see “Contents and Attributes” section of the ListWidget documentation.)

<$list filter=“the big honking and slow filter” counter=“this_count”>
<$list filter="[<this_count>match[1]]">
Whatever Title
</$list>

the rest of the wikitext for whatever item from the big honking and slow filter
</$list>

Something like that …

Yeah, that inner filter will happen many times, but it is so tiny/quick that it should not matter.

Thanks @Charlie_Veniot , bu I’m not asking how to do it, I’m pointing out that I would like for there to be widgets dealing generically with this.

Yeah, but the point of showing how we can do that currently kind of shows what you’re asking for can’t be done (or if can be done, I’m imagining a really messy deal.)

You’re asking for something outside of the <$list> </$list> block to become aware of something going on in the block, to render content before the content rendered by the <$list> block.

As per the way I think TiddlyWiki works (and any programming language I’ve ever used works), what you’re asking for isn’t going to work.

The section for a title above the <$list> block has already been rendered (or processed for rendering) before the <$list> block is even looked at.

I’m of the mindset of “Really? Let me prove you wrong…” whenever anybody says something cannot be done. But the end result of when I’m in that mindset is something that does work, but anybody would crazy to use it.

Which brings up another mindset of mine: just because we can do it doesn’t mean we should.

Fair enough. Would be cool if it did.

Totally.

I imagine it would require a complete overhaul of the TiddlyWiki engine.

Something akin to a “come back and do rendering process for item A after you’ve done the rendering process for item B that is after A, such that the processing of A fits whatever happened during processing of B.”

Ugh.

And, the whole rendering process would need to know how to handle a chain of these things. All intermixed with transclusions and whatever other stuff that’s all going on during wikification/etc.

When a tidy linear process all of a sudden becomes chaotically non-linear, you get the equivalent of early BASIC programs that had GOTO statements all over hell’s acre. (For example, this ACEY DUCEY BASIC program. Loads of GOTO statements and "THEN " shorthand GOTO statements.)

Now somebody totally intimate with the inner architecture of TiddlyWiki could enlighten us here.

What if what you’re thinking actually happened to be a complete no-brainer?

Aside, another mindset of mine: if you cannot measure the cost of doing it, then step the flyin’ fudge back and don’t effing doing it.

The “cost”, among other things, involves the effort testing now, efforts testing later, potential for things being so much easier to break.

Again, somebody intimate with the internals would know way better than I would.

1 Like

I’m obviously not that person but here’s an idea:

Sticking with the names if and else then maybe this structure could work:

<$if>contents</if><$else/>

…or more verbosely:

<$if-there-is-content-inside-me then do actions or show some stuff>
This is contents, perhaps a widget or some other stuff
</if>
<$else-if-there-were-no-contents-back-there then do actions or show some stuff/>

the else could also have separate closing tag if the idea is to show its content, i.e

...<$else> then show this</else>

At that very moment of evaluating “if there is content inside me”, we haven’t yet reached the point of knowing whether or not there is content.

The way to know if there is content is to first evaluate the very thing that generates content.

One thing can’t know about the another thing until after the another thing happened.

I like it. I use very similar patterns where the result is held either in a variable, or where a longer life is required, in a “variables tiddler” stored in field(s).

Yeah, but variables of the <$vars> (or other) kind don’t behave like variables in a standard programming language, hence my use of SessionStorage as something that works like standard programming language variables, as showcased in the Fibonacci Series tiddler.

Code for convenience:

<$macrocall $name=SetSessionStorageItem k="F0" v="0"/>
<$macrocall $name=SetSessionStorageItem k="F1" v="1"/>
F,,0,, = 0<br>
F,,1,, = 1<br>
<$list filter="[range[2,25]]">
<$wikify name="FN_0" text="""<$macrocall $name=GetSessionStorageItem k={{{ [<currentTiddler>subtract[2]addprefix[F]]}}}/>""" mode="block" output="text">
<$wikify name="FN_1" text="""<$macrocall $name=GetSessionStorageItem k={{{ [<currentTiddler>subtract[1]addprefix[F]]}}}/>""" mode="block" output="text">
F,,{{!!title}},, = <$text text={{{ [<FN_0>add<FN_1>]}}}/><br>
<$macrocall $name=SetSessionStorageItem k={{{ [<currentTiddler>addprefix[F]] }}} v={{{ [<FN_0>add<FN_1>]}}}/>
</$wikify>
</$wikify>
</$list>

And now that I look at this again, I now know exactly how I would do this with temporary tiddlers as “variables”. I must do that to compare. (EDIT: Nope, thought dashed as soon as I created a new tiddler to do the job. Other idea I have using $vars/$let, that would work but would be a messy solution that would not be easily maintained.)

:slight_smile:

Your SetSessionStorage macro is “actioned” without the need of a triggered action widget. There’s nothing like that in vanilla TiddlyWiki.

Fun though. I enjoyed the detour :wink:

Yeah, I had a real Super Dave Osborne moment there for a second.