Что мы называем этой (новой?) Функцией более высокого порядка?

Я пытаюсь назвать то, что, по моему мнению, является новой идеей для функции более высокого порядка. К важной части, вот код в Python и Haskell, чтобы продемонстрировать концепцию, которая будет объясняться позже.

Python:

>>> def pleat(f, l):
       return map(lambda t: f(*t), zip(l, l[1:]))
>>> pleat(operator.add, [0, 1, 2, 3])
[1, 3, 5]

Haskell:

Prelude> let pleatWith f xs = zipWith f xs (drop 1 xs)
Prelude> pleatWith (+) [0,1,2,3]
[1,3,5]

Как вы можете сделать вывод, последовательность выполняется итерацией через использование смежных элементов в качестве параметров для функции, которую вы передаете, проецируя результаты в новую последовательность. Итак, кто-нибудь видел функциональность, которую мы создали? Это вообще знакомо с теми, кто работает в функциональном сообществе? Если нет, что мы называем?

---- Update ----
Победители

Pleat

Prelude> let pleat xs = zip xs (drop 1 xs)
Prelude> pleat [1..4]
[(1,2),(2,3),(3,4)]

Prelude> let pleatWith f xs = zipWith f xs (drop 1 xs)
Prelude> pleatWith (+) [1..4]
[3,5,7]

Ответ 1

Я действительно не вижу никаких кодифицированных имен для этого в любом месте Python, это точно. "Слияние" - это хорошо, но говорят в других контекстах. "Плуг" имеет тенденцию быть неиспользуемым и обеспечивает великолепную визуальность непрерывного продвижения по линии почвы. Возможно, я потратил слишком много времени на садоводство.

Я также расширил принцип, чтобы позволить функциям, которые получают любое количество параметров.

Вы также можете подумать: Pleat. Он хорошо описывает то, как вы берете список (например, длинную прядь ткани) и объединяете его вместе.

import operator

def stagger(l, w):
    if len(l)>=w:
        return [tuple(l[0:w])]+stagger(l[1:], w)
    return []

def pleat(f, l, w=2):
    return map(lambda p: f(*p), stagger(l, w))

print pleat(operator.add, range(10))
print pleat(lambda x, y, z: x*y/z, range(3, 13), 3)
print pleat(lambda x: "~%s~"%(x), range(10), 1)
print pleat(lambda a, b, x, y: a+b==x+y, [3, 2, 4, 1, 5, 0, 9, 9, 0], 4)

Ответ 2

Хм... контрапункт.

(`ap` tail) . zipWith

не заслуживает имени.

BTW, quicksilver говорит:

 zip`ap`tail

Ацтекский бог последовательных чисел

Ответ 3

Так как он похож на "сгиб", но не сворачивает список в одно значение, как насчет "складки"? Если вы держите "смятие", вы оказываетесь "складывающимся" (вроде).

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

def pinch(f, l):
    return map(lambda t: f(*t), zip(l, l[1:]+l[:1]))

(Если вам нравится только одна из "сгибов" или "щепотка", обратите внимание на комментарий. Должны ли они быть отдельными предложениями?)

Ответ 4

В Python эквивалент meld находится в получателях itertools и называется попарно.

from itertools import starmap, izp, tee

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Поэтому я бы назвал это:

def pairwith(func, seq):
    return starmap(func, pairwise(seq))

Я думаю, что это имеет смысл, потому что, когда вы вызываете его с помощью функции идентификации, он просто возвращает пары.

Ответ 5

Здесь другая реализация для Python, которая работает, если l тоже является генератором

import itertools as it

def apply_pairwise(f, l):
    left, right = it.tee(l)
    next(right)
    return it.starmap(f, it.izip(left, right))

Я думаю, что apply_pairwise - лучшее имя

Ответ 6

zipWithTail или adjacentPairs.

Ответ 7

Я проголосую за smearWith или smudgeWith, потому что это похоже на то, что вы размываете/смазываете операцию в списке.

Ответ 8

это похоже на ruby ​​each_cons

ruby-1.9.2-p0 > (1..10).each_cons(2).to_a

=> [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10]] 

Ответ 9

Это напоминает мне свертку от обработки изображений. Но не уверен, что это математически правильно.

Ответ 10

Обобщенный вариант простой zip-версии этого - это то, что я думаю как window. Не сейчас на терминале ghci, но я думаю window n = take n . tails. Тогда ваша функция zipWith (\[x,yj -> f x y) . window 2. Такой стиль естественно работает лучше, если f имеет тип [a] -> b.

Ответ 11

в стандартной библиотеке шаблонов С++, она называется adjacent_difference (хотя оператор может быть любой операцией, а не просто вычитанием)

Ответ 12

Итак, потому что, кажется, нет имени для этого, я предлагаю "слияние" или простое "слияние" , потому что вы объединяете смежные значения.

Итак, слияние уже выполнено, поэтому теперь я предлагаю "meld" (или "слияние" по-прежнему, но это может быть слишком близко к "merge" )

Например:

meld :: (a -> a -> b) -> [a] -> [b]
meld _ [] = []
meld f xs = zipWith f (init xs) (tail xs)

который может использоваться как:

> meld (+) [1..10]
[3,5,7,9,11,13,15,17,19]
> meld compare "hello world"
[GT,LT,EQ,LT,GT,LT,GT,LT,GT,GT]

Если второй пример не имеет никакого смысла, но делает классный пример.

Ответ 13

Использование Mathematica

Plus @@@ Partition [{0, 1, 2, 3}, 2, 1] или любой из этих более подробных альтернатив

Apply[Plus, Partition[{0, 1, 2, 3}, 2, 1], {1}]
Map[Apply[Plus, #] &, Partition[{0, 1, 2, 3}, 2, 1]]

Я использовал и пользовался этой функцией более высокого порядка на многих языках, но мне понравилось больше всего в Mathematica; он кажется сжатым и гибким, разбитым на разделы и "Применить" с параметром levelspec.

Ответ 14

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

В обработке музыки также есть два конкретных имени "контуры": валовой контур - шаг вверх или вниз. Другой - очищенный контур, где контур либо вверх, вниз, либо прыгает вверх, либо прыгает вниз, хотя я не могу найти ссылку на то, насколько велика разница в полутонах, чтобы совершить прыжок.

Ответ 15

Хорошая идиома! Мне просто нужно было использовать это в Perl для определения времени между последовательными событиями. Вот что у меня получилось.

sub pinch(&@) {
  my ( $f, @list ) = @_;
  no strict "refs";

  use vars qw( $a $b );

  my $caller = caller;
  local( *{$caller . "::a"} ) = \my $a;
  local( *{$caller . "::b"} ) = \my $b;

  my @res;
  for ( my $i = 0; $i < @list - 1; ++$i ) {
    $a = $list[$i];
    $b = $list[$i + 1];
    push( @res, $f->() );
  }
  wantarray ? @res : \@res;
}

print join( ",", pinch { $b - $a } qw( 1 2 3 4 5 6 7 ) ), $/;
# ==> 1,1,1,1,1,1

Реализация, возможно, была бы более красивой, если бы я сделал ее зависимой от List:: Util, но... meh!

Ответ 16

BinaryOperate или BinaryMerge