2010-03-16 9 views
41

Supongamos que tenemos la siguiente función:¿De qué maneras hay para editar una función en R?

foo <- function(x) 
{ 
    line1 <- x 
    line2 <- 0 
    line3 <- line1 + line2 
    return(line3) 
} 

Y que queremos cambiar la segunda línea a ser:

line2 <- 2 

¿Cómo hacer eso?

Una forma es utilizar

fix(foo) 

Y cambiar la función.

Otra forma es volver a escribir la función.

¿Hay alguna otra manera? (Recuerde, la tarea era cambiar solo la segunda línea)

Lo que me gustaría es representar de alguna manera la función como un vector de cadenas (bueno, caracteres), luego cambiar uno de sus valores, y luego girar en una función de nuevo.

+1

¿Y no es algo que pueda hacer pasando un parámetro a una función? ... Tenga en cuenta que también puede pasar funciones como parámetros. –

+2

Hola Leo: la pregunta es para cuando quiero cambiar una función que alguien más hizo, pero dentro del código para no tener que copiar pegue la función completa. –

+0

si necesita editar una función "interna", encontré los siguientes consejos y fragmentos muy útiles: [nabble: cómo-reemplazar-reemplazar-una-función-en-un-espacio-nombre-de-paquete] (http: // r.789695.n4.nabble.com/how-to-override-replace-a-function-in-a-package-namespace-td866337.html) –

Respuesta

21

O eche un vistazo a la función de depuración trace(). Probablemente no sea exactamente lo que está buscando, pero le permite jugar con los cambios y tiene la característica agradable de que siempre puede regresar a su función original con untrace(). trace() es parte del paquete base y viene con una página de ayuda completa y completa.

Comience por llamar al as.list (body(foo)) para ver todas las líneas de su código.

as.list(body(foo)) 
[[1]] 
`{` 

[[2]] 
line1 <- x 

[[3]] 
line2 <- 0 

[[4]] 
line3 <- line1 + line2 

[[5]] 
return(line3) 

Entonces sólo tiene que definir qué añadir a su función y dónde colocarlo mediante la definición de los argumentos en trace().

trace (foo, quote(line2 <- 2), at=4) 
foo (2) 
[1] 4 

he dicho en el principio que trace() podría no ser exactamente lo que busca, ya que en realidad no cambia su tercera línea de código y en su lugar simplemente reasigna el valor al objeto line2 en la siguiente, inserta línea de código.Se vuelve más clara si se imprime el código de su función ahora trazada

body (foo) 
{ 
    line1 <- x 
    line2 <- 0 
    { 
     .doTrace(line2 <- 2, "step 4") 
     line3 <- line1 + line2 
    } 
    return(line3) 
} 
20

fix es la mejor manera que conozco de hacer esto, aunque también se puede utilizar edit y reasignarlo:

foo <- edit(foo) 

Esto es lo que hace fix internamente. Es posible que desee hacer esto si desea volver a asignar sus cambios a un nombre diferente.

7

Puede utilizar la función 'cuerpo'. Esta función devolverá el cuerpo de la función:

fnx = function(a, b) { return(a^2 + 7*a + 9)} 
body(fnx) 
# returns the body of the function 

Así que una buena manera de 'editar' una función es utilizar 'cuerpo' en el lado izquierdo de una sentencia de asignación:

body(fnx) = expression({a^2 + 11*a + 4}) 
+1

Eso es realmente un uso de la función 'body <-'. –

33
> body(foo)[[3]] <- substitute(line2 <- 2) 
> foo 
function (x) 
{ 
    line1 <- x 
    line2 <- 2 
    line3 <- line1 + line2 
    return(line3) 
} 

(El "{" es el cuerpo (foo) [[1]] y cada línea es un elemento sucesivo de la lista.)

+7

Recientemente me vi obligado a hacer algo similar y una cosa se puede mejorar: puedes profundizar en la lista, por lo que para el caso de pregunta 'cuerpo (foo) [[3]] [[3]] <- 2' funciona y' substituto' es innecesario. – Marek

+0

Gracias. Pensé que el sustituto era necesario para mantener el modo de la expresión como un elemento de idioma. –

+2

Si reemplaza toda la línea, entonces sí, es necesario. En general: las clases deben coincidir: a mi manera trabajo porque reemplazo número por número. Si quiero reemplazar, digamos, 'line2' a' myVariable', entonces se necesita la conversión 'as.symbol'. – Marek

15

fixInNamespace es como fix, para las funciones en un paquete (incluidas las que no se han exportado).

Cuestiones relacionadas