Would you please add some examples here to follow.
@atronoush I will give it a go;
Consider the following
\procedure call-me()
<$parameters $params=call-me-params>
call-me Params: <<call-me-params>><br>
<<sub-proc>>
</$parameters>
\end
\procedure sub-proc()
<$parameters input $params=sub-proc-params>
sub-proc Params: <<sub-proc-params>> and <<call-me-params>>
</$parameters>
\end
<<call-me a:"1" b:"2" "3">>
Procedure call-me
This procedure can be called with an indeterminant number of named and/or unnamed parameters.
- We can now use the parameters widget to define the parameters, their order and default values
- But we can also retrieve all parameters passed in the macros invocation named or otherwise.
- We set the variable name with
$params=varname
eg; call-me-params
- We set the variable name with
- Notice how we then call sub-proc?
- When we do this there is no way to get all the parameters in call-me passed on to the sub-proc.
- Sure in sub-proc we can access the variable
call-me-params
but it is a JSON representation of the parma/value pairs.
Now consider if in call-me, I called the sub-proc as follows
<$transclude $variable=sub-proc $params=<<call-me-params>>/>
- In this example we use the proposed
$params
parameter to pass in the JSON string of parameter value pairs. - These would then be applied to the transclusion of sub-proc as if they were separate
param=value
items in the transclusion (of sub-proc)
That is given we can capture all parameters named or otherwise using the parameters widget provide a means to pass one or more on to the next procedure/widget.
The $genesis
widget has attributes which allow this to be accomplished. See the code in
https://tiddlywiki.com/#%24%3A%2Fcore%2Fui%2FVisibleTransclude for a very advanced example.
Here I’ve loosely adapted the code from there to fit your situation (untested):
<$genesis
$type="$transclude"
$names="[<params-var>jsonindexes[]]"
$values="[<params-var>jsonindexes[]] :map[<params-var>jsonget<currentTiddler>]">
[...]
Adjust [<params-var>jsonindexes[]]
to filter the parameters however you like.
The $names
/$values
attributes of $setmultiplevariables
and $fields
/$values
attributes of $action-setmultiplefields
should have the same behavior of the corresponding attributes in the $genesis
widget.
Thanks @btheado for showing it can be done.
Now imagin the code you provided replaced by a parameter on the transclude widget $input-params=<<varname>>
where varname was set using the $params attribute of the $parameters widget.
- passing all indeterminant parameter names and values from one process/widget to another.
How?
- giving the transclude widget the ability to accept a parameter which replaces or is appended to the calling parameters
- accepting the json form of the parameters
Why
- simplify widgets and procedures calling widgets and procedures.
- allow indefinite numbers and names of parameters to be passed on
- write widgets and procedures that intercept core widgets and procedures and then invoke the original with all parameters without knowledge of all parameters.
- create code that handles and formats parameters into sets of key/value pairs for storage and execution
- do the above with a simple parameter
- other as yet undreamed of code wizardry.
A key value of this idea would be the ease by which one could store a complex set of parameter/value pairs in the JSON format and apply them later. For example;
- filters and values to create new tiddlers
- alternative parameter sets you can select from
- multiple code examples whose only difference is the parameters
- given a filter is a valid parameter value it can be evaluated at render time.
For example it would be possible to store parameter sets in a single value or field capable of conditionaly setting or clearing multiple tags fields and even variables.
- we could even construct logical tiddlers we call parameter sets, that can be applied to any tiddler(s)
- this would help on documentation, interactive examples and tools to write tiddlywiki script.
I think there is a fair argument that unless this is simplified to a special parameter the current way to achive this, illustrated by @btheado, would be too much of a cognative load to be made use of regularly.
- especialy if used to achive some of ideas above.
You could implement a my-transclude
procedure which does this simplification (internally making use of the genesis widget). Then you could illustrate its usefulness with concrete example calls and resulting rendered output.
Do you mean a minimal example of using the $genesis
widget $name
and $values
attributes together with <$parameters $params>
?
No I mean;
That is the idea you alluded to above.
Thank you both for giving examples and insights.
For me, mastering the new features in TW 5.3.1 takes more time comparing to 5.1.x
But these kind of examples are very helpful to shorten my learning curve.
Thank you!
I will just add I have prior history in this space Clarification on the use of hashmap(s)
A quick Illustration of what my suggested solution would look like;
\widget $my.widget()
<$parameters filter="[all[current]]" $params=all-params>
<$list params=<<all-params>>/>
<$transclude $variable=myproc params=<<all-params>>/>
</$parameters>
\end $my.widget
<$my.widget filter="filter" emptyMessage="message"/>
- In this case any parameters provided to
my.Widget
would be passed on as if they were spelt out fto the- list widget.
- myproc would also receive these
\procedure myproc()
<$parameters $params=all-params>
<$transclude $variable=my2nd-proc params=<<all-params>>/>
</$parameters>
\end
<<myproc p1:"value" p2:"value">>
OR
<$transclude $variable=myproc p1="value" p2="value"/>
- In these examples the arbitrary parameter value pairs used to call myproc, would be passed on to my2nd-proc
- The same could work for macros/procedures and even inside transclusions
Many thanks for your examples.
Thanks for sharing a concrete example. Very helpful.
By this do you mean writing this:
<$my.widget filter="filter" emptyMessage="message"/>
would be behave as if you wrote this:
<$list filter="filter" emptyMessage="message"/>
<$transclude $variable=myproc filter="filter" emptyMessage="message"/>
Here is a working example of the above using the genesis widget:
\procedure myproc()
<$parameters $params=all-params>
myproc: <<all-params>>
</$parameters>
\end myproc
\widget $my.widget()
<$parameters filter="[all[current]]" $params=all-params>
<$genesis
$type="$list"
$names="[<all-params>jsonindexes[]]"
$values="[<all-params>jsonindexes[]] :map[<all-params>jsonget<currentTiddler>]"/>
<$genesis
$type="$transclude"
$names="[<all-params>jsonindexes[]] =$variable"
$values="[<all-params>jsonindexes[]] :map[<all-params>jsonget<currentTiddler>] =myproc"/>
</$parameters>
\end $my.widget
<$my.widget filter="a b c" emptyMessage="message"/>
output is
a
b
c
myproc: {"emptyMessage":"message","filter":"a b c"}
See this example live at this share link.
I know you are looking for an easier implementation, but IMO implementing it the “hard way” first can be illustrative.
Note in the transclude genesis call I’m using =
to prevent de-duplication. It is important the $names
and $values
match in order and length. De-duplication would mess that up.
Factoring out a few functions makes it easier to read and write the $genesis
widget calls:
\function all.names(json) [<json>jsonindexes[]]
\function all.values(json) [<json>jsonindexes[]] :map[<json>jsonget<currentTiddler>]
\procedure myproc()
<$parameters $params=all-params>
myproc: <<all-params>>
</$parameters>
\end myproc
\widget $my.widget()
<$parameters filter="[all[current]]" $params=all-params>
<$genesis
$type="$list"
$names="[all.names<all-params>]"
$values="[all.values<all-params>]"/>
<$genesis
$type="$transclude"
$names="[all.names<all-params>] =$variable"
$values="[all.values<all-params>] =myproc"/>
</$parameters>
\end $my.widget
<$my.widget filter="a b c" emptyMessage="message"/>
Thanks @btheado I did read your guidence to explore the genesis widget first, my need to study it delayed me somewhat. But your worked examples are great.
Functions do help make things much more readable. I will focus on this in more detail today.
I have taken this further today and dump an example of my experiments without a complete explanation for people interested in studying the possibilities.
- In the below I take the “functionalisation” - “creation of functions” further
- I abandon the genesis widget by adoption of
params
variable as a defacto standard variable in which to store parameters.
Place this in tiddlywiki.com and read through the code to see the methods I am testing.
\function param.names() [<params>jsonindexes[]]
\function param.values() [<params>jsonindexes[]] :map[<params>jsonget<currentTiddler>]
\function wrap(string) [all[current]addprefix<string>addsuffix<string>]
\function join.titles(function) [function<function>] +[format:titlelist[]join[ ]]
\function join.text(function) [function<function>] +[join[ ]]
\procedure myproc()
<$setmultiplevariables
$names="[param.names[]]"
$values="[param.values[]]"
>
;myproc: <<params>>
: Join function: `<<join.function "[param.names[]]">>`
: Show {{{ [param.names[]] +[format:titlelist[]join[ ]] }}}
: Show {{{ [param.names[]join.titles[]] }}}
: Show {{{ [param.names[]join.text[]] }}}
<$list filter="[param.names[]]" variable=param>
<<param>>=<$text text={{{ [<param>getvariable[]<wrap '"""'>] }}}/><br>
</$list>
</$setmultiplevariables>
\end myproc
\widget $my.widget()
<$parameters filter="[all[current]]" $params=params>
<<myproc>>
</$parameters>
\end $my.widget
<$my.widget filter="a b c" dummy="dummy value" emptyMessage="message"/>
<$let params="""{"filter2":"d e f","dummy2":"dummy value","emptyMessage":"empty message"}""">
<<myproc>>
</$let>
- I am still expertimenting with join’s
Notes
- Can we use the $parameter widget to instantiate parameters?
- Now we can call the proc with canned parameters?
- Just set the params variable before calling myproc
On further reflection with my original desire for the above, and community input especialy @btheado, I can confidently say that with an effective code pattern and some defacto standard variable names, this is not nessasary and in fact would be more limited than what we can already achive.
I would mark this thread as solved if I could.
Hopefully I will get to share these methods with the community in some powerful examples in the fullness of time.
For Example;
- I can now see how I can capture and extract multiple parameters in a JSON string.
- This set of parameters can be stored in a tiddler/field/variable and reapplied later as needed.
- This satisfies my long desired ability to set, share, store and access multiple key/value pairs.
What is the next big thing I can do with these code patterns?
- Capture key/values pairs of the form fieldname/subfilter where subfilter is that used in the listops widget with its rich set of Extended Listops Filters
- These parameter sets can then can be processed and applied to the current tiddler and contain a great deal of logic handling single value and list fields.
- The filters can also be generalised via functions
Yet another big step forward in what I/we can do with TiddlyWiki script
I’m not sure what you mean here, but one possibly related thing I noticed is the $params
parameter of the parameters widget only includes the the parameters which are explicitly passed in. If you want to make use of default values (i.e. filter="[all[current]]"
below) then you would need to explicitly add each one to the filter:
[...]
\widget $my.widget()
<$parameters filter="[all[current]]" $params=all-params>
<$genesis
$type="$list"
$names="[all.names<all-params>] =filter"
$values="[all.values<all-params>] =[<filter>]"/>
<$genesis
$type="$transclude"
$names="[all.names<all-params>] =$variable =filter"
$values="[all.values<all-params>] =myproc =[<filter>]"/>
</$parameters>
\end $my.widget
<$my.widget emptyMessage="message"/>
Output (if inside a tiddler with title $params and $genesis example
$params and $genesis example
myproc: {"emptyMessage":"message","filter":"[all[current]]"}
Without the =filter
and =[<filter>]
, the default value [all[current]]
would not get picked up in the genesis widget calls.
Ha ha. Those notes in my post before last were to myself and slipped in by mistake. I will review the issue you raised about the $parameters own parameters.
By instantiate I think I was asking how to take a set of parameters and values and store them as the JSON object to store for later use and they easiest way is the parameters widget. But I want to know how to do it without the $Params widget.
Thanks to you @btheado I see two areas of complementary research.
- Your examples are about going via the genesis widget to existing widgets without modifying the target widget. This importiant to extend or leverage existing widgets.
- My focus at present is passing all parameters from one procedure or widget to another procedure or widget without nessasarily knowing anything about those parameters. Typicaly where all coding is mine.
- The key observation here is the $params variable set in one procedure or widget is available in ones you call as long as you dont reset the variable.
- So a set of parameters is available in the variable and can be decomposed using setmultiplevariables or the genesis widget at the point the original parameters are needed.
What is clear to me is the OT need not involve core changes and it is sufficent to develop appropriate code patterns based on the JSON parameters objects.
Postscript
- Above I mention using the parameters widget in widgets and procedures but I think we can also use it in transclusions.
Can we say Parameters are alternative to fields when we don’t want to use them in queries?
You could say that, but there may be more presice ways and may other combinations. Of cource a parameter can be a field, tiddler or variable and in many ways now a filter or function.