本地中的本地在程序中评估为空

A local within a local evaluates as empty in a program

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

我在一个 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 最终为空,因此列表之间没有交集。

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

我确定是双局部宏,但我不知道如何修复它。

宏参考中的宏

``1'' 

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

`list1'

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

local vlist `list1' 

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

local vlist  

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

解决方案是你打算写

local vlist "`1'" 

或者只是

args vlist 

然而,这还没有结束。命令

lm list1 

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

此外:程序随后需要修改,因为您可能想将多个名称传递给它,如果您将它们用双引号括起来,它们只会被视为一个参数。

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

*! 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 一起使用。