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
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
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
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)))
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