Announcement

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

  • Quotes and local macros

    Hello all,

    I have been struggling with this for some time and would appreciate any advice. I checked prior statalist posts https://www.stata.com/statalist/arch.../msg01071.html and https://www.stata.com/statalist/arch.../msg00463.html, but have not fully figured this one out.

    Essentially, I want to create a local macro and add to it iteratively. Seems relatively straightforward, except that I need each argument to be in quotes (" ") in the final version of the local.

    My naive first attempt was
    Code:
    local this
    local this `this' "that"
    local this `this' "the other"
    display `"`this'"'
    which led to the output
    Code:
    that "the other"


    But I was not to be deterred. I had seen on other posts that I can "protect" quotation marks by compounding them with `', so I tried
    Code:
    local this
    local this `this' `"that"'
    local this `this' `"the other"'
    display `"`this'"'
    which led to the output
    Code:
    that `"the other"'


    Putting quotation marks around references to the local didn't seem to help
    Code:
    local this
    local this "`this'" "that"
    local this "`this'" "the other"
    display `"`this'"'
    since I got the output
    Code:
    " "that" "the other


    Which is interesting, but still not it. Putting extra single quotes around references to local `this' led to no quotation marks shown at all (no matter how I put quotes around the items being added to the local). I tried one final thing:
    Code:
    local this
    local this `"`this'"' `"that"'
    local this `"`this'"' `"the other"'
    display `"`this'"'
    which led to the output
    Code:
    thatthe other


    Again, not it. There must be some way of doing this - I just can't seem to get the quotes right! Just for clarity, I would like to be iteratively adding a new item in quotation marks, such that the final list reads
    Code:
    "that" "the other"
    Any suggestions would be greatly appreciated!
    Last edited by Jasmine Davidson; 02 Oct 2020, 16:50. Reason: edited for formatting

  • #2
    You went wrong at the very beginning. First, here I run your code and receive the output you expected.
    Code:
    . do "/var/folders/xr/lm5ccr996k7dspxs35yqzyt80000gp/T//SD15037.000000"
    
    . local this
    
    . local this `this' "that"
    
    . local this `this' "the other"
    
    . macro list _this
    _this:          that "the other"
    
    .
    end of do-file
    
    .
    I had the code in the Do-file Editor window and ran the entire contents, as the lines highlighted in red report.

    But suppose ran the lines two at a time. Then I get results like yours.
    Code:
    . do "/var/folders/xr/lm5ccr996k7dspxs35yqzyt80000gp/T//SD15037.000000"
    
    . local this
    
    . local this `this' "that"
    
    .
    end of do-file
    
    . do "/var/folders/xr/lm5ccr996k7dspxs35yqzyt80000gp/T//SD15037.000000"
    
    . local this `this' "the other"
    
    . macro list _this
    _this:          the other
    
    .
    end of do-file
    
    .
    The important thing to keep in mind is that local macros vanish when the do-file within which they were created ends. If you look carefully at the results above, you'll see that when I selected a pair of lines to run, they were copied into a temporary do-file and run, so even though the two pair of lines are in the same window in the do-file editor, they are run as separate do-files, and local macro defined in the first pair of lines vanishes at the end of that do-file, and is undefined when the second pair of lines are run.

    I used macro list rather than display because display tries too hard to figure out what you want; macro list is the only reliable way of seeing exactly what is stored in a macro.
    Code:
    . local sum 2+5
    
    . macro list _sum
    _sum:           2+5
    
    . display `sum'
    7
    
    .
    Last edited by William Lisowski; 02 Oct 2020, 19:33.

    Comment


    • #3
      I was just about to duplicate much of William Lisowski 's very helpful post, but saw it just in time. I will add that packing lots into a complicated local macro is sometimes a little futile if what you next want to do is take them all out again.

      Sometimes something more like this can help.

      Code:
      local i = 1
      
      foreach mac in "this" "that" "the other" {
          local mac`i'  `mac'
          local ++i
      }
      
      mac li
      That way you keep track of several macros in a group which can be used later. I often do something like this in preparing graphs or in saving variable labels or value labels that would otherwise disappear from a restructured dataset.

      Comment


      • #4
        I like Nick's suggestion. Reflecting on my own work, I see I'm probably too quick to store a list of things in a local macro that I then have to use : word of to retrieve.

        Reflecting on Nick's code, I've made it a little more opaque but more in keeping with uses I've made of the ++ prefix operator in other languages. To me, it's strength is precisely that it can be used as part of a complicated expression in a way that
        Code:
        local n = `n'+1
        cannot.
        Code:
        . local n 0
        
        . foreach mac in "this" "that" "the other" {
          2.    local mac`++n'  `mac'
          3. }
        
        . forvalues i=1/`n' {
          2.         macro list _mac`i'
          3. }
        _mac1:          this
        _mac2:          that
        _mac3:          the other
        
        .

        Comment


        • #5
          I just can't seem to get the quotes right
          see
          Code:
          help quotes##double


          Example code to be run from the do file editor.
          Code:
          local this                           // is empty
          local this "that"                    // copy string "that" to local this
          local this `""`this'" "the other""'  // help quotes##double
          
          mac list _this
          
          * evaluate concatenation of strings, explicit adding space separator 
          
          local this = ""
          local this = `"`this'"' + " " + `""that""'      
          local this = `"`this'"' + " " + `""the other""'
          local this = trim(`"`this'"') // if leading and trailing blanks matters
          
          mac list _this
           
          * alternative without explicit adding space separator
          
          local this = ""
          local this = `"`this'"' + `""that""'      
          local this = `"`this'"' + `""the other""'
          local this : list retokenize this  // help macrolists
          
          mac list _this
          Code:
          mac list _this
          _this:          "that" "the other"
          Last edited by Bjarte Aagnes; 03 Oct 2020, 09:23.

          Comment


          • #6
            William Lisowski and Nick Cox, I appreciate your responses. Unfortunately, they do not achieve what I need:
            I need each argument to be in quotes (" ") in the final version of the local
            since in my actual application the items in my macro list are file paths with spaces in them, and Stata reads spaces as a new item. Perhaps I am not going about my problem in the correct way though, since Nick Cox mentioned that he uses the code that he posted when preparing graphs, which is exactly what I'm attempting to do. I'll have to think through this a bit more, since if I were able to save my graphs in a way that didn't refer to the filepath, I wouldn't have to worry about getting the quotes right in the first place.

            All three of the solutions from Bjarte Aagnes worked for me (thank you!). And that is indeed the help file I needed to see where I was going wrong. I noticed the stipulation about running from the do file editor, and I am curious: why don't these work if I run the exact same commands in the command window? I am familiar with the idea that local macros are in fact local, so I can understand how if I create a local in a do file I won't be able to access it through the command window. But why don't these commands work in the command window?

            Comment


            • #7
              The commands work from the command line after removing the // comments

              Comment


              • #8
                Of course, I should have known that one. Thank you again!

                Comment


                • #9
                  I think we need further a specific example of what you are trying to do.

                  fs
                  (SSC) is a wrapper for Stata's official extended macro command that puts a set of filenames in a local macro. It exploits the fact that Stata knows to put filenames with spaces inside double quotes.

                  Not the answer you want, but I am easily old enough to have used operating systems that didn't even allow spaces in filenames, and being able to use spaces once they were allowed didn't change my habits. That works well with Stata. Naturally, at a minimum you may be downstream of other people or agencies putting spaces in their filenames.

                  Comment


                  • #10
                    Yup, I also avoid using spaces in directories, but unfortunately it's not always up to me.

                    Thanks for letting me know about the fs command!

                    I ended up -name-ing my graphs rather than -saving-, which allowed me to circumvent the problem of spaces in directories entirely. (saving was an issue because graphs are to be saved in a subfolder referred to by a macro containing the entire filepath, which contains spaces.)
                    Last edited by Jasmine Davidson; 05 Oct 2020, 09:20.

                    Comment

                    Working...
                    X