- Timestamp:
- Jul 29, 2024, 1:32:51 PM (14 months ago)
- Branches:
- master
- Children:
- f3d2a4f
- Parents:
- 38e20a80 (diff), 1661ad7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/user/user.tex
r38e20a80 rce02877 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Tue Jul 9 10:43:40202414 %% Update Count : 6 88713 %% Last Modified On : Fri Jul 26 06:56:11 2024 14 %% Update Count : 6955 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 1598 1598 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1599 1599 \begin{cfa} 1600 void f( S & s, char ®c® ) with ( s ) ®with( §\emph{\R{params}}§ )® { // syntax notallowed, illustration only1600 void f( S & s, char ®c® ) with ( s ) ®with( §\emph{\R{params}}§ )® { // syntax disallowed, illustration only 1601 1601 s.c = ®c;® i = 3; d = 5.5; 1602 1602 } … … 3313 3313 for example, the following is incorrect: 3314 3314 \begin{cfa} 3315 * [ int x ] f () fp; §\C{// routine name "f" is notallowed}§3316 \end{cfa} 3317 3318 3319 \section{ Named and Default Arguments}3320 3321 Named\index{named arguments}\index{arguments!named} and default\index{default arguments}\index{arguments!default} arguments~\cite{Hardgrave76}\footnote{3315 * [ int x ] f () fp; §\C{// routine name "f" is disallowed}§ 3316 \end{cfa} 3317 3318 3319 \section{Default and Named Parameter} 3320 3321 Default\index{default parameter}\index{parameter!default} and named\index{named parameter}\index{parameter!named} parameters~\cite{Hardgrave76}\footnote{ 3322 3322 Francez~\cite{Francez77} proposed a further extension to the named-parameter passing style, which specifies what type of communication (by value, by reference, by name) the argument is passed to the routine.} 3323 3323 are two mechanisms to simplify routine call. 3324 Both mechanisms are discussed with respect to \CFA. 3325 \begin{description} 3326 \item[Named (or Keyword) Arguments:] 3327 provide the ability to specify an argument to a routine call using the parameter name rather than the position of the parameter. 3328 For example, given the routine: 3329 \begin{cfa} 3330 void p( int x, int y, int z ) {...} 3331 \end{cfa} 3332 a positional call is: 3333 \begin{cfa} 3334 p( 4, 7, 3 ); 3335 \end{cfa} 3336 whereas a named (keyword) call may be: 3337 \begin{cfa} 3338 p( z : 3, x : 4, y : 7 ); §\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}§ 3339 \end{cfa} 3340 Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters. 3341 The compiler rewrites a named call into a positional call. 3342 The advantages of named parameters are: 3343 \begin{itemize} 3344 \item 3345 Remembering the names of the parameters may be easier than the order in the routine definition. 3346 \item 3347 Parameter names provide documentation at the call site (assuming the names are descriptive). 3348 \item 3349 Changes can be made to the order or number of parameters without affecting the call (although the call must still be recompiled). 3350 \end{itemize} 3351 3352 Unfortunately, named arguments do not work in C-style programming-languages because a routine prototype is not required to specify parameter names, nor do the names in the prototype have to match with the actual definition. 3353 For example, the following routine prototypes and definition are all valid. 3354 \begin{cfa} 3355 void p( int, int, int ); §\C{// equivalent prototypes}§ 3356 void p( int x, int y, int z ); 3357 void p( int y, int x, int z ); 3358 void p( int z, int y, int x ); 3359 void p( int q, int r, int s ) {} §\C{// match with this definition}§ 3360 \end{cfa} 3361 Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming. 3362 Alternatively, prototype definitions can be eliminated by using a two-pass compilation, and implicitly creating header files for exports. 3363 The former is easy to do, while the latter is more complex. 3364 3365 Furthermore, named arguments do not work well in a \CFA-style programming-languages because they potentially introduces a new criteria for type matching. 3366 For example, it is technically possible to disambiguate between these two overloaded definitions of ©f© based on named arguments at the call site: 3367 \begin{cfa} 3368 int f( int i, int j ); 3369 int f( int x, double y ); 3370 3371 f( j : 3, i : 4 ); §\C{// 1st f}§ 3372 f( x : 7, y : 8.1 ); §\C{// 2nd f}§ 3373 f( 4, 5 ); §\C{// ambiguous call}§ 3374 \end{cfa} 3375 However, named arguments compound routine resolution in conjunction with conversions: 3376 \begin{cfa} 3377 f( i : 3, 5.7 ); §\C{// ambiguous call ?}§ 3378 \end{cfa} 3379 Depending on the cost associated with named arguments, this call could be resolvable or ambiguous. 3380 Adding named argument into the routine resolution algorithm does not seem worth the complexity. 3381 Therefore, \CFA does \emph{not} attempt to support named arguments. 3382 3383 \item[Default Arguments] 3384 provide the ability to associate a default value with a parameter so it can be optionally specified in the argument list. 3385 For example, given the routine: 3386 \begin{cfa} 3387 void p( int x = 1, int y = 2, int z = 3 ) {...} 3388 \end{cfa} 3389 the allowable positional calls are: 3390 \begin{cfa} 3391 p(); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}§ 3392 p( 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}§ 3393 p( 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}§ 3394 p( 4, 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 4 )}§ 3395 // empty arguments 3396 p( , 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 1, 4, 4 )}§ 3397 p( 4, , 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 4 )}§ 3398 p( 4, 4, ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}§ 3399 p( 4, , ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}§ 3400 p( , 4, ); §\C{// rewrite \(\Rightarrow\) p( 1, 4, 3 )}§ 3401 p( , , 4 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 4 )}§ 3402 p( , , ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}§ 3403 \end{cfa} 3324 3325 3326 \subsection{Default} 3327 3328 A default parameter associates a default value with a parameter so it can be optionally specified in the argument list. 3329 For example, given the routine prototype: 3330 \begin{cfa} 3331 void f( int x ®= 1®, int y ®= 2®, int z ®= 3® ); 3332 \end{cfa} 3333 allowable calls are: 3334 \begin{cquote} 3335 \setlength{\tabcolsep}{0.75in} 3336 \begin{tabular}{@{}ll@{}} 3337 \textbf{positional arguments} & \textbf{empty arguments} \\ 3338 \begin{cfa} 3339 f(); §\C[0.75in]{// rewrite \(\Rightarrow\) f( 1, 2, 3 )}§ 3340 f( 4 ); §\C{// rewrite \(\Rightarrow\) f( 4, 2, 3 )}§ 3341 f( 4, 4 ); §\C{// rewrite \(\Rightarrow\) f( 4, 4, 3 )}§ 3342 f( 4, 4, 4 ); §\C{// rewrite \(\Rightarrow\) f( 4, 4, 4 )}\CRT§ 3343 3344 3345 3346 \end{cfa} 3347 & 3348 \begin{cfa} 3349 f( ®?®, 4, 4 ); §\C[1.0in]{// rewrite \(\Rightarrow\) f( 1, 4, 4 )}§ 3350 f( 4, ®?®, 4 ); §\C{// rewrite \(\Rightarrow\) f( 4, 2, 4 )}§ 3351 f( 4, 4, ®?® ); §\C{// rewrite \(\Rightarrow\) f( 4, 4, 3 )}§ 3352 f( 4, ®?®, ®?® ); §\C{// rewrite \(\Rightarrow\) f( 4, 2, 3 )}§ 3353 f( ®?®, 4, ®?® ); §\C{// rewrite \(\Rightarrow\) f( 1, 4, 3 )}§ 3354 f( ®?®, ®?®, 4 ); §\C{// rewrite \(\Rightarrow\) f( 1, 2, 4 )}§ 3355 f( ®?®, ®?®, ®?® ); §\C{// rewrite \(\Rightarrow\) f( 1, 2, 3 )}\CRT§ 3356 \end{cfa} 3357 \end{tabular} 3358 \end{cquote} 3359 where the ©?© selects the default value as the argument. 3404 3360 Here the missing arguments are inserted from the default values in the parameter list. 3405 3361 The compiler rewrites missing default values into explicit positional arguments. … … 3408 3364 \item 3409 3365 Routines with a large number of parameters are often very generalized, giving a programmer a number of different options on how a computation is performed. 3410 For many of these kinds ofroutines, there are standard or default settings that work for the majority of computations.3366 For many of these routines, there are standard or default settings that work for the majority of computations. 3411 3367 Without default values for parameters, a programmer is forced to specify these common values all the time, resulting in long argument lists that are error prone. 3412 3368 \item … … 3422 3378 Instead, a default value is used, which may not be the programmer's intent. 3423 3379 3424 Default values may only appear in a prototype versus definition context:3425 \begin{cfa} 3426 void p( int x, int y = 2, int z = 3 );§\C{// prototype: allowed}§3427 void p( int, int = 2, int = 3 );§\C{// prototype: allowed}§3428 void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: notallowed}§3380 Default parameters may only appear in a prototype versus definition context: 3381 \begin{cfa} 3382 void f( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§ 3383 void f( int, int = 2, int = 3 ); §\C{// prototype: allowed}§ 3384 void f( int x, int y = 2, int z = 3 ) ®{}® §\C{// definition: disallowed}§ 3429 3385 \end{cfa} 3430 3386 The reason for this restriction is to allow separate compilation. 3431 Multiple prototypes with different default values is an error. 3432 \end{description} 3433 3434 Ellipse (``...'') arguments present problems when used with default arguments. 3435 The conflict occurs because both named and ellipse arguments must appear after positional arguments, giving two possibilities: 3436 \begin{cfa} 3437 p( /* positional */, ... , /* named */ ); 3438 p( /* positional */, /* named */, ... ); 3439 \end{cfa} 3440 While it is possible to implement both approaches, the first possibly is more complex than the second, \eg: 3441 \begin{cfa} 3442 p( int x, int y, int z, ... ); 3443 p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ 3444 p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ 3445 \end{cfa} 3446 In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin. 3447 Hence, this approach seems significantly more difficult, and hence, confusing and error prone. 3448 In the second call, the named arguments separate the positional and ellipse arguments, making it trivial to read the call. 3449 3450 The problem is exacerbated with default arguments, \eg: 3451 \begin{cfa} 3452 void p( int x, int y = 2, int z = 3... ); 3453 p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ 3454 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ 3455 \end{cfa} 3456 The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments; 3457 therefore, argument 5 subsequently conflicts with the named argument z : 3. 3458 In the second call, the default value for y is implicitly inserted after argument 1 and the named arguments separate the positional and ellipse arguments, making it trivial to read the call. 3459 For these reasons, \CFA requires named arguments before ellipse arguments. 3460 Finally, while ellipse arguments are needed for a small set of existing C routines, like ©printf©, the extended \CFA type system largely eliminates the need for ellipse arguments \see{\VRef{s:Overloading}}, making much of this discussion moot. 3387 Multiple prototypes with different default values is undefined. 3461 3388 3462 3389 Default arguments and overloading \see{\VRef{s:Overloading}} are complementary. … … 3466 3393 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}} & \multicolumn{1}{c}{\textbf{overloading}} \\ 3467 3394 \begin{cfa} 3468 void p( int x, int y = 2, int z = 3 ) {...}3395 void f( int x, int y = 2, int z = 3 ) {...} 3469 3396 3470 3397 … … 3472 3399 & 3473 3400 \begin{cfa} 3474 void p( int x, int y, int z ) {...}3475 void p( int x ) { p( x, 2, 3 ); }3476 void p( int x, int y ) { p( x, y, 3 ); }3401 void f( int x, int y, int z ) {...} 3402 void f( int x ) { f( x, 2, 3 ); } 3403 void f( int x, int y ) { f( x, y, 3 ); } 3477 3404 \end{cfa} 3478 3405 \end{tabular} 3479 3406 \end{cquote} 3480 3407 the number of required overloaded routines is linear in the number of default values, which is unacceptable growth. 3481 In general, overloading should only be used over default arguments if the body of the routine is significantly different. 3482 Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as: 3483 \begin{cfa} 3484 p( 1, /* default */, 5 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}§ 3485 \end{cfa} 3486 3487 Given the \CFA restrictions above, both named and default arguments are backwards compatible. 3488 \Index*[C++]{\CC{}} only supports default arguments; 3489 \Index*{Ada} supports both named and default arguments. 3408 In general, overloading is used over default parameters, if the body of the routine is significantly different. 3409 Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list. 3410 \begin{cfa} 3411 f( 1, ®?®, 5 ); §\C{// rewrite \(\Rightarrow\) f( 1, 2, 5 )}§ 3412 \end{cfa} 3413 3414 3415 \subsection{Named (or Keyword)} 3416 3417 A named (keyword) parameter provides the ability to specify an argument to a routine call using the parameter name rather than the position of the parameter. 3418 For example, given the routine prototype: 3419 \begin{cfa} 3420 void f( int ®?®x, int ®?®y, int ®?®z ); 3421 \end{cfa} 3422 allowable calls are: 3423 \begin{cfa} 3424 f( ?x = 3, ?y = 4, ?z = 5 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3425 f( ?y = 4, ?z = 5, ?x = 3 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3426 f( ?z = 5, ?x = 3, ?y = 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3427 f( ?x = 3, ?z = 5, ?y = 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3428 \end{cfa} 3429 Here the ordering of the the parameters and arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters. 3430 The compiler rewrites a named call into a positional call. 3431 Note, the syntax ©?x = 3© is necessary for the argument, because ©x = 3© has an existing meaning, \ie assign ©3© to ©x© and pass the value of ©x©. 3432 The advantages of named parameters are: 3433 \begin{itemize} 3434 \item 3435 Remembering the names of the parameters may be easier than the order in the routine definition. 3436 \item 3437 Parameter names provide documentation at the call site (assuming the names are descriptive). 3438 \item 3439 Changes can be made to the order or number of parameters without affecting the call (although the call must still be recompiled). 3440 \end{itemize} 3441 3442 Named parameters may only appear in a prototype versus definition context: 3443 \begin{cfa} 3444 void f( int x, int ?y, int ?z ); §\C{// prototype: allowed}§ 3445 void f( int ?x, int , int ?z ); §\C{// prototype: allowed}§ 3446 void f( int x, int ?y, int ?z ) ®{}® §\C{// definition: disallowed}§ 3447 \end{cfa} 3448 The reason for this restriction is to allow separate compilation. 3449 Multiple prototypes with different positional parameter names is an error. 3450 3451 The named parameter is not part of type resolution; 3452 only the type of the expression assigned to the named parameter affects type resolution. 3453 \begin{cfa} 3454 int f( int ?i, int ?j ); 3455 int f( int ?i, double ?j ); 3456 f( ?j = 3, ?i = 4 ); §\C{// 1st f}§ 3457 f( ?i = 7, ?j = 8.1 ); §\C{// 2nd f}§ 3458 \end{cfa} 3459 3460 3461 \subsection{Mixed Default/Named} 3462 3463 Default and named parameters can be intermixed and named parameters can have a default value. 3464 For example, given the routine prototype: 3465 \begin{cfa} 3466 void f( int x, int y ®= 1®, int ®?®z ®= 2® ); 3467 \end{cfa} 3468 allowable calls are: 3469 \begin{cfa} 3470 f( 3 ); §\C{// rewrite \(\Rightarrow\) f( 3, 1, 2 )}§ 3471 f( 3, 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 2 )}§ 3472 f( 3, ?z = 5 ); §\C{// rewrite \(\Rightarrow\) f( 3, 1, 5 )}§ 3473 f( 3, 4, ?z = 5 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3474 f( ?z = 5, 3 ); §\C{// rewrite \(\Rightarrow\) f( 3, 1, 5 )}§ 3475 f( 3, ?z = 5, 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3476 \end{cfa} 3477 Finally, the ellipse (``...'') parameter must appear after positional and named parameters in a routine prototype. 3478 \begin{cfa} 3479 void f( int i = 1, int ?j = 2, ®...® ); 3480 \end{cfa} 3481 3482 \CFA named and default arguments are backwards compatible with C. 3483 \Index*[C++]{\CC{}} only supports default parameters; 3484 \Index*{Ada} supports both named and default parameters. 3490 3485 3491 3486
Note:
See TracChangeset
for help on using the changeset viewer.