One nice thing with procedure is that you can use the parameters widget to fiddle with parameters values. But you do not have this mechanism with functions, although you wish you had it!
So I devised a scheme. See it below:
\function .great.stuff(stuff) [<stuff>!is[blank]else[news]!match[men]else[blokes]]
\function .great(stuff)
[.great.stuff<stuff>dump[great stuff?]]
:map[[This $(stuff)$ is great $1$!]substitute<currentTiddler>]
\end .great
\function .notsogreat(stuff) [[This $(stuff)$ is great $(.great.stuff)$.]substitute[]]
\function .great(stuff) [[This $(stuff)$ is great $1$!]substitute<.great.stuff>]
<$let stuff=bug>
* .great test: {{{ [.great[problems]] }}}
* .notsogreat test: {{{ [.notsogreat[problems]] }}}
* .great.stuff test: {{{ [.great.stuff[]] }}} and {{{ [.great.stuff[men]] }}} and {{{ [.great.stuff[women]] }}}
</$let>
whose output is
* .great test: This problems is great problems!
* .notsogreat test: This problems is great news.
* .nogreatr test: This problems is great news!
* .great.stuff test: news and blokes and women
The .great function is my simple demo function. it needs to alter its stuff
parameter and use the .great.stuff function to that end. There is a naming convention here: the inner function is a sub function to alter a parameter of the outer function, so is named by suffixing the outer function name by the outer function parameter name (with a prefixed point)) and the inner function parameter name is the same as the inner function parameter name. So that you know the purpose of things and where they can be used. I did use the same parameter name, hoping it to be accessed by the inner function with the value it has in the outer function.
But this is not the case. This would be working with variables (I tested it), but for functions, these parameters values are not transmitted by the call stack. Hence .nogreat and .notsogreat do not work but .great does work’ at the cost of a complex syntax, which would be very impractical if the .great function had to rely on the :map
prefix to do its real job.
I also tested with a parameterless iner function, to see if that could help. No.
\function .nogreat.stuff() [<stuff>!is[blank]else[news]!match[men]else[blokes]]
\function .nogreat(stuff) [[This $(stuff)$ is great $(.nogreat.stuff)$.]substitute[]]
<$let stuff=bug>
* .nogreat test: {{{ [.nogreat[problems]] }}}
* .nogreat test: {{{ [.nogreat[men]] }}}
* .nogreat test: {{{ [.nogreat[]] }}}
* .nogreat.stuff test: {{{ [.nogreat.stuff[]] }}}
</$let>
The output of which is:
* .nogreat test: This problems is great bug.
* .nogreat test: This men is great bug.
* .nogreat test: This is great bug.
* .nogreat.stuff test: bug
If I don’t set the stuff
variable I get “news” printed instead of “bug” which indicates that the stuff
parameter value of the outer function does not set the stuff
variable value for the inner function.
Could my problem be solved if functions could be defined within functions? If so, would it happen to be done in a later tiddlywiki version?