Giả sử tôi đang gọi hàm PackageFuncA tồn tại trong gói bên thứ 3 (tức là thư viện từ CRAN). PackageFuncA lần lượt gọi PackageFuncB trong cùng gói bên thứ 3. Có cách nào để gọi PackageFuncA như vậy mà khi nó gọi PackageFuncB, nó sẽ trong thực tế gọi của riêng tôi implimentation của PackageFuncB? Nói cách khác, tôi có thể chặn cuộc gọi đến PackageFuncB không? Tôi nghĩ rằng các giải pháp liên quan đến việc tạo ra chức năng PackageFuncB của riêng tôi và sau đó gọi PackageFuncA trong cùng một môi trường và không phải môi trường của PackageFuncA, nhưng tôi không thể làm cho nó hoạt động được với do.call cũng không phải eval.Lệnh chuyển hướng/chặn cuộc gọi trong chức năng gói
Trả lời
Đây là một lớp lót thực hiện. Tại đây PackageFuncA
là stats::acf
và PackageFuncB
là stats:::plot.acf
mà chúng tôi muốn thay thế bằng my.plot.acf
. my.plot.acf
in "Hello"
và sau đó gọi stats:::plot.acf
thực.
# we want this to run in place of stats:::plot.acf
my.plot.acf <- function(x, ...) { cat("Hello\n"); stats:::plot.acf(x, ...) }
# this does it
library(proto)
acf <- with(proto(environment(acf), acf = stats::acf, plot.acf = my.plot.acf), acf)
# test
acf(1:10)
Đối tượng proto là môi trường mà bất kỳ chức năng nào được chèn vào đối tượng qua chức năng proto
đều có môi trường tự động đặt lại đối tượng đó. Arg đầu tiên của proto()
là phụ huynh của đối tượng proto.
Trong ví dụ trên, thiết bị được thiết lập sao cho biến số acf
đề cập đến phiên bản acf
được chèn vào đối tượng proto (giống với bản gốc ngoại trừ môi trường của nó đã được sửa đổi làm đối tượng proto)). Khi chức năng acf
mới chạy plot.acf
là một biến miễn phí (tức là không được định nghĩa trong acf
) để nó được tra cứu trong phụ huynh của acf
và đó là môi trường trong đối tượng proto nơi nó tìm thấy plot.acf
mới. acf
có thể có các biến miễn phí khác nhưng trong những trường hợp này vì chúng không được tìm thấy trong đối tượng proto, nó trông giống như đối tượng gốc của đối tượng proto, là môi trường gốc của acf
gốc. Về sơ đồ, chúng tôi có điều này nơi <-
nghĩa bên trái là mẹ của phía bên phải:
environment(stats::acf) <- proto object <- revised acf
và đối tượng proto chứa cả plot.acf
và sửa đổi acf
.
Chúng tôi cũng đã đặt môi trường của plot.acf
mới thành đối tượng proto. Chúng tôi có thể hoặc có thể không cần thiết để làm điều này. Trong nhiều trường hợp, nó sẽ không thành vấn đề. Nếu điều quan trọng là không để thiết lập môi trường mới plot.acf
sau đó nó sẽ được thực hiện như thế này bởi vì proto không bao giờ lặn môi trường của các chức năng chèn sử dụng [[...]]
:
acf <- with(p <- proto(environment(acf), acf = stats::acf), acf)
p[["plot.acf"]] <- my.plot.acf
Trong ví dụ này, cả hai phương pháp tiếp cận công việc.
Nó sẽ có thể làm tất cả những điều này với môi trường đồng bằng tại các chi phí của việc phải sử dụng một vài dòng mã:
# create new environment whose parent is the original acf's parent
e <- new.env(parent = environment(stats::acf))
# the next statement is only need to overwrite any acf you already might have from
# trying other code. If you were sure there was no revised acf already defined
# then the next line could be omitted. Its a bit safer to include it.
acf <- stats::acf
# This sets the environment of the new acf. If there were no acf already here
# then it would copy it from stats::acf .
environment(acf) <- e
# may or may not need next statement. In this case it doesn't matter.
environment(my.plot.acf) <- e
e$plot.acf <- my.plot.acf
acf(1:10)
Trong trường hợp này, chúng tôi đã không đặt điều chỉnh acf
trong e
như trong proto ví dụ nhưng chỉ đặt cha mẹ của nó. Trong thực tế, đặt acf
sửa đổi thành e
hoặc đối tượng proto là không cần thiết nhưng chỉ được thực hiện trong trường hợp proto vì proto có tác dụng phụ của việc đặt lại môi trường và đó là tác dụng phụ mà chúng tôi đã làm sau đó.Mặt khác, cần phải đặt plot.acf
sửa đổi trong e
hoặc đối tượng proto để đối tượng đó gặp phải trước bản gốc.
Bạn có thể muốn đọc số này paper và cụ thể là phần trên proxy bắt đầu trang 21 vì kỹ thuật được hiển thị ở đây là ví dụ về đối tượng proxy.
Tạo bản sao mới PackageFuncA
, đặt lại môi trường và viết phiên bản PackageFuncB của riêng bạn.
environment(PackageFuncA) <- globalenv() # makes a new copy of PackageFuncA
PackageFuncB <- function(...) .... # will be called from your new PackageFuncA
Bạn có thể phải thực hiện một chút chỉnh sửa nếu PackageFuncA
sử dụng chức năng chưa được xuất từ gói ban đầu. Ngoài ra, nếu bạn không muốn sử dụng PackageFuncB
mới ở nơi khác, bạn có thể bọc nó bên trong PackageFuncA
mới thay vì đặt nó trong môi trường toàn cầu.
- 1. Echo một cuộc gọi chức năng từ dòng lệnh vim
- 2. C++ chức năng cuộc gọi nhận dạng
- 3. jquery chức năng cuộc gọi bằng tên
- 4. gọi sizeof trên một cuộc gọi bỏ qua chức năng thực sự gọi chức năng!}
- 5. Ngăn các cuộc gọi chức năng cũ Trong VB.NET
- 6. "[Chức năng nhẹ]" trong ngăn xếp cuộc gọi
- 7. Sử dụng cuộc gọi chức năng trong vòng lặp foreach
- 8. CodeIgniter chức năng cuộc gọi trong cùng một lớp
- 9. chức năng gọi lỗi, [Cuộc gọi đến chức năng PInvoke không cân bằng chồng]
- 10. Vượt qua một chức năng như một cuộc tranh luận đầu tiên trong một cuộc gọi chức năng trong coffeescript
- 11. trích xuất tên cuộc gọi chức năng từ một cuộc gọi hàm
- 12. Chức năng javascript cuộc gọi có tên là biến
- 13. cuộc gọi đến không xác định chức năng exif_read_data()
- 14. Các cuộc gọi chức năng bị trì hoãn
- 15. Giao dịch PDO và các cuộc gọi chức năng
- 16. không có chức năng phù hợp cho cuộc gọi đến ''
- 17. Chức năng xem cuộc gọi từ subview với BackboneJS
- 18. Perl chức năng cuộc gọi nhầm lẫn tôi
- 19. Chức năng thống kê cuộc gọi từ Scipy
- 20. Cuộc gọi của chức năng quá tải là mơ hồ
- 21. Tại sao chức năng Clojure chỉ bao gồm các cuộc gọi chức năng lười biếng?
- 22. Chức năng cơ sở cuộc gọi sau đó được thừa kế chức năng
- 23. Tại sao lambdas có thể chuyển đổi các cuộc gọi chức năng thành Hành động?
- 24. boost :: adapter :: chuyển đổi theo sau tăng :: adapter :: lọc cuộc gọi chức năng hai lần
- 25. Tăng tốc chức năng sử dụng mà trong một cuộc gọi dễ dàng trong R
- 26. C: loại chuyển đổi khi đi qua một cuộc tranh cãi trên một cuộc gọi chức năng
- 27. Có thể gọi các cuộc gọi thư viện cufft trong chức năng của thiết bị không?
- 28. Có một tính năng trong Emacs cho phân cấp cuộc gọi chức năng
- 29. Chức năng gọi trong SqlCommand
- 30. Overhead của chức năng DLL gọi
Nó sẽ dễ dàng hơn để tạo PackageFunA của riêng bạn và thay đổi cuộc gọi thành PackageFunB sao cho nó gọi hàm của bạn thay thế? – joran
Xem '? AssignInNamespace' – Andrie
joran - Tôi không muốn duy trì phiên bản PackageFuncA của riêng mình, đặc biệt là vì nó không chỉ là một vài dòng mã. – SFun28