View in Telegram
Оптимизация функций в R: переосмысление аргументов с S7 Функции с множеством аргументов могут быть трудными для использования и сопровождения. Чтобы решить эту проблему, можно использовать подход с объектами опций (options objects), применяя возможности системы S7 (новая реализация ООП в R о которой мы недавно говорили). Рассмотрим пример, как можно переработать функцию readr::read_csv(). Проблема: слишком много параметров Функция readr::read_csv() имеет более 20 аргументов, многие из которых редко используются, например, locale, skip, na. Перенос менее востребованных настроек в объект опций позволяет: ● Сократить количество аргументов в функции. ● Улучшить читаемость и поддерживаемость кода. ● Обеспечить строгую типизацию параметров. Шаг 1: Создание свойств с помощью new_property() Для начала определим свойства, которые будут использоваться в нашем объекте опций. Например, свойство для параметра `locale:
library(S7)

.locale <- new_property(
  class_list,
  default = readr::default_locale(),
  validator = function(value) {
    dnames <- value$date_names
    invalid <- !rlang::is_character(dnames$mon, n = 12) ||
      !rlang::is_character(dnames$mon_ab, n = 12) ||
      !rlang::is_character(dnames$day, n = 7) ||
      !rlang::is_character(dnames$day_ab, n = 7) ||
      !rlang::is_character(dnames$am_pm, n = 2) || !rlang::is_scalar_character(value$date_format) || !rlang::is_scalar_character(value$time_format) || !rlang::is_scalar_character(value$decimal_mark) || !rlang::is_scalar_character(value$grouping_mark) || !rlang::is_scalar_character(value$tz) || !rlang::is_scalar_character(value$encoding)

    if (invalid) {
      "expected `locale` object"
    }
  }
)
Этот код задает значения по умолчанию и проверяет, что все элементы locale имеют правильный тип. Подобным образом мы можем создать объекты опций для большинства других аргументов: ● naquotecommenttrim_wsskipn_maxguess_maxname_repairnum_threadsprogressshow_col_typesskip_empty_rowslazy Шаг 2: Создание класса с помощью new_class() Теперь создадим класс для объекта опций, который объединяет все свойства, включая locale, na, trim_ws и другие:
class_readr_opts <- new_class(
  "readr_opts",
  properties = list(
    locale = .locale,
    na = .na,
    quote = .quote,
    comment = .comment,
    trim_ws = .trim_ws,
    skip = .skip,
    n_max = .n_max,
    guess_max = .guess_max,
    name_repair = .name_repair,
    num_threads = .num_threads,
    progress = .progress,
    show_col_types = .show_col_types,
    skip_empty_rows = .skip_empty_rows,
    lazy = .lazy
  )
)

opts <- class_readr_opts()
opts
Такой подход позволяет гибко задавать опции с использованием строгой типизации. Шаг 3: Переопределение функции read_csv() После создания объекта опций можно переопределить функцию read_csv() для работы с новым подходом:
read_csv <- function(
  file,
  col_names = TRUE,
  col_types = NULL,
  col_select = NULL,
  id = NULL,
  options = class_readr_opts()
) {
    # function logic
}
Вместо передачи множества опциональных аргументов пользователь может передать объект options, упростив вызов и настройку функции. ———————————— Использование объектов опций с S7 позволяет уменьшить сложность функций, сделать их более читаемыми и строго типизированными. Такой подход особенно полезен при разработке библиотек и сложных API. Ссылки: ● В основе поста лежит статья "S7 & Options objects" #заметки_по_R
Love Center - Dating, Friends & Matches, NY, LA, Dubai, Global
Love Center - Dating, Friends & Matches, NY, LA, Dubai, Global
Find friends or serious relationships easily