【问题标题】:Stata local macro not defined未定义Stata本地宏
【发布时间】:2014-09-22 17:54:57
【问题描述】:

很多时候,我试图定义一个宏只是为了发现它没有被创建。

  • 我的第一个问题是:有没有比在我尝试的每一个可疑的 local mylocal ... 定义之后手动输入 macro list 更好的方法来跟踪这些故障?

  • 其次,为什么定义一个本地总是默默地失败?有没有办法为此事件启用警告?

  • 第三,下面的代码说明了这种行为最近让我感到沮丧的地方:抓取字符串向量中单词的位置;将位置减一;并在相应的(紧接在前面的)位置抓取单词。欢迎任何指点。

local  cuts      0 15 32 50
local  mycut     32
local  myposn    : list posof "`mycut'" in cuts

// two methods that fail loudly:
local  mynewcut  : word ``myposn'-1' of cuts

local  mynewcut  : word `myposn'-1 of cuts


// five methods that fail silently, creating nothing:
local  mynewcut  : word `=`myposn'-1' of cuts // 1

scalar tmp = `myposn'
local  mynewcut  : word `=tmp-1' of cuts // 2

scalar tmp2 = tmp -1 // 3 
local mynewcut : word `=tmp2' of cuts

local mynewposn = `=`myposn'-1'
local  mynewcut  : word `mynewposn' of cuts // 4

local  mynewcut  : word `=`mynewposn'' of cuts // 5

// also fails silently (and is not what I'm looking for):
local  mysamecut : word `myposn' of cuts

【问题讨论】:

    标签: stata verbosity


    【解决方案1】:

    这行得通:

    local  cuts      0 15 32 50
    local  mycut     32
    local  myposn    : list posof "`mycut'" in cuts
    
    local  mynewcut  : word `=`myposn'-1' of `cuts'
    display "`mynewcut'"
    

    您需要使用= 计算算术运算。在引用本地 cuts 时,您也缺少引号。

    Stata 不会将尝试使用尚未定义的宏视为错误。这是语言设计的一个要素。另外,请注意(至少)您不需要的语法之一

    local  mynewcut  : word `=`myposn'-1' of cuts
    

    并不违法,因此在这些情况下必须小心谨慎。在of 之后,Stata 只期待一些字符串,而cuts 被认为是一个字符串。这样就可以了:

    local  mynewcut  : word 2 of cuts cuts2 cuts3
    display "`mynewcut'"
    

    但可能不如预期。添加引号后情况会发生变化。 Stata 现在知道它必须进行宏替换操作。

    在将它们投入“生产”之前,我通常会好好看看当地人。但你可以使用assert。例如:

    local  cuts      0 15 32 50
    local  mycut     32
    local  myposn    : list posof "`mycut'" in cuts
    display "`myposn'"
    
    local  mynewcut  : word `=`myposn'-1' of cuts
    display "`mynewcut'"
    
    assert "`mynewcut'" != ""
    

    【讨论】:

    • 啊,呃,我的宏变量“cuts”忘记了引号。关于监控这些无声故障有什么建议吗?
    • 谢谢,我会养成使用displayassert的习惯。这种(概念上)简单的检查需要这么多引号,这太糟糕了。有趣的是,Stata 如何解析word # of 之后的任何内容。
    • 我忘记了被“报价问题”咬伤的次数。
    【解决方案2】:

    罗伯托给出了一个很好的详细答案,但另外让我们在这里尝试一个概述。关键在于您对 fail 的理解以及 Stata 是否同意您的观点。

    就 Stata 而言,删除现有的本地宏并将空字符串分配给(潜在的)本地宏名称具有相同的效果。如果我去

    local foo = 42 
    local foo 
    

    local bar 
    

    过程不同,但最终结果是相似的。在第一种情况下,名为 foo 的本地名称消失,而第二种情况下,本地宏 bar 从未创建。第二种情况并非徒劳,因为(例如)程序员经常想明确本地宏最初是空的(除非这不太可能),或者删除任何以前创建的具有该名称的宏。

    更简洁地说,Stata 不区分空(本地或全局)宏和不存在的宏,至少就用户而言。如果您将这里的定义理解为受操作系统外壳而不是字符串处理语言的启发,这就不那么奇怪了。

    但是有一个有用的结果。测试

    if "`bar'" != "" 
    

    既是对本地宏bar的存在性检验,也是对非空性的检验,它也适用于带有数字字符的宏。

    此外,在某些情况下,您可能会尝试将非空字符串放入宏中,就您而言犯了一些错误,并以分配一个空字符串结束。这可能是一个编程错误,但就 Stata 而言,这并不违法,正如上面的示例已经暗示的那样。

    这里的完整性是难以捉摸的,但还有一种情况是宏定义可能由于其他原因是非法的。于是

    local foo = lg(42)
    

    将失败,因为没有函数lg()。另一方面,

    local foo lg(42) 
    

    就 Stata 而言将成功,因为没有强制执行评估,因此 Stata 永远不必解决lg(42)。宏将只包含 lg(42) 作为文本。

    【讨论】:

    • 感谢周到的总结。 Stata 无需将命令视为非法就发出警告。在这里,这意味着注意local foo my_dumb_attempt 在“foo”之后有字符,但将一个空字符串分配给“foo”。 Stata 似乎不太适合程序员使用,所以我希望能有更多人参与。
    • 您将技术问题与更多个人或主观意见混为一谈,一对一辩论可能会很有趣,但不要轻易做出简洁的答复。 Stata 是一种很多人都乐于编程的语言,而且是长期的。 Mata 是一种嵌入式语言,它更像是许多其他人对编程语言的想法。两者都是缺乏牵手或警告的语言。这本身可能是一个问题。您的具体示例local foo my_dumb_attempt 是完全合法的; Stata 程序员一直使用这种将文本复制到宏的方式。
    • 很公平。为了澄清,my_dumb_attempt,我的意思是无数种静默到达空字符串的方法之一,而不是真正地输入或传递该命令。期待学习Mata。
    • 好的,但是这里的反引号文本往往是按字面意思理解的,有趣的例子也是课程的标准。
    猜你喜欢
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    相关资源
    最近更新 更多