Announcement

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

  • List question

    I hava a question about how locals deal with lists.

    If I enter:
    Code:
    local testlist "bob" "bob sue" "sue bob ed"
    foreach x of local testlist {
      2.         di "`x'"
      3. }
    bob
    bob sue
    sue bob ed
    which is what I expected.

    But if I enter:

    Code:
    local testlist "bob sue" "bob" "sue bob ed"
    
    foreach x of local testlist {
      2.         di "`x'"
      3. }
    bob
    sue
    bob
    sue bob ed
    I'm confused why in the second instance "bob sue" is treated as two different values.

    Apologies if the answer is obvious.

    Tim

  • #2
    Welcome to Statalist, Tim.

    First, consider the following.
    Code:
    . local testlist1 "bob" "bob sue" "sue bob ed"
    
    . local testlist2 "bob sue" "bob" "sue bob ed"
    
    . macro list _testlist1 _testlist2
    _testlist1:     bob" "bob sue" "sue bob ed
    _testlist2:     bob sue" "bob" "sue bob ed
    
    .
    . local testlist1 `" "bob" "bob sue" "sue bob ed" "'
    
    . local testlist2 `" "bob sue" "bob" "sue bob ed" "'
    
    . macro list _testlist1 _testlist2
    _testlist1:      "bob" "bob sue" "sue bob ed"
    _testlist2:      "bob sue" "bob" "sue bob ed"
    So the answer to your problem is to surround your full list in compound double quotes. If "compound double quotes" doesn't mean anything to you, read through the output of help quotes.

    Now, as to what happened in your case, this is sort of a known but subtle trap that I find difficult to retain the logic for clearly in my mind, much less explain coherently. All I can say is that the syntax for the local command (look at help local) accepts exactly one string, enclosed at least in double quotes, or optionally in compound double quotes, which are required in this case, since the string itself contains double quotes. Please don't ask me to explain that more coherently, it hurts my head, since I know that generally you can omit the quotation marks with no ill effect, even though the syntax suggests they are required.

    Let me add that if this was a simple example of a longer problem, and you needed to stretch the list over several lines,
    Code:
    local testlist2 `" "bob sue" ///
        "bob" ///
        "sue bob ed" "'
    won't work, a string cannot span several lines. Instead, use the #delimit command.
    Code:
    #delimit ;
    local testlist2 `" "bob sue"
        "bob"
        "sue bob ed" ;
    #delimit cr
    Last edited by William Lisowski; 20 Jan 2018, 17:57.

    Comment


    • #3
      The rule to learn here is that

      * if present, one pair of outer double quotes " " as delimiters are stripped on input to local

      The consequence is that

      * other pairs of " " within a string will survive, ideally to be input for some command later.

      A fuller version of the truth is that this applies to `" "' too.

      So (in this example I delete output irrelevant to the question) the outermost " " are stripped:

      Code:
      . local testlist1 "bob" "bob sue" "sue bob ed"
      
      . mac li
      _testlist1:     bob" "bob sue" "sue bob ed
      The outcome is not what you wanted. You meant all double quotes you typed to survive. So, you must protect all of those from being stripped. An extra pair of outer double quotes must be added as protection, or if you prefer as sacrifice (in a benign sense).

      Comment


      • #4
        Thank you both for the explanation. This was helpful and informative.

        Tim

        Comment


        • #5
          My thanks to Nick for the fuller explanation, which finally cleared things up for me. I find it helpful to think of local exceptionally looking first at the left end of its input for double quotes, and if found, then at the right end for a match -- as opposed to the left-to-right parsing normally encountered with strings. It's that familiarity of left-to-right parsing that confused me.

          Here are some examples demonstrating that compound double quotes are not required in situations analogous to post #1, contrary to my implicit assertion. I will add in passing that I would prefer it if local were to treat my example m41 as it treats m51 - rather than balking at an unmatched double quote on the left when it doesn't do so for the same on the right.

          Code:
          . local m11 a b c
          
          . local m12 "a b c"
          
          . local m13 `"a b c"'
          
          . macro list _m11 _m12 _m13 
          _m11:           a b c
          _m12:           a b c
          _m13:           a b c
          
          . local m21 a "b b" c
          
          . local m22 "a "b b" c"
          
          . local m23 `"a "b b" c"'
          
          . macro list _m21 _m22 _m23
          _m21:           a "b b" c
          _m22:           a "b b" c
          _m23:           a "b b" c
          
          . local m31 "a a" "b b" "c c"
          
          . local m32 ""a a" "b b" "c c""
          
          . local m33 `""a a" "b b" "c c""'
          
          . macro list _m31 _m32 _m33
          _m31:           a a" "b b" "c c
          _m32:           "a a" "b b" "c c"
          _m33:           "a a" "b b" "c c"
          
          . local m41 "a a" b c
          invalid syntax
          r(198);
          
          . local m42 ""a a" b c"
          
          . local m43 `""a a" b c"'
          
          . macro list _m42 _m43
          _m42:           "a a" b c
          _m43:           "a a" b c
           
          . local m51 a b "c c"
          
          . macro list _m51
          _m51:           a b "c c"

          Comment

          Working...
          X