Partial function application: Difference between revisions
(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 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)
- 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
<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