Changeset d02d223
- Timestamp:
- Jul 25, 2024, 4:59:34 PM (4 months ago)
- Branches:
- master
- Children:
- 3cb693c
- Parents:
- 878b1385
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/user/user.tex
r878b1385 rd02d223 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : T ue Jul 9 10:43:40202414 %% Update Count : 6 88713 %% Last Modified On : Thu Jul 25 16:53:43 2024 14 %% Update Count : 6945 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 provides the ability to associate 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} 3404 3359 Here the missing arguments are inserted from the default values in the parameter list. 3405 3360 The compiler rewrites missing default values into explicit positional arguments. … … 3408 3363 \item 3409 3364 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.3365 For many of these routines, there are standard or default settings that work for the majority of computations. 3411 3366 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 3367 \item … … 3422 3377 Instead, a default value is used, which may not be the programmer's intent. 3423 3378 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}§3379 Default parameters may only appear in a prototype versus definition context: 3380 \begin{cfa} 3381 void f( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§ 3382 void f( int, int = 2, int = 3 ); §\C{// prototype: allowed}§ 3383 void f( int x, int y = 2, int z = 3 ) ®{}® §\C{// definition: disallowed}§ 3429 3384 \end{cfa} 3430 3385 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. 3386 Multiple prototypes with different default values is undefined. 3461 3387 3462 3388 Default arguments and overloading \see{\VRef{s:Overloading}} are complementary. … … 3466 3392 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}} & \multicolumn{1}{c}{\textbf{overloading}} \\ 3467 3393 \begin{cfa} 3468 void p( int x, int y = 2, int z = 3 ) {...}3394 void f( int x, int y = 2, int z = 3 ) {...} 3469 3395 3470 3396 … … 3472 3398 & 3473 3399 \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 ); }3400 void f( int x, int y, int z ) {...} 3401 void f( int x ) { f( x, 2, 3 ); } 3402 void f( int x, int y ) { f( x, y, 3 ); } 3477 3403 \end{cfa} 3478 3404 \end{tabular} 3479 3405 \end{cquote} 3480 3406 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 argumentsif the body of the routine is significantly different.3407 In general, overloading is used over default parameters, if the body of the routine is significantly different. 3482 3408 Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as: 3483 3409 \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. 3410 f( 1, ?, 5 ); §\C{// rewrite \(\Rightarrow\) f( 1, 2, 5 )}§ 3411 \end{cfa} 3412 3413 3414 \subsection{Named (or Keyword)} 3415 3416 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. 3417 For example, given the routine prototype: 3418 \begin{cfa} 3419 void f( int ®?®x, int ®?®y, int ®?®z ); 3420 \end{cfa} 3421 allowable calls are: 3422 \begin{cfa} 3423 f( ?x = 3, ?y = 4, ?z = 5 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3424 f( ?y = 4, ?z = 5, ?x = 3 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3425 f( ?z = 5, ?x = 3, ?y = 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3426 f( ?x = 3, ?z = 5, ?y = 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3427 \end{cfa} 3428 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. 3429 The compiler rewrites a named call into a positional call. 3430 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©. 3431 The advantages of named parameters are: 3432 \begin{itemize} 3433 \item 3434 Remembering the names of the parameters may be easier than the order in the routine definition. 3435 \item 3436 Parameter names provide documentation at the call site (assuming the names are descriptive). 3437 \item 3438 Changes can be made to the order or number of parameters without affecting the call (although the call must still be recompiled). 3439 \end{itemize} 3440 3441 Named parameters may only appear in a prototype versus definition context: 3442 \begin{cfa} 3443 void f( int x, int ?y, int ?z ); §\C{// prototype: allowed}§ 3444 void f( int ?x, int , int ?z ); §\C{// prototype: allowed}§ 3445 void f( int x, int ?y, int ?z ) ®{}® §\C{// definition: disallowed}§ 3446 \end{cfa} 3447 The reason for this restriction is to allow separate compilation. 3448 Multiple prototypes with different positional parameter names is an error. 3449 3450 The named parameter is not part of type resolution; 3451 the type of the expression assigned to the named parameter affects type resolution. 3452 \begin{cfa} 3453 int f( int ?i, int ?j ); 3454 int f( int ?i, double ?j ); 3455 f( ?j = 3, ?i = 4 ); §\C{// 1st f}§ 3456 f( ?i = 7, ?j = 8.1 ); §\C{// 2nd f}§ 3457 \end{cfa} 3458 3459 3460 \subsection{Mixed Default/Named} 3461 3462 Default and named parameters can be intermixed and named parameters can have a default value. 3463 For example, given the routine prototype: 3464 \begin{cfa} 3465 void f( int x, int y ®= 1®, int ®?®z ®= 2® ); 3466 \end{cfa} 3467 allowable calls are: 3468 \begin{cfa} 3469 f( 3 ); §\C{// rewrite \(\Rightarrow\) f( 3, 1, 2 )}§ 3470 f( 3, 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 2 )}§ 3471 f( 3, ?z = 5 ); §\C{// rewrite \(\Rightarrow\) f( 3, 1, 5 )}§ 3472 f( 3, 4, ?z = 5 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3473 f( ?z = 5, 3 ); §\C{// rewrite \(\Rightarrow\) f( 3, 1, 5 )}§ 3474 f( 3, ?z = 5, 4 ); §\C{// rewrite \(\Rightarrow\) f( 3, 4, 5 )}§ 3475 \end{cfa} 3476 Finally, the ellipse (``...'') parameter must appear after positional and named parameters in a routine prototype. 3477 \begin{cfa} 3478 void f( int i = 1, int ?j = 2, ®...® ); 3479 \end{cfa} 3480 3481 \CFA named and default arguments are backwards compatible with C. 3488 3482 \Index*[C++]{\CC{}} only supports default arguments; 3489 3483 \Index*{Ada} supports both named and default arguments.
Note: See TracChangeset
for help on using the changeset viewer.