¿Una forma confiable de saber si = es para asignación en código R?

Soy un usuario terco que usa = en lugar de <- todo el tiempo, y aparentemente muchos programadores de R fruncirán el ceño ante esto. escribí el formatR paquete que puede reemplazar = con <- basado en el parser paquete. Como algunos de ustedes sabrán, parser quedó huérfano en CRAN hace unos días. Aunque ahora está de regreso, esto me hizo dudar en depender de él. Me pregunto si hay otra forma de reemplazar de forma segura = con <-, porque no todos =asignación media de , por ejemplo fun(a = 1). Es poco probable que las expresiones regulares sean fiables (ver línea 18 de los mask.inline() Funcionar en formatR), pero sin duda lo apreciaré si puede mejorar el mío. Quizás el codetools paquete puede ayudar?

Algunos casos de prueba:

# should replace
a = matrix(1, 1)
a = matrix(
  1, 1)

(a = 1)
a =
  1

function() {
  a = 1
}

# should not replace
c(
  a = 1
  )

c(
  a = c(
  1, 2))

preguntado el 30 de junio de 12 a las 23:06

El buen y útil código fuente abierto no muere y desaparece, y el analizador ahora tiene un nuevo mantenedor como era de esperar. ¿Dónde está exactamente el problema de depender de una herramienta probada que hace el trabajo? -

¿Por qué molestarse? ¿Y por qué la pregunta sobre reemplazar "=" con "<-" cuando su preferencia es por el primero? -

@mdsumner para satisfacer a otras personas que usan <-... por ejemplo, JSS no aceptará = y supongo que muchas personas mueren un poco por dentro cada vez que ven = para asignaciones en R -

@JasonMorgan Entiendo la decisión de JSS pero no desde el punto de vista de "simplemente trabajar en todas partes"; = funciona muy bien, como puede ver en casi todos los demás lenguajes de programación (R y S son raros al tener su propio <-). La única razón para usar <- es solo convención. No tiene ninguna ventaja sobre = (para algunas personas, tiene ventajas visuales). Trabajar en todas partes puede ser peligroso (ver cómo los expertos pueden cometer errores). -

@JasonMorgan Sí, entiendo que son diferentes. quiero decir desde = funciona bien en otros idiomas, no hay razón (excepto convención) para que sea un hereje en R. Se explicó la razón histórica aquí, que ciertamente no es una razón fuerte hoy en día. -

3 Respuestas

Esta respuesta usa expresiones regulares. Hay algunos casos extremos en los que fallará, pero debería estar bien para la mayoría del código. Si necesita una coincidencia perfecta, deberá usar un analizador, pero las expresiones regulares siempre se pueden modificar si tiene problemas.

Cuidado con

#quoted function names
`my cr*azily*named^function!`(x = 1:10)
#Nested brackets inside functions
mean(x = (3 + 1:10))
#assignments inside if or for blocks
if((x = 10) > 3) cat("foo")
#functions running over multiple lines will currently fail
#maybe fixable with paste(original_code, collapse = "\n")
mean(
  x = 1:10
)

El código se basa en un ejemplo en el ?regmatches página. La idea básica es: intercambiar el contenido de la función por un marcador de posición, hacer el reemplazo y luego volver a colocar el contenido de la función.

#Sample code.  For real case, use 
#readLines("source_file.R")
original_code <- c("a = 1", "b = mean(x = 1)")

#Function contents are considered to be a function name, 
#an open bracket, some stuff, then a close bracket.
#Here function names are considered to be a letter or
#dot or underscore followed by optional letters, numbers, dots or 
#underscores.  This matches a few non-valid names (see ?match.names
#and warning above).
function_content <- gregexpr(
  "[[:alpha:]._][[:alnum:._]*\\([^)]*\\)", 
  original_code
)

#Take a copy of the code to modify
copy <- original_code

#Replace all instances of function contents with the word PLACEHOLDER.
#If you have that word inside your code already, things will break.
copy <- mapply(
  function(pattern, replacement, x) 
  {
    if(length(pattern) > 0) 
    {
      gsub(pattern, replacement, x, fixed = TRUE) 
    } else x
  }, 
  pattern = regmatches(copy, function_content), 
  replacement = "PLACEHOLDER", 
  x = copy,
  USE.NAMES = FALSE
)

#Replace = with <-
copy <- gsub("=", "<-", copy)

#Now substitute back your function contents
(fixed_code <- mapply(
  function(pattern, replacement, x) 
  {
      if(length(replacement) > 0) 
      {
          gsub(pattern, replacement, x, fixed = TRUE) 
      } else x
  }, 
  pattern = "PLACEHOLDER", 
  replacement = regmatches(original_code, function_content), 
  x = copy,
  USE.NAMES = FALSE
))

#Write back to your source file
#writeLines(fixed_code, "source_file_fixed.R")

Respondido 02 Jul 12, 18:07

¡Muchas gracias! Realmente lo aprecio. Kohske ha encontrado una solución brillante con codetools y me envió un solicitud de extracción en Github. Esa es exactamente la solución que estaba buscando. - Yihui Xie

Guau. La solución de Kohske se ve bien. Y caminar el código seguramente será más robusto que un método de expresiones regulares. Relegue mi respuesta a "una linda demostración de expresiones regulares". - Algodón Richie

Kohske envió un solicitud de extracción En el correo electrónico “Su Cuenta de Usuario en su Nuevo Sistema XNUMXCX”. formatR paquete que resolvió el problema usando el codetools paquete. La idea básica es configurar un caminante de código para recorrer el código; cuando detecta = como símbolo de una llamada funcional, se sustituye por <-. Esto se debe a la "naturaleza Lisp" de R: x = 1 es en realidad `=`(x, 1) (lo reemplazamos por `<-`(x, 1)); por supuesto, = se trata de manera diferente en el árbol de análisis de fun(x = 1).

El formatR paquete (>= 0.5.2) desde entonces se ha librado de la dependencia en el parser paquete, y replace.assign debería ser robusto ahora.

Respondido 04 Jul 12, 03:07

Por lo que vale, acabo de escuchar que partes del analizador pueden incorporarse a la base R. - dirk eddelbuettel

¡¡Son excelentes noticias!! Gracias, @DirkEddelbuettel - Yihui Xie

La forma más segura (y probablemente la más rápida) de reemplazar = by <- está escribiendo directamente <- en lugar de tratar de reemplazarlo.

Respondido 01 Jul 12, 09:07

Cierto, pero si tiene miles de scripts que necesita "embellecer", esto podría ser de alguna ayuda. - Luštrik romano

es como decir que los programas de revisión gramatical son inútiles porque nunca se cometen errores tipográficos... - Flodel

@flodel: escribir '=' en lugar de '<-' en mi humilde opinión no es un error tipográfico sino algo deliberado. Es más como no conjugar verbos y simplemente confiar en los programas de revisión gramatical para que lo hagan por ti. - Thierry

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.