2012-05-20 10 views
7

Tengo un problema con el paquete MNP que he rastreado a una desafortunada llamada a deparse (cuyo ancho máximo está limitado a 500 caracteres).Obligar a la función de un paquete a utilizar la función proporcionada por el usuario

de fondo (fácilmente puede omitir si estás aburrido)

Debido mnp utiliza una sintaxis un tanto peculiar para permitir la variación de conjuntos de elección (se incluye en la definición cbind(choiceA,choiceB,...) fórmula), el lado izquierdo de la fórmula la llamada tiene 1700 caracteres o menos cuando model.matrix.default llama al deparse. Desde deparse soporta un máximo width.cutoff de 500 caracteres, la línea sapply(attr(t, "variables"), deparse, width.cutoff = 500)[-1L] en model.matrix.default tiene como primer elemento:

[1] "cbind(plan1, plan2, plan3, plan4, plan5, plan6, plan7, plan8, plan9, plan10, plan11, plan12, plan13, plan14, plan15, plan16, plan17, plan18, plan19, plan20, plan21, plan22, plan23, plan24, plan25, plan26, plan27, plan28, plan29, plan30, plan31, plan32, plan33, plan34, plan35, plan36, plan37, plan38, plan39, plan40, plan41, plan42, plan43, plan44, plan45, plan46, plan47, plan48, plan49, plan50, plan51, plan52, plan53, plan54, plan55, plan56, plan57, plan58, plan59, plan60, plan61, plan62, plan63, "  
[2] " plan64, plan65, plan66, plan67, plan68, plan69, plan70, plan71, plan72, plan73, plan74, plan75, plan76, plan77, plan78, plan79, plan80, plan81, plan82, plan83, plan84, plan85, plan86, plan87, plan88, plan89, plan90, plan91, plan92, plan93, plan94, plan95, plan96, plan97, plan98, plan99, plan100, plan101, plan102, plan103, plan104, plan105, plan106, plan107, plan108, plan109, plan110, plan111, plan112, plan113, plan114, plan115, plan116, plan117, plan118, plan119, plan120, plan121, plan122, plan123, " 
[3] " plan124, plan125, plan126, plan127, plan128, plan129, plan130, plan131, plan132, plan133, plan134, plan135, plan136, plan137, plan138, plan139, plan140, plan141, plan142, plan143, plan144, plan145, plan146, plan147, plan148, plan149, plan150, plan151, plan152, plan153, plan154, plan155, plan156, plan157, plan158, plan159, plan160, plan161, plan162, plan163, plan164, plan165, plan166, plan167, plan168, plan169, plan170, plan171, plan172, plan173, plan174, plan175, plan176, plan177, plan178, plan179, " 
[4] " plan180, plan181, plan182, plan183, plan184, plan185, plan186, plan187, plan188, plan189, plan190, plan191, plan192, plan193, plan194, plan195, plan196, plan197, plan198, plan199, plan200, plan201, plan202, plan203, plan204, plan205, plan206, plan207, plan208, plan209, plan210, plan211, plan212, plan213, plan214, plan215, plan216, plan217, plan218, plan219, plan220, plan221, plan222, plan223, plan224, plan225, plan226, plan227, plan228, plan229, plan230, plan231, plan232, plan233, plan234, plan235, " 
[5] " plan236, plan237, plan238, plan239, plan240, plan241, plan242, plan243, plan244, plan245, plan246, plan247, plan248, plan249, plan250, plan251, plan252, plan253, plan254, plan255, plan256, plan257, plan258, plan259, plan260, plan261, plan262, plan263, plan264, plan265, plan266, plan267, plan268, plan269, plan270, plan271, plan272, plan273, plan274, plan275, plan276, plan277, plan278, plan279, plan280, plan281, plan282, plan283, plan284, plan285, plan286, plan287, plan288, plan289, plan290, plan291, " 
[6] " plan292, plan293, plan294, plan295, plan296, plan297, plan298, plan299, plan300, plan301, plan302, plan303, plan304, plan305, plan306, plan307, plan308, plan309, plan310, plan311, plan312, plan313)" 

Cuando model.matrix.default pruebas de esto en contra de las variables en el data.frame, devuelve un error.

El problema

Para evitar esto, he escrito un nuevo deparse función:

deparse <- function (expr, width.cutoff = 60L, backtick = mode(expr) %in% 
    c("call", "expression", "(", "function"), control = c("keepInteger", 
                 "showAttributes", "keepNA"), nlines = -1L) { 
    ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines)) 
    paste0(ret,collapse="") 
    } 

Sin embargo, cuando corro mnp de nuevo y paso a través, devuelve el mismo error de la misma razón (base::deparse se está ejecutando, no es mi deparse).

Esto es algo sorprendente para mí, como lo que espero es más tipificada por este ejemplo, donde la función definida por el usuario temporalmente sobre-escribe la función de base:

> print <- function() { 
+ cat("user-defined print ran\n") 
+ } 
> print() 
user-defined print ran 

que dan cuenta de la manera correcta para resolver este problema es reescribir model.matrix.default, pero como una herramienta para la depuración tengo curiosidad sobre cómo forzarlo a usar mi deparse y por qué el comportamiento anticipado (por mí) no está sucediendo aquí.

Respuesta

4

Las funciones fixInNamespace y assignInNamespace se proporcionan para permitir la edición de las funciones existentes. Tu podrías intentar ...pero voy a no desde limpiando con deparse parece demasiado peligroso:

assignInNamespace("deparse", 
        function (expr, width.cutoff = 60L, backtick = mode(expr) %in% 
       c("call", "expression", "(", "function"), control = c("keepInteger", 
       "showAttributes", "keepNA"), nlines = -1L) { 
    ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines)) 
    paste0(ret,collapse="") 
         } , "base") 

Hay una indicación en la página de ayuda que el uso de tales funciones tiene restricciones y no me sorprendería que dicha función básica podría tener adicional capas de protección. Dado que funciona a través de efectos secundarios, no debería necesitar asignar el resultado.

+0

Otra precaución se da en '? FixInNamespace':" Ellos [las funciones documentadas] no deberían usarse en el código de producción ". –

+0

Obtuve la idea de los esfuerzos de @ gsk3 de que esto era para fines "experimentales". –

+0

Gracias, y advertencias debidamente anotadas. Probablemente cambie la función que llama 'deparse' en lugar de' deparse'. –

3

Esta es la forma en paquetes con espacios de nombres para las funciones de búsqueda, como se describe en Section 1.6, Package Namespaces de Writing R Extensions

espacios de nombres están selladas una vez que se cargan. El sellado significa que las importaciones y las exportaciones no pueden modificarse y que los enlaces de variables internas no se pueden cambiar. El sellado permite una estrategia de implementación más simple para el mecanismo del espacio de nombres. El sellado también permite el análisis de código y las herramientas de compilación para identificar con precisión la definición correspondiente a una referencia de variable global en un cuerpo de función.

El espacio de nombres controla la estrategia de búsqueda de las variables utilizadas por las funciones en el paquete. Si no se encuentra localmente, R busca primero el espacio de nombre del paquete , luego las importaciones, luego el espacio de nombres base y luego la ruta de búsqueda normal.

+0

Pensé que algo así estaba pasando, por lo que ha identificado el problema. ¿Ahora cómo anular? :-) –

+0

@ gsk3: es probable que rompa algo sobrescribiendo 'deparse', por lo que le sugiero que busque la ubicación exacta de la llamada' deparse' que desea cambiar, inserte su función justo antes de esa llamada y restaure el original 'deparse' inmediatamente después. Es posible que pueda usar 'fixInNamespace' para cambiar la función que contiene la llamada' deparse' que desea cambiar. –

Cuestiones relacionadas