Определить список функций R - PullRequest
0 голосов
/ 02 декабря 2018

Я пытаюсь определить список функций в цикле, например так:

rr <- list(); ss <- list(list(1,2),list(3,4))

for (i in 1:length(ss)) {
  A <- ss[[i]][1]
  B <- ss[[i]][2]
  print(paste("A, B:", A, ",", B))
  rr[[i]] <- function () { force(B); B }
}

Оператор print дает:

[1] "A, B: 1 , 2"
[1] "A, B: 3 , 4"

... чточто я хочу!Но когда я пытаюсь использовать функции, я получаю неправильный ответ (A и B лениво оцениваются и, я думаю, ждут, пока функция не будет вызвана, чтобы получить их значения):

> environment(rr[[1]])$A
[[1]]
[1] 3

> rr[[1]]()
[[1]]
[1] 4

> environment(rr[[2]])$A
[[1]]
[1] 3

> rr[[2]]()
[[1]]
[1] 4

Как я могу переписать вышеуказанный цикл for, чтобы каждая функция rr[[i]] имела свой собственный внутренний набор параметров, который не будет изменен последующими rr[[n > i]] определениями функций?

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Помните fortunes::fortune(106).Конечно, есть лучший способ сделать это.

Одним из способов является создание «фабрики функций» для захвата значений.Например,

make_fn <- function(A, B) {
  force(A)
  force(B)
  function(x) A <= x & x <= B  
}

Тогда ваш цикл будет

for (i in 1:length(ss)) {
  A <- ss[[i]][1]
  B <- ss[[i]][2]
  print(paste("A, B:", A, ",", B))
  rr[[i]] <- make_fn(A, B)
}

Отредактирован для добавления ответа на комментарий: Разница здесь с force() заключается в следующем: force() применяется к обещаниямаргументы функций.В вашем примере B никогда не был аргументом для какой-либо функции, поэтому он никогда не был обещанием, а force(B) ничего не делает, кроме как возвращает его значение.В моем ответе A и B являются аргументами make_fn, поэтому, когда он оценивается, они являются обещаниями, а force() заставляет их выражения оцениваться и их значения фиксироваться.

0 голосов
/ 02 декабря 2018

Редактировать: мое решение, приведенное ниже, может кому-то помочь, поэтому я оставлю его здесь для потомков, но user2554330 s answer - гораздо лучшее решение длямой вариант использования.


Ага!Я понял это с некоторой помощью этого ответа :

rr <- list(); ss <- list(list(1,2),list(3,4))

for (i in 1:length(ss)) {
  rr[[i]] <- function(x){}
  body(rr[[i]]) <- parse(text={
    paste("(", ss[[i]][[1]], "<= x) && (x <=", ss[[i]][[2]], ")")
  })
}

> rr[[1]](1.5) # within range [1,2]
[1] TRUE
> rr[[1]](2.5)
[1] FALSE

> rr[[2]](3.5) # within range [3,4]
[1] TRUE
> rr[[2]](4.5)
[1] FALSE
...