JoeG
JoeG

Reputation: 7642

Can additional parameters be added to a Groovy closure invocation?

I am trying to understand groovy better and came across this usage.

Found this while using Http-Builder, though my question is independent of that - I am mainly interested in finding the "groovy-way" for the general use-case implied.

There is an existing "request" method that takes a closure and when the http-builder invokes that closure it passes it one parameter, the "request". What is the best way to get additional information passed in to such a closure?

Following normal usage, the code might look something like:

myHttpClient.request(POST) { req ->
   uri.path = 'some path'
   uri.query = [ p1:'value1', p2:'value2' ]
....
}

In this example, I would like to be able to dynamically set (or pass in) three values - the path, and the values for the query parameters 1 & 2.

I don't know enough to know the right way, but have done something like this:

EDIT cleaned up the code

def myPath = '/a/b/c'
def p1Param = 'p1Value'
def p2Param = 'p2Value'
def myClosure = { req -> 
   uri.path = myPath
   uri.query = [ p1:p1Param, p2:p2Param ]
....
}

// first call:
myHttpClient.request(POST, myClosure)
// later on: 
myPath = '/new/path'
p1Param = 'newValue1'
p2Param = 'newValue2'
myHttpClient.request(POST, myClosure)

While this works and is DRY, it is also ugly and I think/hope there is a better way. I also thought about putting the entire call into its own closure and simply calling that - again I was hoping there is a better way!

Upvotes: 1

Views: 149

Answers (2)

Alfergon
Alfergon

Reputation: 5909

Just to add another option, you could use currying.

Groovy - Closures formal definition

Wikipedia - Currying

What you would do is a closure that takes 4 parameters like:

def reqClosure = { path, p1, p2, req ->
    uri.path = path
    uri.query = [ p1: p1, p2: p2 ]
    ...
}

Then you would call the httpClient currying the first 3 parameters of the closure:

myHttpClient.request POST, reqClosure.curry('/new/path', 'value1', 'value2')

Upvotes: 2

tim_yates
tim_yates

Reputation: 171054

You could write a closure that returns a closure:

def reqClosure = { path, p1, p2 ->
    { req ->
        uri.path = path
        uri.query = [ p1: p1, p2: p2 ]
        ...
    }
}

And then call httpClient like so:

myHttpClient.request( POST ) reqClosure( '/new/path', 'value1', 'value2' )

Upvotes: 2

Related Questions