Partial function application: Difference between revisions

Rename Perl 6 -> Raku, alphabetize, minor clean-up
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
Line 277:
4 8 12 16
4 16 36 64</pre>
 
=={{header|Clojure}}==
<lang Clojure>(defn fs [f s] (map f s))
(defn f1 [x] (* 2 x))
(defn f2 [x] (* x x))
(def fsf1 (partial fs f1))
(def fsf2 (partial fs f2))
 
(doseq [s [(range 4) (range 2 9 2)]]
(println "seq: " s)
(println " fsf1: " (fsf1 s))
(println " fsf2: " (fsf2 s)))</lang>
Output:
<pre>seq: (0 1 2 3)
fsf1: (0 2 4 6)
fsf2: (0 1 4 9)
seq: (2 4 6 8)
fsf1: (4 8 12 16)
fsf2: (4 16 36 64)</pre>
 
=={{header|Common Lisp}}==
<lang lisp>(defun fs (f s)
(mapcar f s))
(defun f1 (i)
(* i 2))
(defun f2 (i)
(expt i 2))
(defun partial (func &rest args1)
(lambda (&rest args2)
(apply func (append args1 args2))))
 
(setf (symbol-function 'fsf1) (partial #'fs #'f1))
(setf (symbol-function 'fsf2) (partial #'fs #'f2))
(dolist (seq '((0 1 2 3) (2 4 6 8)))
(format t
"~%seq: ~A~% fsf1 seq: ~A~% fsf2 seq: ~A"
seq
(fsf1 seq)
(fsf2 seq)))
</lang>
 
Output: <pre>seq: (0 1 2 3)
fsf1 seq: (0 2 4 6)
fsf2 seq: (0 1 4 9)
seq: (2 4 6 8)
fsf1 seq: (4 8 12 16)
fsf2 seq: (4 16 36 64)</pre>
 
=={{header|C}}==
Line 396 ⟶ 347:
6
8</lang>
 
=={{header|C++}}==
<lang cpp>#include <utility> // For declval.
#include <algorithm>
#include <array>
#include <iterator>
#include <iostream>
 
/* Partial application helper. */
template< class F, class Arg >
struct PApply
{
F f;
Arg arg;
 
template< class F_, class Arg_ >
PApply( F_&& f, Arg_&& arg )
: f(std::forward<F_>(f)), arg(std::forward<Arg_>(arg))
{
}
 
/*
* The return type of F only gets deduced based on the number of arguments
* supplied. PApply otherwise has no idea whether f takes 1 or 10 args.
*/
template< class ... Args >
auto operator() ( Args&& ...args )
-> decltype( f(arg,std::declval<Args>()...) )
{
return f( arg, std::forward<Args>(args)... );
}
};
 
template< class F, class Arg >
PApply<F,Arg> papply( F&& f, Arg&& arg )
{
return PApply<F,Arg>( std::forward<F>(f), std::forward<Arg>(arg) );
}
 
/* Apply f to cont. */
template< class F >
std::array<int,4> fs( F&& f, std::array<int,4> cont )
{
std::transform( std::begin(cont), std::end(cont), std::begin(cont),
std::forward<F>(f) );
return cont;
}
 
std::ostream& operator << ( std::ostream& out, const std::array<int,4>& c )
{
std::copy( std::begin(c), std::end(c),
std::ostream_iterator<int>(out, ", ") );
return out;
}
 
int f1( int x ) { return x * 2; }
int f2( int x ) { return x * x; }
 
int main()
{
std::array<int,4> xs = {{ 0, 1, 2, 3 }};
std::array<int,4> ys = {{ 2, 4, 6, 8 }};
 
auto fsf1 = papply( fs<decltype(f1)>, f1 );
auto fsf2 = papply( fs<decltype(f2)>, f2 );
 
std::cout << "xs:\n"
<< "\tfsf1: " << fsf1(xs) << '\n'
<< "\tfsf2: " << fsf2(xs) << "\n\n"
<< "ys:\n"
<< "\tfsf1: " << fsf1(ys) << '\n'
<< "\tfsf2: " << fsf2(ys) << '\n';
}</lang>
 
=={{header|C sharp}}==
Line 568 ⟶ 446:
fsf2, 0-3: 0, 1, 4, 9
fsf2, evens: 4, 16, 36, 64</pre>
 
=={{header|C++}}==
<lang cpp>#include <utility> // For declval.
#include <algorithm>
#include <array>
#include <iterator>
#include <iostream>
 
/* Partial application helper. */
template< class F, class Arg >
struct PApply
{
F f;
Arg arg;
 
template< class F_, class Arg_ >
PApply( F_&& f, Arg_&& arg )
: f(std::forward<F_>(f)), arg(std::forward<Arg_>(arg))
{
}
 
/*
* The return type of F only gets deduced based on the number of arguments
* supplied. PApply otherwise has no idea whether f takes 1 or 10 args.
*/
template< class ... Args >
auto operator() ( Args&& ...args )
-> decltype( f(arg,std::declval<Args>()...) )
{
return f( arg, std::forward<Args>(args)... );
}
};
 
template< class F, class Arg >
PApply<F,Arg> papply( F&& f, Arg&& arg )
{
return PApply<F,Arg>( std::forward<F>(f), std::forward<Arg>(arg) );
}
 
/* Apply f to cont. */
template< class F >
std::array<int,4> fs( F&& f, std::array<int,4> cont )
{
std::transform( std::begin(cont), std::end(cont), std::begin(cont),
std::forward<F>(f) );
return cont;
}
 
std::ostream& operator << ( std::ostream& out, const std::array<int,4>& c )
{
std::copy( std::begin(c), std::end(c),
std::ostream_iterator<int>(out, ", ") );
return out;
}
 
int f1( int x ) { return x * 2; }
int f2( int x ) { return x * x; }
 
int main()
{
std::array<int,4> xs = {{ 0, 1, 2, 3 }};
std::array<int,4> ys = {{ 2, 4, 6, 8 }};
 
auto fsf1 = papply( fs<decltype(f1)>, f1 );
auto fsf2 = papply( fs<decltype(f2)>, f2 );
 
std::cout << "xs:\n"
<< "\tfsf1: " << fsf1(xs) << '\n'
<< "\tfsf2: " << fsf2(xs) << "\n\n"
<< "ys:\n"
<< "\tfsf1: " << fsf1(ys) << '\n'
<< "\tfsf2: " << fsf2(ys) << '\n';
}</lang>
 
=={{header|Ceylon}}==
Line 587 ⟶ 538:
print("fsf1(``evens``) is ``fsf1(evens)`` and fsf2(``evens``) is ``fsf2(evens)``");
}</lang>
 
=={{header|Clojure}}==
<lang Clojure>(defn fs [f s] (map f s))
(defn f1 [x] (* 2 x))
(defn f2 [x] (* x x))
(def fsf1 (partial fs f1))
(def fsf2 (partial fs f2))
 
(doseq [s [(range 4) (range 2 9 2)]]
(println "seq: " s)
(println " fsf1: " (fsf1 s))
(println " fsf2: " (fsf2 s)))</lang>
Output:
<pre>seq: (0 1 2 3)
fsf1: (0 2 4 6)
fsf2: (0 1 4 9)
seq: (2 4 6 8)
fsf1: (4 8 12 16)
fsf2: (4 16 36 64)</pre>
 
=={{header|CoffeeScript}}==
Line 613 ⟶ 583:
</lang>
 
=={{header|Common Lisp}}==
<lang lisp>(defun fs (f s)
(mapcar f s))
(defun f1 (i)
(* i 2))
(defun f2 (i)
(expt i 2))
(defun partial (func &rest args1)
(lambda (&rest args2)
(apply func (append args1 args2))))
 
(setf (symbol-function 'fsf1) (partial #'fs #'f1))
(setf (symbol-function 'fsf2) (partial #'fs #'f2))
(dolist (seq '((0 1 2 3) (2 4 6 8)))
(format t
"~%seq: ~A~% fsf1 seq: ~A~% fsf2 seq: ~A"
seq
(fsf1 seq)
(fsf2 seq)))
</lang>
 
Output: <pre>seq: (0 1 2 3)
fsf1 seq: (0 2 4 6)
fsf2 seq: (0 1 4 9)
seq: (2 4 6 8)
fsf1 seq: (4 8 12 16)
fsf2 seq: (4 16 36 64)</pre>
 
=={{header|D}}==
Line 693 ⟶ 692:
{4 16 36 64}
</lang>
 
=={{header|Elena}}==
{{trans|Smalltalk}}
Line 720:
</pre>
 
=={{Headerheader|F_Sharp|F#}}==
Translation of Racket
 
Line 1,142:
fsf1(array): [4, 8, 12, 16]
fsf2(array): [4, 16, 36, 64]</pre>
 
 
=={{header|JavaScript}}==
Line 1,740 ⟶ 1,739:
fs_double(2 4 6 8): 4 8 12 16
fs_square(2 4 6 8): 4 16 36 64</pre>
 
=={{header|Perl 6}}==
{{works with|rakudo|2015-09-25}}
All Code objects have the .assuming method, which partially applies its arguments. For both type safety reasons and parsing sanity reasons we do not believe in implicit partial application by leaving out arguments. Also, people can understand "assuming" without being steeped in FP culture.
<lang perl6>sub fs ( Code $f, @s ) { @s.map: { .$f } }
sub f1 ( $n ) { $n * 2 }
sub f2 ( $n ) { $n ** 2 }
my &fsf1 := &fs.assuming(&f1);
my &fsf2 := &fs.assuming(&f2);
for [1..3], [2, 4 ... 8] X &fsf1, &fsf2 -> ($s, $f) {
say $f.($s);
}</lang>
 
Output:<pre>(2 4 6)
(1 4 9)
(4 8 12 16)
(4 16 36 64)</pre>
The <tt>*+2</tt> is also a form of partial application in Perl&nbsp;6. In this case we partially apply the <tt>infix:<+></tt> function with a second argument of 2. That is, the star (known as the "whatever" star) indicates which argument <em>not</em> to apply. In contrast to languages that keep some arguments unbound by leaving holes, the explicit star in Perl&nbsp;6 allows us to avoid syntactic ambiguity in whether to expect a term or an infix operator; such self-clocking code contributes to better error messages when things go wrong.
 
=={{header|Phix}}==
Line 1,930 ⟶ 1,908:
(fsf2 '(2 4 6 8))
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|2015-09-25}}
All Code objects have the .assuming method, which partially applies its arguments. For both type safety reasons and parsing sanity reasons we do not believe in implicit partial application by leaving out arguments. Also, people can understand "assuming" without being steeped in FP culture.
<lang perl6>sub fs ( Code $f, @s ) { @s.map: { .$f } }
sub f1 ( $n ) { $n * 2 }
sub f2 ( $n ) { $n ** 2 }
my &fsf1 := &fs.assuming(&f1);
my &fsf2 := &fs.assuming(&f2);
for [1..3], [2, 4 ... 8] X &fsf1, &fsf2 -> ($s, $f) {
say $f.($s);
}</lang>
 
Output:<pre>(2 4 6)
(1 4 9)
(4 8 12 16)
(4 16 36 64)</pre>
The <tt>*+2</tt> is also a form of partial application in Perl&nbsp;6. In this case we partially apply the <tt>infix:<+></tt> function with a second argument of 2. That is, the star (known as the "whatever" star) indicates which argument <em>not</em> to apply. In contrast to languages that keep some arguments unbound by leaving holes, the explicit star in Perl&nbsp;6 allows us to avoid syntactic ambiguity in whether to expect a term or an infix operator; such self-clocking code contributes to better error messages when things go wrong.
 
=={{header|REXX}}==
10,333

edits