Groovy:完美的转发

时间:2013-06-05 03:19:49

标签: groovy perfect-forwarding

我想创建一个闭包,比如说print_args,它接受​​另一个闭包,比如f,打印它的参数而不是将参数传递给f

我对此的第一次尝试如下:

def print_args(f) { { Object... args -> args.each { println it }; f(*args) } }

所以,如果我们也定义:

def add = { x, y -> x + y }

我们可以这样做:

println add(1,2)

def print_args_add = print_args(add)

println print_args_add(1,2)

可以看出,print_args_add只是一个封闭,它会add,但也打印出它的参数。

我们还可以定义sum

def sum = { x -> x.inject { acc, val -> acc + val } }

同样地:

println sum([1,2])

def print_args_sum = print_args(sum)
println print_args_sum([1,2])

这适用于传递arrayList。但是,在传递普通数组时:

Object x = new Object[2]
x[0] = 1
x[1] = 2

println sum(x)

工作正常,但以下内容:

println print_args_sum(x)

中断,因为闭包print_args扩展了传递的数组,而不是按原样传递它。

有没有办法可以编写print_args所以它可以处理可以作为参数传递单个数组的闭包f,而不会对调用者或闭包{{1可以处理?

我已将代码放在ideone here上。

1 个答案:

答案 0 :(得分:0)

将对象数组视为List,如果它已通过。

你必须这样做的原因是因为sum闭包只需要一个参数。对象数组上的Sp​​read运算符在出错时会产生两个参数。因此,您需要在print_args

中进行低于增强
def print_args(f) { 
    {Object... args -> 
        args.each { println it}
        args.find{it instanceof List} ? f(*args) : f(args as List)
    }
}