Partial function application: Difference between revisions

From Rosetta Code
Content added Content deleted
(New task and Python solution.)
 
(→‎Tcl: Added implementation)
Line 43: Line 43:


The program runs without triggering the assertions.
The program runs without triggering the assertions.

=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<lang tcl>package require Tcl 8.6
proc fs {f {s {}}} {
variable ctr
set c [coroutine __curry[incr ctr] apply {f {
set r [info coroutine]
while 1 {
set s [yield $r]
set r {}
foreach n $s {lappend r [{*}$f $n]}
}
}} $f]
if {[llength [info level 0]] == 3} {
return [$c $s][rename $c {}]
} else {
return $c
}
}</lang>
Demonstration:
<lang tcl>proc f1 x {expr {$x * 2}}
proc f2 x {expr {$x ** 2}}
set fsf1 [fs f1]
set fsf2 [fs f2]
foreach s {{0 1 2 3} {2 4 6 8}} {
puts "$s ==f1==> [$fsf1 $s]"
puts "$s ==f2==> [$fsf2 $s]"
}</lang>
Output:
<pre>
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
</pre>

Revision as of 13:48, 25 March 2011

Partial function application is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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) returns f'(param2)
And f(param1=v1, param2=v2) == f'(param2=v2) (for any value v2)
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.

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

Works with: Tcl version 8.6

<lang tcl>package require Tcl 8.6 proc fs {f {s {}}} {

   variable ctr
   set c [coroutine __curry[incr ctr] apply {f {

set r [info coroutine] while 1 { set s [yield $r] set r {} foreach n $s {lappend r [{*}$f $n]} }

   }} $f]
   if {[llength [info level 0]] == 3} {

return [$c $s][rename $c {}]

   } else {

return $c

   }

}</lang> Demonstration: <lang tcl>proc f1 x {expr {$x * 2}} proc f2 x {expr {$x ** 2}} set fsf1 [fs f1] set fsf2 [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