Partial function application: Difference between revisions

Undo revision 190799 by Hernan (talk) Please don't change the formatting of every other example
No edit summary
(Undo revision 190799 by Hernan (talk) Please don't change the formatting of every other example)
Line 251:
(dolist (seq '((0 1 2 3) (2 4 6 8)))
(format t "~%seq: ~A~% fsf1 seq: ~A~% fsf2 seq: ~A"
seq (funcall fsf1 seq) (funcall fsf2 seq)))</lang>
 
Output: <pre>seq: (0 1 2 3)
Line 274:
pfunc partial(intfunc fin)
{
pfunc f;
static int idx = 0;
char cc[256], lib[256];
FILE *fp;
sprintf(lib, "/tmp/stuff%d.so", ++idx);
sprintf(cc, "cc -pipe -x c -shared -o %s -", lib);
 
fp = popen(cc, "w");
fprintf(fp, "#define t typedef\xat int _i,*i;t _i(*__)(_i);__ p =(__)%p;"
"void _(i _1, _i l){while(--l>-1)l[_1]=p(l[_1]);}", fin);
fclose(fp);
 
*(void **)(&f) = dlsym(dlopen(lib, RTLD_LAZY), "_");
unlink(lib);
return f;
}
 
int square(int a)
{
return a * a;
}
 
int dbl(int a)
{
return a + a;
}
 
int main()
{
int x[] = { 1, 2, 3, 4 };
int y[] = { 1, 2, 3, 4 };
int i;
 
pfunc f = partial(square);
pfunc g = partial(dbl);
 
printf("partial square:\n");
f(x, 4);
for (i = 0; i < 4; i++) printf("%d\n", x[i]);
 
printf("partial double:\n");
g(y, 4);
for (i = 0; i < 4; i++) printf("%d\n", y[i]);
 
return 0;
}</lang>output<lang>partial square:
1
Line 542:
{4 8 12 16}
{4 16 36 64}
</lang>
 
=={{header|Erlang}}==
 
Partial applications can be built using the Erlang Meta Interpreter.
 
<lang erlang>
-module(partial_application).
 
-export([run/0]).
 
partial(F, Args) ->
{arity, InitialArity} = erlang:fun_info(F, arity),
case length(Args) of
L when L < InitialArity ->
MissingArgs = [{var, 1, N} || N <- lists:seq(1, InitialArity - L)],
ArgList = [case is_function(A) of
false -> erl_parse:abstract(A);
true -> {var, 1, erlang:fun_to_list(A)}
end || A <- Args] ++ MissingArgs,
Parsed = [{'fun', 1,
{clauses, [{clause, 1, MissingArgs, [],
[{call, 1, {var, 1, 'F'}, ArgList}]}]}}],
{value, R, _} = erl_eval:exprs(Parsed, [{'F', F}] ++
[{erlang:fun_to_list(A), A} ||
A <- Args, is_function(A)]),
R
end.
 
run() ->
F = partial(fun lists:map/2, [fun(X) -> X + 1 end]),
F([0, 1, 2, 3, 4]).
</lang>
'''Output:'''
<lang erlang>
> partial_application:run().
[1,2,3,4,5]
</lang>
 
Line 641 ⟶ 604:
// fs applies fn to each argument returning all results.
func (f fn) fs(s ...int) (r []int) {
for _, i := range s {
r = append(r, f(i))
}
return r
}
 
Line 655 ⟶ 618:
// addn returns a function that adds n to a sequence of numbers
func addn(n int) func(...int) []int {
return func(s ...int) []int {
var r []int
for _, i := range s {
r = append(r, n+i)
}
}
return r
}
}
 
func main() {
// Turning a method into a function bound to it's reciever:
fsf1 := fn(f1).fs
fsf2 := fn(f2).fs
// Or using a function that returns a function:
fsf3 := addn(100)
 
s := []int{0, 1, 2, 3}
fmt.Println("For s =", s)
fmt.Println(" fsf1:", fsf1(s...)) // Called with a slice
fmt.Println(" fsf2:", fsf2(0, 1, 2, 3)) // ... or with individual arguments
fmt.Println(" fsf3:", fsf3(0, 1, 2, 3))
fmt.Println(" fsf2(fsf1):", fsf2(fsf1(s...)...))
 
s = []int{2, 4, 6, 8}
fmt.Println("For s =", s)
fmt.Println(" fsf1:", fsf1(2, 4, 6, 8))
fmt.Println(" fsf2:", fsf2(s...))
fmt.Println(" fsf3:", fsf3(s...))
fmt.Println(" fsf3(fsf1):", fsf3(fsf1(s...)...))
}</lang>
{{out}}
Line 843 ⟶ 806:
 
public class PartialApplication {
interface IntegerFunction {
int call(int arg);
}
 
// Original method fs(f, s).
static int[] fs(IntegerFunction f, int[] s) {
int[] r = new int[s.length];
for (int i = 0; i < s.length; i++)
r[i] = f.call(s[i]);
return r;
}
 
interface SequenceFunction {
int[] call(int[] arg);
}
 
// Curried method fs(f).call(s),
// necessary for partial application.
static SequenceFunction fs(final IntegerFunction f) {
return new SequenceFunction() {
public int[] call(int[] s) {
// Call original method.
return fs(f, s);
}
}
};
}
 
static IntegerFunction f1 = new IntegerFunction() {
public int call(int i) {
return i * 2;
}
}
};
 
static IntegerFunction f2 = new IntegerFunction() {
public int call(int i) {
return i * i;
}
}
};
 
static SequenceFunction fsf1 = fs(f1); // Partial application.
 
static SequenceFunction fsf2 = fs(f2);
 
public static void main(String[] args) {
int[][] sequences = {
{ 0, 1, 2, 3 },
{ 2, 4, 6, 8 },
};
 
for (int[] array : sequences) {
System.out.printf(
"array: %s\n" +
" fsf1(array): %s\n" +
" fsf2(array): %s\n",
Arrays.toString(array),
Arrays.toString(fsf1.call(array)),
Arrays.toString(fsf2.call(array)));
}
}
}
}</lang>
 
Line 1,303 ⟶ 1,266:
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.
 
create_partial(P, fs(P)).
Line 1,316 ⟶ 1,279:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fs :-
% partial functions
create_partial(f1, FSF1),
create_partial(f2, FSF2),
 
S1 = [0,1,2,3],
call(FSF1,S1, S11), format('~w : ~w ==> ~w~n',[FSF1, S1, S11]),
call(FSF1,S1, S12), format('~w : ~w ==> ~w~n',[FSF2, S1, S12]),
 
S2 = [2,4,6,8],
call(FSF1,S2, S21), format('~w : ~w ==> ~w~n',[FSF2, S2, S21]),
call(FSF2,S2, S22), format('~w : ~w ==> ~w~n',[FSF1, S2, S22]).
</lang>
Output :
Line 1,359 ⟶ 1,322:
 
Explicitly spelling out the partial function without hiding behind a library:<lang Python>def partial(f, g):
def fg(*x): return f(g, *x)
return fg
 
def fs(f, *x): return [ f(a) for a in x]
Line 1,507 ⟶ 1,470:
variable ctr
coroutine __curry[incr ctr] apply {{f1 f2} {
for {set x [info coroutine]} 1 {} {
set x [{*}$f1 $f2 [yield $x]]
}
}} $f1 $f2
}</lang>
Line 1,516 ⟶ 1,479:
set r {}
foreach n $s {
lappend r [{*}$f $n]
}
return $r
Anonymous user