Announcement

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

  • Global macro before strings

    Dear,

    I would like to generate a new variable whose name includes a global macro in the middle of strings. An example is aaa_$var_bbb where aaa and bbb are random strings, respectively. I already defined $var (let's say, mmm) in the previous step.

    So, I would like to refer "aaa_mmm_bbb" by using aaa_$var_bbb. But when I type aaa_$var_bbb, stata thinks that there is a macro, var_bbb not var. How can I figure this out?

    Best,
    Jae

  • #2
    Do you really need globals for that? Locals are less likely to mess things up if you lose track of them.

    If you stick with globals, type

    Code:
    aaa_${var}_bbb
    The same would be easier with locals

    Code:
    aaa_`var'_bbb
    Best
    Daniel

    Comment


    • #3
      Code:
      aaa_${var}_bbb
      That said, you probably shouldn't be using a global macro for this anyway. Global macros are an inherently unsafe coding practice and should be used only when there is no alternative.* Local macros are safe. As it happens, because the `' notation is used to reference local macros, they also do not encounter the problem you ran into: when Stata encounters aaa_`var'_bbb there is no guesswork as to what is part of the macro (var) and what isn't (_bbb). So for both reasons you will be better off using a local macro to store the information.

      *For what it's worth, I have been programming in Stata for just short of 25 years now, and in all that time I have only found one situation where the use of a global macro was necessary. Most of the reasons people give for using a global macro are actually just minor inconveniences that have easy workarounds. It is true that, if you choose your global macro names carefully (and var is a very uncareful choice of name for a global macro), the chances of getting bitten by a clash with a global macro in some other program you didn't even know is running are small. But I can tell you from painful experience that if it ever does happen to you, the debugging is so frustrating and difficult that you will go to great lengths to assure yourself that it never happens to you again.

      Added: Crossed with #2. Dan Klein offers the same advice, far more succinctly, as usual.

      Comment


      • #4
        Thanks a lot for your kind suggestions, Clyde and Daniel. I've used SAS for a long time and I've just started using Stata. Stata's global macro looks more similar to the macro in SAS. I don't think that SAS has such a thing like Stata's local macro. Anyway, I think I should use local macros more often.

        An extra reason I use a global macro comes from my laziness. I'm still a beginner of Stata, so I have to execute my command to see if everything is OK whenever a new line is added. It means that I need to execute my code pretty often. As far as I know, I don't have to run the global macro every time once it is declared. But I need to always execute from the local macro when it is used. With this reason, I sometimes use a global macro. Would there be any good suggestion about this?

        Comment


        • #5
          Yes, this is a commonly offered reason for using global macros. But there are two simple workarounds.

          The key is that the code that defines the local macro must be executed in the same pass through the do-file as any code that uses that local macro. And people sometimes define a local macro near the top of the file and then refer to it much farther done. If the local macro is just a way of storing a constant value, you can simply copy the original definition of the local macro and paste it in just above the segment of code that you do want to run. Then run the code starting from that pasted copy of the definition. Alternatively, you can comment out the code between the original local macro definition and the place where you want to start and run the whole thing. (Commenting out code in the do-file editor is particularly easy in version 15 as you can just highlight the parts you want to comment out and then press CTRL-/ in Windows. There's a similar way to do it in Mac, though I don't recall what it is.)

          The above approach will only fail if the code that you want to skip over modifies the local macro when it runs and you need to refer to the updated value. In that case, when you have finished developing one section of the code and are ready to move on to the next, the last time you run the finished section, include -macro dir- at the end. That way Stata will show you the updated values of all your macros (global and local). Then write into your code new commands to set the local macros to their current values just above where you want to start your next chunk of development. Then you can just run the code from those new commands. Important, though, is to remember to remove those macro redefinitions from the do-file when it's all done. This part sounds cumbersome, and, it is, to an extent. But at least in my work, I find that the code sections that I want to avoid re-running during development are the ones with computationally intensive commands, for example, doing a mixed-effects logistic regression on a large data set. Commands like that typically don't modify any macros that you might have used to set them up. In principle, they could, but my experience is that they don't. Rather, the code that modifies the values of local macros is usually actually fairly "light on its feet" and runs quickly enough that there is no appreciable amount of time lost re-running it as I progress through code development.

          I'm still a beginner of Stata, so I have to execute my command to see if everything is OK whenever a new line is added. It means that I need to execute my code pretty often.
          Well, I don't know at what point one ceases being a beginner; I have been programming in Stata for just a few months short of 25 years now. And I still need to add code to my programs in small chunks and then execute them to make sure they are doing what I need them to do. Not one command at a time any more, but typically I don't extend my code by more than half a dozen commands at once, unless they are really simple commands.

          Finally, I will just remark that SAS and Stata have very different conceptions of data management and analysis and require very different ways of thinking about programming. I always found SAS's approach to things uncongenial to my way of thinking and I was happy to stop using it back in the mid-80's. I didn't know Stata existed until 1994--but once somebody showed it to me, I immediately recognized that its developers thought about data the same way I do. I was hooked from day one and almost never use any other statistical package any more (and never SAS, in particular). But a person who is really comfortable with SAS's way of doing things may well find converting to Stata inconvenient, particularly a person who has used SAS long enough to really have ingrained habits of use.
          Last edited by Clyde Schechter; 04 Mar 2019, 13:16.

          Comment


          • #6
            You could set up a wrapper to make sure you do not accidentally overwrite existing global macros.

            Code:
            program newglobal
                version 11
                gettoken name : 0
                capture macro list `name'
                if (_rc) {
                    global `0'
                    exit
                }
                display as err  "global macro \$`name' already defined"
                exit 110
            end
            However, this would not safeguard you against other programs overwriting your globals. Also, the wrapper would not really replace the global command; for example,

            Code:
            local foo bar
            newglobal foo : copy local foo
            would not work.


            Edit: This time, Clyde was quicker. I would just like to pick up on one of his points.

            Commenting out code in the do-file editor is particularly easy in version 15 as you can just highlight the parts you want to comment out and then press CTRL-/ in Windows. There's a similar way to do it in Mac, though I don't recall what it is.
            I found that

            Code:
            /**/
            ...
            **/
            works fine for me. Just addding (or removing) an extra white space character in the first line

            Code:
            /** /
            will outcomment (or not) the whole block of code.

            Best
            Daniel
            Last edited by daniel klein; 04 Mar 2019, 13:26.

            Comment

            Working...
            X