Reputation: 6082
I have a Java method:
void copy(Object src, Object dest);
I am using it in Groovy as such:
def copyGroovy = { p1, p2 -> copy(p1,p2) }
def copyFixP1 = { p1 -> copyGroovy.curry(p1) }
def cp = // How to define this?
How can I write the invocation in Groovy so that it looks like:
cp src dest
Any ideas?
Upvotes: 2
Views: 478
Reputation: 24468
The following is a DSL answer that is arguably more of a kludge to solve a puzzle: it does not address currying syntax, but provides the veneer of cp src dest
. But I hope it illustrates some Groovy features.
If we begin with the copy functions:
class Copy {
def copy = { a, b -> println "TRACER copy ${a} to ${b}" }
def copyGroovy = { p1, p2 -> copy(p1,p2) }
def copyFixP1 = { p1 -> copyGroovy.curry(p1) }
}
and define a Copier
with some meta-programming methods:
class Copier {
def copyContext
def runContext
def p1, p2
def methodMissing(String name, args) {
p1 = args[0]
return this
}
Object getProperty( String property ) {
p2 = runContext.getProperty(property)
copyContext.copyFixP1(p1)(p2)
}
}
Then consider the following (assuming a single Groovy script as shown here):
// ----- main
class Example {
def src = "A"
def dest = "B"
def run = { ->
def cp = new Copier(copyContext: new Copy(), runContext: this)
// at long last:
cp src dest
}
}
new Example().run()
Upvotes: 2
Reputation: 42174
If you want to create a DSL like command chain you can take advantage of passing arguments without parentheses and/or dot notation. The closest form of cp
command you mentioned in the question is something like:
cp (src) (dest)
cp
in this case is a function that returns a closure that calls your Java's copy(Object src, Object dest)
method. Something like this:
def cp(src) {
return { dest ->
copy(src, dest)
}
}
If you would like to get rid of parentheses and you accept additional keyword, you could get something like this:
copy src to dest
which is an equivalent of:
copy(src).to(dest)
copy
method can be implemented as:
def copy(src) {
[to: { dest ->
copy(src, dest)
}]
}
And last, but not least - you can actually call this Java method as:
copy src, dest
You get rid of parentheses, but you need to add ,
to tell the compiler that you pass two arguments to this function.
Below you can find example of all 3 combinations:
void copy(Object src, Object dest) {
println "Copying ${src} to ${dest}..."
}
def copy(src) {
[to: { dest ->
copy(src, dest)
}]
}
def cp(src) {
return { dest ->
copy(src, dest)
}
}
def src = "/tmp/test.txt"
def dest = "/tmp/test2.txt"
// Example 1
copy src to dest
// Example 2
cp (src) (dest)
// Example 3
copy src, dest
Running this script produces following output:
Copying /tmp/test.txt to /tmp/test2.txt...
Copying /tmp/test.txt to /tmp/test2.txt...
Copying /tmp/test.txt to /tmp/test2.txt...
You can read more about Groovy DSL features here
Upvotes: 2
Reputation: 7509
You can't write the invocation with space separated arguments like you would in Haskell (or other functional languages). Instead you need to write:
copyFixP1(src)(dst)
Also, you called the second variable as copyFixP1
but you are not actually fixing p1
, copyFixP1
still needs an argument. Fixing would be to explicitly set the first argument of copyGroovy
let's say to 'sourcePath'
like so:
def copyFixedSrc = copyGroovy.curry('sourcePath')
You did curry it however so copyFixP1
is what I assume you wanted as cp
.
Upvotes: 2