Pregunta R: Promesa no puede encontrar objeto


Sé que es posible que pueda escribir una función en R, donde el valor predeterminado de un argumento es usar otro argumento de la misma función.

foo <- function(a, b = length(a)) {
  b
}

foo(a = c(1, 2))
[1] 2

Sin embargo, tan pronto como uso el mismo argumento en la llamada a la función real, aparece un error:

foo(a = c(1, 2), b = length(a))
Error in foo(a = c(1, 2), b = length(a)) : object 'a' not found

Pensé la promesa de b = length(a) debe evaluarse dentro de la función, donde a Se sabe, pero al parecer esto no está sucediendo. ¿Alguien puede explicarme dónde está el problema y cómo podría hacerlo?

foo(a = c(1, 2), b = length(a))

¿trabajo?


5
2017-07-05 07:37


origen


Respuestas:


Mi entendimiento es que cuando usted da explícitamente argumentos a una función, el comportamiento predeterminado es evaluar dichos argumentos en el entorno en el que se dieron, no el entorno de ejecución de la función (como @ Respuesta de Axeman detalles).

Es posible sortear esto (ya sea que debería es un asunto diferente). Puedes usar una combinación de substitute() (para capturar el argumento no evaluado) y eval() para cambiar el entorno en el que se evalúa el argumento. Aquí evaluamos explícitamente b en fooEntorno de ejecución:

foo <- function(a, b = length(a)) {
  eval(substitute(b), env = environment())
}

(Debido a los valores por defecto en eval(), seria suficiente con solo escribir eval(substitute(b)). Pero a veces es bueno ser explícito; De esta manera, es mucho más obvio que estamos cambiando el entorno de evaluación.)

Ahora lo siguiente no arrojará un error:

foo(a = c(1, 2), b = length(a))
#> [1] 2

sin embargo, si decide seguir esta ruta, debe ser muy explícito al documentar tal función que el b El argumento se evalúa en el entorno de ejecución. Por ejemplo, ¿qué debería pasar cuando a ¿Está presente tanto en el entorno en el que se presenta el argumento como en el entorno de ejecución? Este puede ser un comportamiento inesperado, si no está bien documentado (y es una fuente de errores difíciles de diagnosticar, incluso si está bien documentado).

a <- 1:10
foo(a = c(1, 2), b = length(a))
#> [1] 2

Para obtener más detalles sobre la evaluación (y las dificultades), puede consultar El capítulo de evaluación en Advanced R.

Creado el 2018-07-05 por el paquete reprex (v0.2.0).


3
2017-07-05 07:50



Al escribir foo(a = c(1, 2), b = length(a)), a tiene que venir del entorno de llamada, no del entorno de la función. Tendrá que utilizar:

x <- 1:2
foo(a = x, b = length(x))

O alternativamente use un argumento de función:

foo <- function(a, fun = length) { fun(a) }

Citar Hadley:

Más técnicamente, un argumento no evaluado se llama promesa, o   (menos comúnmente) un thunk. Una promesa se compone de dos partes:

  • La expresión que da lugar a la computación retrasada. (Se puede acceder con sustituto (). Ver evaluación no estándar para   más detalles.)

  • El entorno donde se creó la expresión y dónde debe evaluarse.

Tienes razón en que los argumentos son promesas y no se evalúan hasta que se necesitan. Pero, la promesa incluye el entorno donde se creó, que en este caso en el entorno global.


4
2017-07-05 07:48