patterns-metaprogramming-dev
1
总安装量
1
周安装量
#42499
全站排名
安装命令
npx skills add https://github.com/arustydev/ai --skill patterns-metaprogramming-dev
Agent 安装分布
moltbot
1
opencode
1
cursor
1
continue
1
codex
1
claude-code
1
Skill 文档
Metaprogramming Patterns
Cross-language reference for metaprogramming mechanisms including decorators, macros, annotations, and code generation. This skill helps translate metaprogramming patterns between languages during code conversion.
Overview
This skill covers:
- Decorator/annotation/attribute comparison across languages
- Macro systems (compile-time vs runtime)
- Code generation patterns
- Translation strategies between paradigms
This skill does NOT cover:
- Language-specific metaprogramming tutorials (see
lang-*-devskills) - Building specific decorators/macros for applications
- Runtime reflection for debugging (see language-specific skills)
Metaprogramming Mechanism Comparison
| Language | Primary Mechanism | Execution Time | Power Level |
|---|---|---|---|
| TypeScript | Decorators | Runtime | Medium |
| Python | Decorators | Runtime | High |
| Rust | Proc macros, derive | Compile-time | Very High |
| Java/Kotlin | Annotations | Compile + Runtime | Medium |
| Go | //go:generate |
Build-time | Low |
| C# | Attributes | Runtime (reflection) | Medium |
| Ruby | Metaprogramming APIs | Runtime | Very High |
| Elixir | Macros | Compile-time | Very High |
Execution Time Impact
Compile-time (Rust, Elixir)
âââ Zero runtime overhead
âââ Full type information available
âââ Complex transformations possible
âââ Errors caught at compile time
Runtime (Python, TypeScript, Ruby)
âââ Runtime overhead (usually minimal)
âââ Dynamic behavior possible
âââ Can inspect runtime values
âââ Errors may occur at runtime
Build-time (Go generate)
âââ Separate build step
âââ Generates source files
âââ No runtime mechanism
âââ Manual regeneration needed
Decorator/Annotation Comparison
TypeScript Decorators
// Class decorator
@Controller('/users')
class UserController {
// Method decorator
@Get('/:id')
@Authorized(['admin'])
getUser(@Param('id') id: string): User {
return this.userService.find(id);
}
}
// Decorator factory (returns decorator)
function Log(prefix: string) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`${prefix}: ${key} called`);
return original.apply(this, args);
};
};
}
Capabilities:
- Class, method, property, parameter decorators
- Decorator factories for configuration
- Metadata reflection (
reflect-metadata) - Runtime execution (after class definition)
Python Decorators
from functools import wraps
# Function decorator
def log(prefix: str):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"{prefix}: {func.__name__} called")
return func(*args, **kwargs)
return wrapper
return decorator
# Class decorator
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
pass
# Method with multiple decorators (applied bottom-up)
@app.route('/users/<id>')
@requires_auth
@log("API")
def get_user(id: str) -> User:
return user_service.find(id)
Capabilities:
- Function, method, class decorators
- Stacking multiple decorators
- Access to wrapped function’s attributes
- Full runtime introspection
- Arbitrary Python code in decorators
Rust Derive Macros and Attributes
// Derive macro (generates trait implementations)
#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
#[serde(rename = "user_id")]
id: String,
#[serde(skip_serializing_if = "Option::is_none")]
email: Option<String>,
}
// Attribute macro (transforms the item)
#[tokio::main]
async fn main() {
// ...
}
// Proc macro (custom compile-time code generation)
#[route(GET, "/users/:id")]
async fn get_user(id: Path<String>) -> impl Responder {
// Handler implementation
}
Capabilities:
- Derive macros for trait implementation
- Attribute macros for code transformation
- Function-like macros (
macro_rules!, proc macros) - Full AST access at compile time
- Zero runtime overhead
Java/Kotlin Annotations
// Runtime annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Cached {
int ttlSeconds() default 300;
}
// Usage
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
@Cached(ttlSeconds = 60)
public User getUser(@PathVariable String id) {
return userService.find(id);
}
}
Capabilities:
- Compile-time (
SOURCE), class-file (CLASS), runtime (RUNTIME) retention - Annotation processors for compile-time code generation
- Runtime reflection for reading annotations
- Limited to metadata (no code transformation)
Go Generate Directives
//go:generate stringer -type=Status
type Status int
const (
Pending Status = iota
Active
Completed
)
//go:generate mockgen -source=service.go -destination=mock_service.go
type UserService interface {
Find(id string) (*User, error)
}
Capabilities:
- Build-time code generation
- Executes external tools
- Generates new source files
- No runtime mechanism (just comments)
- Manual
go generatestep required
C# Attributes
[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{
[HttpGet("{id}")]
[Authorize(Roles = "Admin")]
[ResponseCache(Duration = 60)]
public ActionResult<User> GetUser(string id)
{
return userService.Find(id);
}
}
// Custom attribute
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute
{
public string Prefix { get; set; }
}
Capabilities:
- Runtime reflection to read attributes
- Compile-time analysis with Roslyn
- Source generators for code generation
- Metadata only (no direct code transformation)
Translation Patterns
Decorator â Derive Macro (TS/Python â Rust)
| Source Pattern | Rust Equivalent | Notes |
|---|---|---|
@Serialize |
#[derive(Serialize)] |
Derive macro |
@validate |
Validator crate derives | #[derive(Validate)] |
@log method decorator |
Tracing + custom wrapper | No direct equivalent |
@cache |
Memoization crate or manual | cached crate |
@singleton |
lazy_static! or OnceCell |
Different pattern |
Example Translation:
// TypeScript
@Entity()
class User {
@Column()
@Length(1, 100)
name: string;
@Column()
@IsEmail()
email: string;
}
// Rust equivalent
#[derive(Debug, Serialize, Deserialize, Validate)]
struct User {
#[validate(length(min = 1, max = 100))]
name: String,
#[validate(email)]
email: String,
}
Decorator â Annotation (Python/TS â Java)
# Python
@app.route('/users/<id>', methods=['GET'])
@requires_auth
def get_user(id: str) -> User:
return user_service.find(id)
// Java equivalent
@GetMapping("/users/{id}")
@PreAuthorize("isAuthenticated()")
public User getUser(@PathVariable String id) {
return userService.find(id);
}
Method Decorator â Manual Wrapper (Any â Go)
Go lacks decorators. Use wrapper functions or middleware:
// TypeScript
@Log("API")
@Timed()
async getUser(id: string): Promise<User> {
return this.service.find(id);
}
// Go equivalent - middleware pattern
func LogMiddleware(prefix string, next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s: %s %s", prefix, r.Method, r.URL.Path)
next(w, r)
}
}
func TimedMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next(w, r)
log.Printf("Duration: %v", time.Since(start))
}
}
// Usage
http.HandleFunc("/users/", LogMiddleware("API", TimedMiddleware(getUser)))
Class Decorator â Trait Implementation (Python â Rust)
# Python
@dataclass
@total_ordering
class User:
name: str
age: int
// Rust equivalent
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct User {
name: String,
age: i32,
}
Common Use Cases
1. Serialization/Validation
| Use Case | TypeScript | Python | Rust | Go |
|---|---|---|---|---|
| JSON serialization | class-transformer |
@dataclass + json |
#[derive(Serialize)] |
struct tags |
| Validation | class-validator |
pydantic |
#[derive(Validate)] |
validator pkg |
| ORM mapping | TypeORM decorators | SQLAlchemy | Diesel derives | GORM tags |
2. Web Frameworks
| Framework Pattern | TypeScript | Python | Rust | Java |
|---|---|---|---|---|
| Route definition | @Get('/path') |
@app.route() |
#[get("/path")] |
@GetMapping |
| Dependency injection | @Injectable() |
@inject |
Constructor | @Autowired |
| Middleware | @UseGuards() |
@requires_auth |
Tower layers | @PreAuthorize |
3. Logging/Tracing
| Pattern | TypeScript | Python | Rust | Go |
|---|---|---|---|---|
| Method logging | @Log() |
@log |
#[instrument] |
Middleware |
| Timing | @Timed() |
@timer |
#[instrument] |
Middleware |
| Tracing | OpenTelemetry decorators | @trace |
tracing macros |
Context |
Anti-Patterns
1. Over-decoration
// â Too many decorators obscure the logic
@Controller()
@UseGuards(AuthGuard)
@UseInterceptors(LoggingInterceptor)
@UsePipes(ValidationPipe)
@UseFilters(HttpExceptionFilter)
class UserController {
@Get()
@UseGuards(RoleGuard)
@Serialize(UserDto)
@Cache(60)
@Throttle(10, 60)
@ApiOperation({ summary: 'Get users' })
@ApiResponse({ status: 200 })
getUsers() { }
}
// â Group related concerns
@Controller()
@UseGuards(AuthGuard, RoleGuard)
class UserController {
@Get()
@Cache(60)
getUsers() { }
}
2. Side Effects in Decorators
# â Decorator with hidden side effects
def register(func):
global_registry.append(func) # Hidden mutation!
return func
# â Explicit registration
def register(func):
func._registered = True
return func
def collect_registered(module):
return [f for f in dir(module) if getattr(f, '_registered', False)]
3. Decorator Order Confusion
# Decorators apply bottom-up!
@decorator_a # Applied SECOND
@decorator_b # Applied FIRST
def func():
pass
# Equivalent to:
func = decorator_a(decorator_b(func))
4. Losing Function Metadata
# â Loses original function name, docstring
def bad_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
# â Preserve metadata
from functools import wraps
def good_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
When No Direct Equivalent Exists
Strategy 1: Manual Implementation
When target language lacks metaprogramming for a pattern, implement manually:
// TypeScript: Memoization decorator
@Memoize()
function expensiveComputation(n: number): number {
// ...
}
// Go: Manual memoization
var cache = make(map[int]int)
var mu sync.RWMutex
func expensiveComputation(n int) int {
mu.RLock()
if val, ok := cache[n]; ok {
mu.RUnlock()
return val
}
mu.RUnlock()
result := // ... compute
mu.Lock()
cache[n] = result
mu.Unlock()
return result
}
Strategy 2: Code Generation
Use build-time generation when runtime metaprogramming isn’t available:
//go:generate go run gen_memoize.go -type=expensiveComputation
Strategy 3: Interface/Trait Abstraction
Replace decorator behavior with explicit interfaces:
// TypeScript: Decorator-based
@Injectable()
class UserService {
@Transactional()
async createUser(data: UserData): Promise<User> { }
}
// Rust: Trait-based
trait Transactional {
async fn in_transaction<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce() -> Result<T>;
}
impl UserService {
async fn create_user(&self, data: UserData) -> Result<User> {
self.in_transaction(|| {
// ... implementation
}).await
}
}
Best Practices
- Prefer compile-time over runtime when possible for performance
- Keep decorators focused – one responsibility per decorator
- Document decorator behavior – especially execution order
- Preserve function metadata – use
@wrapsin Python, etc. - Consider testability – decorated code should remain testable
- Avoid magic – decorator behavior should be predictable
- Match target language idioms – don’t force patterns that don’t fit
Related Skills
meta-convert-dev– Code conversion patternsconvert-*skills – Language-specific conversionslang-*-devskills – Language-specific metaprogramming detailspatterns-serialization-dev– Serialization patterns (often uses metaprogramming)