Làm thế nào để xem mã nguồn của hàm R .Internal hoặc .Primitive?


81

Cả hai đều không hiển thị mã nguồn của pnormchức năng,

stats:::pnorm
getAnywhere(pnorm)  

Làm thế nào tôi có thể xem mã nguồn của pnorm?

sum
 (..., na.rm = FALSE)  .Primitive("sum")
.Primitive("sum")
function (..., na.rm = FALSE)  .Primitive("sum")
methods(sum)
no methods were found

và, làm cách nào để tôi có thể xem mã nguồn của sumhàm?

Câu trả lời:


96

Mã nguồn R của pnormlà:

function (q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE) 
.Call(C_pnorm, q, mean, sd, lower.tail, log.p)

Vì vậy, về mặt kỹ thuật, gõ "pnorm" sẽ hiển thị cho bạn mã nguồn. Tuy nhiên, hữu ích hơn: Ruột của pnormđược mã hóa bằng C, vì vậy lời khuyên trong mã nguồn xem câu hỏi trước trong R chỉ hữu ích về mặt ngoại vi (hầu hết tập trung vào các hàm ẩn trong không gian tên, v.v.).

Bài báo của Uwe Ligges trên tờ R news (trang 43) là một tài liệu tham khảo chung tốt. Từ tài liệu đó:

Khi xem mã nguồn R, đôi khi các lệnh gọi đến một trong các hàm sau sẽ hiển thị: .C (), .Call (), .Fortran (), .External () hoặc .Internal () và .Primitive (). Các hàm này đang gọi các điểm vào trong mã đã biên dịch như các đối tượng chia sẻ, thư viện tĩnh hoặc thư viện liên kết động. Vì vậy, cần phải xem xét các nguồn của mã đã biên dịch, nếu cần phải hiểu đầy đủ về mã. ... Bước đầu tiên là tra cứu điểm nhập trong tệp '$ R HOME / src / main / names.c', nếu hàm R đang gọi là .Primitive () hoặc .Internal (). Điều này được thực hiện trong ví dụ sau đối với mã thực hiện hàm sum () R 'đơn giản'.

(Nhấn mạnh thêm vì hàm chính xác mà bạn hỏi về ( sum) được đề cập trong bài báo của Ligges.)

Tùy thuộc vào mức độ nghiêm túc bạn muốn đào sâu vào mã, có thể đáng để tải xuống và giải nén mã nguồn như Ligges đề xuất (ví dụ: sau đó bạn có thể sử dụng các công cụ dòng lệnh như grepđể tìm kiếm thông qua mã nguồn). Để kiểm tra thông thường hơn, bạn có thể xem các nguồn trực tuyến thông qua máy chủ R Subversion hoặc máy nhân bản github của Winston Chang (các liên kết ở đây dành riêng cho src/nmath/pnorm.c). (Đoán đúng nơi để xem, src/nmath/pnorm.chãy làm quen với cấu trúc của mã nguồn R.)

meansumcả hai đều được thực hiện tóm tắt . c.


1
nó thuộc một danh mục khác với pnorm. Hãy thử mean.defaultmã R và github.com/wch/r-source/blob/trunk/src/main/summary.c cho mã C. Và hãy đọc bài viết của Uwe Ligges được liên kết ở trên!
Ben Bolker

1
Chỉ cần theo dõi câu trả lời này: có thể cần phải cẩn thận về tên hàm chính xác trong C hoặc Fortran. Ví dụ: Tôi đang cố gắng tìm kiếm các nguồn stl, trong đó kêu gọi dòng này: z <- .Fortran(C_stl, x, n, as.integer(period), as.integer(s.window). Vì vậy, tôi đã tìm kiếm nhân bản Github được liên kết ở trên bằng từ khóa C_stlnhưng không có kết quả. Tuy nhiên, khi tôi tìm kiếm, stlcó một tệp được gọi là tệp stl.ftôi muốn tìm. Điều cần giải quyết là tên tệp .c hoặc .f có thể không hoàn toàn giống với tên hàm đang được gọi.
yuqli

35

Tôi biết bài đăng này đã hơn 2 năm tuổi, nhưng tôi nghĩ điều này có thể hữu ích cho một số người dùng duyệt qua câu hỏi này.

Về cơ bản, tôi chỉ sao chép câu trả lời của mình cho câu hỏi tương tự khác này để nó có thể tỏ ra hữu ích đối với một số người dùng R muốn khám phá các tệp nguồn C.

  1. Đầu tiên, với pryr, bạn có thể sử dụng show_c_sourcechức năng sẽ tìm kiếm trên GitHub đoạn mã có liên quan trong các tệp nguồn C. Hoạt động cho các chức năng .Internal và .Primitive.

    body(match.call)
    
    # .Internal(match.call(definition, call, expand.dots))
    
    pryr::show_c_source(.Internal(match.call(definition, call, expand.dots)))
    

    Điều này sẽ đưa bạn đến trang này , hiển thị unique.ccó chứa hàm do_matchcall .

  2. Tôi đã tập hợp tệp phân cách bằng tab này lại với nhau , xây dựng trên names.ctệp và sử dụng tệp tìm trong để xác định vị trí của mã nguồn. Có một số chức năng có các tệp dành riêng cho nền tảng và một số chức năng khác có nhiều tệp có mã nguồn liên quan. Nhưng đối với phần còn lại, ánh xạ đã được thiết lập khá tốt, ít nhất là đối với phiên bản hiện tại (3.1.2).


pryr không làm việc khi tôi cố gắng xác định vị trí mã C cho system: pryr::show_c_source(.Internal(system(x))), tôi đã nhậnError: Could not find entry for system
zhanxw

7
> methods(mean)
[1] mean.data.frame mean.Date       mean.default    mean.difftime   mean.IDate*    
[6] mean.POSIXct    mean.POSIXlt    mean.yearmon*   mean.yearqtr*  

   Non-visible functions are asterisked
> mean.default
function (x, trim = 0, na.rm = FALSE, ...) 
{
    if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) {
        warning("argument is not numeric or logical: returning NA")
        return(NA_real_)
    }
    if (na.rm) 
        x <- x[!is.na(x)]
    if (!is.numeric(trim) || length(trim) != 1L) 
        stop("'trim' must be numeric of length one")
    n <- length(x)
    if (trim > 0 && n) {
        if (is.complex(x)) 
            stop("trimmed means are not defined for complex data")
        if (any(is.na(x))) 
            return(NA_real_)
        if (trim >= 0.5) 
            return(stats::median(x, na.rm = FALSE))
        lo <- floor(n * trim) + 1
        hi <- n + 1 - lo
        x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]
    }
    .Internal(mean(x))
}
<bytecode: 0x155ef58>
<environment: namespace:base>

Điều này dường như không trả lời câu hỏi ban đầu của OP (về pnorm), nhưng nhận xét của họ bên dưới về mean- và lưu ý rằng điều này cũng rơi vào mã C, ở phía dưới (xem nhận xét của tôi bên dưới).
Ben Bolker

2
Thật. Và "câu trả lời chính xác" là câu mà bạn đã đưa ra trước đó ... hãy đọc bài báo của Uwe Ligges trên RNews.
IRTFM
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.