【问题标题】:Use main function in R在 R 中使用 main 函数
【发布时间】:2016-01-28 18:33:19
【问题描述】:

我已经使用 R 4 个月了,我真的希望有一种方法可以像在其他语言(C++、Python...)中一样使用 main 函数

我想这样做的主要原因是我在 R 脚本中使用的所有变量都是全局变量,可能会污染我在同一脚本中定义的函数的命名空间:

f <- function(x) {
  x + a
}
a <- 50
f(5)

对我来说,这只是个人喜好。我是一个草率的程序员,我想防止自己犯愚蠢的错误。

我当然可以定义main &lt;- function() {},但我想知道是否有类似的东西:

if __name__ == "__main__": 
    main()

(在这个Python脚本中,如果函数名是main,则运行main()调用主函数。)

【问题讨论】:

  • 不懂python的朋友,if __name__ == "__main__": main()是做什么的?
  • 听起来对全局变量的依赖是问题所在。我可以建议重新考虑一下吗?替代方法是在适当的时候设置全局选项,并在函数参数中传递值。
  • @Alex:当我与他人合作时,我不希望他们花时间仔细阅读我的每一行代码并在他们的代码中采取预防措施。 ——换句话说,我不能指望其他人不那么马虎,我不怪他们,因为他们不应该这样做。我不认为 R 是一种非常面向对象的编程语言......现在,我可以确保我只使用局部变量并在我的函数中传递参数。我希望我能做得比这更好

标签: r main interactive


【解决方案1】:

所以,它与__name__ == "__main__" 不太一样,但您可能会发现这里的interactive 函数很有趣。如果您处于交互模式,则返回 TRUE

所以你可以这样做:

main <- function() {
    ....
}

if(!interactive()) {
    main()
}

这有点不同,因为如果脚本需要它,它将始终运行。

【讨论】:

  • 如果我在交互模式下使用 source("..") 这将不起作用。
【解决方案2】:

但是有什么类似的

if __name__ == "__main__": 
    main()

在 python 中?

确实有!

但是你需要使用包‘box’而不是source/packages。然后,在您的模块中,您可以编写

if (is.null(box::name())) …

...相当于Python的if __name__ == '__main__'

或者你甚至可以使用klmr/sys 模块。然后你可以写如下:

box::use(klmr/sys)

f = function(x) {
    x + a
}

sys$run({
    a = 50
    sys$print(f(5))
})

如果你在命令行(通过RscriptR CMD BATCH)执行这个脚本,它将执行sys$run指定的main函数。相反,如果将此脚本作为模块导入到另一个脚本中,则不会执行 main 函数,但仍会定义并导出 f

【讨论】:

  • @NoName “没想到”多于“不打算”。这是内置 R 机制的一个明显缺陷。 “盒子”只是解决了这些缺陷。值得注意的是,Hadley Wickham('tidyverse' 成名,R 基金会成员之一)评论了'box' 模块系统的原始版本,说如果我们可以重新设计 R 包机制,这是(类似)它应该是什么样子。
【解决方案3】:

回答您的确切问题(我没有解决它在 R 的上下文中是否有意义。我只是开始深入研究 R 并发现它不适合编写非交互式程序,所以我责备它包在我身上)。您可以创建一个主函数并将输入参数传递给它。但是,请注意,对于这项工作,您不能通过 R 调用它。看来您需要改用Rscript

main <-function (argv)
{
  if (length (argv) < 3)
    {
      cat ('usage error: requires at least 3 arguments\n',
           file=stderr ());
      return (1);
    }

  cat (sprintf ('This program was called with %d arguments\n',
                length (argv)));

  return (0);
}

if (identical (environment (), globalenv ()))
  quit (status=main (commandArgs (trailingOnly = TRUE)));

【讨论】:

  • 优雅的黑客。但是,应该注意的是,在 R 中强烈不鼓励使用分号作为语句分隔符,空格也是如此。
  • @KonradRudolph 为什么不鼓励它?它的行为很奇怪吗?还是只是风格问题?
  • 因为它没有任何意义,所以它的语法是visual clutter,即它降低了代码的信噪比,因此使它更难阅读并且更容易出错。不鼓励使用 chartjunk 的类似原因。
  • 代码中的间距并不杂乱,但它非常不习惯。几乎一致的约定是在运算符周围有两个空格,函数调用和左括号之间没有空格,左大括号与前一个语句在同一行,右大括号与父块在同一级别。 (对于运算符间距,GNU 编码标准也是如此)。 GNU 标准在 GNU 项目之外也几乎没有使用过,并且通常被视为非常古怪。
  • R 可能是一个 GNU 项目,但它不遵循 GNU 代码风格。我之所以提出格式要求,是因为 Stack Overflow 的答案是教编程,除非有充分的理由,否则教授非标准或有问题的技术通常是个坏主意。
【解决方案4】:

不确定你的函数的意义是什么,但也许解决方案是使用默认参数

f <- function(x, a = 45) {
  x + a
}
a <- 50
f(5)

然后,如果您需要更改 a 术语,请在函数内更改它,而不是依赖于调用它的上下文。

【讨论】:

    【解决方案5】:

    您可以尝试以下... 将以下块作为全局环境的一部分放在您的 R 脚本中,它会在脚本执行时调用 main() 方法。

    if(getOption("run.main", default=TRUE)) {
       main()
    }
    

    希望这符合您的要求

    if __name__ == "__main__": 
        main()
    

    【讨论】:

      猜你喜欢
      • 2012-12-31
      • 1970-01-01
      • 2019-04-25
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多