ADVPL in essence is the Clipper (worsened). Language has a thing called dynamic scope, one of the worst computer inventions. But it’s not a big problem, because this mechanism is totally optional, you can use local variables like any language and have the lexical scope normally, without harm. Every good programmer knows not to use dynamic scope, except in languages made only to create scripts, even in these languages is not encouraged by the authors themselves.
The scope of the variable is determined by the time of execution it was created and survives and is visible until the scope is still active, even if the lexical scope is another. That is, the variable is created in a function and all the functions that it calls and those that were called in the whole stack, it exists and is visible normally, it only ceases to exist when the function that created it is finished. It is created by default if you do not put any scope modifier attribute or if you are explicit and declare the variable as private
.
It’s a kind of global public variable, where it has the lifetime for the entire application from the moment it’s created and it’s always visible, even outside (after it’s finished) where it was created, only the private variable has a slightly reduced scope, since it only exists up the pile and not down.
You might think, public
is worse than private
, since it has a much broader scope, right? In theory yes, in practice no. In practice every programmer knows that public
is too dangerous and avoids its use (no Clipper/Harbour code needs public
or private
to have its full potential, is completely unnecessary resource, in thesis ADVPL could also, but in practice not), while the variable private
(dynamic scope) the programmer feels safe and uses as if the variable were so private, and is not quite as already shown above.
But guess what? Protheus is all developed with private
in mind. You have to guess which variables are in the scope at that time. And there could be hundreds. And you have to be careful not to create a new one in the scope of this function because it may conflict with the existing "private". It’s crazy, it’s insane, even for a small app, imagine for one with millions of phone lines with dozens of call stacks.
So in your codes just use local
(or static
in some rare cases), do not use public
or private
under no circumstances. But consume the existing variables declared so by the system. They end up being part of the contract, the API. Always consider them as if they had been received as a parameter.
So you think: there should be documentation showing all the variables in each function. But it does not, first because the documentation is weak, second because it hardly makes sense. Depending on the order of call will be other variables. Your user role has no documentation, and it is in your role that they will be available. Depends on who you call can change the available variables. It’s in trial and error, and look at debugging which variables are there now (which may be different depending on the version (it’s bad anyway, I have recent experience, even had open call to resolve certain situations that made it impossible to resolve a certain issue I was working on).
I’m sorry you have to go through this. I did too. I had to ask for new entry points to be created to resolve without depending on these variables. When they create new things they do it right and pass arguments to my user role, today they know it’s not to use it. But guess what again? Not all programmers there know what they are doing or are committed to doing right and a lot of stuff is still created this way. When it passes in the only department that is ISO 9000 there (yes, only a tiny department has the certification) do it right. And obviously everything that is legacy has no way to solve because most variables have become part of the "contract".
Look at the available variables in debugging, do this in several places and see if it is something punctual as the other answer says. Some people have access to current sources of Protheus, if you have see if it is punctual. I saw, and it is not yet, today. The list only does not increase anymore because now they understand that they should not create new ones like this, which confirms everything I said above.
In his example makeUniJson()
"exports" the variable _cTabela
for all the functions that it calls or the others that are being called by them, it must be the case of Conv2Json()
. There’s nothing you can do to stop it, except in your code, you don’t create new variables like that. Prefer only to export what you need by parameters, as in any healthy language.
Any reader of this answer, I suggest this complementary reading to deepen the concept and absurdity that is dynamic scope: https://answall.com/a/13471/64969
– Jefferson Quesado
I also recommend reading the TDN documentation, which talks about the scopes of variables in Advpl -- http://tdn.totvs.com/pages/viewpage.action?pageId=6063097
– siga0984