Announcement

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

  • Where to put sub-functions used by two commands published togehter?

    Hi Statalist!

    I am writing two commands that I intend to publish in a single package on SSC. These two commands will share a lot of functionality and code, and I would like to know if someone has a suggested best practice for this.

    I do not want to copy and paste code between the two .ado files for the two commands, as it will make maintaining and updating the commands very error prone and time demanding. I want to write the sub-functions at one place in one file and have both these commands to be able to call all those sub-functions. What is the Stata/SSC best practice related to this?

    I know that additional files can be added to the package published on SSC, but what do I need to think of in order to have the two commands be able to call functions from that third file? I would prefer to not have one extra file per sub-functions as there will be many of them.

    Thanks for any advice!

    Kristoffer

  • #2
    I am guessing that by functions and "sub-functions" you refer to Stata commands used by other commands.

    If you're referring to Mata code then the details will differ but my strategic advice would be on similar lines.

    If I understand you correctly, it is fine to have a package that includes three .ado files, generically

    Code:
    main1 
    
    main2 
    
    helper
    where in practice helper would not be called directly but would be called within main1 and main2

    My experience does not match yours. Having two files, say

    main1 with command helper1 included

    main2 with command helper2 included

    has not been in my experience more notably more time-consuming or error-creating. It also leaves scope for helper1 and helper2 to differ.

    There are yet other possibilities and most hinges on what the programs do and how minor or major each one is.

    Yet more: two related commands might better belong together within a command and subcommand syntax. So that could mean one .ado file only! (One of my lesser known packages with perhaps 50 to 100 files, at least in its latest private version, could well be rewritten helpfully as a much smaller number of commands,)

    Many of us have written commands that may be used consciously most often by other programmers in the community, and knowingly rather less by users who aren't programmers. A really useful utility [word play intended] could be of more interest than your main programs. That would encourage the complete opposite, making the utility visible.

    It's a source of chagrin that use of programs can bear little relationship to how interesting or useful or engaging their own authors find them.

    I can't say more without seeing examples of what you intend, but I can't have said everything possible.

    Comment


    • #3
      Hi Nick,

      Thank you very much! Yes, you assumed correctly, and this is very close to what I want. I am a believer in the https://en.wikipedia.org/wiki/Don%27t_repeat_yourself principle so I would like one helper.ado file. And we just decided to split this up into two commands as the options required to keep them in one command grew way too complex. I could go into further detail about what it is I am doing with these commands specifically, but my question is general as I have had thought of this question before but not have not been needing it as much as this time.

      There is still one thing that is not clear to me. Correct me if I am wrong, but isn't it the case that if I have an .ado file called helper.ado saved in the ado/plus/h folder, then the only command in that file accessible outside that file is the command you call exactly helper. To use terminology used more often in other languages, a command named the same as the .ado file itself is public, all other commands in that file are private. I googled but could not find the place I had read that, so I am sorry if I am wrong.

      But if I remember correctly, if I have a file named helper.ado and it has the code below, how would I call the command subB from command main1 and main2? I want to avoid the situation with 50-100 files you mention if I were to give each utility sub-command its own .ado file.

      helper.ado
      Code:
      program define subA
          //some code
      end
      
      program define subB
         //some code 
      end
      
      program define subC
         //some code 
      end
      While working on this right now I have the following setup to get the functionality that I am looking for. But the file path used after do is to a folder in my local test environment, and I do not know how to set this up so that it works when publishing and other users installs the package from SSC.

      main1.ado
      Code:
      program define main1
      
          syntax ...
      
          do "$local_file_path/helper.ado"
      
          //the rest of the code that calls subA, subB etc.
      
      end

      Comment


      • #4
        I don't know about not repeating yourself. The principle would undermine Statalist. We should just write FAQs or articles and let people find them. Oddly, many users are very willing to answer interesting questions but it is harder work to get them to write FAQs or articles. Also, I have only a small number of statistical tricks. I just use them again and again.

        Back to the question: I think you have it correctly.

        Folders are irrelevant here in the sense that Stata is willing to look along your adopath.

        But what does makes a program helper invisible outside is being defined in an .ado with a different name. That makes it a subroutine and visible inside.

        What you are reaching for is more like what can be done with Mata where you can bundle a lot of functions into one library.

        Comment


        • #5
          Originally posted by Kristoffer Bjarkefur View Post
          [...]
          But if I remember correctly, if I have a file named helper.ado and it has the code below, how would I call the command subB from command main1 and main2?
          Nick sketched the strategy in #2.

          Code:
          proram define helper
              version 15
              gettoken subcmd 0 : 0
              if      ("`subcmd'"=="A") subA `0'
              else if ("`subcmd'"=="B") subB `0'
              else if ...
              else assert 0
          end
          
          program define subA
          //some code
          end
          
          program define subB
          //some code
          end
          
          program define subC
          //some code
          end
          Then, to call subA from main1

          Code:
          program define main1
              version 15
              helper A
          end
          Best
          Daniel

          Comment


          • #6
            haha, that is an interesting reflection about the DRY principle, Nick!

            Thanks Daniel! I will experiment with that approach!

            Comment

            Working...
            X