Partial function application
Partial function application is the ability to take a function of many parameters and apply arguments to some of the parameters to create a new function that needs only the application of the remaining arguments to produce the equivalent of applying all arguments to the original function.
E.g:
- Given values
v1, v2
- Given
f(param1, param2)
- Then
partial(f, param1=v1)
returnsf'(param2)
- And
f(param1=v1, param2=v2) == f'(param2=v2)
(for any value v2)
Note that in the partial application of a parameter, (in the above case param1), other parameters are not explicitely mentioned. This is a recurring feature of partial function application.
- Task
- Create a function fs( f, s ) that takes a function, f( n ), of one value and a sequence of values s.
Function fs should return an ordered sequence of the result of applying function f to every value of s in turn.
- Create function f1 that takes a value and retuns it multiplied by 2.
- Create function f2 that takes a value and returns it squared.
- Partially apply f1 to fs to form function fsf1( s )
- Partially apply f2 to fs to form function fsf2( s )
- Test fsf1 and fsf2 by evaluating them with s being the sequence of integers from 0 to 3 inclusive and then the sequence of even integers from 2 to 8 inclusive.
J
Given:
<lang j>fs=:1 :'u"0 y' f1=:*&2 f2=:^&2 fsf1=:f1 fs fsf2=:f2 fs</lang>
The required examples might look like this:
<lang j> fsf1 i.4 0 2 4 6
fsf2 i.4
0 1 4 9
fsf1 fsf1 1+i.4
4 8 12 16
fsf2 fsf1 1+i.4
4 16 36 64</lang>
Prolog
Works with SWI-Prolog. <lang Prolog>fs(P, S, S1) :- maplist(P, S, S1).
f1(X, Y) :- Y is 2 * X.
f2(X, Y) :- Y is X * X.
fsf1(S,S1) :-
fs(f1, S, S1).
fsf2(S,S1) :- fs(f2, S, S1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% fs :- S1 = [0,1,2,3], fsf1(S1, S11), format('~w : ~w ==> ~w~n',[fsf1, S1, S11]), fsf2(S1, S12), format('~w : ~w ==> ~w~n',[fsf2, S1, S12]),
S2 = [2,4,6,8], fsf1(S2, S21), format('~w : ~w ==> ~w~n',[fsf1, S2, S21]), fsf2(S2, S22), format('~w : ~w ==> ~w~n',[fsf2, S2, S22]). </lang> Output :
?- fs. fsf1 : [0,1,2,3] ==> [0,2,4,6] fsf2 : [0,1,2,3] ==> [0,1,4,9] fsf1 : [2,4,6,8] ==> [4,8,12,16] fsf2 : [2,4,6,8] ==> [4,16,36,64] true.
Python
<lang python>from functools import partial
def fs(f, s): return [f(value) for value in s]
def f1(value): return value * 2
def f2(value): return value ** 2
fsf1 = partial(fs, f1) fsf2 = partial(fs, f2)
s = [0, 1, 2, 3] assert fs(f1, s) == fsf1(s) # == [0, 2, 4, 6] assert fs(f2, s) == fsf2(s) # == [0, 1, 4, 9]
s = [2, 4, 6, 8] assert fs(f1, s) == fsf1(s) # == [4, 8, 12, 16] assert fs(f2, s) == fsf2(s) # == [4, 16, 36, 64]</lang>
The program runs without triggering the assertions.
Tcl
<lang tcl>package require Tcl 8.6 proc partial {f1 f2} {
variable ctr coroutine __curry[incr ctr] apply {{f1 f2} {
for {set x [info coroutine]} 1 {} { set x [{*}$f1 $f2 [yield $x]] }
}} $f1 $f2
}</lang> Demonstration: <lang tcl>proc fs {f s} {
set r {} foreach n $s {
lappend r [{*}$f $n]
} return $r
} proc f1 x {expr {$x * 2}} proc f2 x {expr {$x ** 2}} set fsf1 [partial fs f1] set fsf2 [partial fs f2] foreach s {{0 1 2 3} {2 4 6 8}} {
puts "$s ==f1==> [$fsf1 $s]" puts "$s ==f2==> [$fsf2 $s]"
}</lang> Output:
0 1 2 3 ==f1==> 0 2 4 6 0 1 2 3 ==f2==> 0 1 4 9 2 4 6 8 ==f1==> 4 8 12 16 2 4 6 8 ==f2==> 4 16 36 64