Hello,
In the code below, I use mata functions to update and query 2 local macros (vtSuccessfulRuns and vtFailedRuns). By making these macros local to this file, I was hoping that these macros will be shielded from the effects of whatever code the caller of these functions might write between calls to them. If you run the tests at the bottom of this post, you will see that everything works fine even if I issued "clear" and "clear all" in the current file. But if you type "clear" in the command window, the code fails because both macros are gone (you will get missing values if not outright failures). The same thing happens if you run another do file that includes "clear".
Why clear behaves so differently?
What is the best way to have a set of variables hidden behind an interface like the one below? I tried to use structs in mata but the complier did not like struct vars declared outside the functions.
I guess what I need is the equivalent of a static variable in C or a module-level variable in Pascal.
Any suggestions?
Thanks,
mata: mata clear
set matastrict on //all vars must be pre-declared
local vtSuccessfulRuns = 0
local vtFailedRuns = 0
mata:
version 13.2
void vtRestTesting() {
st_local("vtSuccessfulRuns", "0")
st_local("vtFailedRuns", "0")
}
void vtIncSuccessCounter() {
real scalar n
n = vtSuccessfulRuns() + 1
st_local("vtSuccessfulRuns", strofreal(n))
st_global("r(SuccessfulRuns)", strofreal(n))
}
void vtIncFailCounter() {
real scalar n
n = vtFailedRuns() + 1
st_local("vtFailedRuns", strofreal(n))
st_global("r(FailedRuns)", strofreal(n))
}
real scalar vtSuccessfulRuns(){
real scalar n
n = strtoreal(st_local("vtSuccessfulRuns"))
st_global("r(SuccessfulRuns)", strofreal(n))
return(n)
}
real scalar vtFailedRuns(){
real scalar n
n = strtoreal(st_local("vtFailedRuns"))
st_global("r(FailedRuns)", strofreal(n))
return(n)
}
end //mata code
//testing routines
mata:
vtRestTesting()
if (vtSuccessfulRuns() != 0) errprintf("expected 0 got %g", vtSuccessfulRuns());;
vtIncSuccessCounter()
if (vtSuccessfulRuns() != 1) errprintf("expected 1 got %g", vtSuccessfulRuns());;
vtIncSuccessCounter()
if (vtSuccessfulRuns() != 2) errprintf("expected 2 got %g", vtSuccessfulRuns());;
if (vtFailedRuns() != 0) errprintf("expected 0 got %g", vtFailedRuns());;
vtIncFailCounter()
if (vtFailedRuns() != 1) errprintf("expected 1 got %g", vtFailedRuns());;
vtIncFailCounter()
if (vtFailedRuns() != 2) errprintf("expected 2 got %g", vtFailedRuns());;
end
mata: vtRestTesting()
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
mata: vtIncSuccessCounter()
local nsuccess = r(SuccessfulRuns)
mata: vtIncFailCounter()
local nfail = r(FailedRuns)
noi di `nfail' `nsuccess'
mata: vtIncSuccessCounter()
local nsuccess = r(SuccessfulRuns)
mata: vtIncFailCounter()
local nfail = r(FailedRuns)
noi di `nfail' `nsuccess'
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
clear
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
clear all
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
//Above code works fine, now type clear in the command window and run the following code. It will no longer works.
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
In the code below, I use mata functions to update and query 2 local macros (vtSuccessfulRuns and vtFailedRuns). By making these macros local to this file, I was hoping that these macros will be shielded from the effects of whatever code the caller of these functions might write between calls to them. If you run the tests at the bottom of this post, you will see that everything works fine even if I issued "clear" and "clear all" in the current file. But if you type "clear" in the command window, the code fails because both macros are gone (you will get missing values if not outright failures). The same thing happens if you run another do file that includes "clear".
Why clear behaves so differently?
What is the best way to have a set of variables hidden behind an interface like the one below? I tried to use structs in mata but the complier did not like struct vars declared outside the functions.
I guess what I need is the equivalent of a static variable in C or a module-level variable in Pascal.
Any suggestions?
Thanks,
mata: mata clear
set matastrict on //all vars must be pre-declared
local vtSuccessfulRuns = 0
local vtFailedRuns = 0
mata:
version 13.2
void vtRestTesting() {
st_local("vtSuccessfulRuns", "0")
st_local("vtFailedRuns", "0")
}
void vtIncSuccessCounter() {
real scalar n
n = vtSuccessfulRuns() + 1
st_local("vtSuccessfulRuns", strofreal(n))
st_global("r(SuccessfulRuns)", strofreal(n))
}
void vtIncFailCounter() {
real scalar n
n = vtFailedRuns() + 1
st_local("vtFailedRuns", strofreal(n))
st_global("r(FailedRuns)", strofreal(n))
}
real scalar vtSuccessfulRuns(){
real scalar n
n = strtoreal(st_local("vtSuccessfulRuns"))
st_global("r(SuccessfulRuns)", strofreal(n))
return(n)
}
real scalar vtFailedRuns(){
real scalar n
n = strtoreal(st_local("vtFailedRuns"))
st_global("r(FailedRuns)", strofreal(n))
return(n)
}
end //mata code
//testing routines
mata:
vtRestTesting()
if (vtSuccessfulRuns() != 0) errprintf("expected 0 got %g", vtSuccessfulRuns());;
vtIncSuccessCounter()
if (vtSuccessfulRuns() != 1) errprintf("expected 1 got %g", vtSuccessfulRuns());;
vtIncSuccessCounter()
if (vtSuccessfulRuns() != 2) errprintf("expected 2 got %g", vtSuccessfulRuns());;
if (vtFailedRuns() != 0) errprintf("expected 0 got %g", vtFailedRuns());;
vtIncFailCounter()
if (vtFailedRuns() != 1) errprintf("expected 1 got %g", vtFailedRuns());;
vtIncFailCounter()
if (vtFailedRuns() != 2) errprintf("expected 2 got %g", vtFailedRuns());;
end
mata: vtRestTesting()
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
mata: vtIncSuccessCounter()
local nsuccess = r(SuccessfulRuns)
mata: vtIncFailCounter()
local nfail = r(FailedRuns)
noi di `nfail' `nsuccess'
mata: vtIncSuccessCounter()
local nsuccess = r(SuccessfulRuns)
mata: vtIncFailCounter()
local nfail = r(FailedRuns)
noi di `nfail' `nsuccess'
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
clear
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
clear all
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
//Above code works fine, now type clear in the command window and run the following code. It will no longer works.
mata: vtFailedRuns()
local nfail = r(FailedRuns)
mata: vtSuccessfulRuns()
local nsuccess = r(SuccessfulRuns)
noi di `nfail' `nsuccess'
Comment