Генерация функций; изменить значения по умолчанию других функций (частичные)

Мне нужен генератор функций, который принимает другую функцию и любые аргументы этой функции и устанавливает новые значения по умолчанию. Я думал @ хэдли pryr::partial была эта магическая функция. Он делает именно то, что я хочу, но вы не можете изменить это новое значение по умолчанию. Так что здесь я могу изменить sep в моем новом paste функция, но не новый по умолчанию collapse = "_BAR_", Как я могу сделать partial выполнить таким образом (т.е. по умолчанию collapse = "_BAR_" но включите настройку collapse = NULL при желании)? Если это невозможно с partial Есть ли способ переписать код для partial Для этого: https://github.com/hadley/pryr/blob/master/R/partial.r

library(pryr)
.paste <- pryr::partial(paste, collapse = "_FOO_")

.paste(1:5)
.paste(1:5, LETTERS[1:5], sep="_BAR_")
.paste(1:5, collapse=NULL)

> .paste(1:5)
[1] "1_FOO_2_FOO_3_FOO_4_FOO_5"

> .paste(1:5, LETTERS[1:5], sep="_BAR_")
[1] "1_BAR_A_FOO_2_BAR_B_FOO_3_BAR_C_FOO_4_BAR_D_FOO_5_BAR_E"

> .paste(1:5, collapse=NULL)
Error in paste(collapse = "_FOO_", ...) : 
  formal argument "collapse" matched by multiple actual arguments

3 ответа

Решение

partial подходит для фиксирования определенных значений параметров, но если вы хотите изменить значения по умолчанию, вы можете рассмотреть другую стратегию. Это будет работать

.paste <- paste
formals(.paste)$collapse <- "_FOO_"

Это изменяет параметры функции

args(.paste)
# function (..., sep = " ", collapse = "_FOO_") 
# NULL

Тогда вы можете сделать

.paste(1:5)
# [1] "1_FOO_2_FOO_3_FOO_4_FOO_5"
.paste(1:5, LETTERS[1:5], sep="_BAR_")
# [1] "1_BAR_A_FOO_2_BAR_B_FOO_3_BAR_C_FOO_4_BAR_D_FOO_5_BAR_E"
.paste(1:5, collapse=NULL)
# [1] "1" "2" "3" "4" "5"

Это постоянная функция, принимающая отличный ответ @MrFlick и включающая его в функцию для будущих поисковиков:

hijack <- function(FUN, ...){

    .FUN <- FUN

    args <- list(...)
    invisible(lapply(seq_along(args), function(i) {
        formals(.FUN)[[names(args)[i]]] <<- args[[i]]
    }))
    .FUN
}

# Теперь попробуйте

.paste <- hijack(paste, collapse = "_FOO_")

.paste(1:5)
.paste(1:5, LETTERS[1:5], sep="_BAR_")
.paste(1:5, collapse=NULL)

Уступая

> .paste(1:5)
[1] "1_FOO_2_FOO_3_FOO_4_FOO_5"

> .paste(1:5, LETTERS[1:5], sep="_BAR_")
[1] "1_BAR_A_FOO_2_BAR_B_FOO_3_BAR_C_FOO_4_BAR_D_FOO_5_BAR_E"

> .paste(1:5, collapse=NULL)
[1] "1" "2" "3" "4" "5"

Вы могли бы просто написать простую обертку

.paste <- function(..., collapse = "_FOO_"){paste(..., collapse = collapse)}

который дает

> .paste <- function(..., collapse = "_FOO_"){paste(..., collapse = collapse)}
> .paste(1:5)
[1] "1_FOO_2_FOO_3_FOO_4_FOO_5"
> .paste(1:5, collapse = NULL)
[1] "1" "2" "3" "4" "5"
Другие вопросы по тегам