Observation is it a bug? Using a variable once $set

Please note these two ways to set a value for use in a checkbox;

Using the filter parameter
<$set name=data-tiddler filter="[all[current]addprefix[$:/data/tiddler/]]">

Using a filter in a filtered transclusion
<$set name=data-tiddler value={{{[all[current]addprefix[$:/data/tiddler/]] }}}>

Using the data-tiddler varible in a checkbox
<$checkbox tiddler=<<data-tiddler>> index=<<item>> checked="checked" unchecked="unchecked" default="unchecked">

When using the filter parameter it creates a tiddler;
[[$:/data/tiddler/tiddlername]] - exactly and erroneously.
When using the filtered transclusion if creates the tiddler;
$:/data/tiddler/tiddlername - as required and correct.

But they are the same filter!

Is it a bug? is it new to 5.2.0 or have I missed something?

Note: The tiddler created is a data tiddler because I am using the index parameter.

1 Like

Read the section on “Filtered Item Variable Assignment Single Element” in the SetWidget docs:

https://tiddlywiki.com/#SetWidget

If the <<currentTiddler>> value contains spaces (e.g., “New Tiddler”), then using filter=... will add brackets to the result, since the filter can potentially return a list of items. In contrast, using value={{{ [...] }}} always returns only the first item from the filtered transclusion and thus omits the brackets.

Note that if the <<currentTiddler>> value does NOT contain spaces, then both $set widgets return a value without brackets.

Lovely explanation @EricShulman

As directed by @saqimtiaz the set widget does document this, despite many visits I did not recall this. It also points out using the select=“0” also returns a single value without [[with spaces]] if the tiddler contains spaces. It makes sense because 0 is the first title in a variable and when returning one it need not be delimited as a tile.

<$set name=data-tiddler filter="[all[current]addprefix[$:/data/tiddler/]]" select="0">

I wonder if this is a feature or a workaround?

Unfortunately this is an example that demands commitment to memory as it is not self evident as far as I can see.

@TW_Tones as I recently came across the same thing in preparation for doing a lot of listops commands, the thing that gave me an aha moment was that most programming languages separately have “values” and “arrays”, and each command either generates, or expects one or the other.

For example within listops, the before, after etc. expect a single value, whereas append, remove expect lists (which in my world is an array) which in TiddlyWiki is a titlelist. All of the sudden then it clicked for me.

Now where most languages keep these very distinct, I feel like TiddlyWiki tries to be helpful and most of the time you can’t tell the difference between a list with a single item vs. just a single item. In practice now I’m aware of when I’m going to need a value to be in the shape of an array/list for a future operation, and I’ll pre-handle with the <value>format:titlelist[] operation so that it works.

To your code there, I’ll use <$set name="x" value={{{...}}}> when I need a value, but <$set name="x" filter="..." when I need an array/list.

Anyways, that might not be helpful at all, but since it was a recent realization, I thought others might have a similar “aha” if they have a similar background to me. Cheers.

2 Likes

Simple rule of thumb that helps in most situations: use <$vars> unless you want a titlelist returned.

2 Likes

I do plan to use vars more often especially with filtered transclusions
{{{ filter }}} allowing vars to be computed.

This would be a good “soft rule” though I do find I usually only set/vars variables if I need something “evaluated” for a subsequent step, a common use is testing if a value exists and providing an emptyValue.

This is a following is a common pattern I use;

<$set name=variable value="$param$" emptyValue=emptyValue=<<varname>>
<$set name=variable value=<<variable>> > >
<$set name=variable value=<<variable>> emptyValue="default" >

above code not tested

So the learning from this thread suggests perhaps I move to;

<$vars
variable={{{ [[$param$]] [<varname>] [[default]] [{tiddlername!!fieldname}] +[first[]] }}}
>

<<variable>>
</$vars>

Not only is the above more elegant and less text according to @saqimtiaz it is a way to ensure the value returned is not turned into a title if it has spaces.

Further given the “filtered transclusion” returns only the First result, so I need not have the +[first[]]

I m currently testing and will post a working solution back in this reply.

<$vars myvar={{{ [[$param$]] [<varname>] [[default]] [{tiddlername!!fieldname}] +[!is[blank]] }}}

Undefined variables (and I think text references) return an empty string which I presume is not what you want.

I think it is what I want

I want it to return the first with a value.

Are you implying we must ask +[!is[blank]] because it differs from “empty string” ? Are empty strings not blank?

An example would be if you use a macro with a parameter that’s what you get, if not it tests if a variable has a value, if not it test if a field has a value if not it tests if a config tiddler has a value if not it returns the default (or nothing).

Try this filter in Advanced Search and confirm that the result is what you expect:

[<foo>] [{bar!!baz}] hello +[first[]]

If not, I expect this will give you the result you expect:

[<foo>] [{bar!!baz}] hello +[!is[blank]first[]]

1 Like

To clarify, +[!is[blank]] says “only keep any non-blank i.e. non-empty-strings from the previous output”. So, yes, we must ask it to. In certain javascript contexts, an empty-string is “falsey” i.e. resolves to false when used in comparison, etc. In Tiddlywiki, on the other hand, an empty string is a valid string output, and if you do not want those in your ouptut, you must filter them out. The confusion may be from the fact that certain filter operators already discard empty results.

Best,
Joshua Fontany

1 Like

A good distinction to be aware of is how text references in filters behave differently from the get[] operator for non-existent fields. Given a tiddler HelloThere that does not have the field foo

[[HelloThere]get[foo]] => 0 results

[{HelloThere!!foo}] => 1 result, an empty string

Similarly undefined variables return an empty string, but do return a value.

[<foo>] => 1 result, an empty string
[<foo>is[variable]] => 0 results
[<foo>!is[blank]] => 0 results
1 Like

@saqimtaiaz this is very helpful and explains what one could think were inconsistencies.

Of course in this case we want the value returned as well.

So is +[!is[blank]first[]] looks like being the the pattern.