Page 1 of 1
Embed function inside a procedure?
Posted: Thu Oct 29, 2015 6:29 pm
by macro
I have a procedure of this form:
Code: Select all
procedure findstep criterion N
option choice criterion 1 aic sbc hq
type integer N
if criterion == 1 {
function cT T {
type real cT T
compute cT = 2.0
}
compute criterion_lbl = "AIC"
}
else if criterion == 2 {
function cT T {
type real cT T
compute cT = 2.0 * log(T)
}
compute criterion_lbl = "SBC"
}
else if criterion == 3 {
function cT T {
type real cT T
compute cT = 2.0 * log(log(T))
}
compute criterion_lbl = "HQ"
}
/*
Iterations that change the value of T and derive
the value of the function cT(T); this function
changes with the criterion.
*/
end
that performs some iterations that involve a (changing) value T. The code uses a function cT(T), where the function cT is determined by the selected criterion. Is there a way to embed a function, FRML, etc. inside the first if statements in the procedure so I can recycle the function cT throughout the procedure?
For simplicity and ease of maintenance, I'd like to have
one set of -if- statements that branch based on the criterion, and then be able to avoid them through the rest of the procedure. For example, if I need to add a new criterion or change the function cT, I only have to do it once in the procedure, not numerous times by adding to a slew of branching -if- statements. I don't think FRML is the way to go because those depend on an entry number (whereas the function cT only takes a value), and I can't find anything in the manuals about anonymous functions or lambda operators, which would take care of this.
Re: Embed function inside a procedure?
Posted: Thu Oct 29, 2015 10:18 pm
by TomDoan
Wouldn't this work?
Code: Select all
procedure findstep criterion N
option choice criterion 1 aic sbc hq
type integer N
local frml ct
*
dec frml[vect
if criterion == 1 {
compute criterion_lbl = "AIC"
frml ct = 2.0
}
else if criterion == 2 {
compute criterion_lbl = "SBC"
frml ct = log(t)
}
else if criterion == 3 {
compute criterion_lbl = "HQ"
frml ct = 2.0*log(log(t))
}
/*
Iterations that change the value of T and derive
the value of the function cT(T); this function
changes with the criterion.
*/
end
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 8:02 am
by macro
That fails is the argument to the FRML is real (hence why I typed the argument T as real in the functions):
Code: Select all
procedure findstep criterion N
option choice criterion 1 aic sbc hq
type integer N
if criterion == 1 {
frml real ct = 2.0
compute criterion_lbl = "AIC"
}
else if criterion == 2 {
frml real ct = 2.0 * log(t)
compute criterion_lbl = "SBC"
}
else if criterion == 3 {
frml real ct = 2.0 * log(log(t))
compute criterion_lbl = "HQ"
}
/*
Iterations that change the value of T and derive
the value of the function ct(T); this function
changes with the criterion.
*/
compute T = 2.5
display ct(T)
end
@findstep(criterion = aic) 2
throws an error:
Code: Select all
## SX22. Expected Type INTEGER, Got REAL Instead
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 8:07 am
by TomDoan
Why would the argument be real? Isn't it the number of observations?
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 8:46 am
by macro
In this case, yes, so FRML works. This was a poor example on my part, since I was hoping for a more general solution that allowed for a) variable numbers of arguments, and b) the possibility of real arguments, which would allow for a lot more flexibility when programming.
Also, I'm still missing something, I think, because this code doesn't calculate -ct- properly:
Code: Select all
calendar(q) 1947 1
compute t0 = 1970:1
compute tT = 2002:4
open data "data.csv"
data(format = cdf, org = columns) /
close data
procedure findstep criterion
option choice criterion 1 aic sbc hq
if criterion == 1 {
frml real ct = 2.0
compute criterion_lbl = "AIC"
}
else if criterion == 2 {
frml real ct = 2.0 * log(t)
compute criterion_lbl = "SBC"
}
else if criterion == 3 {
frml real ct = 2.0 * log(log(t))
compute criterion_lbl = "HQ"
}
linreg lgdpk t0 tT
# fcm10c{1 to 2} ffedc{1 to 2} lcdk{1 to 4} constant
compute T = %nobs
compute gamma = ct(T)
display T gamma
end
@findstep(criterion = aic)
This displays
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 10:14 am
by TomDoan
frml ct, not frml real ct
The latter defines a FRML named REAL with dependent variable CT.
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 10:30 am
by macro
Ok, thank you. I guess there's no way to use a FRML with multiple arguments, though, right? Any free parameters need to be declared before the FRML is instantiated and defined before it's called?
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 10:34 am
by TomDoan
Correct.
Is there a reason you can't just move the "IF" logic down into the area where you're doing the calculations (as is done in, say, @DFUNIT)?
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 10:43 am
by macro
I was trying to avoid that for maintenance reasons, because then I have numerous statements that branch based on the criterion scattered throughout the program, and if I add a criterion, I need to update all of them. Whereas, if I can have the branching done all in one place in the procedure, maintenance is significantly easier. Code reuse and all that.
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 11:57 am
by TomDoan
This seems to work on our development version now---I'm not sure at what build of 9 all of this comes together.
Code: Select all
dec hash[function[real](real,real)] fh
*
function f1 x1 x2
type real f1 x1 x2
compute f1=x1*x2
end
function f2 x1 x2
type real f2 x1 x2
compute f2=x1/x2
end f2
function f3 x1 x2
type real f3 x1 x2
compute f3=x1^x2
end f3
compute fh("bic")=f1
compute fh("sbc")=f2
compute fh("hq")=f3
*
disp fh("bic")(4.0,8.0)
disp fh("sbc")(4.0,8.0)
disp fh("hq")(4.0,8.0)
Re: Embed function inside a procedure?
Posted: Fri Oct 30, 2015 12:46 pm
by macro
Wow, thank you for the quick turnaround! I don't think that's a build I have; I'm still using the most recent Fixed Term that you sent me, and that code returns an error:
Code: Select all
Can't Interpret FUNCTION(REAL,REAL)-->REAL = FUNCTION(REAL,REAL)-->REAL
## SX27. Illegal Combination of Data Types for Operation
>>>>mpute fh("bic")=f1<<<<
I assume there isn't a timeline for a newer licensed version of RATS that incorporates all these various new features (even if the documentation isn't updated yet)? It's always convenient to have a full version instead of a time-limited one, although I realize I might be pushing the envelope here.