Procedure argument default value

I had a function once with default value for its argument.

\define myproc(arg:"joe")

I transformed it into a procedure

\procedure  myproc(arg:"joe")

and… there was no more default value for arg :frowning: I hade to code :frowning:

<$let arg = {{{ [<arg>!is[empty]else[joe]] }}}

Why procedure argument cannot have defult value?

1 Like

Tested right now in a new tiddler on tiddlywiki.com:

image

There must be another problem in your code I guess.

Fred

While searching what the problem could be, I found that the default value won’t be working until the \end line of a multiline procedure is typed.

Hope this helps

Fred

Perhaps you used the wrong reference to input param.

Tested on https://tiddlywiki.com/

\define mx(x:"1") Hi <<__x__>>
\procedure px(x:"2") Hi <<x>>


<<mx>>

<<px>>

produces

Hi 1

Hi 2

NOTE how x is called in macro and procedure. <<__x__>> and <<x>>

@jypre your examples need to go a little further to see what it’s not working.

Sometimes where you try and prepare a more thorough example you find the answer any way.

Write out some working examples like this

\define macro(arg:"default") Standard '$arg$', Parameter as variable '<<__arg__>>', Variable '$(currentTiddler)$', direct variable '<<currentTiddler>>'.
\procedure proc(arg:"default") Standard argument only '<<arg>>',  direct variable '<<currentTiddler>>'.
\function func(arg:"default") [<arg>addsuffix[ as variable in filter only]]
\procedure myproc()
   \function my.func() [<transclusion>]
<$parameters arg="default">
The argument is <<arg>>, myfunc is <<my.func>>
</$parameters>
\end myproc

;Sample code
# `<<macro>>` <<macro>>
# `<<macro new>>` <<macro new>>
# `<<proc>>` <<proc>> 
# `<<proc new>>` '<<proc new>>' 
# `<<func>>` '<<func>>'
# `<<func new>>` '<<func new>>'
# `<<myproc>>` '<<myproc>>' note the spaces left and right?
# `<<myproc new>>` '<<myproc new>>' note the spaces left and right?
#* Inside myproc use all on one line to fix spaces `<$parameters arg="default">The argument is <<arg>></$parameters>

I agree with @tw-FRed if any of the above are created on more than one line you must close them with an \end and if they are nested inside another, (at least the outer) or any internally with an \end should be \end name so it knows to which Item you are referring.

The above are examples single line macro, procedure and functions. However there are now alternative ways to define and set default parameters, one example is;

Then you end up with a reference of sorts.

OK, I shall make a point here. I tried again today. Trivial examples are fine indeed. Both with procedure and function.

BUT when I wrote to you, I already had a working macro doing real stuff. Working.

Here is the beginning of the old code:

\function importPlayers(pre:"Raw List of Players")
<$action-log $$message="importPlayers($pre$)"/>
<$let
  pre = """$pre$"""
  data = "$:/user/data"
>
</$let>
\end

As an aside in my previous post, I can’t get out of the coding block mode! So my post is garbaged. And I can’t edit it.

Thank you all of you for yours answers and being so kind with me.

I suspect that you want to use a procedure and not a function since you use wikitext and not just a filter expression.

Also note that text substitution is not supported in procedures so <$let pre="""$pre$""" becomes $let pre=<<pre>>, or in other words the pre variable already exists.

@jypre I am just trying my best to help, and I thought I demonstrated;

They can in all forms and permutations I listed

I also suggested

As far as I can see there is insufficient information in your questions and examples to give you a full answer. I am trying to get enough information so we (the community can help you).

  • Your questions are usually much easier to follow, except perhaps in the last few days. I hope everything is ok?

@saqimtiaz Note that I completely deleted that line in the new code. It was hure in the macro to get a variable when I had none in the first place. with a procedure I already had an argument.

I want to show you an other example. The code is that of a working example. I just modified the dehault value from FOO to <<lou>>, “lou” being the name of the argument of the procedure (which has none in the official example).

\define tv-action-refresh-policy() always

\procedure actions(lou:REED)
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<lou>>/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
<$action-log lou=<<lou>> $$filter="[prefix[tv-]]"/>
</$set>
\end

Current value of ActionTestTiddler: {{ActionTestTiddler}}

<$button actions=<<actions>>>
Click me
</$button>

Click on the button: the ActionTestTiddler tiddler content is created but its content is emptyx the action-log widget does nothing (no debug output).

Same things if I had some action-confirm widgets just to be on the safe side:

\define tv-action-refresh-policy() always

\procedure actions(lou:REED)
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<lou>>/>
<$action-confirm $prompt=no/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
<$action-confirm $prompt=no/>
<$action-log lou=<<lou>> $$filter="[prefix[tv-]]"/>
</$action-confirm>
</$action-confirm>
</$set>
\end

Current value of ActionTestTiddler: {{ActionTestTiddler}}

<$button actions=<<actions>>>
Click me
</$button>

I’m afraid I’m to tired to spot what stupidity I must have done in this simple code (again, it works if you have a constant like "LOU" as the text value when creating the target tiddler).

The confusion is understandable and I originally overlooked the issue as well due to the use of function rather than procedure.

Parameters as variables are indeed not available when using the procedure as attributes, see https://tiddlywiki.com/#Procedure%20Parameter%20Handling

In this situation, consider writing your procedure to use a variable that is set outside the procedure.

1 Like

“when a procedure is used as an attribute value.” IT’s not tooo obvious what it means. An example is required here. It would help not overlook that importans (mis)feature.

Indeed th,e use of a procedure as an argument of “actions” in a button widget is a simple and very common example. It should be used there.

So many thanks @saqimtiaz for having anwered to my conundrum! Closed case!!!

To have a default value mechanism that is operative in a wikified context but not otherwise seem to be a trap to me. A function or a procedure must behave all the same however it is called (except for border effects like changing values of fields, creating tiddlers, where we know we have to be on an action context).

I would argue that no default value would be much better than the present situation. This thread is a proof to it.

In order to facilitate the manipulation of default value, we could perhaps have specialized operator called “default”. The two line of code have the same effect and explain what I mean.

<$let myarg = {{{ [<myarg>!is[blank]else[my default value]] }}}/>
<$let myarg = {{{ [<myarg>default[my default value]] }}}/>

the onus is on code intent not on shorter code per se.

May I suggest the use of the \parameters pragma in these cases (or the <$parameters> widget for that matter) ? Like in

\procedure actions()
\parameters (lou:REED)
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<lou>>/>

<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>

<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>

<$action-log lou=<<lou>> $$filter="[prefix[tv-]]"/>

</$set>
\end

No, because it’s the same thing as: \procedure actions(lou:REED) which does not work as stated at: https://tiddlywiki.com/#Procedure%20Parameter%20Handling

Accessing parameters as variables only works in procedures that are wikified and not, for example, when a procedure is used as an attribute value

I think this is why its proven difficult to understand what is going on @jypre, I am confident this explains the problems you have had.

This behaviour of \procedures is identical to that of macros using \define. As the documentation says they need to be wikified. If simply given as a parameter value they will return the “tiddlywiwiki script” contained within the macro, not the value you expect.

  • Unfortunately this is not obvious because it’s kind of hidden from us. We just see it break.
  • When used in wikitext <<macroname or <<procedurename>> and for that matter <$awidget/> they get “rendered/wikified” at the last moment as the result is displayed, and only then (unless you use wikify).

You can prove this by using <$text text=<<macro-or-procname>> and you will see the result is not the wikified value, but the source tiddlywiki script.

With macros, and now procedures, the only way to make use of this is to first convert it to a variable, in a way, that first evaluates the wiki text. This method is using the wikify widget (which it is recommended to avoid)

The best workaround method is what I call “just in time wikification”. But “functions/filters” below, are much better.

<$wikify name=result text="<<procname params>>" >

<<result>> can now be uses as the value of a parameter eg `=<<result>>`

</$wikify>

I was disappointed that this was not resolved with the development of the new procedure, but I have now come to have some understanding of why this is the case. But it is hard to explain, it is to do with the difference, or lack of, between “macros” and “widgets”.

  • You will notice how an attribute can’t be given a widget as a value, try it, it will not work.
  • I believe macros and procedures are rewritten internally as $set widgets, so they may as well be widgets.
  • I have come to realise that widgets are really only “display outputs”, although powerful ones. They can not themself be a value to an attribute.

Saved by the function/filter

However functions, whilst only able to contain filters, can be used as values to parameters, or used in subsequent filters without need of wikification, because they are first evaluated as a filter, before the call/value is used/takes place.

  • functions by default only return the first value, this is all that is needed in many cases.
    • you can get around this by using +[join[]] to turn the function result into a single string, you can also keep it as a full list of titles by using ...format:titlelist[]join[ ]] you will later need to use enlist to extract all items from the value.
  • Most things you would like a macro or procedure to generate and use, as the value to an attribute can be now be achieved inside a filter and using the new function/filter.
    • These can also accept titles and parameters as their input, access other variables and fields/tiddlers.
    • With a “.” in their name they can also be used as custom operators, so anything that could be written in a filter can be written in a function.
      • @saqimtiaz demonstrated elsewhere functions can even be used recursively, or in a nested way.

Intriguing, because it works on tiddlywiki.com with \parameters, when I just replace this line in Jean-Pierre’s code:

\procedure actions(lou:REED)

with those two:

\procedure actions()
\parameters (lou:REED)

to read:

\define tv-action-refresh-policy() always

\procedure actions()
\parameters (lou:REED)
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<lou>>/>
<$action-confirm $prompt=no/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
<$action-confirm $prompt=no/>
<$action-log lou=<<lou>> $$filter="[prefix[tv-]]"/>
</$action-confirm>
</$action-confirm>
</$set>
\end

Current value of ActionTestTiddler: {{ActionTestTiddler}}

<$button actions=<<actions>>>
Click me
</$button>

@xcazin I have found out! What is making the code working is not the action-confirm but its very first linee

\define tv-action-refresh-policy() always

Remove it(as I did) and the wanted effect disappear.

The doc about this is in “ActionWidget Execution Modes”:

The new behaviour avoids these problems by refreshing all widgets before execution, not just action widgets. It is engaged by running the actions in a scope that includes the variable `tv-action-refresh-policy` set to the value `always`. (The default value for `tv-action-refresh-policy` is `once`).

Again, that’s an important thing to spot, and perhaps, surely enough even, it should be more understandable. Easy to say…