0

我正在尝试编写一个小程序,它只需要一个变量列表,并返回一个包含数据集中实际变量的子列表。

我在一个文件中多次执行此do操作(不是按顺序执行的,因此没有循环),因此使用快速程序而不是每次都有效地复制此代码更容易。

该程序的简化版本如下。主要问题出现在第 6 行。程序的第一个参数应该是本地宏的名称,其中包含要与数据集中的变量名称进行比较的变量名称。因此,例如,如果本地宏是list1,则程序的第一个参数是list1,并且我想存储一个新的本地宏vlist,它包含 中的所有变量list1

但是当我尝试这样做时:

``1'' 

生成的本地宏vlist最终只是空的,而本地allvars很好。

我的程序代码如下:

    clear
    cap program drop lm
    program define lm
        * Create a new local, vlist, that is all the variables in the local macro identified in argument 1
        local vlist  ``1''

        * Create a new local, allvars, that is all variables in teh dataset
        qui ds, a
        local allvars `r(varlist)'

        * Display both macros, to illustrate that vlist is empty, while allvars contains all variables
        di as text "vlist:      " as result "`vlist'"
        di as text "allvars:    " as result "`allvars'" _newline

        * Create a new local macro that is the intersection of the two lists (if it worked)
        local `1'_inter : list vlist & allvars

        * Display different messages depending on the outcome (e.g. if a list was created, or empty)
        if missing("``1'_inter'") di as error "There are no common variables between `1' and the dataset."
        else di as result "`1' intersection with varlist _all now stored as local: `1'_inter"
        end

    clear
    input float(var1 var2 var3 var4 var5)   // Input irrelevant data
    . . . . .
    end

    /*  Next, create a macro with a list of variables that are in the dataset
        (e.g. var1 and var2), and even some that are not in teh data (var7). */ 
    local list1 var1 var2 var7

    * Execute the list-match program
    lm list1

如您所见,本地vlist最终为空,因此列表之间没有交集。

知道我在这里做错了什么吗?

我确定这是双本地宏,但我不确定如何修复它。

4

1 回答 1

2

宏参考中的宏

``1'' 

评价如下。首先,宏1是您作为命令参数键入的第一件事,在您的示例中是list1,因此替换Stata 然后看到

`list1'

并且整个命令现在被评估为

local vlist `list1' 

然后评估如下。本地宏中有list1什么?完全没有,或者是一个空字符串,因为在程序中的那个点不存在这样的本地宏(并且在其他任何地方创建的任何其他本地宏都是不可见的,因为这就是本地的意思:对相关程序空间来说是本地的)。所以接下来的Stata会看到

local vlist  

您可以同时创建一个本地宏并将其清空,从而将其销毁。

解决方案是你打算写

local vlist "`1'" 

或者也许只是

args vlist 

然而,这还不是结束。命令

lm list1 

提及您刚刚创建的本地宏的名称。但是将本地宏的名称传递给另一个程序是徒劳的,因为其他程序看不到宏的内容。你必须传递内容。

还有更多:然后需要修改程序,因为您可能希望将多个名称传递给它,并且如果您将它们绑定在双引号中,它们只会被视为单个参数。

FWIW,您描述的问题似乎是由isvarSSC 解决的。这里是:

*! NJC 1.0.0 20 Sept 2005 
program isvar, rclass  
        version 8 
        syntax anything 

        foreach v of local anything { 
                capture unab V : `v' 
                if _rc == 0 local varlist `varlist' `V' 
                else        local badlist `badlist' `v' 
        }

        di 

        if "`varlist'" != "" { 
                local n : word count `varlist' 
                local what = plural(`n', "variable") 
                di as txt "{p}`what': " as res "`varlist'{p_end}" 
                return local varlist "`varlist'" 
        }       

        if "`badlist'" != "" {
                local n : word count `badlist' 
                local what = plural(`n', "not variable") 
                di as txt "{p}`what': " as res "`badlist'{p_end}" 
                return local badlist "`badlist'" 
        }       
end 

我喜欢,ds但我不会在这里使用它。您可能会调用数千个变量名称来检查数据集中是否有几个名称。

关于风格的最后评论

local list1 var1 var2 var7
lm list1

也可能是

lm var1 var2 var7

因为将名称放入包(本地宏)并在您可以直接传递名称时使用包的名称没有任何价值。如前所述,在您修复它之前,这不适用于您的程序,但它适用于isvar.

于 2018-03-01T15:55:49.847 回答