Можно ли реализовать js-версию распаковки Haskell чисто функциональным способом? - PullRequest
13 голосов
/ 15 декабря 2011

Я реализую алгоритм точечного-полигонального преобразования лучей javascript чисто функциональным способом (без особых на то причин).

Я застрял, так как мне нужно было получить два массива из 2-размерный массив (репликация списка кортежей);что-то похожее на unzip.

на Haskell * Возможно ли, начиная с чего-то вроде [[a,b],[c,d],[e,f]], получить [[a,c,e],[b,d,f]] без использования итераторов в процедурном стиле?

(я знаю, это тривиальный вопрос, и я мог бы просто реализовать функцию процедурно, а затем забыть об этом, но мне было любопытно узнать, было ли решение)


РЕДАКТИРОВАТЬ: Чтобы уточнить, я знаю, как реализовать zip иunzip: Мне было интересно, возможно ли реализовать их без for петель и переменных переназначений.

1 Ответ

6 голосов
/ 15 декабря 2011

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

В Dojo, библиотеке, которую я использую, они реализуют zip и распаковывают как

unzip: function(/*Array*/ a){
    // summary: similar to dojox.lang.functional.zip(), but takes
    // a single array of arrays as the input.
    // description: This function is similar to dojox.lang.functional.zip()
    // and can be used to unzip objects packed by
    // dojox.lang.functional.zip(). It is here mostly to provide
    // a short-cut for the different method signature.

    return df.zip.apply(null, a);
}

zip: function(){
    // summary: returns an array of arrays, where the i-th array
    // contains the i-th element from each of the argument arrays.
    // description: This is the venerable zip combiner (for example,
    //    see Python documentation for general details). The returned
    //    array is truncated to match the length of the shortest input
    //    array.
    var n = arguments[0].length,
        m = arguments.length,
        i = 1,
        t = new Array(n),
        j,
        p;
    for(; i < m; n = Math.min(n, arguments[i++].length));
    for(i = 0; i < n; ++i){
        p = new Array(m);
        for(j = 0; j < m; p[j] = arguments[j][i], ++j);
        t[i] = p;
    }
    return t;
},

Обратите внимание, что zip получает несколько аргументов, поэтому он больше похож на Python zip, а не на Haskell.


Нетрудно преобразовать этот код в «чисто функциональный» стиль без присвоения переменных. Ваш существующий код уже должен обрабатывать работу первых двух форов в примере, который я разместил (обрезка zip до минимальной длины и итерация по индексам одного из списков). Все, что осталось, - это сделать то же самое для третьего - собрать i-ое значение из списка списков вместо того, чтобы собирать два значения из двух списков.

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