Announcement

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

  • Can I "de-reference" a string scalar?

    Hello,

    In Mata, is there a way to "de-reference" (for lack of a better term) a string scalar to return the real object that has a name equal to the value of the string scalar?

    For example, if I create mymatrix=J(7,7,32) and I create myscalar="mymatrix", is there any function f, such that f(myscalar)=J(7,7,32)?

    Thanks,
    Randy

  • #2
    Could you explain what you're trying to do? It sounds like you might be looking for pointers; but it is also likely that you're heading the wrong way.

    Edit: Let me rephrase: It's also likely that you're making things more complicated than they need to be. Depending on what exactly you want to do, you can use Stata's local macros in Mata code, as in
    Code:
    local mymatrix "J(7,7,32)" // <- define a Stata local macro
    
    mata :
    
    void mymatrix()
    {
        real matrix mymatrix
        
        
        mymatrix = `mymatrix' // <- dereference the local Macro (at compile time!)
        
        mymatrix
    }
    
    end
    which yield:
    Code:
    . mata : mymatrix()
    [symmetric]
            1    2    3    4    5    6    7
        +------------------------------------+
      1 |  32                                |
      2 |  32   32                           |
      3 |  32   32   32                      |
      4 |  32   32   32   32                 |
      5 |  32   32   32   32   32            |
      6 |  32   32   32   32   32   32       |
      7 |  32   32   32   32   32   32   32  |
        +------------------------------------+
    Last edited by daniel klein; 19 Jun 2025, 13:53.

    Comment


    • #3
      Thanks, Dan. I have a Mata function that creates a number of matrices that store the results of various calculations. Suppose the matrices are named "dog", "cat", "fred", "mary", etc. I want to add new variables to Stata and store these matrices into those new variables. The variables should take names like "dog1", "dog2", etc. where the prefix is the name of the matrix and the suffix is the column within that matrix. I could do this "manually" with one st_addvar() and one st_store() command per matrix, but since there are many, many such matrices, it would be good to be able to automate the process. If I had something like an "eval()" command, that would execute the content of a string as if it were a command, then I could loop through the elements of a string vector that contained the names of the matrices, and at each iteration, I would have the prefix for the new variable and by doing eval(stringvector[i]), I would also have the matrix to be loaded.

      So, is there such an "eval()" command in Mata? That is, a command to execute the content of a string as if it were a command? Many other languages have such a command.

      Thanks again,
      Randy

      Comment


      • #4
        Update: Here's a weird and remarkable solution. To summarize the problem, I have a matrix mymat=J(7,7,32) and a string mystring="mymat". Now, I want to execute the content of mystring as if it were typed into the command window, which would result in the matrix stored in mymat being displayed or stored into some new name. The solution is: stata("mata: newmat=" + mystring). This will create a new matrix called newmat that holds the same content held by mymat. Or, if you simply want to display the result, you can type stata("mata:"+mystring).

        It's a little odd that Mata doesn't have an eval() function, but this *seems* to be a reasonably tidy workaround.

        Comment


        • #5
          Another Update: The above solution works interactively, but not from within a function. The "stata(mata: )" command above is asking stata to issue a command into the mata command window - there's no way to instruct stata to instruct mata to reach into the within-function environment. Nor can one declare the matrix to be external from within the function because to that you'd need to be able to evaluate the string, which leads us back to the original problem.

          An alternative solution is to use an associative array. This is less than ideal because I will have to pack the array manually - providing an explicit mapping from string to matrix. But at least I'll be able to loop through the string vector and unpack the array from within that loop.

          Comment


          • #6
            Originally posted by Randy Chugh View Post
            I have a Mata function that creates a number of matrices that store the results of various calculations. Suppose the matrices are named "dog", "cat", "fred", "mary", etc. I want to add new variables to Stata and store these matrices into those new variables. The variables should take names like "dog1", "dog2", etc. where the prefix is the name of the matrix and the suffix is the column within that matrix. I could do this "manually" with one st_addvar() and one st_store() command per matrix, but since there are many, many such matrices, it would be good to be able to automate the process.
            Mata doesn't have an eval() function; it doesn't have much in the way of reflection.

            Not fully understanding what it is that you're trying to do, where do these matrix names come from? From your description, they seem to be arbitrarily derived somehow. If that's the case, then rather than keeping the matrix and its name disassociated and then grasping at how to re-associate them, you could package them together, for example, in a struct.

            As an example that allows for an arbitrary set of matrix names and for automating the integration of the corresponding matrixes into the Stata dataset afterward at a time of your choosing, perhaps consider something like the following as a possibility.
            Code:
            version 19
            
            mata:
            mata set matastrict on
            
            struct ToStata {
                real matrix Matrix
                string scalar matname
            }
            
            void function sendOne(struct ToStata scalar t) {
            
                real scalar length
                length = cols(t.Matrix)
            
                st_store(
                    1::rows(t.Matrix), 
                    st_addvar("double", J(1, length, t.matname) :+ strofreal(1..length)), 
                    t.Matrix)
            }
            
            void function send2Stata(struct ToStata vector T) {
            
                real scalar index, length
                length = length(T)
                for (index=1; index<=length; index++) {
                    sendOne(T[index])
                }
            }
            
            void function calc() {
            
                string vector MatNames
                MatNames = "Dog", "Cat", "Fred", "Mary" // Or from wherever these names come
            
                real scalar index, length
                length = length(MatNames)
            
                struct ToStata vector T
                T = ToStata(length)
            
                for (index=1; index<=length; index++) {
                    T[index].matname = MatNames[index]
                    T[index].Matrix = J(7, 7, 32)
                }
            
                // Sometime later, at your discretion
                send2Stata(T)
            }
            
            end
            
            quietly set obs 100
            mata: calc()
            
            exit
            If the matrix names are known beforehand and aren't arbitrarily created at runtime, then you might be able to tighten the code up substantially.

            Also consider class programming, which might offer a more elegant solution, depending upon the bigger picture of whatever it is that you're trying to do.

            Comment

            Working...
            X