Function prototype: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Added Erlang)
(Added COBOL examples.)
Line 31: Line 31:
next : accBox; -- including that a box holds access to other boxes
next : accBox; -- including that a box holds access to other boxes
end record;</lang>
end record;</lang>
Example of a package specification (i.e. prototype).:
Example of a package specification (i.e. prototype):
<lang Ada>
<lang Ada>package Stack is
package Stack is
procedure Push(Object:Integer);
procedure Push(Object:Integer);
function Pull return Integer;
function Pull return Integer;
end Stack;
end Stack;</lang>
</lang>


Example of a package body:
Example of a package body:
<lang Ada>
<lang Ada>package body Stack is
package body Stack is


procedure Push(Object:Integer) is
procedure Push(Object:Integer) is
Line 53: Line 50:
end;
end;


end Stack;
end Stack;</lang>
</lang>


To use the package and function
To use the package and function:
<lang Ada>
<lang Ada>with Stack;
with Stack;
procedure Main is
procedure Main is
N:integer:=5;
N:integer:=5;
Line 65: Line 60:
...
...
N := Pull;
N := Pull;
end Main;
end Main;</lang>
</lang>


=={{header|Aime}}==
=={{header|Aime}}==
Line 89: Line 83:
int anyargs(...); /* An ellipsis can be used to declare a function that accepts varargs */
int anyargs(...); /* An ellipsis can be used to declare a function that accepts varargs */
int atleastoneargs(int, ...); /* One mandatory integer argument followed by varargs */</lang>
int atleastoneargs(int, ...); /* One mandatory integer argument followed by varargs */</lang>

=={{header|COBOL}}==

Prototypes were introduced in COBOL 2002, and are typically used by <code>COPY</code>ing the copybook in which they are contained into the beginning of the source file. In the following examples, <code>PROGRAM-ID</code> and <code>PROGRAM</code> can be replaced with the equivalents for functions and methods. However, in method prototypes the <code>PROTOTYPE</code> clause is not used.

<lang cobol> *> A subprogram taking no arguments and returning nothing.
PROGRAM-ID. no-args PROTOTYPE.
END PROGRAM no-args.

*> A subprogram taking two 8-digit numbers as arguments (passed by
*> value), and returning an 8-digit number.
PROGRAM-ID. two-args PROTOTYPE.
DATA DIVISION.
LINKAGE SECTION.
01 arg-1 PIC 9(8).
01 arg-2 PIC 9(8).
01 ret PIC 9(8).
PROCEDURE DIVISION USING BY VALUE arg-1, arg-2 RETURNING ret.
END PROGRAM two-args.

*> A subprogram taking two optional arguments which are 8-digit
*> numbers (passed by reference (the default and compulsory for
*> optional arguments)).
PROGRAM-ID. optional-args PROTOTYPE.
DATA DIVISION.
LINKAGE SECTION.
01 arg-1 PIC 9(8).
01 arg-2 PIC 9(8).
PROCEDURE DIVISION USING OPTIONAL arg-1, OPTIONAL arg-2.
END PROGRAM optional-args.

*> Standard COBOL does not support varargs or named parameters.

*> A function from another language, taking a 32-bit integer by
*> value and returning a 32-bit integer (in Visual COBOL).
PROGRAM-ID. foreign-func PROTOTYPE.
OPTIONS.
ENTRY-CONVENTION some-langauge.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 arg PIC S9(9) USAGE COMP-5.
01 ret PIC S9(9) USAGE COMP-5.
PROCEDURE DIVISION USING arg RETURNING ret.
END PROGRAM foreign-func.</lang>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
Line 175: Line 213:
=={{header|J}}==
=={{header|J}}==
J assumes an unknown name is a verb of infinite rank. Rank determines the frames on which the verb executes. As the demonstration shows, changing the rank, assigning the rank before the verb is used in other definitions affects the result. We could, of course, play other games by changing the unknown name from verb to another part of speech.
J assumes an unknown name is a verb of infinite rank. Rank determines the frames on which the verb executes. As the demonstration shows, changing the rank, assigning the rank before the verb is used in other definitions affects the result. We could, of course, play other games by changing the unknown name from verb to another part of speech.
<lang J> NB. j assumes an unknown name f is a verb of infinite rank
<lang J>
NB. j assumes an unknown name f is a verb of infinite rank
NB. f has infinite ranks
NB. f has infinite ranks
f b. 0
f b. 0
Line 235: Line 272:
0 2 4 6 8
0 2 4 6 8
0 3 6 9 12
0 3 6 9 12
0 4 8 12 16
0 4 8 12 16</lang>
</lang>


=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
Line 269: Line 305:


<lang perl>sub noargs(); # Declare a function with no arguments
<lang perl>sub noargs(); # Declare a function with no arguments
sub twoargs($$); # Declare a function with two scalar arguments. The two sigils act as argument type placeholders
sub twoargs($$); # Declare a function with two scalar arguments. The two sigils act as argument type placeholders</lang>
</lang>


=={{header|Perl 6}}==
=={{header|Perl 6}}==
Line 305: Line 340:
=={{header|Racket}}==
=={{header|Racket}}==
Most of the points are covered in this program
Most of the points are covered in this program
<lang racket>
<lang racket>#lang racket
#lang racket


(define (no-arg) (void))
(define (no-arg) (void))
Line 316: Line 350:
(define (varargs2 a . args) (void)) ;one obligatory argument and the rest are contained in the list
(define (varargs2 a . args) (void)) ;one obligatory argument and the rest are contained in the list


(define (optional-arg (a 5)) (void)) ;a defaults to 5
(define (optional-arg (a 5)) (void)) ;a defaults to 5</lang>
</lang>


<tt>(void)</tt> is a function that returns "nothing", so this are prototypes that do nothing.
<tt>(void)</tt> is a function that returns "nothing", so this are prototypes that do nothing.
Although standard Racket doesn't allow type declarations, it allows contracts, so we can add this to the previous declarations
Although standard Racket doesn't allow type declarations, it allows contracts, so we can add this to the previous declarations
<lang racket>
<lang racket>(provide (contract-out
[two-args (integer? integer? . -> . any)]))</lang>
(provide (contract-out
[two-args (integer? integer? . -> . any)]))
</lang>
then any module that imports the function can only pass integers to two-args.
then any module that imports the function can only pass integers to two-args.


Another way is using the <tt>typed/racket</tt> language, like this
Another way is using the <tt>typed/racket</tt> language, like this
<lang racket>
<lang racket>#lang typed/racket
#lang typed/racket


(: two-args (Integer Integer -> Any))
(: two-args (Integer Integer -> Any))

Revision as of 16:38, 25 July 2013

Task
Function prototype
You are encouraged to solve this task according to the task description, using any language you may know.

Some languages provide the facility to declare functions and subroutines through the use of function prototyping. The task is to demonstrate the methods available for declaring prototypes within the language. The provided solutions should include:

  • An explanation of any placement restrictions for prototype declarations
  • A prototype declaration for a function that does not require arguments
  • A prototype declaration for a function that requires two arguments
  • A prototype declaration for a function that utilizes varargs
  • A prototype declaration for a function that utilizes optional arguments
  • A prototype declaration for a function that utilizes named parameters
  • Example of prototype declarations for subroutines or procedures (if these differ from functions)
  • An explanation and example of any special forms of prototyping not covered by the above

Languages that do not provide function prototyping facilities should be omitted from this task.

Ada

In Ada, prototypes are called specifications.

  • Specifications must be an exact copy of everything prior to the "is" statement for a function or procedure.
  • All specifications must appear in a declarative section, ie: before a "begin" statement.
  • For a main program, specifications are only necessary if a function call appears in the source before the function definition.
  • For a package, specifications must appear as part of the specification(.ads) file, and do not appear in the body file(.adb) (The file extensions apply to Gnat Ada and may not apply to all compilers).

<lang Ada>function noargs return Integer; function twoargs (a, b : Integer) return Integer; -- varargs do not exist function optionalargs (a, b : Integer := 0) return Integer; -- all parameters are always named, only calling by name differs procedure dostuff (a : Integer);</lang> Other Prototyping: Since pointers are not generic in Ada, a type must be defined before one can have a pointer to that type, thus for making linked-list type semantics another trivial prototyping exists: <lang Ada>type Box; -- tell Ada a box exists (undefined yet) type accBox is access Box; -- define a pointer to a box type Box is record -- later define what a box is

  next : accBox; --  including that a box holds access to other boxes

end record;</lang> Example of a package specification (i.e. prototype): <lang Ada>package Stack is

  procedure Push(Object:Integer);
  function Pull return Integer;

end Stack;</lang>

Example of a package body: <lang Ada>package body Stack is

  procedure Push(Object:Integer) is
  begin
     -- implementation goes here
  end;
  function Pull return Integer;
  begin
     -- implementation goes here
  end;

end Stack;</lang>

To use the package and function: <lang Ada>with Stack; procedure Main is

  N:integer:=5;

begin

  Push(N);
  ...
  N := Pull;

end Main;</lang>

Aime

<lang aime>integer f0(void); # No arguments void f1(integer, real); # Two arguments real f2(...); # Varargs void f3(integer, ...); # Varargs

void f4(integer &, text &); # Two arguments (integer and string), pass by reference integer f5(integer, integer (*)(integer));

                               # Two arguments: integer and function returning integer and taking one integer argument

integer f6(integer a, real b); # Parameters names are allowed record f7(void); # Function returning an associative array</lang>

C

Function prototypes are typically included in a header file at the beginning of a source file prior to functional code. However, this is not enforced by a compiler.

<lang c>int noargs(); /* Declare a function with no arguments that returns an integer */ int twoargs(int a,int b); /* Declare a function with no arguments that returns an integer */ int twoargs(int ,int); /* Parameter names are optional in a prototype definition */ int anyargs(...); /* An ellipsis can be used to declare a function that accepts varargs */ int atleastoneargs(int, ...); /* One mandatory integer argument followed by varargs */</lang>

COBOL

Prototypes were introduced in COBOL 2002, and are typically used by COPYing the copybook in which they are contained into the beginning of the source file. In the following examples, PROGRAM-ID and PROGRAM can be replaced with the equivalents for functions and methods. However, in method prototypes the PROTOTYPE clause is not used.

<lang cobol> *> A subprogram taking no arguments and returning nothing.

      PROGRAM-ID. no-args PROTOTYPE.
      END PROGRAM no-args.
      *> A subprogram taking two 8-digit numbers as arguments (passed by
      *> value), and returning an 8-digit number.
      PROGRAM-ID. two-args PROTOTYPE.
      DATA DIVISION.
      LINKAGE SECTION.
      01  arg-1 PIC 9(8).
      01  arg-2 PIC 9(8).
      01  ret   PIC 9(8).
      PROCEDURE DIVISION USING BY VALUE arg-1, arg-2 RETURNING ret.
      END PROGRAM two-args.
      *> A subprogram taking two optional arguments which are 8-digit
      *> numbers (passed by reference (the default and compulsory for
      *> optional arguments)).
      PROGRAM-ID. optional-args PROTOTYPE.
      DATA DIVISION.
      LINKAGE SECTION.
      01  arg-1 PIC 9(8).
      01  arg-2 PIC 9(8).
      PROCEDURE DIVISION USING OPTIONAL arg-1, OPTIONAL arg-2.
      END PROGRAM optional-args.
      *> Standard COBOL does not support varargs or named parameters.
      *> A function from another language, taking a 32-bit integer by
      *> value and returning a 32-bit integer (in Visual COBOL).
      PROGRAM-ID. foreign-func PROTOTYPE.
      OPTIONS.
          ENTRY-CONVENTION some-langauge.
      DATA DIVISION.
      WORKING-STORAGE SECTION.
      01  arg PIC S9(9) USAGE COMP-5.
      01  ret PIC S9(9) USAGE COMP-5.
      PROCEDURE DIVISION USING arg RETURNING ret.
      END PROGRAM foreign-func.</lang>

Common Lisp

The lambda list is part of the function definition. It describes the arguments to a function.

<lang lisp>;; An empty lambda list () takes 0 parameters. (defun 0args ()

 (format t "Called 0args~%"))
This lambda list (a b) takes 2 parameters.

(defun 2args (a b)

 (format t "Called 2args with ~A and ~A~%" a b))
Local variables from lambda lists may have declarations.
This function takes 2 arguments, which must be integers.

(defun 2ints (i j)

 (declare (type integer i j))
 (/ (+ i j) 2))</lang>

When a program calls a function, Common Lisp uses the lambda list to check the number and type of arguments. Calls like (0args "extra arg"), (2args) and (2ints 3.0 4/5) would cause errors.

The lambda list has several more features.

<lang lisp>;; Rest parameter, for variadic functions: r is a list of arguments. (a b &rest r)

Optional parameter
i defaults to 3, (f 1 2) is same as (f 1 2 3).

(a b &optional (i 3))

Keyword parameters
(f 1 2
c 3 :d 4) is same as (f 1 2 :d 4 :c 3).

(a b &key c d)</lang>

D

Beside function prototypes similar to the ones available in C (plus templates, D-style varargs), you can define class method prototypes in abstract classes and interfaces. The exact rules for this are best explained by the documentation <lang d>/// Declare a function with no arguments that returns an integer. int noArgs();

/// Declare a function with no arguments that returns an integer. int twoArgs(int a, int b);

/// Parameter names are optional in a prototype definition. int twoArgs2(int, int);

/// An ellipsis can be used to declare a function that accepts /// C-style varargs. int anyArgs(...);

/// One mandatory integer argument followed by C-style varargs. int atLeastOneArg(int, ...);

/// Declare a function that accepts any number of integers. void anyInts(int[] a...);

/// Declare a function that accepts D-style varargs. void anyArgs2(TArgs...)(TArgs args);

/// Declare a function that accepts two or more D-style varargs. void anyArgs3(TArgs...)(TArgs args) if (TArgs.length > 2);

/// Currently D doesn't support named arguments.

/// One implementation. int twoArgs(int a, int b) {

   return a + b;

}

interface SomeInterface {

   void foo();
   void foo(int, int);
   // Varargs
   void foo(...); // C-style.
   void foo(int[] a...);
   void bar(T...)(T args); // D-style.
   // Optional arguments are only supported if a default is provided,
   // the default arg(s) has/have to be at the end of the args list.
   void foo(int a, int b = 10);

}

void main() {}</lang>

J

J assumes an unknown name is a verb of infinite rank. Rank determines the frames on which the verb executes. As the demonstration shows, changing the rank, assigning the rank before the verb is used in other definitions affects the result. We could, of course, play other games by changing the unknown name from verb to another part of speech. <lang J> NB. j assumes an unknown name f is a verb of infinite rank

  NB. f has infinite ranks
  f b. 0

_ _ _

  NB. The verb g makes a table.
  g=: f/~
  NB. * has rank 0
  f=: *


  NB. indeed, make a multiplication table
  f/~ i.5

0 0 0 0 0 0 1 2 3 4 0 2 4 6 8 0 3 6 9 12 0 4 8 12 16

  NB. g was defined as if f had infinite rank.
  g i.5

0 1 4 9 16

  NB. f is known to have rank 0.
  g=: f/~
  NB. Now we reproduce the table
  g i.5

0 0 0 0 0 0 1 2 3 4 0 2 4 6 8 0 3 6 9 12 0 4 8 12 16


  NB. change f to another rank 0 verb
  f=: +   
  NB. and construct an addition table
  g i.5

0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8


  NB. f is multiplication at infinite rank
  f=: *"_
  
  NB. g, however, has rank 0
  g i.5

0 0 0 0 0 0 1 2 3 4 0 2 4 6 8 0 3 6 9 12 0 4 8 12 16</lang>

PARI/GP

GP does not use function prototypes.

PARI uses C prototypes. Additionally, gp2c parser codes are essentially function prototypes. They must be placed in the file called by gp2c, not in a file included by it, and they must appear as a GP; comment. For a function

<lang c>long foo(GEN a, GEN b)</lang> which takes two (required) t_INT arguments, returns a small integer (a C long) and appears as bar to the gp interpreter, the following command would be used: <lang c>/* GP;install("foo","LGG","bar","./filename.gp.so");

  • /</lang>

If its arguments were optional it could be coded as <lang c>/* GP;install("foo","LDGDG","bar","./filename.gp.so");

  • /</lang>

although other parser codes are possible; this one sends NULL if the arguments are omitted.

A code like <lang c>/* GP;install("foo","s*","bar","./filename.gp.so");

  • /</lang>

can be used to take a variable (0 or more) number of arguments. Note that the return type in this case is implicitly GEN

Other special forms are described in the User's Guide to the PARI library, section 5.7.3.

Perl

The perl scripting language allows prototypes to be checked during JIT compilation. Prototypes should be placed before subroutine definitions, declarations, or anonymous subroutines. The sigil special symbols act as argument type placeholders.

<lang perl>sub noargs(); # Declare a function with no arguments sub twoargs($$); # Declare a function with two scalar arguments. The two sigils act as argument type placeholders</lang>

Perl 6

There is no restriction on placement of prototype declarations. (Actually, we call them "stub declarations".) In fact, stub declarations are rarely needed in Perl 6 because post-declaration of functions is allowed, and normal function declarations do not bend the syntax the way they sometimes do in Perl 5.

Note that the ... in all of these stub bodies is literally part of the declaration syntax.

A prototype declaration for a function that does not require arguments (and returns an Int): <lang perl6>sub foo ( --> Int) {...}</lang>

A prototype declaration for a function that requires two arguments. Note that we can omit the variable name and just use the sigil in the stub, since we don't need to reference the argument until the actual definition of the routine. Also, unlike in Perl 5, a sigil like @ defaults to binding a single positional argument. <lang perl6>sub foo (@, $ --> Int) {...}</lang>

A prototype declaration for a function that utilizes varargs after one required argument. Note the "slurpy" star turns the @ sigil into a parameter that accepts all the rest of the positional arguments. <lang perl6>sub foo ($, *@ --> Int) {...}</lang>

A prototype declaration for a function that utilizes optional arguments after one required argument. Optionality is conferred by either a question mark or a default: <lang perl6>sub foo ($, $?, $ = 42 --> Int) {...}</lang>

A prototype declaration for a function that utilizes named parameters: <lang perl6>sub foo ($, :$faster, :$cheaper --> Int) {...}</lang>

Example of prototype declarations for subroutines or procedures, which in Perl 6 is done simply by noting that nothing is returned: <lang perl6>sub foo ($, $ --> Nil) {...}</lang>

A routine may also slurp up all the named arguments that were not bound earlier in the signature: <lang perl6>sub foo ($, :$option, *% --> Int) {...}</lang>

A routine may make a named parameter mandatory using exclamation mark. (This is more useful in multi subs than in stubs though.) <lang perl6>sub foo ($, :$option! --> Int) {...}</lang>

Racket

Most of the points are covered in this program <lang racket>#lang racket

(define (no-arg) (void))

(define (two-args a b) (void)) ;arguments are always named

(define (varargs . args) (void)) ;the extra arguments are stored in a list

(define (varargs2 a . args) (void)) ;one obligatory argument and the rest are contained in the list

(define (optional-arg (a 5)) (void)) ;a defaults to 5</lang>

(void) is a function that returns "nothing", so this are prototypes that do nothing. Although standard Racket doesn't allow type declarations, it allows contracts, so we can add this to the previous declarations <lang racket>(provide (contract-out

         [two-args (integer? integer? . -> . any)]))</lang>

then any module that imports the function can only pass integers to two-args.

Another way is using the typed/racket language, like this <lang racket>#lang typed/racket

(: two-args (Integer Integer -> Any)) (define (two-args a b) (void))</lang>