1. ホーム
  2. r

[解決済み] Rでパッケージを書くときに、print()よりもmessage()の方が良いのはなぜですか?

2023-02-09 22:28:33

質問

なぜか知りたい message() よりも良い選択です。 print() よりも良い選択です。

例えば print() のようなRオブジェクトを表示するには、この関数を使うのがよいでしょう。 'iris' のようなRオブジェクトを表示するのに適しています。 message() は文字列を連結する場合に適しています。 message("a", "b") よりも短い print(paste0("a", "b")) .

しかし、上に挙げたような単純なもの以外にも、もっと多くの違いがあると思います。私は両方のメソッドのドキュメントを読みました。

が、私の質問に対して期待していたほど有益なものではなさそうです。

私は誰かがどのような場合に私たちに教えてくれることを感謝します message() よりも print() よりも良いのか、そしてその理由は?

どのように解決するのですか?

TL;DR

あなたは cat() を作成する際に print.*() 関数を作成します。それ以外のものについては message() プログラムの状態が問題でない限り、例えば、回復可能な悪いエラーは warning() vs. 表示停止エラーは stop() .

目標

この投稿の目的は、パッケージ開発者がアクセスできるさまざまな出力オプションと、新しいオブジェクトに潜在する、または文字列に基づく出力をどのように構成すべきかについてフィードバックを提供することです。

R 出力の概要

従来の出力機能としては

  1. print()
  2. cat()
  3. message()
  4. warning()
  5. stop()

さて、最初の2つの関数( print() cat() ) は、その出力を stdout または標準出力に送ります。最後の3つの関数( message() , warning() そして stop() ) は、その出力を stderr または標準エラーに送る。つまり 結果出力 のようなコマンドからの lm() は一つのファイルに送られ、エラー出力は - 存在すれば - 完全に別のファイルに送られます。これはユーザー体験にとって特に重要で、診断が ではなく ログファイル内の結果の出力を乱雑にせず、エラーは素早く検索できるようになるからです。

ユーザーと外部パッケージのための設計

さて、上記をさらにフレーム化したのが I/O の考え方であり、必ずしもユーザー向けのフレームセットではありません。そこで、日常のRユーザーのコンテキストで、その動機を提供しましょう。特に、3-5を使うことで、あるいは stderr 関数を使うことで、それらの出力は、コンソールテキストをいじらずに sink() または capture.output() . 抑制は通常、以下のような形で行われます。 suppressWarnings() , suppressMessages() , suppressPackageStartupMessages() といった具合である。このように、ユーザーは結果に直面する出力にのみ直面することになります。これは、動的なドキュメントを作成する際に、ユーザーがテキストベースの出力を柔軟にオフにできるようにすることを計画している場合、特に重要です。 knitr , rmarkdown または スウィーブ .

特に knitr は、次のようなチャンクオプションを提供します。 error = F , message = F そして warning = F . これにより、文書中のコマンドに付随するテキストを削減することができます。さらに,これによって results = "hide" オプションを使用する必要がなくなります。

出力の具体的な内容

print()

まず最初に、古いものですが、良いものを紹介します。 print() . この関数には、いくつかの重大な制限がある。そのひとつは、項を埋め込んで連結することができないことです。もうひとつは、おそらくより深刻なことですが、各出力の前に [x] があり、その後に実際の内容を引用符で囲んでいることです。その x のように、この場合は表示される要素番号を指します。これはデバッグの際には便利ですが、それ以外では何の役にも立ちません。

print("Hello!")

[1] "Hello!"

連結のために、我々は paste() と同期して動作する print() :

print(paste("Hello","World!"))

[1] "Hello World!"

あるいは paste0(...) 関数の代わりに paste(...) をデフォルトで使用しないようにするため スペース で管理される要素間に paste() 's sep = " " というパラメータがあります。 (別名:スペースなしの連結)

など

print(paste0("Hello","World!"))

[1] "HelloWorld!"

print(paste("Hello","World!", sep = ""))

[1] "HelloWorld!"

cat()

裏を返せば cat() は、これらの批判をすべて解決しています。最も注目すべきは sep=" " のパラメータが paste() を書くのを省略できるようにする機能が組み込まれています。 paste() の中で cat() . しかし cat() 関数の唯一の欠点は、改行を強制的に \n で強制的に改行させるか fill = TRUE (デフォルトの印刷幅を使用)。

など。

cat("Hello!\n")
Hello!

cat("Hello","World!\n")
Hello World!

cat("Hello","World!\n", sep = "")
HelloWorld!

このような理由で cat() をデザインする際に print.*() S3メソッドです。

メッセージ()

この message() 関数よりも一段と優れた cat() ! に誘導されるため、出力が従来のプレーンテキストとは異なるからです。 stderr ではなく stdout . 例:ユーザーの目を引くために、標準の黒い出力から赤い出力に色を変更した。

さらに、内蔵の paste0() の機能があります。

message("Hello ","World!") # Note the space after Hello
"Hello World!"

さらに message() で使用できるエラー状態を提供します。 tryCatch()

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

警告()

warning() 関数は気軽に使うものではありません。警告機能は、メッセージ機能との違いは、主にその前にある行( "Warning message:" ) を持つことで、メッセージ関数と区別され、その状態は問題があるとみなされます。

Misc: 関数内で何気なく使用すると、パッケージを CRAN にアップロードしようとすると、例のチェックと警告が通常 "エラー" として扱われるため、不注意に心が折れることがあります。

stop()

最後になりますが、私たちは stop() . これは、手元のタスクを完全に終了させ、ユーザーにコントロールを戻すことで、警告を次のレベルへと導きます。さらに、最も深刻な接頭辞を持つ用語である "Error:" が追加されます。