Higher-order functions: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Clean example)
No edit summary
Line 361: Line 361:
}
}



==[[Pop11]]==
[[Category: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) =>





Revision as of 17:04, 11 May 2007

Task
Higher-order functions
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]

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

Passing a pointer to a function

my $retval = first('data', \&second);

sub first ($ $){
  my $val = shift;
  my $func = shift;
  return $func->($val);
}

sub second ($){
  return(reverse(shift));
}

Passing a string to be used as a function

my $retval = first('data', 'second');

sub first ($ $){
  my $val = shift;
  my $func = shift;
  return &{$func}($val);
}

sub second ($){
  return(reverse(shift));
}


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');

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