3

I wrote a function and I'd like to find out if it is an implementation of some functional programming pattern or construct. I'd like to find out the name of this pattern or construct (if it exists)?

I have a function which takes a list of functions and does this to them:

    wrap(fn1, fn2, fn3, fn4)
    # returns
    partial(fn4, partial(fn3, partial(fn2, fn1)))

There are strong similarities to compose, reduce, and other fp metaprogramming constructs, since the functions are being arranged together and returned as one function.

It also has strong similarities to decorators and Python context managers since it provides a way to encapsulate pre and post execution behaviors in one function. Which was the impetus for writing this function. I wanted the ability that context managers provide, but I wanted to be able to have it defined in one function, and to be able to layer function after function on top.

UPDATE:

For clarity I've added the implementation:


_wrap = partial(reduce, lambda inner, outer: partial(outer, inner))
def wrap(fns):
    fns = tuple(fns)
    if len(fns)==1:
        return fns[0]
    return lambda *a, **kw: _wrap(iter(fns))(*a, **kw)

and an example:


def fn_one(fn, *a, **kw):
  print "entered one"
  response = fn(*a, **kw)
  print "exited one"
  return response

def fn_two(fn, *a, **kw):
  print "entered two"
  response = fn(*a, **kw)
  print "exited two"
  return response

def zero():
  print "zero"

wrapped_zero = wrap((zero, fn_one, fn_two))
wrapped_zero() # returns entered two, entered one, zero, exited one, exited two 
1
  • It's right associative but it's still currying. The examples I used below are left associative so they look slightly different, that's just a matter of the ordering you used for the parameters to your wrap function. Commented Nov 26, 2012 at 21:28

3 Answers 3

9

tl;dr

This is called currying, also sometimes schoenfinkelization and it's built-in default behaviour in Haskell and derivative languages. Plausibly other languages to I'm unfamiliar with.

http://en.wikipedia.org/wiki/Currying

In mathematics and computer science, currying is the technique of transforming a function that takes n multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions, each with a single argument (partial application). It was originated by Moses Schönfinkel[1] and later re-discovered by Haskell Curry.[2][3] Because of this, some say it would be more correct to name it schönfinkeling.[4][5]


Unnecessary details on currying:

Any language with higher order functions can have this behaviour mimicked, generics greatly help it be not clumsy, but the least clumsy languages for this are functional ones with facilities specifically to do it.

That said here are some articles about doing it in various languages to illustrate as you said it is a pattern:

http://msmvps.com/blogs/jon_skeet/archive/2012/01/30/currying-vs-partial-function-application.aspx

http://mtomassoli.wordpress.com/2012/03/18/currying-in-python/

https://wiki.php.net/rfc/currying

By default in haskell, every function takes no more than one value and returns one value, until eventually it takes no values and returns a value.

This is written as:

someFunc :: inputVal -> (returnVal)

This becomes currying as:

someFunc :: inputVal1 -> (inputVal2 -> (inputVal3 -> (returnVal))))

In this example, someFunc takes a value, and returns (a function which takes a value and returns (a function which takes a value and returns (a value)))).

Each of the functions in that chain take one value, the last return is not a function as it does not take anything but rather holds a computation (perhaps 1+2, something that doesn't take parameters).

I say this is default behaviour in Haskell because in Haskell, passing 2 values to someFunc will hand it one value, and hand the next value to the returned function, returning the 3rd function in the chain.

i.e. using the signature above, if I defined someFunc as:

someFunc x y z = x + y + z

then I call it as:

plusTwo :: inputVal3 -> (returnVal)
plusTwo = someFunc 1 1

Now I have captured the 2nd returned function in the chain by giving it one parameter which causes it to return the first function, and the second parameter I gave it is curried into that first returned function causing it to be called and return the 3rd function, which I use as the value for plusTwo

So in closing, currying works about like so:

given:

someFunc a b c d = a + b + c + d
plusOne   = someFunc 1
plusTwo   = someFunc 1 1
plusThree = someFunc 1 1 1
    four  = someFunc 1 1 1 1

The signatures would be:

someFunc :: a -> (b -> (c -> (d -> (e))))
       plusOne :: b -> (c -> (d -> (e)))
             plusTwo :: c -> (d -> (e))
                 plusThree :: d -> (e)
                            four :: e
7
  • Scala also supports currying but, AFAIK, not as flexibly as Haskell.
    – Giorgio
    Commented Nov 23, 2012 at 23:13
  • @Giorgio I know there's a myriad of languages which support it, though I'm not aware of languages which have it as default behaviour other than Haskell derivatives, either way that's a side note, I was just using Haskell to illustrate it, there are articles which show it can be done in any language which has higher order functions Commented Nov 23, 2012 at 23:24
  • 6
    The whole ML familly support currying.
    – BenjaminB
    Commented Nov 23, 2012 at 23:39
  • @Ubiquité Is it default behaviour in the ML family? I've been meaning to play with SML, I meddled with F# a bit but didn't notice if currying was default behaviour in it Commented Nov 23, 2012 at 23:50
  • @Jimmy Hoffa: As I pointed out, I think Scala's support for currying it not the default and not as flexible as Haskell's: in Scala you have to indicate in the signature at which point you want to cut your function, like: def f(x: Int)(y: Int): Int (with currying) vs def f(x: Int, y: Int): Int (no currying).
    – Giorgio
    Commented Nov 24, 2012 at 9:55
1

I believe you're referring to "threading". Here's a nice Clojure explanation from Michael Fogus.

(-> (Math/sqrt 25) int list)

Can literally be read:

Take the result of (Math/sqrt 25) Feed it into the function int Feed that result into the function list Graphically, this can be viewed as:

(Math/sqrt 25) --5.0--> (int 5.0) --5--> (list 5) 
=> (5) 

Which expands into the following s-expression:

(list (int (Math/sqrt 25)))
0

Isn't it essentially a (mathematical) function composition, only with reversed order of application? Your wrap is left-associative, compared with compose which usually is right associative, at least in Common Lisp.

The regular notation would be something like that:

fn1∘fn2∘fn3∘fn4(x) = fn1(fn2(fn3(fn4(x))))

In your case it's reversed:

fn1∘fn2∘fn3∘fn4(x) = fn4(fn3(fn2(fn1(x))))

This is akin to threading, described in Daniel J. Pritchett's answer, only with the argument omitted.

(-> Math/sqrt int list)

1
  • 2
    The partialing is what makes it differ from composition Commented Nov 23, 2012 at 23:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.