2014-09-25 33 views
12

Ho notato che quando chiamo args su un po 'di delle funzioni primitive, vengono visualizzati anche i codici byte. Ma su altri primitivi, non appare alcun codice byte. Per esempioPerché alcune primitive hanno codici byte e altre no?

args(length) 
# function (x) 
# NULL 
args(list) 
# function (...) 
# NULL 
# <bytecode: 0x44a0f38> 

Perché è quello?

Inizialmente ho pensato che potesse essere correlato all'argomento ..., ma quanto segue smentisce questa teoria.

args(dim) 
# function (x) 
# NULL 
args(unclass) 
# function (x) 
# NULL 
# <bytecode: 0x44a0450> 

Mi confonde che un codice byte si presenta solo in alcuni di questi e non in altri. Ho sempre avuto l'impressione che tutti i primitivi siano speciali e condividano tutti gli stessi "attributi" (per mancanza di una parola migliore, non degli attributi R reali).

+0

Immagino che la differenza di stampa sia per ragioni più storiche. 'args' è più usato per la stampa da console, forse usa' formals' per ottenere un output più coerente. – agstudy

risposta

9

Come già rilevato, questa è una stranezza legata al modo in cui args stampa le cose. Ovvero, se args include una riga di bytecode nel suo output non è un indicatore affidabile se la funzione è stata o meno compilata in byte. a confronto:

args(writeLines) 
## function (text, con = stdout(), sep = "\n", useBytes = FALSE) 
## NULL 

writeLines 
## function (text, con = stdout(), sep = "\n", useBytes = FALSE) 
## { 
## if (is.character(con)) { 
##  con <- file(con, "w") 
##  on.exit(close(con)) 
## } 
## .Internal(writeLines(text, con, sep, useBytes)) 
## } 
## <bytecode: 0x000000001bf3aeb0> 

Possiamo paragonare la stampa di una linea di bytecode per args contro la stampa funzione standard.

arg_shows_bytecode <- function(fn) 
{ 
    output <- capture.output(args(fn)) 
    grepl("^<bytecode", output[length(output)]) 
} 

printing_shows_bytecode <- function(fn) 
{ 
    output <- capture.output(print(fn)) 
    length(output) > 1 && grepl("^<bytecode", output[length(output) - 1]) 
} 

base_fns <- Filter(is.function, mget(ls(baseenv()), baseenv())) 
yn_args <- vapply(base_fns, arg_shows_bytecode, logical(1)) 
yn_print <- vapply(base_fns, printing_shows_bytecode, logical(1)) 

vale la pena notare che tutte le funzioni in cui sono riportate le informazioni args bytecode sono primitive.

head(base_fns[yn_args]) 
## $`%*%` 
## function (x, y) .Primitive("%*%") 
## 
## $as.call 
## function (x) .Primitive("as.call") 
## 
## $attr 
## function (x, which, exact = FALSE) .Primitive("attr") 
## 
## $`attr<-` 
## function (x, which, value) .Primitive("attr<-") 
## 
## $attributes 
## function (obj) .Primitive("attributes") 
## 
## $`attributes<-` 
## function (obj, value) .Primitive("attributes<-") 

Il contrario non è vero: alcune funzioni base in cui args non mostra le informazioni bytecode sono primitive; altri non lo sono.

yn_prim <- vapply(base_fns, is.primitive, logical(1)) 
table(yn_args, yn_print, yn_prim) 
## , , yn_prim = FALSE 
## 
##  yn_print 
## yn_args FALSE TRUE 
## FALSE  0 988 
## TRUE  0 0 
## 
## , , yn_prim = TRUE 
## 
##  yn_print 
## yn_args FALSE TRUE 
## FALSE  119 0 
## TRUE  63 0 

funzioni Quindi non primitive nel pacchetto di base sono tutti compilati, ma args non menzionano. Le funzioni primitive non mostrano un messaggio bytecode quando vengono stampate, e solo a volte mostrano un messaggio bytecode quando vengono chiamate con args.

+3

Spiegazione più semplice: questo è un bug in 'args()'. Non dovrebbe mai visualizzare lo stato di compilazione del codice byte, perché non è una proprietà dell'elenco di argomenti di una funzione. – hadley

1

Grazie per il rapporto. Questo comportamento non è intenzionale (un bug, come dice Hadley), non è coerente internamente poiché l'indirizzo bytecode viene visualizzato solo per builtin e speciali e solo quando i loro formals sono in .ArgsEnv (possono anche essere in .GenericArgsEnv). Ora fissato in R-devel. Le segnalazioni di bug sono meglio indirizzate direttamente a R bugzilla (anche la mailing list di R-devel funziona).

Problemi correlati