LINUX.ORG.RU

Функциональное программирование: «продвинутый» аналог filter


0

0

Встала следующа проблема: в списке -- размер его заранее не определен в алгоритме, поэтому удобнее считать его бесконечным потоком -- требуется выбрать определенные элементы по предикату. Это легко сделать стандартным filter. Но есть задача не только выделить нужные элементы, но и вернуть номер их позиции в списке. Как написать такую процедуру в "функциональном" стиле (подозреваю необходимость продолжений [continuations])?

(require srfi/41)

(define-stream (stream-filter-counting pred stream [counter 0])
  (if (stream-null? stream)
      stream-null
      (let ((head (stream-car stream)))
        (if (pred head)
            (stream-cons (cons head counter)
                         (stream-filter-counting pred (stream-cdr stream) (add1 counter)))
            (stream-filter-counting pred (stream-cdr stream) (add1 counter))))))

Sphinx ★★☆☆
()
Ответ на: комментарий от Sphinx

Ээээ, я понимаю, что наглею: но нельзя ли чуть-чуть разжевать. Зачем? Дело в том, что язык реализации будет не scheme (для которой я только формулировку придумал), а... Maple

annoynimous ★★★★★
() автор топика
Ответ на: комментарий от Sphinx

В смысле, `stream-filter-counting` возвращает поток из пар (cons),
первыми элементами которых являются удовлетворяющие предикату pred
элементы исходного списка, а вторыми — номер в исходном списке
(начиная с 0)

    > (define naturals (stream-from 0 1))
    > (define evens (stream-from 0 2))
    > (stream-ref (stream-filter-counting even? naturals) 0)
    (0 . 0)
    > (stream-ref (stream-filter-counting even? evens) 0)
    (0 . 0)
    > (stream-ref (stream-filter-counting even? naturals) 5)
    (10 . 10)
    > (stream-ref (stream-filter-counting even? evens) 5)
    (10 . 5)
    > (define odds (stream-from 1 2))
    > (stream-car (stream-filter-counting even? odds))
    [бесконечное ожидание]

Можно переписать с хвостом используя стандартную идиому с
дополнительным аргументом.

Sphinx ★★☆☆
()

Не совсем понял проблему.

почти С++ в функциональном стиле:

template <Producer, Consumer, Predicate>
void filter(const Producer &producer, const Consumer &consumer, const Predicate& predicate, int position = 0) {
    auto item = producer();
    if (predicate(item)) {
        consumer(item, position);
    }
    filter(producer, consumer, predicate, position + 1);
}

Legioner ★★★★★
()
Ответ на: удаленный комментарий

В питоне, раз бесконечно, нужно будет сделать не list, а generator comprehension:

( (i,j) for i,j in enumerate (<list>) if predicate(j) )

в Хаскеле, соотвественно (там все списки генераторы):

[ (i, j) | (i, j) <- (zip [N..] <list>), predicate j ]

Joe_Bishop
()
Ответ на: комментарий от Legioner

2 Legioner
>Не совсем понял проблему.

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

alex4
()

filter (predicate . snd) . (zip [1..])

imp ★★
()
Ответ на: комментарий от Joe_Bishop

В последнем ghc можно сделать так

[(i,j) | i <- [0..] | j <- list]

Miguel ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.