fox@cs.cs.columbia.edu (David Fox) (07/24/89)
It seems to me that as long as you are going to have default argument values, you might as well allow any combination of arguments to be omitted. I often find myself trying to figure out what order to put the arguments of a function in so that I can give the "right ones" default values. I often fail to find that order: many functions just aren't that "linear". The way to do this is to allow caller to name the parameters the way Ada does: foo(parm1 = a, parm3 = b, parm2 = c). Is it too late to add this, or something like it, to C++? G++? Would it be a Good Thing? Would it break anything? Has it already been discussed? Can I have it by Tuesday? David Fox fox@cs.columbia.edu P.S. If it can't be part of the language, perhaps this could be done with a preprocessor?
beshers@cs.cs.columbia.edu (Clifford Beshers) (07/24/89)
In article <FOX.89Jul23151217@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes:
It seems to me that as long as you are going to have default
argument values, you might as well allow any combination of
arguments to be omitted. I often find myself trying to
figure out what order to put the arguments of a function in
so that I can give the "right ones" default values. I often
fail to find that order: many functions just aren't that
"linear".
I have fought this problem as well.
The way to do this is to allow caller to name the parameters
the way Ada does: foo(parm1 = a, parm3 = b, parm2 = c).
Is it too late to add this, or something like it, to C++? G++?
The problem is that it is already there, but with different semantics:
void foo(int parm1, int parm3, int parm2)
{ ... }
...
int parm1, parm2, parm3;
foo(parm1 = 1, parm2 = 3, parm3 = 2);
What interpretation do you place on this?
--
-----------------------------------------------
Cliff Beshers
Columbia University Computer Science Department
beshers@cs.columbia.edu
fox@cs.cs.columbia.edu (David Fox) (07/24/89)
Well, you'd need some new syntax, like foo(parm1 <- val1, parm3 <- val2, parm2 <- val3) or foo(parm1 := val1, parm3 := val2, parm2 := val3) or foo(parm1 ---> val1, parm3 ---> val2, parm2 ---> val3). I know, some of these can be interpreted differently. Maybe we could use some character with its eighth bit set that shows up as a little left arrow on an IBM PC. (1/4 a smile) We clearly need some more symbols on our keyboards. David Fox fox@cs.columbia.edu
beshers@cs.cs.columbia.edu (Clifford Beshers) (07/24/89)
In article <FOX.89Jul23165225@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes:
Well, you'd need some new syntax, like
foo(parm1 <- val1, parm3 <- val2, parm2 <- val3)
or
foo(parm1 := val1, parm3 := val2, parm2 := val3)
or
foo(parm1 ---> val1, parm3 ---> val2, parm2 ---> val3).
And some more semantics. Should you allow mixing of the two
types or specification, e.g.
foo(val1, parm3 <- val2, parm2 <- val3)
what happens with:
foo(parm3 <- val2, val1, parm2 <- val3)
It is not a simple addition to the language, but it would be useful.
--
-----------------------------------------------
Cliff Beshers
Columbia University Computer Science Department
beshers@cs.columbia.edu
grunwald@flute.cs.uiuc.edu (Dirk Grunwald) (07/24/89)
In article <BESHERS.89Jul23152110@cs.cs.columbia.edu> beshers@cs.cs.columbia.edu (Clifford Beshers) writes:
.....
void foo(int parm1, int parm3, int parm2)
{ ... }
...
int parm1, parm2, parm3;
foo(parm1 = 1, parm2 = 3, parm3 = 2);
What interpretation do you place on this?
you don't - you switch notation:
foo(parm1 <- 1, parm2 <- 3, parm3 <- 2);
--
Dirk Grunwald -- Univ. of Illinois (grunwald@flute.cs.uiuc.edu)
dlw@odi.com (Dan Weinreb) (07/24/89)
In article <FOX.89Jul23151217@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes:
The way to do this is to allow caller to name the parameters
We did exactly this to Common Lisp, for exactly the reason you cite.
(Actually we did it to Common Lisp's ancestor, the MIT Lisp Machine
dialect of Lisp, and the feature was carried over into Common Lisp).
It turned out to be useful and is used fairly often in large Lisp
programs. In my opinion, in the abstract, it would be a good thing.
I can certainly see why making such a change to C++ at this point in
its life might be significantly more difficult than making such a
change to Lisp was in the late 1970's. But in this I should defer to
the C++ designers, since I don't know all the considerations and
ramifications.
Dan Weinreb Object Design, Inc.
lpringle@bbn.com (Lewis G. Pringle) (07/25/89)
In article <FOX.89Jul23151217@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes: >The way to do this is to allow caller to name the parameters >the way Ada does: foo(parm1 = a, parm3 = b, parm2 = c). I second the emotion, but it may be harder than it looks. What your are describing (I think) are called keyword parameters. The difficulty, is that they impose even more ambiguity into the language. Default params, together with overloading, and conversion operators, already add lots ambiguity - keyword paramers would make things even worse. The ambiguity can - of cousrse be resolved by disambiguating rules. Any ADA people want to share their experiences. Lewis. "OS/2: half an operating system for half a computer." In Real Life: Lewis Gordon Pringle Jr. Electronic Mail: lpringle@labs-n.bbn.com Phone: (617) 873-4433
schmidt@glacier.ics.uci.edu (Doug Schmidt) (07/26/89)
In article <43253@bbn.COM>, lpringle@bbn (Lewis G. Pringle) writes: >In article <FOX.89Jul23151217@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes: >>The way to do this is to allow caller to name the parameters >>the way Ada does: foo(parm1 = a, parm3 = b, parm2 = c). > >I second the emotion, but it may be harder than it looks. What your are >describing (I think) are called keyword parameters. The difficulty, >is that they impose even more ambiguity into the language. Default params, >together with overloading, and conversion operators, already add >lots ambiguity - keyword paramers would make things even worse. There's also another problem. Allowing ``named parameters,'' a la Ada, weakens information hiding, since formal parameter names are now visible *outside* their original scope! For example, consider the effect of changing a formal parameter name in C or C++. All you need to modify are the uses of this formal parameter name *inside* the enclosing function. This change is trivial to perform using an interactive query-replace editor feature. On the other hand, in a language that allows named parameters you need to hunt down all instances of the formal parameter names occurring in all *calls* to the function. These calls are potentially spread throughout many source files, and it becomes difficult to change the names in an automated fashion, for the reasons alluded to above. IMHO, named parameters are another Ada (mis)feature that adds gratuitous complexity to the compiler and programmer without providing much value-added benefit. Doug -- Master Swordsman speak of humility; | schmidt@ics.uci.edu (ARPA) Philosophers speak of truth; | office: (714) 856-4034 Saints and wisemen speak of the Tao of no doubt; The moon, sun, and sea speaks for itself. -- Hiroshi Hamada
chase@Ozona.orc.olivetti.com (David Chase) (07/26/89)
In article <20077@paris.ics.uci.edu> schmidt@glacier.ics.uci.edu (Doug Schmidt) writes: >There's also another problem. Allowing ``named parameters,'' a la >Ada, weakens information hiding, since formal parameter names are now >visible *outside* their original scope! > >On the other hand, in a language that allows named parameters you need >to hunt down all instances of the formal parameter names occurring in >all *calls* to the function. These calls are potentially spread >throughout many source files, and it becomes difficult to change the >names in an automated fashion, for the reasons alluded to above. > >IMHO, named parameters are another Ada (mis)feature that adds >gratuitous complexity to the compiler and programmer without providing >much value-added benefit. Don't knock them until you've tried them (and compiled them). Keyword and default parameters are in Mesa and in Modula-3 (among others), and they work just fine. If you have a language with separate interfaces and implementations, the "exposes formal parameter names" argument is bogus. From the point of view of the called procedure, the only important thing is the parameter position and the parameter type (yes, it is correct that the compiler fills in the parameters at call sites if they aren't supplied). Thus, the names in the interface and the names in the implementation need not correspond to each other (though I'm not sure what Ada, Modula-3, and Mesa do about this), so nothing has been revealed about the implementation. That is, there's two scopes, not one, and the conditions on signature matching say nothing about the names of the parameters. This is a curious sort of "information hiding"; I thought one was supposed to hide the internals of a module, not its interface. Choice of parameter names has plenty to do with the interface, and very little to do with the implementation. Generally (anyhow), interfaces are expected to be somewhat unchanging, and signatures of procedures are certainly expected to be somewhat unchanging. Even so, if you did find it necessary to change a procedure signature, you may rest assured that the compiler will inform you of any calls which do not conform to the standard. If you fail to recompile a module, then the pre-linker will inform you of this (since generation of makefiles and dependency checking is automated, this should not happen, anyway). (The above may sound like some weird fairy-tale, but it's all in place, and it all works well for Modula-3. I don't know enough about C++ to think of any reasons why it shouldn't be possible for C++.) How does this differ from the exchange of two parameters in a list, anyway? You'd need to hunt *those* down, and (if they were of the same type) the compiler and linker wouldn't tell you anything. This doesn't look like a win to me. Keyword parameters take care of *that* automatically. David
jbw@eyebeam.UUCP (Jeremy B. Wohlblatt) (07/26/89)
schmidt@glacier.ics.uci.edu (Doug Schmidt) writes: >In article <43253@bbn.COM>, lpringle@bbn (Lewis G. Pringle) writes: >>In article <FOX.89Jul23151217@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes: [talk about named parameters] >There's also another problem. Allowing ``named parameters,'' a la >Ada, weakens information hiding, since formal parameter names are now >visible *outside* their original scope! from a software engineering point of view, i see no problem here. the keyword names need only be visible in the function call, which is the interface between the calling routine and the function itself. why shouldn't some aspects of both be visible there? already, the calling routine must know the order and types of the arguments (to say nothing of the semantics), so why not provide a name if it helps the caller write the call more clearly? e.g., in a language which gives you defaults and named paramenter, you might want to use an 8-parameter function but with all defaults except one. you could write this simply as load_file(infile <- foo); rather than copying all the defaults or writing something like load_file(,,,, foo,,,); basically this frees you from having to know the order of arguments at the expense of requiring you to know the names of the ones you're interested in. this may make the call more clear. consider copy (x, y); versus copy (from <- y, to <- x); note that i did not use the traditional `=' for parameter assignment. it seems too hard to read and understand function calls when ordinary assignment and parameter assignment use the same syntax, e.g. { int y; ... foo (x = 3); // keyword assignment foo (y = 3); // local variable assignment } >For example, consider the effect of changing a formal parameter name >in C or C++. All you need to modify are the uses of this formal >parameter name *inside* the enclosing function. This change is >trivial to perform using an interactive query-replace editor feature. but this is a problem with editors, not the software engineering structure of the program. the solution is better multi-file editors. moreover, if you change the *order* of the arguments, you've got the same problem anyway, right? it's reasonable to visit all the function calls whenever you change the interface to the function. >On the other hand, in a language that allows named parameters you need >to hunt down all instances of the formal parameter names occurring in >all *calls* to the function. These calls are potentially spread >throughout many source files, and it becomes difficult to change the >names in an automated fashion, for the reasons alluded to above. on the other hand, you can change the order of the arguments and *not* have to visit all the calls if they always used the keyword names! >IMHO, named parameters are another Ada (mis)feature that adds >gratuitous complexity to the compiler and programmer without providing >much value-added benefit. i may agree with you that this isn't a tremendously exciting feature, but not for the reasons you cite. personally, though, it seems to me that if the language has a clear syntax associated with named parameters (like the `<-' i suggested above) then there's little room for ambiguity. nor should the compiler be all that more complex. -- jeremy these opinions might not be those of my employer. they might not even be mine. jeremy b. wohlblatt: samsung software america, inc. uucp: {decvax!{gsg,cg-atla},uunet,ulowell}!ginosko!jbw internet: jbw@ginosko.samsung.com
dlw@odi.com (Dan Weinreb) (07/26/89)
In article <20077@paris.ics.uci.edu> schmidt@glacier.ics.uci.edu (Doug Schmidt) writes:
There's also another problem. Allowing ``named parameters,'' a la
Ada, weakens information hiding, since formal parameter names are now
visible *outside* their original scope!
You can allow the formal parameter name to be different from the
outside-visible keyword name. Common Lisp allows this. They're the
same by default but you can control it if you want to. People
interested in this sort of language feature might want to check out
Common Lisp, which has had it for a long time. However, I'm not sure
there's much point to discussing it on comp.lang.c++. I like the idea
too, but based on the philosophy of C++ evolution that I've heard, as
I understand it, this is not the sort of change we're likely to see in
C++.
alonzo@microsoft.UUCP (Alonzo Gariepy) (07/26/89)
>In article <FOX.89Jul23165225@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes: > > > Well, you'd need some new syntax, like > > foo(parm1 <- val1, parm3 <- val2, parm2 <- val3) Why not some more simple compromise such as allowing empty commas. This way, all the default parameters don't have to be at the end of the list. int foo(a = 3, b, c = 12, d = 12); foo(4, 7, , 10); // c gets 12 foo(, 6); // a gets 3, c gets 12, d gets 12 foo(4,,7); // **error** b has no default Or am I naive? Alonzo Gariepy // If Microsoft has an opinion, alonzo@microsoft // they haven't told it to me.
benson@odi.com (Benson I. Margulies) (07/26/89)
In article <20077@paris.ics.uci.edu> schmidt@glacier.ics.uci.edu (Doug Schmidt) writes: >In article <43253@bbn.COM>, lpringle@bbn (Lewis G. Pringle) writes: >>In article <FOX.89Jul23151217@cs.cs.columbia.edu> fox@cs.cs.columbia.edu (David Fox) writes: >>>The way to do this is to allow caller to name the parameters >>>the way Ada does: foo(parm1 = a, parm3 = b, parm2 = c). >> >>I second the emotion, but it may be harder than it looks. What your are >>describing (I think) are called keyword parameters. The difficulty, >>is that they impose even more ambiguity into the language. Default params, >>together with overloading, and conversion operators, already add >>lots ambiguity - keyword paramers would make things even worse. > >There's also another problem. Allowing ``named parameters,'' a la >Ada, weakens information hiding, since formal parameter names are now >visible *outside* their original scope! > Not true. In Common Lisp, it is possible to decouple the two. (defun foo (&key (:x 1 y)) (+ y 1)) means: - call it like (foo :x VAL) - bind a variable named "y" in the body. - Default to 1. C++ need "merely" design a parallel syntax. >IMHO, named parameters are another Ada (mis)feature that adds >gratuitous complexity to the compiler and programmer without providing >much value-added benefit. If the language didn't have optional params with defaults, I would be sympathetic to adding neither those nor by-name parameters. However, as it is, functions tend to become incomprehensible as they are overloaded. Constructors are particularly subject to this abuse. One sees (even in the documentation from AT&T) substantially different behavior triggered by subtlties of the argument list. I believe that the problem results from a particular limitation. Often, I desire a family of functions with nearly identical content but different parameters. I can write them in C++ as a bunch of inline wrappers and one body function, but inlines don't always work, and I begrudge the procedure call. In PL/I, this was addressed by multiple entrypoints. A standard Multics PL/I cliche was: procedure full_interface (x, y, z, q, r, s); ... goto start; entry quick_interface (x, y, z); q = qdefault; r = rdefault; s = sdefault; start: end; Optional parameters attempt to address this case. However, they lose the self-documentation of the different entry names. Constructors are particularly plagued by this. The experience in the lisp community was that optional arguments are often the route to disaster. Who can remember how many zeros to supply to get out to the critical argument I need today? If you are lucky, the optionals will have types without inter-conversions, and then errors will be obvious. But if there are 4 optionals in a row that are either numbers or pointers, then you can have one too many or one too few and never find out till the bridge falls down. In a word, "unsafe". What might a syntax be in C++? Its not obvious. A keyword seems to be needed. int x (byname (name1, default1, var1), (name2, default2, var2)) { If "var" is omitted, then name is the name. If default and var are omitted, then the parens can be omitted. How would one call it? That's the ugly part, I fear. x (name1:=val1, name2:=val2) would serve. Benson I. Margulies
lindsay@MATHOM.GANDALF.CS.CMU.EDU (Donald Lindsay) (07/27/89)
In article <20077@paris.ics.uci.edu> schmidt@glacier.ics.uci.edu (Doug Schmidt) writes: >IMHO, named parameters are another Ada (mis)feature that adds >gratuitous complexity to the compiler and programmer without providing >much value-added benefit. Well, yes. They allowed the intermixture of positional and named arguments, this making it potentially hard to understand the positional material. If you really need named arguments, you can have them now, even in C and Pascal. Pass a data structure, and precede the call with assignments to named fields. It doesn't allow a simple defaulting scheme, but there are a variety of less-simple schemes that can be pressed into service. And, it has wins of its own, such as using const structures, or ones that don't vary around a loop. -- Don D.C.Lindsay Carnegie Mellon School of Computer Science
minshall@kinetics.UUCP (Greg Minshall) (08/02/89)
I assume that various participants in this newsgroup had occasion in years past to use the IBM 370 assembler macro facility. How much this discussion of named parameters (and even default parameter values in C++) remind/amuses me of the above assembler. The macro facility allowed both "positional" and "keyword" parameters. Positional parameters needed to come first in the parameter list; any or all could be left out (an intervening positionaly parameter could be excluded by use of the "comma" operator: foo a,b,,d). Keyword parameters could be specified (in the call) in any order; they could be defined by the macro to have default values. It was quite an assembler. Greg Minshall Kinetics/Excelan/Novell minshall@kinetics.com 1-415-947-0998