2014-09-03 4 views
2

У меня есть функция, как это:Закрытие с условным протоколирования

private downloadAllFiles() { 
    sftpRetriever.listFiles().findAll { 
     filter.isResponse(it) || filter.isResponseTurned(it) 
    }.each { String fileName -> 
     log.info 'Downloading file: {}', fileName 
     sftpRetriever.downloadFile(fileName) 
     log.info 'File downloaded' 
     removeRemoteFile(fileName) 
    } 
} 

Ищу простой способ модифицирующий это замыкание внутри этой функции, так что если размер() из FindAll 0 это будет просто войти «Больше файлов для загрузки» и .each не будут выполнены. Есть ли простой способ сделать это в одном закрытии? Это действительно просто задача, если я разделить его на несколько частей, но пытаюсь изучить закрытие здесь и улучшить свою выразительность :) Спасибо заранее за вашу помощь.

ответ

4

Посмотрите на существо ниже :) Это работает из-за того факта, что each возвращает коллекцию, на которую она вызывается (+ elvis operator и довольно неплохая Groovy's truth evaluation):

def printContents(Collection collection) { 
    collection.each { 
     println it 
    } ?: println('Collection is empty') 
} 

printContents([1,2,'hello']) 
printContents([]) 

Мне не нравится этот синтаксис, но это более короткая версия, которая мне пришла в голову.

Вы также можете использовать metaprogramming, чтобы добавить метод, предоставляемый Steinar. Он должен быть добавлен к metaClass перед первым использованием, но вы не захотите сделать модуль расширения:

Collection.metaClass.doIfEmpty { Closure ifEmptyClosure -> 
     if (delegate.empty) { 
      ifEmptyClosure() 
     } 
     return delegate 
} 

def printContents(Collection collection) { 
    collection.doIfEmpty { 
     println "Collection is empty" 
    }.each { 
     println it 
    } 
} 

printContents([1,2,'hello']) 
printContents([]) 
+0

Вы можете использовать '||' вместо '?:' –

+0

@tim_yates Хороший отзыв, спасибо! –

3

Вы можете попробовать следующий фрагмент кода:

def l1 = [1,2,3,4] 
def l2 = [5,6,7,8] 

def m(list) { 
    list.findAll { it < 5}.with { l -> 
     size > 0 ? 
      l.each { e -> 
       println e 
      } 
     : 
      println('Zero elements found') 
    } 
} 

m(l1) 
m(l2) 

Нет лучше идеи на данный момент.

+0

Спасибо! Но я все еще надеюсь, что это можно сделать еще проще :) –

+0

+1 для 'with'; но я бы предпочел использовать вы добрый ole 'if':' if (! l.size()) {log(); return} l.each {... ' – cfrick

+0

Спасибо @cfrick: D – Opal

4

Одним из довольно универсальных и многоразовых вариантов является расширение Collection с использованием extension module. Это удивительно легко сделать и даже распознается в IDE (по крайней мере, в IntelliJ), поэтому вы получаете завершение кода и т. Д.

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

package stackoverflow 

class CollectionExtension { 
    static <T extends Collection> T doIfEmpty(T self, Closure closure) { 
     if (self.empty) { 
      closure() 
     } 
     return self 
    } 
} 

Вы также должны сказать заводной, что этот файл является модулем расширения. Добавьте файл свойства в качестве ресурса в пути к классам: META-INF/services/org.codehaus.groovy.runtime.ExtensionModule (обратите внимание: это имя и расположение обязательны для модулей расширения, то есть вы не можете его изменить).

moduleName=stackoverflow-module 
moduleVersion=1.0 
extensionClasses=stackoverflow.CollectionExtension 

Наконец простой тестовый скрипт, чтобы показать, как это можно использовать:

def printContents(Collection collection) { 
    collection.doIfEmpty { 
     println "Collection is empty" 
    }.each { 
     println it 
    } 
} 

printContents([1,2,'hello']) 
printContents([]) 

Выход:

1 
2 
hello 
Collection is empty 
+0

Ницца, очень приятно. Единственная проблема заключается в дополнительной работе дополнительного модуля, в любом случае очень приятной. – Opal

+0

@ Opal: Да, это слишком сложно сделать, если вы используете его один раз, но не много дополнительной работы, если вам это нужно в нескольких разных местах. – Steinar

+0

Конечно, как я сказал ранее, мне нравится это решение. – Opal

Смежные вопросы