为什么message()比R中的print()更适合编写包?

时间:2016-04-18 16:17:06

标签: r

我希望知道为什么message()在打印诊断消息方面比print()更好。

例如,print()函数是打印R对象(例如'iris')的更好选择,而message()在我们想要连接字符串时更好,例如message("a", "b")print(paste0("a", "b"))短。

但是,我认为与上面列出的那些简单的差异更多。我已经阅读了两种方法的文档

但是,似乎它们没有像我希望的那样提供信息。

如果有人告诉我们message()优于print(),为什么会这样,我将不胜感激。

1 个答案:

答案 0 :(得分:85)

TL; DR

在为S3对象创建cat()函数时,应使用print.*。对于其他所有内容,除非程序状态有问题,否则应使用message()。例如可恢复的错误错误会导致warning()与显示停止错误使用stop()

目标

这篇文章的目的是提供有关包开发人员可以访问的不同输出选项的反馈,以及如何构造可能在新对象上或基于字符串的输出。

R输出概述

传统的输出功能是:

  1. print()
  2. cat()
  3. message()
  4. warning()
  5. stop()
  6. 现在,前两个函数(print()cat())将其输出发送到stdout或标准输出。最后三个函数(message()warning()stop())将其输出发送到stderr或标准错误。也就是说,来自lm()之类命令的结果输出被发送到一个文件,错误输出 - 如果存在 - 被发送到一个完全独立的文件。这对于用户体验尤为重要,因为诊断会使日志文件中的结果输出混乱,然后可以快速搜索错误。

    为用户和外部包设计

    现在,上面的内容更多地是在 I / O 思维模式中构建的,而不一定是面向用户的框架集。所以,让我们在日常R用户的背景下为它提供一些动力。特别是,通过使用3-5或stderr函数,可以抑制其输出,而无需通过sink()修改控制台文本。抑制通常以suppressWarnings()suppressMessages()suppressPackageStartupMessages()等形式出现。因此,用户只面临面向输出的结果。如果您计划通过knitrrmarkdownSweave创建动态文档时允许用户灵活地关闭基于文本的输出,这一点尤为重要。

    特别是,knitr提供了诸如error = Fmessage = Fwarning = F等块选项。这使得能够减少伴随文档中的命令的文本。此外,这可以防止使用会禁用所有输出的results = "hide"选项。

    输出的细节

    print()

    首先,我们有一个老人,但有一个好人,print。此功能有一些严重的限制。其中之一是缺乏嵌入式术语串联。第二个,可能更严重的是,每个输出都以[x]开头,然后是实际内容周围的引号。在这种情况下,x指的是要打印的元素编号。这有助于调试目的,但除此之外它不起任何作用。

    e.g。

    print("Hello!")
    
    [1] "Hello!"
    

    对于连接,我们依赖与paste同步的print函数:

    print(paste("Hello","World!"))
    
    [1] "Hello World!"
    

    或者,我们可以使用paste0(...)函数代替paste(...),以避免在paste()的{​​{1}} {{{{}} {{}} {{{}} {{{{ {1}}参数。 (a.k.a连接没有空格)

    e.g。

    sep = " "

    print(paste0("Hello","World!")) [1] "HelloWorld!" print(paste("Hello","World!", sep = "")) [1] "HelloWorld!"

    另一方面,cat()解决了所有这些批评。最值得注意的是,cat()功能的sep=" "参数是内置的,允许其在paste()内跳过paste()。但是,cat()函数的唯一缺点是您必须通过末尾附加的cat()\n强制换行(使用默认打印宽度)。

    e.g。

    fill = TRUE

    正是出于这个原因,您在设计cat("Hello!\n") Hello! cat("Hello","World!\n") Hello World! cat("Hello","World!\n", sep = "") HelloWorld! S3方法时应该使用cat()

    print.*

    message()功能比偶数message()更好一步!原因是输出与传统纯文本不同,因为它指向cat()而不是stderr。例如。他们将颜色从标准黑色输出更改为红色输出,以吸引用户的眼球。

    Message Output

    此外,您还拥有内置的stdout功能。

    paste0

    此外,message("Hello ","World!") # Note the space after Hello "Hello World!" 提供了可与message()

    一起使用的错误状态

    e.g。

    tryCatch()

    tryCatch(message("hello\n"), message=function(e){cat("goodbye\n")}) goodbye

    警告功能不是随便使用的。警告功能主要通过为其预先添加一行(“警告消息:”)来区分消息功能,并且其状态被认为是有问题的。

    warning output

    其他:由于示例检查和警告通常被视为“错误”,因此在尝试将程序包上传到CRAN时,函数中的偶然使用可能会无意中触发心碎。

    warning()

    最后但并非最不重要的是,我们有stop()。这会通过完全杀死手头的任务并将控制权返回给用户来将警告提升到下一级别。此外,它有最严重的附属物,添加了“错误:”一词。

    Error Output