Announcement

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

  • Use of local macros in master do-file.

    Hello,

    I am running several slave do-files using a master do-file, and I am defining locals in the master do-file that are going to be used in the slave do-files. However, this does not work, and when running the master, the locals are not recognize in the slaves do-files. When using global macros, the code did the work. However, I was wondering how safe it is, since global macros are not recommended in general.


    See a simple example:

    The master do-file would be something like: (of course the real do-files are more complex (and there are several slave do-files, with different sub-tasks each one), and I really need to keep the master & slave structure - you know I don't want to have a do-file with thousands of lines, that would be very difficult to edit and recognize sub-tasks)

    Code:
    local word1 "Hello"
    local word2 "World"
    
    do "example1.do" 
    do "example2.do"
    The slave do-files would be:

    1. example1.do
    Code:
    dis "`word1'"
    2. example2.do
    Code:
    dis "`word2'"
    When running the master do-file using the locals, they are not recognizing, and the only way to did this is using global macros. I am actually familiar with the difference between local and global macros, however, I was wondering if this kind of use of global is safe in general (since the use of global is not recommended, only if it is absolutely necessary). And If you have any other idea of a different way to do this, they are also welcome! (or maybe I am missing something?)


    Thank you!




  • #2
    Sorry I forgot to mention. I actually, need to keep the locals in the master file (and not putting them in the slave do-files), since I am planning to iterate over them.

    Comment


    • #3
      The under-appreciated -include- command will solve this problem for you. Create a separate do-file that contains nothing other than the commands that create the local macros.

      Then, in the master do-file and also in all of the slave do-files, add an -include- command that includes the separate macro-defining do file. The unique thing about -include-ing a file is that Stata virtually inserts the actual contents of that do-file into the current do-file so that the macro-defining commands become part of the code in the receiving do file, and so the macros do not go out of scope. And since the macro definitions are all in a single do-file you are assured that they will always be consistent across the master and all the slaves no matter how you edit things.

      -help include-

      Comment


      • #4
        Thank you Clyde! It works perfect. I didn't know that command. What I did is use -include- command instead of the -do- command in the master file. In this way, I don't need to create a separate file for the local macros, and even I can iterate between the locals in the same master file.

        Code:
        local word1 "Hello"
        local word2 "World"
        
        include "example1.do"
        include "example2.do"

        Comment


        • #5
          Thank you for making me discover this command, Clyde.

          However, you would still need to define a local macro at the beginning of every slave do-file to locate the actual macro-defining do-file before using it. And, correct me if I'm wrong, this is not the best solution when you work with other colleagues because they would need to change this path as well for every slave do-file, while this would only need to be done once when using a global macro in the master do-file.

          I'm really trying to avoid using globals but here I don't know if there is an alternative. Would someone be kind enough to suggest me something about this topic?
          Last edited by Julia Simon; 26 Jul 2023, 05:58.

          Comment


          • #6
            If you and your colleagues keep the work-in-progress in the current working directory, then all your master do-file would need is to refer to is c(pwd).
            Code:
            help creturn##directories

            Comment


            • #7
              And, correct me if I'm wrong, this is not the best solution when you work with other colleagues because they would need to change this path as well for every slave do-file, while this would only need to be done once when using a global macro in the master do-file.
              You are implicitly assuming that the do-files involved will always be used by call from the master do-file. If run in isolation, they still require some way of designating the relevant path(s), and it is no more expensive to do that with -include- than with -global-.

              I do not deny that global macros are convenient. And I suppose the tradeoff between convenience and the danger they pose is a matter of judgment/taste. For my part, having early in my career spent a nightmarish week trying to debug a program that was broken by the use of a deeply hidden global variable (this was early days FORTRAN, not Stata), I am particularly averse to the use of globals, and have become an "information-hiding absolutist" in my programming.

              That said, I think that the use of global macros to define pathnames is a particularly high-risk use case, at least the way I usually see it done here on Statalist. If I felt compelled to use a global macro for a purpose like this, I would at least give it a name that is unlikely to be used by anybody else. Yet I frequently see -$global path whatever-. It requires a great act of faith in the team that will work on and use your code that nobody will include in the project a program that contains -$global path something_else-, which has the potential to break the entire project! If I were forced at gunpoint to use a global to define a path I would give it some bizarre hash-like name that is unlikely to be appropriated elsewhere.

              Comment

              Working...
              X