Higher-order functions: Difference between revisions
→[[Pascal]]: bug |
No edit summary |
||
Line 453: | Line 453: | ||
$result = first('second'); |
$result = first('second'); |
||
==[[Ruby]]== |
|||
[[Category:Ruby]] |
|||
With a proc (procedure): |
|||
succ = proc{|x| x+1} |
|||
def to2(&f) |
|||
f[2] |
|||
end |
|||
to2(&succ) #=> 3 |
|||
to2{|x| x+1} #=> 3 |
|||
With a method: |
|||
def succ(n) |
|||
n+1 |
|||
end |
|||
def to2(m) |
|||
m[2] |
|||
end |
|||
meth = method(:succ) |
|||
to2(meth) #=> 3 |
|||
== [[Scala]]== |
== [[Scala]]== |
Revision as of 01:11, 30 September 2007
You are encouraged to solve this task according to the task description, using any language you may know.
Pass a function as an argument to another function.
Ada
Simple Example
with Ada.Text_Io; use Ada.Text_Io; procedure Subprogram_As_Argument is type Proc_Access is access procedure; procedure Second is begin Put_Line("Second Procedure"); end Second; procedure First(Proc : Proc_Access) is begin Proc.all; end First; begin First(Second'Access); end Subprogram_As_Argument;
Complex Example
with Ada.Text_Io; use Ada.Text_Io; procedure Subprogram_As_Argument_2 is -- Definition of an access to long_float type Lf_Access is access Long_Float; -- Definition of a function returning Lf_Access taking an -- integer as a parameter function Func_To_Be_Passed(Item : Integer) return Lf_Access is Result : Lf_Access := new Long_Float; begin Result.All := 3.14159 * Long_Float(Item); return Result; end Func_To_Be_Passed; -- Definition of an access to function type matching the function -- signature above type Func_Access is access function(Item : Integer) return Lf_Access; -- Definition of an integer access type type Int_Access is access Integer; -- Define a function taking an instance of Func_Access as its -- parameter and returning an integer access type function Complex_Func(Item : Func_Access; Parm2 : Integer) return Int_Access is Result : Int_Access := new Integer; begin Result.All := Integer(Item(Parm2).all / 3.14149); return Result; end Complex_Func; -- Declare an access variable to hold the access to the function F_Ptr : Func_Access := Func_To_Be_Passed'access; -- Declare an access to integer variable to hold the result Int_Ptr : Int_Access; begin -- Call the function using the access variable Int_Ptr := Complex_Func(F_Ptr, 3); Put_Line(Integer'Image(Int_Ptr.All)); end Subprogram_As_Argument_2;
C
Standard: ANSI C
Compiler: GCC version 3.4.2 (mingw-special)
Simple example
The pointer to the function to be passed as an argument is the only involved pointer.
Definition of a function whose only parameter is a pointer to a function with no parameters and no return value:
void myFuncSimple( void (*funcParameter)(void) ) { /* ... */ (*funcParameter)(); /* Call the passed function. */ funcParameter(); /* Same as above with slight different syntax. */ /* ... */ }
Note that you can't call the passed function by " *funcParameter() ", since that would mean "call funcParameter and than apply the * operator on the returned value".
Call:
void funcToBePassed(void); /* ... */ myFuncSimple(&funcToBePassed);
Complex example
Definition of a function whose return value is a pointer to int and whose only parameter is a pointer to a function, whose (in turn) return value is a pointer to double and whose only parameter is a pointer to long.
int* myFuncComplex( double* (*funcParameter)(long* parameter) ) { long* inLong; double* outDouble; /* ... */ outDouble = (*funcParameter)(inLong); /* Call the passed function and store returned pointer. */ outDouble = funcParameter(inLong); /* Same as above with slight different syntax. */ /* ... */ }
Call:
double* funcToBePassed(long* parameter); /* ... */ int* outInt; outInt = myFuncComplex(&funcToBePassed);
Pointer
Finally, declaration of a pointer variable of the proper type to hold such a function as myFunc:
int* (*funcPointer)( double* (*funcParameter)(long* parameter) ); /* ... */ funcPointer = myFuncComplex;
Of course, in a real project you shouldn't write such a convoluted code, but use some typedef instead, in order to break complexity into steps.
C++
Function Pointer
Standard: ANSI C++
Compiler: GCC version 3.4.2 (mingw-special)
Same as C.
Template
Compiler: Visual C++ 2005
#include <iostream> template<class Func> void first(Func func) { func(); } void second() { std::cout << "second" << std::endl; } int main() { first(second); return 0; }
Template and Inheritance
Compiler: Visual C++ 2005
#include <iostream> #include <functional> template<class Func> typename Func::result_type first(Func func, typename Func::argument_type arg) { return func(arg); } class second : public std::unary_function<int, int> { public: result_type operator()(argument_type arg) { return arg * arg; } }; int main() { std::cout << first(second(), 2) << std::endl; return 0; }
Clean
Take a function as an argument and apply it to all elements in a list:
map f [x:xs] = [f x:map f xs] map f [] = []
Pass a function as an argument:
incr x = x + 1 Start = map incr [1..10]
Do the same using a anonymous function:
Start = map (\x -> x + 1) [1..10]
Do the same using currying:
Start = map ((+) 1) [1..10]
Common Lisp
In Common Lisp, functions are first class objects, so you can pass function objects as arguments to other functions:
CL-USER> (defun add (a b) (+ a b)) ADD CL-USER> (add 1 2) 3 CL-USER> (defun call-it (fn x y) (funcall fn x y)) CALL-IT CL-USER> (call-it #'add 1 2) 3
E
def map(f, list) { var out := [] for x in list { out with= f(x) } return out }
? map(fn x { x + x }, [1, "two"]) # value: [2, "twotwo"]
? map(1.add, [5, 10, 20]) # value: [6, 11, 21] ? def foo(x) { return -(x.size()) } > map(foo, ["", "a", "bc"]) # value: [0, -1, -2]
Forth
Forth words can be referenced on the stack via their execution token or XT. An XT is obtained from a word via the quote operator, and invoked via EXECUTE. Anonymous functions may be defined via :NONAME (returning an XT) instead of a standard colon definition.
: square dup * ; : cube dup dup * * ; : map. ( xt addr len -- ) 0 do 2dup i cells + @ swap execute . loop 2drop ;
create array 1 , 2 , 3 , 4 , 5 , ' square array 5 map. cr \ 1 4 9 16 25 ' cube array 5 map. cr \ 1 8 27 64 125 :noname 2* 1+ ; array 5 map. cr \ 3 5 7 9 11
Haskell
Interpreter: GHCi 6.6
A function is just a value that wants arguments:
func1 f = f "a string" func2 s = "func2 called with " ++ s main = putStrLn $ func1 func2
Or, with an anonymous function:
func f = f 1 2 main = print $ func (\x y -> x+y) -- output: 3
Note that func (\x y -> x+y) is equivalent to func (+). (Operators are functions too.)
Java
There is no real callback in java like in C or C++, but we can do the same as swing do for executing an event. We need to create an interface that has the method we want to call or create an that will call the method we want to call. The following example use the second way.
public class NewClass { public NewClass() { first(new AnEventOrCallback() { public void call() { second(); } }); } public void first(AnEventOrCallback obj) { obj.call(); } public void second() { System.out.println("Second"); } public static void main(String[] args) { new NewClass(); } } interface AnEventOrCallback { public void call(); }
JavaScript
function first(func) { return func(); } function second() { return "second"; } var result = first(second); result = first(function() { return "third"; });
Pascal
Standard Pascal (will not work with Turbo Pascal):
program example(output); function first(function f(x: real): real): real; begin first := f(1.0) + 2.0; end; function second(x: real): real; begin second := x/2.0; end; begin writeln(first(second)); end.
Turbo Pascal (will not work with Standard Pascal):
program example; type FnType = function(x: real): real; function first(f: FnType): real; begin first := f(1.0) + 2.0; end; function second(x: real): real; begin second := x/2.0; end; begin writeln(first(second)); end.
Perl
Interpreter: Perl
sub another { # take a function and a value my $func = shift; my $val = shift; # call the function with the value as argument return $func->($val); }; sub reverser { return scalar reverse shift; }; # pass named coderef print another \&reverser, 'data'; # pass anonymous coderef print another sub {return scalar reverse shift}, 'data'; # if all you have is a string and you want to act on that, # set up a dispatch table my %dispatch = ( square => sub {return shift() ** 2}, cube => sub {return shift() ** 3}, rev => \&reverser, ); print another $dispatch{$_}, 123 for qw(square cube rev);
Pop11
;;; Define a function define x_times_three_minus_1(x); return(3*x-1); enddefine;
;;; Pass it as argument to builtin function map and print the result mapdata({0 1 2 3 4}, x_times_three_minus_1) =>
Python
Interpreter: Python 2.5
def first(function): return function() def second(): return "second" result = first(second)
or
result = first(lambda: "second")
PHP
function first($func) { return $func(); } function second() { return 'second'; } $result = first('second');
Ruby
With a proc (procedure):
succ = proc{|x| x+1} def to2(&f) f[2] end to2(&succ) #=> 3 to2{|x| x+1} #=> 3
With a method:
def succ(n) n+1 end def to2(m) m[2] end meth = method(:succ) to2(meth) #=> 3
Scala
def functionWithAFunctionArgument(x : int, y : int, f : (int, int) => int) = f(x,y)
Call:
functionWithAFunctionArgument(3, 5, {(x, y) => x + y}) // returns 8
Tcl
# this procedure executes its argument: proc demo {function} { $function } # for example: demo bell
Toka
Toka allows obtaining a function pointer via the ` (backtick) word. The pointers are passed on the stack, just like all other data.
[ ." First\n" ] is first [ invoke ] is second ` first second