switch(expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}
The below codes can do equivalent operation!
Case i
This is a simple solution and simple action can be used here.
\define switch(item, list:"a b c")
<$list filter="[enlist<__list__>search<__item__>]" emptyMessage="Default">
You passed <<currentTiddler>>
</$list>
\end
<<switch a>>
<<switch b>>
Case ii
This is a more sophisticated solution as it implements the code blocks through action macros
\define a() This is the action for a.
\define b() This is action for b.
\define c() This is action for c.
\define default() This is default action.
\define switch(item, list:"a b c")
<$list filter="[enlist<__list__>search<__item__>]" emptyMessage=<<default>> variable="actMacro">
<$macrocall $name=<<actMacro>> />
</$list>
\end
<<switch a>>
<<switch b>>
<<switch d>>
The request was to add <$switch>/<$case> to simply do above operation. Decision making using switch/case is a very common in other programming languages. See [3].
What you have there is more akin to a switch with break:label, I think. Except the break doesn’t prevent more matches being found.
In C-like languages, switch-case (and select-case etc) are selection mechanisms, choosing one code path (even if more than one selection matches the selection: “fall through”).
In TW, the filter is essentially an iterator which potentially visits all possible selections, matching or not, even after a match (code-path) is found. The filter should be carefully constructed to reduce the list as much as possible
I’m also concerned for huge lists with huge numbers of possibilities.
I do wonder if TWs approach to JSON datatiddlers might be more efficient. Maybe.
I recall @TW_Tones had a structure for switch cases, posted in gg. I think this was made before any of the various filter prefixes and it was certainly before the possibility to evaluate macros in filters.
The “case structure” is one of the key programing structure after the most fundamental ones in coding Sequence, Iteration, Selection. I am a fan of the case structure in COBOL using EVALUATE which continues to be the most flexible I have seen because it does not preclude any of its possible actions and contains the WHEN OTHER to capture the no case case.
However I may just add that filters allow something similar and the the new cascade may allow our condition tests to return filters not just values.
Using the list widget we can even use emptyMessage as an “else” which is effectively what we need to replicate a CASE structure which is in effect a nested if then else structure. However I continue to find this non-intuitive to use.
I believe we have sufficient in TiddlyWiki to make good and adaptable equivalents of the CASE structure however a simple way to represent it would be nice. Perhaps smart use of the new $let statement wrapping a macro could do it?
On GitHub (see [3]) above, Jeremy stated he is interested in having such programming constructs in the core! So, perhaps in 5.2.3 or 5.2.x we have switch-case and if-then-else constructs
Mohammad, I suppose what I am saying is the “switch case” a general answer or a specific one. If for example we allowed “nested if statements” would we provide a simple way to do “case switch” and many other things?, rather than address only the “case statement”.
From deep in my memory a Case Statement often returns one of the listed items (optional default behaviour), typically returns a value in a variable, however it is possible to write multiple conditions and return values for every different condition that is found true. Even if only one value is returned the conditions tested need to be logically related and ordered to be sure.
I will look at the use of let widget for case now and come back
Ok, So I have played with the idea of “case structures” in tiddlywiki and as I suspected it really depends on what you want to achieve, display something, return something, transclude something, deal with else cases, return only one value etc…
I can see us documenting a range of case structures without necessarily developing a separate widget, in part because it would be hard to write one that can cater for the large number of possible uses. Here is a simple example;
While playing with this I saw a lot of alternative possibilities, I suspect one or more will be the most general in nature.
Observations
SImple case switches can be hidden away in a macro and simple return a value.
More complex case structures that may utilise different wikitext for different inputs will most likely spread through the body of wikitext to make use of inline wikitext when a condition is true or the emptyMessage
Filters contain a whole suite of if then and if then else like statements within, in fact the list template (or its content) is if/true and empty message else/false as well.
I think this is why the possibility of nested if then else and end-if structures have being neglected somewhat.
In conclusion if we had a way to represent;
nested if then else and end-if structures
It would be easier to represent clearly quite a few other coding or logical structures, and use them in various contexts.
<$list filter="condition" template="""
If true
"""
emptyMessage="""
else
""">>
If the template parameter permitted a “literal/inline” and had a alias “then”, and emptyMessage an alias of “else” we could write this;
<$list filter="condition" then="""
Do this
"""
else="""
otherwise this
""">>
or
<$list filter="condition" then="Do this" else="otherwise this">>
Allso nest
<$list filter="condition" then="""
Do this
"""
else="""
<$list filter="condition" then="""
Do this now
"""
else="""
otherwise this default
""">>
""">>
My thought would be a widget very similar to list ideally called <$if and closed by </$if> which reads as end-if. Change template to then, and emptyMessage to else and leave all other features intact.
To clarify, I do not think that we need new widgets for if/then/else or switch/case; as @TW_Tones has shown, the required logic can be performed with the list widget. I am interested in exploring new wikitext syntax that acts a shortcut for those widgets.
Hi @jeremyruston
What you have have proposed is a clear and concise syntax and very semantic!
This makes branching and decision making constructs for complex logic quite simple and easy to maintain in Tiddlywiki!
I’m excited about these ideas but I “fear” one thing:
If the user is to define and use these constructs similar to how local macro pragmas are defined and used, then this presumably means that they must be placed in the top of the text field… which must then be called in the subsequent code, right? IMO this risks “detouring” the code and make things more difficult to read. Here is another example of this problem.
Constructs like “if-then” seem too primitive to need to be invoked - or do I misunderstand the intention here? Maybe you’re only talking about a “core implementation” of these constructs that the user would somehow use it like any system macro by just providing arguments?
Thank you for this @Mohammad and @TW_Tones . Concise, clear explanations, multiple, complete, real world examples and pointers relating the solution to well known programming constructs. Beginners and long term beginners like me salute you!
The example I gave above assumes another potential improvement: that we allow pragmas to appear anywhere in a tiddler, with only some pragmas needing to be at the top of the tiddler (notably the \rules pragma). The restriction on only using \import or \define at the start of a tiddler has always been rather unnecessary.