На информационном ресурсе применяются рекомендательные технологии (информационные технологии предоставления информации на основе сбора, систематизации и анализа сведений, относящихся к предпочтениям пользователей сети "Интернет", находящихся на территории Российской Федерации)

Comparator closure & currying

Есть в Groovy такая возможность, как currying (каррирование что-ли?) замыканий.
Само понятие прийшло из функционального программирования и означает преобразование функции с один количеством агрументов, в функцию меньшего количества путем "фиксации" значений некоторых аргументов.
Например есть функция f(x,y,z), тогда её каррированием по фиксированному значению арргумента x=10 будет функция Λ(f)=f(10, y, z).
Термин currying прозшел от имени известного математика Хаскеля Карри, и ещё иногда называется  Шейнфинкелизацией (от имени Украинского математика Моисея Шейфинкля, который изобрел это понятие)

Покажу небольшой пример того, как можно использовать каррирование замыканий в Groovy.

Предположим есть обычные POGO класс:

class User {
    String name
    String emailAddress
    Date dateOfBirth
    int weight

    String toString() {
        name
    }
}

И стоит задача реализовать сортировку списка обьектов этого класса по каждому из свойств (name, emailAddress, dateOfBirth, weight).
Для выполнения сортировки списка можно использовать метод sort(), в какой необходимо передать свой экземпляр Comparator-а.
Решением задачи "в лоб" будет реализация для каждого из сортируемых свойств отдельного Comparator-а.

Например для свойства name он будет выглядеть приблизительно так:

public class UserNameComparator implements Comparator<User> {

    public int compare(User a, User b) {
        def aValue = a.getName();
        def bValue = b.getName();

        if (!aValue && !bValue)
            return 0;
        else if (!aValue)
            return -1;
        else if (!bValue)
            return 1;
        else
            return aValue.compareTo(bValue);
    }

}

И так 4 раза (с)... Не много ли кода для такой мелочи как сортировка?

Теперь же попробуем реализовать подобный функционал с помощью замыканий Groovy.
Создаем такое вот универсальное замыкание-компаратор (а может функцию 3х аргументов?):

def comparator = { attribute, a, b ->
    def aValue = a.getProperty(attribute)
    def bValue = b.getProperty(attribute)

    if (!aValue && !bValue)
        return 0
    else if (!aValue)
        return -1
    else if (!bValue)
        return 1
    else
        return aValue.compareTo(bValue)
}

Теперь для сортировки по каждому свойствую обьекта User используем каррирование замыкания с фиксированием имени свойства:

usersList.sort( comparator.curry("name")  )
usersList.sort( comparator.curry("emailAddress")  )
usersList.sort( comparator.curry("dateOfBirth")  )
usersList.sort( comparator.curry("weight")  )

Вот так все просто и элегантно - немного функционального программирования, немного meta-программирования, немного duck typing-а.

Ссылки:
О понятии Currying в Wikipedia.
Англоязычная версия этой заметки в блоге MustardGrain
Большинство языков программирования которые поддерживают замыкания поддерживают и каррирование:
Currying в Scala (функциональном языке для JVM), Currying в Python, Currying в Ruby.

 

 

Источник: http://voituk.kiev.ua/2008/05/12/comparator-closure-currying...

Картина дня

наверх