Это довольно простой и общий вопрос, но я не видел, чтобы это уже обсуждалось. Надеюсь, я ничего не пропустил.
Я начинаю разрабатывать большие программы с несколькими уровнями функций, и хотя на других языках программирования есть четкие стратегии, я не могу найти каноническое решение в R о том, как обрабатывать "параметры" функции, которая также будет имеют "аргументы". Я делаю концептуальную разницу между "параметрами" и "аргументами", даже если они на самом деле одинаковы для функции: входы. Первые будут установлены на более высоком уровне и не будут меняться часто, а последние - это реальные данные, которые будут обрабатывать функции.
Рассмотрим этот простой пример:
Подфункция интереса SF() многократно запрашивается с помощью разных аргументов "WORKER", но с теми же параметрами, которые установлены "выше". Конечно, тот же вопрос относится к более сложным случаям с несколькими слоями.
Я вижу два способа борьбы с этим: 1. Передача всего, но: а. Вы получите множество аргументов в вызове функции или структуру, включающую все эти аргументы. б. Поскольку R делает копии аргументов для вызова функций, это может быть не очень эффективно. 2. Динамически оценивать функции каждый раз, когда вы меняете параметры, и "убирать" их в определение функции. Но я не уверен, как это сделать, особенно в чистом виде.
Ничто из этого не кажется действительно симпатичным, поэтому мне было интересно, есть ли у вас, ребята, мнение по этому поводу? Может быть, мы могли бы использовать некоторые экологические особенности R?:-)
Спасибо!
РЕДАКТИРОВАТЬ. Поскольку для некоторых код лучше, чем графики, вот пример фиктивного примера, в котором я использовал метод "1.", передавая все аргументы. Если у меня много слоев и подфункций, передача всех параметров промежуточным слоям (здесь WORKER()) кажется невелика. (с точки зрения кода и производительности)
F <- function(){
param <- getParam()
result <- WORKER(param)
return(result)
}
getParam <- function(){
return('O')
}
WORKER <- function(param) {
X <- LETTERS[1:20]
interm.result <- sapply(X,SF,param) # The use of sapply here negates maybe the performance issue?
return(which(interm.result=='SO'))
}
SF <- function(x,param) {
paste0(x,param)
}
EDIT 2. Простота приведенного выше примера вводит в заблуждение некоторых из тех, кто смотрит на мою проблему, так что вот более конкретная иллюстрация, использующая дискретный градиентный спуск. Опять же, я сохранил это просто, поэтому все можно было записать в одной и той же большой функции, но это не то, что я хочу сделать для моей реальной проблемы.
gradientDescent <- function(initialPoint= 0.5, type = 'sin', iter_max = 100){
point <- initialPoint
iter <- 1
E <- 3
deltaError <- 1
eprev <- 0
while (abs(deltaError) > 10^(-2) | iter < iter_max) {
v_points <- point + -100:100 / 1000
E <- sapply(v_points, computeError, type)
point <- v_points[which.min(E)]
ef <- min(E)
deltaError <- ef - eprev
eprev <- ef
iter <- iter+1
}
print(point)
return(point)
}
computeError <- function(point, type) {
if (type == 'sin') {
e <- sin(point)
} else if (type == 'cos') {
e <- cos(point)
}
}
Я считаю неоптимальным передавать параметр "type" подфункции каждый раз, когда он оценивается. Похоже, что ссылка, приводимая @hadley на Closures и объяснение @Greg, - хорошие пути к решению, которое мне нужно.