2012-03-07 37 views
10

Tôi có một wrapper xung quanh trong xây dựng warning() hàm trong R mà về cơ bản gọi warning(sprintf(...)):R cảnh báo() wrapper - nâng cao chức năng mẹ

warningf <- function(...) 
    warning(sprintf(...)) 

Điều này là do tôi sử dụng warning(sprintf(...)) thường xuyên đến nỗi tôi quyết định làm cho một chức năng ra khỏi nó (nó trong một gói tôi có các chức năng tôi sử dụng thường xuyên).

Sau đó, tôi sử dụng warningf khi tôi viết chức năng. ví dụ, thay vì viết:

f <- function() { 
    # ... do stuff 
    warning(sprintf('I have %i bananas!',2)) 
    # ... do stuff 
} 

tôi viết:

f <- function() { 
    # ... do stuff 
    warningf('I have %i bananas!',2) 
    # ... do stuff 
} 

Nếu tôi gọi là f() đầu tiên, tôi nhận được:

Warning message: 
In f() : I have 2 bananas! 

này là tốt - nó nói với tôi nơi cảnh báo đến từ f() và những gì đã xảy ra.

Nếu tôi gọi là thứ hai f(), tôi nhận được:

Warning message: 
In warningf("I have %i bananas!",2) : I have 2 bananas! 

Đây không phải là lý tưởng - nó nói với tôi cảnh báo là trong warningf chức năng (tất nhiên, bởi vì đó là warningf chức năng mà các cuộc gọi warning, không f), mặt nạ thực tế rằng nó thực sự đến từ các chức năng f().

Vì vậy, câu hỏi của tôi là: Tôi có thể bằng cách nào đó "nâng cao" cuộc gọi warning để nó hiển thị thông báo warning in f() thay vì warning in warningf?

Trả lời

12

Một cách để giải quyết vấn đề này là lấy danh sách các môi trường trong ngăn xếp cuộc gọi của bạn, sau đó dán tên của khung chính trong cảnh báo của bạn.

Bạn làm điều này với hàm sys.call() trả về một mục trong ngăn xếp cuộc gọi. Bạn muốn trích xuất thứ hai từ yếu tố cuối cùng trong danh sách này, ví dụ: phụ huynh để warningf:

warningf <- function(...){ 
    parent.call <- sys.call(sys.nframe() - 1L) 
    warning(paste("In", parent.call, ":", sprintf(...)), call.=FALSE) 
} 

Bây giờ, nếu tôi chạy chức năng của bạn:

> f() 
Warning message: 
In f() : I have 2 bananas! 
+0

@richiecotton cảm ơn bạn đã chỉnh sửa. Cách của bạn tốt hơn nhiều. – Andrie

+0

+1 - câu trả lời hay. Thậm chí đơn giản hơn là chỉ sử dụng 'sys.call (-1)'. (Nó hoạt động b/c đối số 'which' đối với' sys.call() 'đại diện cho" số khung sẽ quay trở lại nếu âm "). –

+0

Tuyệt vời! Tôi nghĩ rằng nó có thể có một cái gì đó để làm với đi qua ngăn xếp cuộc gọi khi tôi nhìn vào mã 'cảnh báo', nhưng không biết làm thế nào để làm điều đó. Cảm ơn! –

Các vấn đề liên quan