You use $variable, then it is shared in every recursion. Try without $.
I don't think it is clearly described, but $variable has scope in
Thank you for your reply and indeed, it does work without $
I started looking for what you said and the scope of $ and $$ variables is mentioned in the documentation of the Let function.
As you also said, it is not clearly described, at least not there.
The confusing part is that it is not explicitly said (although it is made clear by example) that apparently there is third type of variable that has neither $ nor $$. $ variables are called 'local' but when defined in a calculation the scope is the file (when scripts are not running). This does not sound so local to me.
Anyways, I can move on. thanks again.
Is that the actual function you're working with, or an example of odd behavior you were troubleshooting? If that really is the function you're working with, there's a more efficient way that's completely non-recursive:
number * ( number + 1 ) / 2
Using a "local" $variable isn't necessary for this function, but don't let it dissuade you from using $variables in custom functions when appropriate. It's the most efficient way to pass data from one recursion to the next without adding parameters to the function. You just have to remember to clear the variables when returning the final result.
The scope of "local" $variables outside a script isn't well documented, but it's nothing particularly complicated. A local $variable declared outside of a script is available in a file-wide "script 0", if you will. As long as no script is running, any reference to the $variable will refer to the script 0 version. Once you start a script, the script 0 version isn't available, and only local $variables declared while that script was running are available. Once all scripts are done, the script 0 version is available again. It's been trustworthy for custom functions for a long time, but I wouldn't get in the habit of using script 0 variables for anything else. We can't count on undocumented features to continue behaving the same way in future versions.
Thank you for your addition, jbante. I'll take your advice and don't make a habit out of using this feature.
Thank you for your concern about the example function. It wasn't the actual function. I can't remember exactly, but maybe I just wrote the example for the question and perhaps I actually made it to see if I could recreate the behaviour in a different function.
jbante alluded to this, but it may be worth noting: If you're in a script when you call this function, you'll set $step in that script. So, for instance, if you call this function within a script loop where you're using $step to count iterations, your custom function will reset the $step you're using to count iterations. Using a generic variable name like $step seems a big risk to me, since you, or another developer, may well use "$step" to mean something else, and end up with results that seem bizarre, and have a hard time telling where the changes to $step are coming from.
Some time ago, there seemed to be a trend of using $ variables in custom functions (and other let statements) to clearly identify all the variables. This seems to have passed. I've seen the ~ used for identification of variables jbante's (very useful!) functions, and while I personally find them a bit difficult to read, it makes more sense to me that throwing out a bunch of $variables that could conflict.
OTOH, the ability to set a bunch of script variables at once can be useful. I have logbegin and logend functions I use in all my scripts, for instance, where logbegin sets things like script name, user, timestamp and so on at the beginning of every script, and logend reads those variables to create a log parameter at the end of the script. When using this on purpose, though, I do things like including the function name in the variable name, so that I don't inadvertently use the same variable name for something else during my scripts.
I "set" many variables in one Let():
Set Variable $sp ;
[ $a = 1
; $b = 3
; $c = "abc"
in the end $sp, $a, $b & $c will be set. The same would work for setting $$variables.
Likewise. It's a great tool when used intentionally.
I've seen some developers do the same just to set $sp, though, not realizing that $a, $b and $c aren't just let variables now, they're $variables that can (and sometimes should) overlap with your script variables. Especially with custom functions, I'd be worried that someone would use $b later as a script variable and go, "hey! where'd that 3 come from?!"
It's definitely a powerful tool for setting multiple variables at once, but not if your intent was to just use them in the context of your Let.
But I don't use this method in a custom function, just in a script step in a script that will use the "set" variables from the Let().
"a bit difficult to read"
I tried using UUID for variable name that should be global, so that never conflict others
but looks so bad
If you're writing a recursive custom function, it's not easy creating a random $variable name that doesn't simply get reset on every call.
It's usually best to use a $variable that has the same name as the custom function itself: $cf_ValuePosition and to be sure to clear it at the end of the recursion.
I'm sure that there are handy and powerful applications of, say, non-local variables, but I would stick to making sure a variable does not exist outside the script or function where I use it. For me finding out that the $variable existed outside the function (better: function call) that declared it was an unwelcome surprise.
My thought was, using UUID can be some protection for "copy and paster", but anyway function name should be changed if conflict, so using "same name as cf" is good.
I thought using really random name that Get(UUID) function itself is in cf, but containing the name as parameter for recursive call seems a bit foolish
Ah, I think I understand. You're saying use a hardcoded UUID for $variable names inside a custom function. That could work. But what if you called the same cf more than once in a script? Would that cause problems?
Aside from defining $variables to be deliberately used outside of the script (per Beverly's post), the only reason I see to use a $variable is to pass information (usually a counter) from one iteration to another instead of using a function parameter. Obviously, using a parameter slot to pass a UUID to encode a $variable doesn't help towards that goal.
The function (return random number sequence) need keeping value until next time it is called (not only in script), so I used $$variable. (and, the function is not recursive)