I’m hoping to formulate some heuristic that I can stick to when writing a procedure that is called in an environment where the variables it uses are already defined.
So what is the reason for using params/arguments at all when the “surrounding variable” is accessible anyway? The use of the params/args make things a lot more verbose.
The only reason I can come up with is that it is perhaps “faster to understand” when reading the code.
That’s a good experiment. I didn’t know you could put variable references on the \procedure call line like that. I feel like widgets are needed inside the procedure definition to do anything with the parameters. Otherwise, it expects wikitext, which is the content of the procedure, itself a variable. Right?
So what is the reason for using params/arguments at all when the “surrounding variable” is accessible anyway?
I think there is no need to pass the argument in such a case! As the inner has access to foo in this case. The scope of foo also covers inner procedure.
Here is an example where args seems to be required
\procedure greetings(name, phone) <<name>> : +001-<<phone>>
Some texts....
<<greetings Joe "124-5426">>
Another text ...
<<greetings Sita "124-5426">>
If you do not use arguments then you should use a longer script like
Some texts....
<$let name="Joe" phone="124-5426">
<<greetings>>
<$/let>
Another text ...
That’s right. It should show, that before and after “calling” <<showVariable>> the privateVariable is outer … So variables in TW are scoped. If they have the same name, you can only see 1 of them.
But in your example, #1 and #3 are identical and in identical environments.
I’m talking about the post here, not the attached file which, for some reason, when I drop it onto a wiki it instead opens a new tab where the json is shown. (win/brave)
But to use them with the surrounding variable means that your procedure—which should be usable across many situations—now is only able to run in those situations where the variables that it needs have already been set appropriately. If it’s not already the case, then you’re required to surround the call with <$let> / <$set> widgets.
That is, imagine calling <<greet {{!!role}}>> to get “Hello, Your Honor!”. To use this simple procedure, that’s all you have to do. If you depended on implicit variables, you’d have to set them: <$let name={{!!role}}><<greet>></$let> and then ensure that you didn’t also use code inside that <$let> that used some outer association of name.
OK, fair point. On the other hand, it feels like this is quickly discovered if the need arises? The cost of regarding that all the time is verbosity, afaict.
I want to say, “Well, you’re free to skip the arguments and always depend upon implicit context.” But I would really argue that ever allowing implicit context is the problem. It would be so much cleaner if you had to pass everything. Think of being able to reuse practically any procedure you’ve ever written, or anyone has either, wherever you wish, because of the guarantee that given the same arguments it always returns the same result.
Huh, what? My inner functional programmer is showing? Sorry, I’ll stop now.