Named parameters

From Rosetta Code
Revision as of 16:43, 30 June 2009 by rosettacode>Paddy3118 (→‎Examples: Formatting)
Task
Named parameters
You are encouraged to solve this task according to the task description, using any language you may know.

Create a function which takes in a number of arguments which are specified by name rather than (necessarily) position, and show how to call the function. If the language supports reordering the arguments or optionally omitting some of them, note this.

See also:

Ada

All callable entities (procedures, functions, entries) require named arguments. All of them can be called using either positional or keyed association of the actual arguments. The arguments supplied with default values can be omitted. <lang Ada> procedure Foo (Arg_1 : Integer; Arg_2 : Float := 0.0); </lang> It can be equivalently called as: <lang Ada> Foo (1, 0.0); Foo (1); Foo (Arg_2 => 0.0, Arg_1 => 1); Foo (Arg_1 => 1); </lang>

Fortran

Works with: Fortran version 95 and later

Fortran accepts named parameter and optional parameter. Arguments are always named: if the name is omitted, the order used in the definition of the function / subroutine must be used.

<lang fortran> subroutine a_sub(arg1, arg2, arg3)

   integer, intent(in) :: arg1, arg2
   integer, intent(out), optional :: arg3
   ! ...
 end subroutine a_sub</lang>

<lang fortran>! usage

 integer :: r
 call a_sub(1,2, r)
 call a_sub(arg2=2, arg1=1)</lang>

The presence of an optional argument can be tested with PRESENT; if optional arguments come before a non optional argument, the usage of the name of the argument is mandatory.

<lang fortran> subroutine b_sub(arg1, arg2)

    integer, intent(in), optional :: arg1
    integer, intent(in) :: arg2
    !...
 end subroutine b_sub</lang>

<lang fortran> call b_sub(1)  ! error: missing non optional arg2

 call b_sub(arg2=1)         ! ok
 call b_sub(1, 2)           ! ok: arg1 is 1, arg2 is 2
 call b_sub(arg2=2, arg1=1) ! the same as the previous line</lang>

Objective C

Objective C has a method call syntax that is visually identical to named arguments, but they are not optional and may not be reordered. (The effect may be simulated by declaring multiple functions with the same leading name part and arguments reordered.) <lang objc>@interface Demo : Object {

   // Omitted ...

} - (double) hypotenuseOfX: (double)x andY: (double)y; @end</lang> <lang objc>@implementation Demo

- (double) hypotenuseOfX: (double)x andY: (double)y {

   return hypot(x,y);

} @end</lang> <lang objc>Demo example = [Demo new]; double h = [example hypotenuseOfX:1.23 andY:3.79];</lang> Note in the example above that the name of the method is actually “-hypotenuseOfX:andY:”.

Python

Function definition parameters

Function definitions in Python allow for the following parameter types:

  • Optional default parameter types which are explicitly specified by name, and may have an optional default value.
  • An optional positional parameter which is an identifier preceded by "*".
  • And an optional keyword parameter which is an identifier preceded by "**".

If any of the parameter types are given then they must appear in the order specified above.

Function parameters are more formally defined as:

funcdef        ::=  "def" funcname "(" [parameter_list] ")" ":" suite
dotted_name    ::=  identifier ("." identifier)*
parameter_list ::=  (defparameter ",")*
                    (  posparameter [, keyparameter]
                    | keyparameter
                    | defparameter [","] )
defparameter   ::=  parameter ["=" expression]
posparameter   ::=  "*" identifier
keyparameter   ::=  "**" identifier
sublist        ::=  parameter ("," parameter)* [","]
parameter      ::=  identifier | "(" sublist ")"

function call arguments

The call of a function in python can use the following argument types:

  • Positional arguments that are mapped by their position in the call argument list to the defparameter name in the corresponding position of the function definition.
  • Sequence arguments that are the character "*" followed by an expression evaluating to a sequence (such as a list or tuple). The values from the sequence are unpacked and mapped like individual positional arguments to defparameters of the function definition. Sequence arguments are evaluated before any keyword argument, irrespecctive of their relative positions in an argument list.
  • All positional arguments must appear before any keyword argument.
  • Keyword arguments of the form parameter_name "=" value will map the value to the defparameter in the definition of the same name.
  • Mapping arguments that are the characters "**" followed by an expression evaluating to a mapping (such as a dict/hash). The key, value pairs from the mapping are unpacked and mapped like individual keyword arguments to defparameters of the function definition.
  • If the function definition includes a positional parameter, then if the assignment of positional arguments and sequence arguments in the call gives more values than the defparameters of the definition, then these extra arguments are assembled, in order, into a tuple that is assigned to the posparameter of the definition.
  • If the function definition includes a keyword parameter, then if the parameter name of any keyword arguments and mapping arguments in the call is unknown in the defparameters of the function definition, then these extra keyword/value pairs are assembled into a dict that is assigned to the keyparameter of the definition.
  • Any default parameter of the function definition that is not assigned a value at this point, but which has a default value, will be aassigned this default value, without re-evaluating the default value.
  • Any default parameter of the function definition that is still un-assigned will cause a TypeError exception to be raised.
  • In addition, multiple mappings to any parameter will raise a TypeError exception. (This includes multiple mappings into a keyparameter or keyword arguments clashing with positional/sequence arguments).


The more formal definition of a function call is

call                 ::=  primary "(" [argument_list [","]
                          | expression genexpr_for] ")"
argument_list        ::=  positional_arguments ["," keyword_arguments]
                            ["," sequence_argument] ["," keyword_arguments]
                            ["," mapping_argument]
                          | keyword_arguments ["," sequence_argument]
                            ["," mapping_argument]
                          | sequence_argument ["," sequence_argument] ["," mapping_argument]
                          | mapping_argument
positional_arguments ::=  expression ("," expression)*
keyword_arguments    ::=  keyword_item ("," keyword_item)*
sequence_argument    ::=  "*" expression
mapping_argument     ::=  "**" expression
keyword_item         ::=  identifier "=" expression

Examples

<lang python> >>> from __future__ import print_function >>> >>> def show_args(defparam1, defparam2 = 'default value', *posparam, **keyparam):

 "Straight-forward function to show its arguments"
 print ("  Default Parameters:")
 print ("    defparam1 value is:", defparam1)
 print ("    defparam2 value is:", defparam2)
 print ("  Positional Arguments:")
 if posparam:
   n = 0
   for p in posparam:
     print ("    positional argument:", n, "is:", p)
     n += 1
 else:
   print ("    <None>")
 print ("  Keyword Arguments (by sorted key name):")
 if keyparam:
   for k,v in sorted(keyparam.items()):
     print ("    keyword argument:", k, "is:", v)
 else:
   print ("    <None>")


>>> show_args('POSITIONAL', 'ARGUMENTS')

 Default Parameters:
   defparam1 value is: POSITIONAL
   defparam2 value is: ARGUMENTS
 Positional Arguments:
   <None>
 Keyword Arguments (by sorted key name):
   <None>

>>> show_args(defparam2='ARGUMENT', defparam1='KEYWORD')

 Default Parameters:
   defparam1 value is: KEYWORD
   defparam2 value is: ARGUMENT
 Positional Arguments:
   <None>
 Keyword Arguments (by sorted key name):
   <None>

>>> show_args( *('SEQUENCE', 'ARGUMENTS') )

 Default Parameters:
   defparam1 value is: SEQUENCE
   defparam2 value is: ARGUMENTS
 Positional Arguments:
   <None>
 Keyword Arguments (by sorted key name):
   <None>

>>> show_args( **{'defparam2':'ARGUMENTS', 'defparam1':'MAPPING'} )

 Default Parameters:
   defparam1 value is: MAPPING
   defparam2 value is: ARGUMENTS
 Positional Arguments:
   <None>
 Keyword Arguments (by sorted key name):
   <None>

>>> show_args('ONLY DEFINE defparam1 ARGUMENT')

 Default Parameters:
   defparam1 value is: ONLY DEFINE defparam1 ARGUMENT
   defparam2 value is: default value
 Positional Arguments:
   <None>
 Keyword Arguments (by sorted key name):
   <None>

>>> show_args('POSITIONAL', 'ARGUMENTS',

             'EXTRA', 'POSITIONAL', 'ARGUMENTS')
 Default Parameters:
   defparam1 value is: POSITIONAL
   defparam2 value is: ARGUMENTS
 Positional Arguments:
   positional argument: 0 is: EXTRA
   positional argument: 1 is: POSITIONAL
   positional argument: 2 is: ARGUMENTS
 Keyword Arguments (by sorted key name):
   <None>

>>> show_args('POSITIONAL', 'ARGUMENTS',

             kwa1='EXTRA', kwa2='KEYWORD', kwa3='ARGUMENTS')
 Default Parameters:
   defparam1 value is: POSITIONAL
   defparam2 value is: ARGUMENTS
 Positional Arguments:
   <None>
 Keyword Arguments (by sorted key name):
   keyword argument: kwa1 is: EXTRA
   keyword argument: kwa2 is: KEYWORD
   keyword argument: kwa3 is: ARGUMENTS

>>> show_args('POSITIONAL',

             'ARGUMENTS', 'EXTRA', 'POSITIONAL', 'ARGUMENTS', 
             kwa1='EXTRA', kwa2='KEYWORD', kwa3='ARGUMENTS')
 Default Parameters:
   defparam1 value is: POSITIONAL
   defparam2 value is: ARGUMENTS
 Positional Arguments:
   positional argument: 0 is: EXTRA
   positional argument: 1 is: POSITIONAL
   positional argument: 2 is: ARGUMENTS
 Keyword Arguments (by sorted key name):
   keyword argument: kwa1 is: EXTRA
   keyword argument: kwa2 is: KEYWORD
   keyword argument: kwa3 is: ARGUMENTS

>>> # But note: >>> show_args('POSITIONAL', 'ARGUMENTS',

             kwa1='EXTRA', kwa2='KEYWORD', kwa3='ARGUMENTS', 
             'EXTRA', 'POSITIONAL', 'ARGUMENTS')

SyntaxError: non-keyword arg after keyword arg >>> </lang>

Smalltalk

As for Objective-C the methods signature is made of "Symbol:[OtherSymbol:]*" (* stands for 0 or more repetition of the part in the brackets), without the possibility to reorder them (it would be another signature) or to make them optional.

Works with: GNU Smalltalk

<lang smalltalk>Object subclass: AnotherClass [

  "..."
  initWithArray: anArray [ "single argument" ]
  initWithArray: anArray andString: aString [ 
       "two args; these two methods in usage resemble
        a named argument, with optional andString argument"
  ]
  "..."

]</lang>

Tcl

The simplest way of passing named parameters is to use the Tcl language's strong support for variadic commands together with its arrays. By convention (originally from Tk) the named parameters names start with a hyphen (“-”) and are called options. <lang tcl>proc example args {

   # Set the defaults
   array set opts {-foo 0 -bar 1 -grill "hamburger"}
   # Merge in the values from the caller
   array set opts $args
   # Use the arguments
   return "foo is $opts(-foo), bar is $opts(-bar), and grill is $opts(-grill)"

}

  1. Note that -foo is omitted and -grill precedes -bar

example -grill "lamb kebab" -bar 3.14

  1. => ‘foo is 0, bar is 3.14, and grill is lamb kebab’</lang>

More complex option parsing is possible, e.g., with the opt package (of which only a small fraction of the functionality is shown here). This package also allows you to specify type constraints, though that is usually not necessary: <lang tcl>package require opt tcl::OptProc example {

   {-foo   -int   0           "The number of foos"}
   {-bar   -float 1.0         "How much bar-ness"}
   {-grill -any   "hamburger" "What to cook on the grill"}

} {

   return "foo is $foo, bar is $bar, and grill is $grill"

} example -grill "lamb kebab" -bar 3.14

  1. => ‘foo is 0, bar is 3.14, and grill is lamb kebab’

example -help

  1. Usage information:
  2. Var/FlagName Type Value Help
  3. ------------ ---- ----- ----
  4. ( -help gives this help )
  5. -foo int (0) The number of foos
  6. -bar float (1.0) How much bar-ness
  7. -grill any (hamburger) What to cook on the grill</lang>