Hello. I just (re-)discovered that structure(sum, init = 100) is "sticky", i.e. it stays with base::sum(). Here's an minimal example:
$ R --vanilla --quiet > void <- structure(sum, some_attr = TRUE) > str(sum) function (..., na.rm = FALSE) - attr(*, "some_attr")= logi TRUE >From my very basic troubleshooting, it looks like this is happening for primitive functions. I think I understand that this comes down to primitive functions cannot be copied and baseenv() being special, i.e. in structure() there will be no copy made of the primitive function, and then attributes()<- ends up modifying the original primitive function. Even if this is a documented feature, I believe, it is a silent feature with risky side effects. We might already have code out there that silently produces incorrect results, because of this behavior. For example, I was about to a custom reduce() function where I control the initial value via an "init" attribute of the reducer function, e.g. x <- 1:10 sum1 <- reduce(x, `+`) sum2 <- reduce(x, structure(`+`, init = 100)) # == 100 + sum1 If I then call: sum3 <- reduce(x, `+`) the 'init' attribute that was set in the sum2 statement will affect sum3 such that sum3 == sum2, not sum3 == sum1 as one would expect. SUGGESTIONS: If this is a bug, then I think it needs to be fixed. If it cannot be fixed, maybe this could be protected against, e.g. > void <- structure(sum, some_attr = TRUE) Error: You must not set attributes on a primitive function: sum Maybe it's sufficient to implement a protection against this in attr()<-, attributes()<-, and class()<-. Comments? /Henrik PS. I've verified this with R 4.4.3 and R Under development (unstable) (2025-03-19 r88003). ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel