Как выложить два замыкания в Groovy? - PullRequest
0 голосов
/ 31 мая 2018

У меня есть метод Java:

void copy(Object src, Object dest);

Я использую его в Groovy следующим образом:

def copyGroovy = { p1, p2 -> copy(p1,p2) }
def copyFixP1 = { p1 -> copyGroovy.curry(p1) }
def cp = // How to define this?

Как я могу написать вызов в Groovy, чтобы он выглядел следующим образом:

cp src dest

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Если вы хотите создать DSL-подобную цепочку команд, вы можете воспользоваться передачей аргументов без скобок и / или точечных обозначений.Самая близкая форма команды cp, которую вы упомянули в вопросе, выглядит примерно так:

cp (src) (dest)

cp в этом случае - это функция, которая возвращает замыкание, которое вызывает ваш Java-метод copy(Object src, Object dest).Примерно так:

def cp(src) {
    return { dest ->
        copy(src, dest)
    }
}

Если вы хотите избавиться от скобок и принять дополнительное ключевое слово, вы можете получить что-то вроде этого:

copy src to dest

, что эквивалентно:

copy(src).to(dest)

copy метод может быть реализован как:

def copy(src) {
    [to: { dest ->
        copy(src, dest)
    }]
}

И, наконец, что не менее важно - вы можете вызвать этот метод Java как:

copy src, dest

Вы избавляетесь от скобок, но вам нужно добавить ,, чтобы сообщить компилятору, что вы передаете два аргумента этой функции.

Пример

Ниже вы можете найти пример всех 3комбинации:

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

Запуск этого скрипта приводит к следующему выводу:

Copying /tmp/test.txt to /tmp/test2.txt...
Copying /tmp/test.txt to /tmp/test2.txt...
Copying /tmp/test.txt to /tmp/test2.txt... 

Подробнее о возможностях Groovy DSL можно узнать здесь

0 голосов
/ 01 июня 2018

Ниже приведен DSL-ответ, который, возможно, является большим шагом для решения загадки: он не затрагивает синтаксис карри, но обеспечивает фанеру cp src dest.Но я надеюсь, что он иллюстрирует некоторые возможности Groovy.

Если мы начнем с функций копирования:

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) }
}

и определим Copier с помощью некоторых методов метапрограммирования:

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)
    }
}

Затем рассмотрим следующее (при условии, что один скрипт Groovy, как показано здесь ):

// ----- 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()
0 голосов
/ 31 мая 2018

Вы не можете написать вызов с разделенными пробелом аргументами, как это было бы в Haskell (или других функциональных языках).Вместо этого вам нужно написать:

copyFixP1(src)(dst)

Кроме того, вы назвали вторую переменную как copyFixP1, но на самом деле вы не исправляете p1, copyFixP1 все еще нуждается в аргументе.Исправление будет заключаться в том, чтобы явно установить первый аргумент copyGroovy, скажем, 'sourcePath', например, так:

def copyFixedSrc = copyGroovy.curry('sourcePath')

Вы сделали это, однако, так что copyFixP1 - это то, что, я полагаю, вы хотели получить как cp.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...