Embed function inside a procedure?

Use this forum to post questions about syntax problems or general programming issues. Questions on implementing a particular aspect of econometrics should go in "Econometrics Issues" below.
macro
Posts: 70
Joined: Thu Jul 16, 2015 3:01 pm

Embed function inside a procedure?

Unread post 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.
TomDoan
Posts: 7814
Joined: Wed Nov 01, 2006 4:36 pm

Re: Embed function inside a procedure?

Unread post 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
macro
Posts: 70
Joined: Thu Jul 16, 2015 3:01 pm

Re: Embed function inside a procedure?

Unread post 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
TomDoan
Posts: 7814
Joined: Wed Nov 01, 2006 4:36 pm

Re: Embed function inside a procedure?

Unread post by TomDoan »

Why would the argument be real? Isn't it the number of observations?
macro
Posts: 70
Joined: Thu Jul 16, 2015 3:01 pm

Re: Embed function inside a procedure?

Unread post 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

Code: Select all

132    NA
TomDoan
Posts: 7814
Joined: Wed Nov 01, 2006 4:36 pm

Re: Embed function inside a procedure?

Unread post by TomDoan »

frml ct, not frml real ct

The latter defines a FRML named REAL with dependent variable CT.
macro
Posts: 70
Joined: Thu Jul 16, 2015 3:01 pm

Re: Embed function inside a procedure?

Unread post 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?
TomDoan
Posts: 7814
Joined: Wed Nov 01, 2006 4:36 pm

Re: Embed function inside a procedure?

Unread post 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)?
macro
Posts: 70
Joined: Thu Jul 16, 2015 3:01 pm

Re: Embed function inside a procedure?

Unread post 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.
TomDoan
Posts: 7814
Joined: Wed Nov 01, 2006 4:36 pm

Re: Embed function inside a procedure?

Unread post 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)
macro
Posts: 70
Joined: Thu Jul 16, 2015 3:01 pm

Re: Embed function inside a procedure?

Unread post 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.
Post Reply