如何获取purrr部分应用函数的真实形参并转为常规函数?
解决purrr::partial生成函数的形参获取问题
purrr::partial生成的部分应用函数本质是一个闭包,它用...来接收剩余参数,所以直接调用formals()只能看到...,无法获取原函数中未被绑定的真实形参。要将其转换为保留剩余形参的常规函数,可以通过以下方法实现:
自定义转换函数
我们可以从partial函数的闭包环境中提取原函数和已绑定的参数,然后构造一个带有剩余形参的新函数:
library(purrr) library(rlang) partial_to_regular <- function(partial_fn) { # 从闭包环境中获取原函数和已绑定参数 env <- environment(partial_fn) original_fn <- env$.f bound_args <- env$... # 提取原函数中未被绑定的形参 original_formals <- formals(original_fn) remaining_formals <- original_formals[!names(original_formals) %in% names(bound_args)] # 构造新函数的执行体:调用原partial函数并传递参数 new_body <- expr({ do.call(!!partial_fn, as.list(environment())) }) # 创建新的常规函数 new_fn <- function() {} formals(new_fn) <- remaining_formals body(new_fn) <- new_body environment(new_fn) <- environment(partial_fn) new_fn }
测试示例
用你的代码测试这个转换函数:
# 定义原函数 a <- function(x=2,y=2) {return(list(x,y))} # 创建部分应用函数 b <- purrr::partial(a,x=3) # 转换为常规函数 c <- partial_to_regular(b) # 查看形参,符合预期 formals(c) #> $y #> [1] 2 # 调用测试 c() #> [[1]] #> [1] 3 #> #> [[2]] #> [1] 2 c(y=5) #> [[1]] #> [1] 3 #> #> [[2]] #> [1] 5
原理说明
purrr::partial生成的闭包会在内部环境中保存原函数(.f)和已绑定的参数(...),调用时通过...接收剩余参数并合并后传递给原函数。我们的转换函数:
- 从闭包环境中提取原函数和已绑定参数
- 筛选出原函数中未被绑定的形参,作为新函数的形参
- 构造新函数的执行逻辑,将新函数的参数传递给原partial函数
这样得到的新函数就是带有真实剩余形参的常规函数,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Fredrik Nylén
相关产品推荐
相关产品推荐

