Подтвердить что ты не робот

Почему message() лучший выбор, чем print() в R для написания пакета?

Я надеюсь узнать, почему message() является лучшим выбором, чем print(), когда дело доходит до печати диагностических сообщений.

Например, функция print() является лучшим выбором для печати объекта R, такого как 'iris', тогда как message() лучше, когда мы хотим объединить строки, например. message("a", "b") короче print(paste0("a", "b")).

Однако, я думаю, что есть больше различий, чем те простые, которые перечислены выше. Я прочитал документацию для обоих методов.

но, похоже, они не настолько информативны, как я надеялся на мой вопрос.

Буду признателен, если кто-то сообщит нам, в каком случае message() лучше, чем print(), и почему.

4b9b3361

Ответ 1

TL; DR

Вы должны использовать cat() при создании функций print.*() для объектов S3. Для всего остального вы должны использовать message(), если состояние программы не является проблематичным. например ошибка, которую можно исправить, дает warning() против ошибки остановки показа, использует stop().

Цель

Цель этого поста - предоставить обратную связь о различных параметрах вывода, к которым имеет доступ разработчик пакета, и о том, как следует структурировать вывод, который потенциально основан на новом объекте или основан на строках.

Обзор вывода R

Традиционные функции вывода:

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

Теперь первые две функции (print() и cat()) отправляют свой вывод на stdout или стандартный вывод. Последние три функции (message(), warning() и stop()) отправляют свои выходные данные в stderr или стандартную ошибку. То есть вывод результата из команды, подобной lm(), отправляется в один файл, а вывод ошибки - если он существует - отправляется в совершенно отдельный файл. Это особенно важно для взаимодействия с пользователем, поскольку диагностика не не загромождает вывод результатов в файлах журналов, а ошибки становятся доступными для быстрого поиска.

Проектирование для пользователей и внешних пакетов

Теперь, вышеупомянутое сформулировано больше в мышлении ввода/вывода и не обязательно в пользовательском наборе кадров. Итак, давайте предоставим некоторую мотивацию для этого в контексте обычного пользователя R. В частности, используя 3-5 или функции stderr, их вывод можно подавить, не вмешиваясь в текст консоли с помощью sink() или capture.output(). Подавление обычно происходит в виде suppressWarnings(), suppressMessages(), suppressPackageStartupMessages() и так далее. Таким образом, пользователи сталкиваются только с результатами, с которыми сталкиваются. Это особенно важно, если вы планируете предоставить пользователям возможность отключения текстового вывода при создании динамических документов с помощью knitr, rmarkdown или Sweave.

В частности, knitr предлагает опции чанков, такие как error = F, message = F и warning = F. Это позволяет уменьшить текст, сопровождающий команду в документе. Кроме того, это исключает необходимость использования опции results = "hide", которая отключит все выходные данные.

Особенности выхода

печать()

Во-первых, у нас есть старое, но хорошее, print(). Эта функция имеет некоторые серьезные ограничения. Одним из них является отсутствие встроенной конкатенации терминов. Вторым, и, возможно, более серьезным, является тот факт, что каждому выходу предшествует [x], за которым следуют цитаты вокруг фактического содержимого. x в этом случае относится к печатаемому номеру элемента. Это полезно для целей отладки, но за исключением этого не служит никакой цели.

например,

print("Hello!")

[1] "Hello!"

Для объединения мы полагаемся на функцию paste(), работающую синхронно с print():

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

[1] "Hello World!"

В качестве альтернативы можно использовать функцию paste0(...) вместо paste(...), чтобы избежать использования по умолчанию space между элементами, управляемыми paste()sep = " " параметр. (a.k.a конкатенация без пробелов)

например

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

[1] "HelloWorld!"

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

[1] "HelloWorld!"

кот()

С другой стороны, 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. Например. Они изменили цвет со стандартного черного на красный, чтобы привлечь внимание пользователей.

Message Output

Кроме того, у вас есть встроенная функция 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:"), и ее состояние считается проблематичным.

warning output

Прочее: случайное использование в функции может непреднамеренно вызвать разбитое сердце при попытке загрузить пакет в CRAN из-за примеров проверок и предупреждений, которые обычно рассматриваются как "ошибки".

остановки()

И последнее, но не менее важное: у нас есть stop(). Это переводит предупреждения на следующий уровень, полностью убивая задачу и возвращая управление пользователю. Кроме того, он имеет самый серьезный префикс с добавляемым термином "Error:".

Error Output