R装饰器改变输入和输出

vat*_*mut 4 r decorator

我试图重构这个.在Python中,我会使用装饰器.什么是'糟糕的方式来做到这一点?说,我们有这种模式

good_input <- format_input( bad_input )
bad_output <- use_this_func( good_input )
good_output <- format_output( bad_output )
Run Code Online (Sandbox Code Playgroud)

然后,

good_input <- format_input( bad_input )
bad_output <- use_this_other_func( good_input )
good_output <- format_output( bad_output )
Run Code Online (Sandbox Code Playgroud)

你可以想象,它会像野生蘑菇一样繁殖.我想要接近这个解决方案

use_this_robust_func <- wrapper( use_this_func ) # Or wrapper( use_this_other_func )
good_output <- use_this_robust_func( bad_input )
Run Code Online (Sandbox Code Playgroud)

我试图总结调用use_this_funcuse_this_other_func使用(和相关函数)format_inputformat_output.到目前为止,我已经部分地使用了这个问题

wrapper <- function( func_not_robust ){
  func_robust <- function( ... ){
   # This is the bit I haven't figured out
   ... format_input( ) ... # supposed to convert bad input - the function argument - to good
   bad_output <- func_not_robust( ... ) # supposed to take good input as argument
   good_output <- format_output( bad_output )
   return( good_output )
   }
  return( func_robust )
}
Run Code Online (Sandbox Code Playgroud)

抱歉,伪代码.注意我不确定这是进入R的方法.我不是很接近上面解决方案的草图,它是通过将Python翻译成R而生成的.R.R本地人如何做到这一点?提前致谢.

Spa*_*man 6

我觉得你差不多了.这是一个例子,清洁的第一阶段是用NA代替负输入值,输出清理很容易否定一切:

format_input <- function(x){
    x[x<0] <- NA
    return(x)
}

format_output <- function(x){
    return(-x)
}

wrapper <- function(f){
    force(f)
    g = function(bad_input){
        good_input = format_input(bad_input)
        bad_output = f(good_input)
        good_output = format_output(bad_output)
        return(good_output)
    }
    g
}
Run Code Online (Sandbox Code Playgroud)

然后:

> wrapper(sqrt)(c(-2,2))
[1]        NA -1.414214
Run Code Online (Sandbox Code Playgroud)

wrapper(sqrt)返回一个"闭包",它是一个包含数据的函数.该函数将该函数f的值sqrt作为该机箱的一部分.

force自调用需要f的时候没有得到评估g被创建,并在某些情况下,如果没有它,然后f运行封装版本,由于与R的懒惰评估或"承诺"或东西时,将不会发现.我不确定这种情况何时发生,但是force对闭包生成器添加对未评估参数的调用是零开销.它有点像货物编程,但从来没有问题.

更灵活的解决方案可能是将输入和输出清理函数指定为闭包生成器的函数,默认值为:

wrapper <- function(f, fi=format_input, fo=format_output){
    force(f) ; force(fi); force(fo)
    g = function(bad_input){
        good_input = fi(bad_input)
        bad_output = f(good_input)
        good_output = fo(bad_output)
        return(good_output)
    }
    g
}
Run Code Online (Sandbox Code Playgroud)

然后我可以sqrt用不同的输入和输出格式化程序包装.例如,用正面函数改变负面函数:

> make_pos = function(x){abs(x)}
> wrapper(sqrt,fo=make_pos)(c(-2,2))
[1]       NA 1.414214
Run Code Online (Sandbox Code Playgroud)

更灵活的解决方案是发现您在此处生成功能链.你的输出是format_output(sqrt(format_output(bad_input))).这是功能组合,包中有一个功能functional:

> require(functional)
> w = Compose(format_input, sqrt, format_output)
> w(c(-2,2))
[1]        NA -1.414214
Run Code Online (Sandbox Code Playgroud)

当你的合成中有三个以上的函数时,这可能会更有用,例如你可以有一个函数列表并使用它们组合它们do.call....

一旦你看到函数式编程中的模式,就会让人上瘾.我现在就停下来.