I’m replying 8 months later to say a proper thanks to Duncan for the function 
below. It’s been helping me clean up duplicate (and not-quite duplicate!) 
function definitions in amateur code ever since, and I’m reminded to say so now 
because I just passed it along to Ben Zipperer in response to a very similar 
question[1] on Mastodon. 

In the Mastodon thread there were several R experts expecting the existing 
package checks to catch this and being surprised to realize they don't, which I 
think mostly goes to highlight that it really is a corner case… but in any case 
thank you for your help to keep the “bitten by function redefinition” club a 
small one.

Thanks,
Chris

[1] https://mastodon.social/@benzipperer/113328761897124440



> On Feb 7, 2024, at 11:53 AM, Duncan Murdoch <murdoch.dun...@gmail.com> wrote:
> 
> I put the idea below into a function that gives nicer looking results. Here's 
> the new code:
> 
> dupnames <- function(path = ".") {
> 
>  Rfiles <- pkgload:::find_code(path)
>  allnames <- data.frame(names=character(), filename=character(), line = 
> numeric())
>  result <- NULL
>  for (f in Rfiles) {
>    exprs <- parse(f, keep.source = TRUE)
>    locs <- getSrcLocation(exprs)
>    names <- character(length(exprs))
>    lines <- numeric(length(exprs))
>    for (i in seq_along(exprs)) {
>      expr <- exprs[[i]]
>      if (is.name(expr[[1]]) &&
>          deparse(expr[[1]]) %in% c("<-", "=") &&
>          is.name(expr[[2]])) {
>        names[i] <- deparse(expr[[2]])
>        lines[i] <- locs[i]
>      }
>    }
>    keep <- names != ""
>    if (any(keep)) {
>      names <- names[keep]
>      lines <- lines[keep]
> 
>      prev <- nrow(allnames)
>      allnames <- rbind(allnames, data.frame(name = names, filename = 
> basename(f), line = lines))
>      dups <- which(duplicated(allnames$name))
>      dups <- dups[dups > prev]
>      if (any(dups)) {
>        origfile <- character(length(dups))
>        origline <- numeric(length(dups))
>        for (i in seq_along(dups)) {
>          prev <- which(allnames$name == allnames$name[dups[i]])[1]
>          origfile[i] <- allnames$filename[prev]
>          origline[i] <- allnames$line[prev]
>        }
> 
>        result <- rbind(result,
>                        data.frame(name = allnames$name[dups],
>                                   first = paste(origfile, origline, sep=":"),
>                                   dup = paste(allnames$filename[dups], 
> allnames$line[dups], sep = ":")))
>      }
>    }
>  }
>  result
> }
> 
> 
> And here's what I get when I run it on rgl:
> 
> dupnames("rgl")
>  name      first          dup
> 1  fns knitr.R:12  knitr.R:165
> 2  fns knitr.R:12 pkgdown.R:14
> 3  fns knitr.R:12    shiny.R:8
> 
> Those are okay; the fns object is a temporary that is later removed in each 
> case.
> 
> Duncan Murdoch

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to