Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Use of st_local() to put items in the return list of a Stata program

    I'd like to use st_local()to put items directly into the return list of the Stata program that called the Mata code or program, but what seems to me the most straightforward approach causes a run-time error. For example:
    Code:
    cap prog drop test1
    prog test1, rclass
    // ... whatever
    // The following could of course occur as one line inside a Mata program callled here.
    mata: st_local("r(mylocal)", "1 2 3")
    end
    test1
    This fails with the following run-time error:
    _r(mylocal) invalid name
    st_local(): 3300 argument out of range
    <istmt>: - function returned error
    r(3300);


    This confuses me, since the analogous st_numscalar("r(myscalar)", 999) runs and works without complaint (although I do have questions about it, which I'll save for another day.)

    I can avoid the illegal st_local() usage by using a temporary local as an intermediary:
    Code:
    cap prog drop test2
    prog test2, rclass
    mata: st_local("temp", "1 2 3")
    return local mylocal = "`temp'"
    end
    test2
    ret list
    That's a good approach for a single local, but it doesn't work when the Mata program is going to create and return lots of macros. (An example: I have a Mata program that generates combinations from N choose k in the midst of a loop.) Rather than store each k-tuple in the Mata program, I'd like to put each one in the return list of the Stata program as it is called. Here's a silly example to play with:
    Code:
    cap prog drop test3
    prog test3, rclass
    mata: alphabet(1000)
    end
    //
    mata:
    void alphabet(real scalar n) {
       real scalar i
       string scalar s, retname
       for (i = 1; i <=n; i++) {
          s = char(runiformint(1, 1, 65, 123))
          retname = "r(mylocal" + strofreal(i) + ")"
         // I'd like to just do this here: st_local(retname, s)  
       }
    }
    end
    I could, of course, have the Mata program store each string in a Mata matrix, and then have have the Stata program extract each one and return it using a temporary local per above. That seems roundabout, and unnecessarily stores items the Mata program doesn't need. Is there another approach? Perhaps I'm missing something about how st_local() can work with r()?

  • #2
    r(), e(), s(), and c() results require st_global():

    Code:
    mata: st_global("r(mylocal)", "1 2 3")

    Comment


    • #3
      Hi Mike,

      I stepped into the same pitfall a few months ago; we did not read the documentation carefully enough. It documents that it is possible to write into return values of the calling program with st_global(), not st_local():
      Code:
      cap prog drop test1
      prog test1, rclass
          // ... whatever
          // The following could of course occur as one line inside a Mata program callled here.
          mata: st_global("r(mylocal)","1 2 3") // I modified this line
          return add // I added this line
      end
      test1
      return list
      Be careful: For this to take effect, you will have to issue a -return add- after writing back the r()-value to your program from within Mata. Otherwise, your program will not return the values in r() to its caller.

      Your second example works when modified like this:
      Code:
      cap prog drop test3
      mata : mata clear
      prog test3, rclass
          mata: alphabet(1000)
          return add // I added this line
      end
      //
      mata:
      void alphabet(real scalar n) {
         real scalar i
         string scalar s, retname
         for (i = 1; i <=n; i++) {
            s = char(runiformint(1, 1, 65, 123))
            retname = "r(mylocal" + strofreal(i) + ")"
            st_global(retname, s) // I modified this line
         }
      }
      end
      Kind regards
      Bela
      Last edited by Daniel Bela; 05 Nov 2018, 08:34.

      Comment


      • #4
        Thanks to both of you; this does it for me. I am so adverse to using globals that I wouldn't even think to read about st_global() <grin>. However, in the current situation, the usage is actually functionally a "local" usage, i.e., local to the return list of a particular program.

        Comment

        Working...
        X