For all my fellow software engineers who have yearned for being able to declare local variables in Qlik script subroutines, I have found a workaround for achieving this: declare them as parameters in the SUB's parameter list; like this:
/* SUB printTriangularNumber (pN) - print the (pN)th triangular number
Outputs pN x (pN+1) / 2.
SUB printTriangularNumber (pN, /* local variables: */ lTriangularNumber )
CALL printTriangularNumber( (5) );
The CALL has fewer parameters than the SUB declaration, but the QlikView engine nevertheless matches the two and initialises the missing parameters (lTriangularNumber, in this case) to null().
Style: I've used variable prefixes (p and l) and an inline comment to distinguish the genuine parameters from the local variables in the subroutine's signature; but have omitted the local variables in the comment block explaining the subroutine. This makes it as easy as possible for the maintainer to understand what is going on.
Like any other SUB parameter, there is no need to "clean-up" lTriangularNumber with a "SET lTriangularNumber=;" statement - the variable will be automatically deleted on return from the subroutine.
EXCEPTION: this technique does not work if there are no genuine parameters for the subroutine (i.e. the subroutine's signature contains only 'local' variables or you call it with no parameters: in these cases, the QlikView engine will create the variables at global scope and not dispose of them when it reaches ENDSUB. (Add that to the case file of Qlik's poor language design decisions that make it harder to easily create defect-free code.)
Qlik script behaves correctly when a SUB with a given parameter is called from a SUB that has a parameter with exactly the same name: it will indeed treat the outer subroutine's parameter and the inner subroutine's namesake parameter as two distinct variables, even if it's a recursive call.
I've put extra parentheses around the '5' in the CALL to force the QlikView engine to treat this as an expression. Without this, the QlikView engine will create a variable named '5' (yes, really!). (See previous comment about language design).
Message was edited by: Angus Monro -
* added Exception dot point re this technique not working when the subroutine's CALL passes no parameters;
* altered the recommended style - previous I'd demarcated the local variables in the SUB signature with an inline comment both before and after the list of local variables; but having a comment at the end of the list is redundant, since all variables through to the end of the signature will be 'local' when this technique is used.
* added a couple of self-indulgent rants about Qlik's language design. It's an ongoing issue and I wish they'd take a community-consultative approach so that impacts of design choices can be assessed. Argh! There I go again!
I ran your version of the script, and the post-CALL TRACE statement failed to print any number i.e. it cleaned-up the variable as expected. My suspicion is that when you were playing around with this technique, you accidentally created a global variable. So, go to Settings > Variable Overview..., explicitly remove the variable, and try running again.
Post-scriptum: I've just noticed that if $(#var) notation is used with a "local" variable, the variable ceases to be local. Actually, $(#var) notation is even weirder than this - it looks like the Qlik script engine finds all instances of this notation and creates the variables, and does all this before it has executed a single line of the script! To see this effect, run this script: exit script; trace $(#ghostvar); Obviously, the trace statement should never run. But if you execute this bit of script and then check Settings > Variable Overview..., you'll find that there is now a variable named 'ghostvar'! Bizarre.