能否在R包中使用tinsel包实现Python风格的装饰器模式?
source_decorates) Yes, you absolutely can use the tinsel package in your R package—you just need to adjust how you apply decorators to avoid relying on source_decorates() for loading your functions. Here's a practical breakdown of how to make this work:
Step 1: Use Tinsel's Core decorate() Function Directly
Tinsel's @decorator syntax (the part that feels like Python) is just syntactic sugar for its underlying tinsel::decorate() function. Instead of writing code that requires source_decorates() to parse, you can apply decorators directly in your package's .R files like this:
# Define your decorator first (e.g., in R/decorators.R) my_decorator <- function(func) { function(...) { message("Running decorated function...") func(...) } } # Apply the decorator to your function (no source needed!) my_package_function <- tinsel::decorate(my_decorator, function(x) { x * 3 })
This achieves exactly the same result as the @ syntax, but it’s standard R code that your package will compile natively during installation—no file-reading hacks required.
Step 2: Export and Document As Usual
Treat your decorated functions and decorators like any other package components:
- Add roxygen2 tags like
@exportif you want them accessible to package users - Include documentation for decorators so others understand their purpose
- Run
devtools::document()to update yourNAMESPACEautomatically
Alternative: Polish Your %decorate% Operator for Package Use
You mentioned the infix operator approach, and it’s a great lightweight alternative if you want to avoid tinsel entirely or prefer a syntax that mirrors Python even closer. Here’s how to refine it for package use:
# Define the operator in your package (e.g., R/utils.R) `%@%` <- function(decorator, func) { decorator(func) } # Use it to decorate functions with Python-like syntax my_decorated_func <- my_decorator %@% function(x) { x + 10 }
I renamed it to %@% to mimic Python’s @ symbol, but you can stick with %decorate% if you prefer. This avoids the clunky double parentheses you disliked, and it’s easy to batch-apply decorators with a simple helper function if you need to process multiple functions at once.
Why source_decorates() Isn’t Ideal for Packages
source_decorates() works by reading and rewriting a file’s code at runtime—this is fine for scripts, but in packages, it introduces unnecessary complexity:
- It bypasses R’s standard package compilation pipeline
- It can cause issues with
R CMD CHECK(since the tool expects valid, parseable R code) - It adds runtime overhead from file reading and code rewriting
Using tinsel::decorate() directly or your custom infix operator keeps your package code clean, compliant, and easy to maintain.
Final Takeaways
- If you want to stick with tinsel’s ecosystem, use
tinsel::decorate()instead ofsource_decorates()—it’s the package-friendly way to leverage its decorator logic. - If you prefer a dependency-free solution, the infix operator approach is lightweight, flexible, and feels almost identical to Python’s decorator syntax.
内容的提问来源于stack exchange,提问作者jhylands

