Kaip peržiūrėti šaltinio kodą funkcijai?

Noriu pamatyti funkcijos šaltinio kodą, kad pamatytumėte, kaip jis veikia. Žinau, kad galiu spausdinti funkciją įvesdamas jo pavadinimą eilutėje:

 > t function (x) UseMethod("t") <bytecode: 0x2332948> <environment: namespace:base> 

Šiuo atveju, ką reiškia „ UseMethod("t") ? Kaip rasti iš tikrųjų naudojamą šaltinio kodą, pavyzdžiui: t(1:10) ?

Ar yra skirtumas tarp to, kada matau „ UseMethod ir kada matau standardGeneric ir showMethods , kaip ir with ?

 > with standardGeneric for "with" defined from package "base" function (data, expr, ...) standardGeneric("with") <bytecode: 0x102fb3fc0> <environment: 0x102fab988> Methods may be defined for arguments: data Use showMethods("with") for currently available ones. 

Kitais atvejais matau, kad vadinamos R funkcijos, tačiau negaliu rasti šių funkcijų šaltinio kodo.

 > ts.union function (..., dframe = FALSE) .cbind.ts(list(...), .makeNamesTs(...), dframe = dframe, union = TRUE) <bytecode: 0x36fbf88> <environment: namespace:stats> > .cbindts Error: object '.cbindts' not found > .makeNamesTs Error: object '.makeNamesTs' not found 

Kaip rasti tokias funkcijas kaip .cbindts ir .makeNamesTs ?

Kitais atvejais yra keletas R kodų, tačiau dauguma darbų atrodo kitur.

 > matrix function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL) { if (is.object(data) || !is.atomic(data)) data <- as.vector(data) .Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow), missing(ncol))) } <bytecode: 0x134bd10> <environment: namespace:base> > .Internal function (call) .Primitive(".Internal") > .Primitive function (name) .Primitive(".Primitive") 

Kaip žinoti, kas yra. Be to, kai kurios funkcijos vadina .Call , .Fortran , .External .Internal arba .Internal . Kaip rasti jų kodą?

425
07 окт. 07 Spalis - Joshua Ulrich 2013-10-07 16:58 '13, 16:58, 2013-10-07 16:58
@ 9 atsakymai

UseMethod("t") nurodo, kad t() yra ( S3 ) bendroji funkcija, turinti metodus skirtingų objektų klasėms.

S3 metodo siuntimo sistema

S3 klasėms galite naudoti methods funkciją tam tikrų bendrų funkcijų ar klasių metodų sąrašui.

 > methods(t) [1] t.data.frame t.default t.ts* Non-visible functions are asterisked > methods(class="ts") [1] aggregate.ts as.data.frame.ts cbind.ts* cycle.ts* [5] diffinv.ts* diff.ts kernapply.ts* lines.ts [9] monthplot.ts* na.omit.ts* Ops.ts* plot.ts [13] print.ts time.ts* [<-.ts* [.ts* [17] t.ts* window<-.ts* window.ts* Non-visible functions are asterisked 

„Nematomos funkcijos yra žvaigždutės“ reiškia, kad funkcija nėra eksportuojama iš paketo vardų erdvės. Šaltinio kodą galite peržiūrėti funkcija ::: (t.y. stats:::t.ts ) arba su getAnywhere() . getAnywhere() yra naudinga, nes jums nereikia žinoti, iš kurios paketo ši funkcija buvo gauta.

 > getAnywhere(t.ts) A single object matching 't.ts' was found It was found in the following places registered S3 method for t from namespace stats namespace:stats with value function (x) { cl <- oldClass(x) other <- !(cl %in% c("ts", "mts")) class(x) <- if (any(other)) cl[other] attr(x, "tsp") <- NULL t(x) } <bytecode: 0x294e410> <environment: namespace:stats> 

S4 siuntimo sistema

S4 sistema yra naujesnio metodo dispečerinė sistema ir yra alternatyva S3 sistemai. Čia yra S4 funkcijos pavyzdys:

 > library(Matrix) Loading required package: lattice > chol2inv standardGeneric for "chol2inv" defined from package "base" function (x, ...) standardGeneric("chol2inv") <bytecode: 0x000000000eafd790> <environment: 0x000000000eb06f10> Methods may be defined for arguments: x Use showMethods("chol2inv") for currently available ones. 

Išvestyje jau yra daug informacijos. standardGeneric yra S4 funkcijos rodiklis. Siūlomas metodas tam tikriems S4 metodams pamatyti:

 > showMethods(chol2inv) Function: chol2inv (package base) x="ANY" x="CHMfactor" x="denseMatrix" x="diagonalMatrix" x="dtrMatrix" x="sparseMatrix" 

getMethod naudoti getMethod kad pamatytumėte vieno iš metodų šaltinio kodą:

 > getMethod("chol2inv", "diagonalMatrix") Method Definition: function (x, ...) { chk.s(...) tcrossprod(solve(x)) } <bytecode: 0x000000000ea2cc70> <environment: namespace:Matrix> Signatures: x target "diagonalMatrix" defined "diagonalMatrix" 

Pavyzdžiui, yra ir metodų su sudėtingesniais parašais kiekvienam metodui

 require(raster) showMethods(extract) Function: extract (package raster) x="Raster", y="data.frame" x="Raster", y="Extent" x="Raster", y="matrix" x="Raster", y="SpatialLines" x="Raster", y="SpatialPoints" x="Raster", y="SpatialPolygons" x="Raster", y="vector" 

Norėdami pamatyti vieno iš šių metodų šaltinio kodą, reikia pateikti visą parašą.

 getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") ) 

Nepakanka pateikti dalinį parašą.

 getMethod("extract",signature="SpatialPolygons") #Error in getMethod("extract", signature = "SpatialPolygons") : # No method found for function "extract" and signature SpatialPolygons 

Funkcijos, skambinančios nepaaiškintomis funkcijomis

ts.union atveju .cbindts ir .makeNamesTs yra neišpildytos stats vardų erdvės funkcijos. getAnywhere funkcijų šaltinio kodą galite peržiūrėti naudodami operatorių ::: arba getAnywhere .

 > stats:::.makeNamesTs function (...) { l <- as.list(substitute(list(...)))[-1L] nm <- names(l) fixup <- if (is.null(nm)) seq_along(l) else nm == "" dep <- sapply(l[fixup], function(x) deparse(x)[1L]) if (is.null(nm)) return(dep) if (any(fixup)) nm[fixup] <- dep nm } <bytecode: 0x38140d0> <environment: namespace:stats> 

Funkcijos, sujungiančios kodą

Atkreipkite dėmesį, kad „kompiliuojamas“ nenurodo kompiliatoriaus paketo sukurto baitų rinkinio. <bytecode: 0x294e410> aukščiau esančioje išvestyje rodo, kad funkcija yra sudaryta baitais, ir vis tiek galite peržiūrėti šaltinį iš R komandų eilutės.

Funkcijos, .Call .Fortran , .Call , .Fortran , .External , .Internal arba .Primitive call entry points į .Primitive kodą, todėl jūs turite ieškoti kompiliuojamo kodo šaltinių, jei norite visiškai suprasti šią funkciją. Šis „ GitHub Mirror R“ šaltinio kodas yra tinkama vieta paleisti. Funkcija „ pryr::show_c_source gali būti naudinga priemonė, nes ji tiesiogiai .Internal į „GitHub“ puslapį, skirtą .Internal ir .Primitive . Paketai gali naudoti .Call , .Fortran , .Fortran ir .External ; bet ne .Internal arba .Primitive , nes jie naudojami vertėjams R.

Skambinant kai kurioms pirmiau nurodytoms funkcijoms, galima naudoti objektą vietoj simbolių eilutės, kad būtų galima apibūdinti sukomponuotą funkciją. Tokiais atvejais objektas turi klasę "NativeSymbolInfo" , "RegisteredNativeSymbol" arba "NativeSymbol" ; ir objekto spausdinimas suteikia naudingos informacijos. Pavyzdžiui, optim skambučiai .External2(C_optimhess, res$par, fn1, gr1, con) (atkreipkite dėmesį, kad C_optimhess , o ne "C_optimhess" ). optim yra statistikos pakete, todėl galite įvesti stats:::C_optimhess kad galėtumėte peržiūrėti informaciją apie stats:::C_optimhess funkciją.

Kompiliuotas kodas pakete

Jei norite peržiūrėti kompiliuotą kodą pakete, reikia atsisiųsti / išpakuoti paketo kodą. Nepakanka įdiegtų dvejetainių. Paketo šaltinis yra prieinamas iš to paties CRAN saugyklos (arba CRAN suderinamo), iš kurio paketas buvo įdiegtas. Funkcija download.packages() gali jums suteikti paketo šaltinį.

 download.packages(pkgs = "Matrix", destdir = ".", type = "source") 

Tai įkels pradinį Matricos paketą ir išsaugos atitinkamą .tar.gz failą į dabartinį katalogą. Kompiliuojamų funkcijų šaltinio kodą galima rasti nesuspaustų ir pašalintų failų src kataloge. Atviras ir negrįžtamas žingsnis gali būti atliekamas už R arba R naudojant untar() funkciją. Atsisiųsti žingsnį ir plėtinį galite sujungti į vieną skambutį (atkreipkite dėmesį, kad tą patį paketą galima atsisiųsti ir išpakuoti tokiu būdu):

 untar(download.packages(pkgs = "Matrix", destdir = ".", type = "source")[,2]) 

Arba, jei paketo kūrimas yra viešai prieinamas (pvz., Per „ GitHub“ , „ R-Forge“ arba „ RForge.net“ ), tikriausiai galite peržiūrėti šaltinio kodą internete.

Sukurtas kodas baziniame pakete

Kai kurie paketai laikomi pagrindiniais paketais. Šie paketai pateikiami su R, o jų versija yra užblokuota pagal R. versiją. Pavyzdžiai apima base , compiler , stats ir utils . Taigi, jie nėra prieinami kaip atskiri atsisiunčiami paketai CRAN, kaip aprašyta aukščiau. Atvirkščiai, jie yra R šaltinio medžio dalis atskiruose paketų kataloguose /src/library/ . Kaip pasiekti R šaltinį, aprašyta kitame skyriuje.

Sukurtas kodas, įterptas į vertėjo R kalbą

Jei norite peržiūrėti įterptąjį R vertėjo kodą, turėsite atsisiųsti / išpakuoti R šaltinius; arba galite naršyti šaltinius internete per „Subversion R“ saugyklą arba „ Winston Chang github“ veidrodį .

Uwe Ligges R naujienų straipsnis (PDF) (43 psl.) Yra gera bendroji nuoroda, kaip peržiūrėti .Internal ir .Primitive šaltinio kodą. Pagrindiniai žingsniai yra pirmiausia ieškoti funkcijos pavadinimo src/main/names.c , tada ieškoti vardo „C-entry“ failuose src/main/* .

411
07 окт. Joshua Ulrich atsakymas, 07 spalis 2013-10-07 16:58 '13, 16:58, 2013-10-07 16:58

Be kitų atsakymų į šį klausimą ir jo dublikatus, čia yra geras būdas gauti paketo funkcijos kodą, nežinant, kuris paketas yra. pavyzdžiui, jei mums reikia randomForest::rfcv() šaltinio randomForest::rfcv() :

Jei norite peržiūrėti / redaguoti iššokantį >

 edit(getAnywhere('rfcv'), file='source_rfcv.r') 

Peradresuojant į atskirą failą :

 capture.output(getAnywhere('rfcv'), file='source_rfcv.r') 
79
23 мая '14 в 1:46 2014-05-23 01:46 Atsakymas pateikiamas smci gegužės 23 d., 14 d. 1:46 2014-05-23 01:46

Jis aptinkamas derinant debug () funkciją. Tarkime, kad norite pamatyti bazinį kodą transponavimo funkcijoje t (). Tiesiog įvesdami „t“, nematote daug.

 >t function (x) UseMethod("t") <bytecode: 0x000000003085c010> <environment: namespace:base> 

Bet naudojant „debug (functionName)“, jis rodo pagrindinį kodą be vidinių elementų.

 > debug(t) > t(co2) debugging in: t(co2) debug: UseMethod("t") Browse[2]> debugging in: t.ts(co2) debug: { cl <- oldClass(x) other <- !(cl %in% c("ts", "mts")) class(x) <- if (any(other)) cl[other] attr(x, "tsp") <- NULL t(x) } Browse[3]> debug: cl <- oldClass(x) Browse[3]> debug: other <- !(cl %in% c("ts", "mts")) Browse[3]> debug: class(x) <- if (any(other)) cl[other] Browse[3]> debug: attr(x, "tsp") <- NULL Browse[3]> debug: t(x) 

EDIT: debugonce () daro tą patį, nenaudojant undebug ()

21
12 авг. atsakymas duotas Selva 12 rug. 2014-08-12 10:01 '14, 10:01 AM 2014-08-12 10:01

Aš nematau, kaip jis atitinka pagrindinio atsakymo srautą, tačiau jis kurį laiką sustabdė mane, todėl pridedu čia:

Infix operatoriai

Jei norite pamatyti kai kurių pagrindinių infix operatorių kodą (pvz., %% , %*% , %% ), naudokite getAnywhere , pavyzdžiui:

 getAnywhere("%%") # A single object matching '%%' was found # It was found in the following places # package:base # namespace:base # with value # # function (e1, e2) .Primitive("%%") 

Pagrindinis atsakymas apibūdina, kaip tada naudoti veidrodžius giliau gilinti.

13
01 дек. Atsakymą pateikė MichaelChirico, gruodžio 1 d. 2015-12-01 23:18 '15, 23:18, 2015-12-01 23:18

Ne primityviosioms funkcijoms bazė R apima funkciją, vadinamą body() , kuris grąžina funkciją. Pavyzdžiui, funkcijos print.Date() šaltinis gali būti peržiūrėtas:

 body(print.Date) 

gamins jį:

 { if (is.null(max)) max <- getOption("max.print", 9999L) if (max < length(x)) { print(format(x[seq_len(max)]), max = max, ...) cat(" [ reached getOption(\"max.print\") -- omitted", length(x) - max, "entries ]\n") } else print(format(x), max = max, ...) invisible(x) } 

Jei dirbate scenarijuje ir norite, kad funkcijos kodas būtų simbolis, galite jį gauti.

 capture.output(print(body(print.Date))) 

gausite:

 [1] "{" [2] " if (is.null(max)) " [3] " max <- getOption(\"max.print\", 9999L)" [4] " if (max < length(x)) {" [5] " print(format(x[seq_len(max)]), max = max, ...)" [6] " cat(\" [ reached getOption(\\\"max.print\\\") -- omitted\", " [7] " length(x) - max, \"entries ]\\n\")" [8] " }" [9] " else print(format(x), max = max, ...)" [10] " invisible(x)" [11] "}" 

Kodėl turėčiau tai daryti? Aš sukūriau pasirinktinį S3 objektą ( x , kur class(x) = "foo" ) pagal sąrašą. Vienas iš sąrašo narių (vadinamas „įdomu“) buvo funkcija, ir aš norėjau print.foo() rodyti print.foo() funkcijos šaltinio kodą. Taigi, aš gaunu šį fragmentą print.foo() :

 sourceVector = capture.output(print(body(x[["fun"]]))) cat(paste0(" ", sourceVector, "\n")) 

kuri įtraukia ir rodo kodą, susijusį su x[["fun"]] .

11
31 дек. Geoffrey Poole atsakymas yra gruodžio 31 d. 2016-12-31 00:41 '17 ne 0:41 2016-12-31 00:41

edit

yra labai patogi funkcija,
 new_optim <- edit(optim) 

Jis atidarys optim šaltinio kodą naudodamas R options nurodytą redaktorių, tada galite jį redaguoti ir priskirti modifikuotą funkciją į new_optim . Man tikrai patinka ši funkcija peržiūrėti kodą arba ištaisyti kodą, pavyzdžiui, įvesti kai kuriuos pranešimus ar kintamuosius arba net priskirti juos pasauliniams kintamiesiems tolesniems tyrimams (žinoma, galite naudoti debug ).

Jei tik norite peržiūrėti šaltinio kodą ir nenorite, kad konsolei būtų išspausdintas ilgas šaltinis, galite naudoti

 invisible(edit(optim)) 

Akivaizdu, kad tai neįmanoma naudoti C / C ++ arba Fortran kodo peržiūrai.

BTW, edit gali atidaryti kitus objektus, tokius kaip sąrašas, matrica ir tt, kurie taip pat rodo duomenų struktūrą su atributais. de funkciją galima naudoti norint atidaryti „Excel“ redaktorių (jei jis palaiko GUI) pakeisti matricą ar duomenų rėmelį ir grąžinti naują. Kartais tai patogu, tačiau įprastu atveju, ypač kai esate didelis, reikia vengti.

6
05 дек. Atsakymą pateikė Eric 05 Dec 2014-12-05 02:39 '14 at 2:39 2014-12-05 02:39

Tol, kol ši funkcija yra parašyta gryname R, ne C / C ++ / Fortran, galima naudoti toliau nurodytus veiksmus. Priešingu atveju, geriausias būdas yra derinti ir naudoti „ šokti “:

 > functionBody(functionName) 
3
24 янв. atsakymas duotas MCH 24 jan. 2017-01-24 19:42 '17, 07:42 pm 2017-01-24 19:42

Taip pat galite pabandyti naudoti print.function() , kuri yra bendrinė S3, kad funkcija būtų įrašyta į konsolę.

2
26 дек. atsakymas suteiktas 26 d. 2017-12-26 14:45 '17, 14:45 pm 2017-12-26 14:45

View([function_name]) - pvz. View(mean) Būtinai naudokite dideles raides [V]. Redaktoriuje bus atidarytas tik skaitomas kodas.

2
11 янв. Atsakymas pateikiamas Koo 11 jan. 2017-01-11 05:45 '17, 5:45 am 2017-01-11 05:45

Kiti klausimai apie žymių arba Užduoti klausimą