Jump to content

Partial function application: Difference between revisions

no edit summary
(Add Lua solution)
No edit summary
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 604 ⟶ 641:
// 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 618 ⟶ 655:
// 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 806 ⟶ 843:
 
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,266 ⟶ 1,303:
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,279 ⟶ 1,316:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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,322 ⟶ 1,359:
 
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,470 ⟶ 1,507:
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,479 ⟶ 1,516:
set r {}
foreach n $s {
lappend r [{*}$f $n]
}
return $r
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.