Search code examples
pythonhaskellfunctional-programmingtheoryhigher-order-functions

What do we call this (new?) higher-order function?


I am trying to name what I think is a new idea for a higher-order function. I want to call it a BinaryProjection, but my compatriot wants to call it the Plow. We tossed around the idea of a Snow Blower for a minute, too. Anyway, to the important part, here is the code in Python and Haskell to demonstrate the concept, which will be explained afterward.

Python:

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

Haskell:

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

As you may be able to infer, the sequence is being iterated through, utilizing adjacent elements as the parameters for the function you pass it, projecting the results into a new sequence. So, has anyone seen the functionality we've created? Is this familiar at all to those in the functional community? If not, what do we name it?

---- Update ----

There are three candidates for the name. meld, pinch, and pleat. In Haskell, they would be implemented as so (using "meld"):

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

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

I think it's time for a vote. I'm partial to pinch or pleat, myself.


Solution

  • I really can't see any codified names for this anywhere in Python, that's for sure. "Merge" is good but spoken for in a variety of other contexts. "Plow" tends to be unused and supplies a great visual of pushing steadily through a line of soil. Maybe I've just spent too much time gardening.

    I also expanded the principle to allow functions that receive any number of parameters.

    You might also consider: Pleat. It describes well the way you're taking a list (like a long strand of fabric) and bunching segments of it together.

    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)