PGupta
PGupta

Reputation: 183

Local macro is "disappearing" when used in a loop

I have a small code snippet where I have defined a local macro i to be used in a forvalues loop:

matrix I=I(4)
scalar x1=b[1,1]
scalar sum1=0

local  i = 2
forvalues i = 2/4 {
    scalar chk=i-1

    forvalues j = 1/`=chk' {
        scalar sum1=I[`i',`j']*x`j'+sum1
    }
    scalar x`i'=(b[`i',1]-sum1)/I[`i',`i']
}

However, Stata complains:

error 111 
i not found 

Note that this error is appearing only if I use the macro in a loop, not otherwise.

Upvotes: 0

Views: 215

Answers (1)

Nick Cox
Nick Cox

Reputation: 37278

The Stata problem you raise is with the line

scalar chk = i - 1

Stata sees a reference there to i, which evidently cannot be interpreted as a variable or scalar name, hence the error message you got. That's Stata's point of view.

From your point of view, the error is not using single quotation marks to extract the value or contents of the local macro i, or at least that appears to be your intention, as you nowhere else explain your aim. So, nothing is disappearing; you just referred to a non-existent entity. That's only a detail, however, and there is a larger story here.

Here is a first rewriting of your code.

matrix I = I(4)
scalar x1 = b[1,1]
scalar sum1 = 0

forvalues i = 2/4 {
    local chk = `i' - 1
    forvalues j = 1/`chk' {
        scalar sum1 = I[`i',`j'] * x`j' + sum1
    }
    scalar x`i' = (b[`i',1] - sum1) / I[`i',`i']
}

Notes.

  1. The line local i = 2 appears redundant. The forvalues loop initialises the macro.

  2. As a matter of style, experienced Stata programmers would typically use a local macro, not a permanent scalar, for a transient loop limit.

But wait: I(4) is just an identity matrix with 4 rows and columns, 1s on the principal diagonal and 0s elsewhere. So

I[`i',`i'] 

is necessarily 1 and

I[`i',`j'] 

for earlier entries on the same row of the matrix is 0. So sum1 is never anything but 0. So you don't need the identity matrix for any obvious purpose and your code seems reducible to extracting four scalars from a vector:

forvalues i = 1/4 {
    scalar x`i' = b[`i',1] 
}

EDIT. Double loops like

forvalues i = 2/4 {
    local chk = `i' - 1
    forvalues j = 1/`chk' {
        ...  
    }
    ...
}

can also be written more concisely

forvalues i = 2/4 {
    forvalues j = 1/`= `i' - 1' {
        ...  
    }
    ...
}

Upvotes: 1

Related Questions