Post by Henry MillerPost by David BrownPost by Henry MillerThere have been many, all died because of opposition to the idea.
You have a syntax, but you need to convince people that there
isn't a better way.
Strong types are generally preferred.
No, they are not generally preferred. At the moment, they are all
we've got.
Strong types certainly have their uses, and their advantages over
other solutions. They also have their disadvantages.
I haven't actually surveyed the committee, but I think that my
statement stands.
I haven't seen anything from the committee either. But even if they
have a firm opinion, there is a long way from that to claiming that one
method is "generally preferred". The fact that these threads are
brought up here again and again, and that there are multiple proposals
flying around, shows that there is a great interest in getting named
parameters in place and that strong types - or strong types alone - is
/not/ the generally preferred. We /have/ strong types today in C++ - it
is very, very far from good enough for named parameters.
Post by Henry MillerThere is a great desire that if the code compiles
it is correct.
On that, I think we all agree!
Post by Henry MillerMax(left: varShouldBeRight, right: varShouldBeLeft);
This will compile, but is wrong.
That claim makes no sense. Since the syntax does not exist today, it is
a matter of how it is implemented. Getting the parameter order wrong
will either be a compile-time error, or will be accepted with parameter
re-ordering - the jury is still out on which is the best. Silently
compiling the incorrect code is not suggested by anyone - that is what
we have today, and what we are trying to get away from!
Given the declaration:
max(int left, int right);
and the call:
max(right: 12, left: 20);
then there are two acceptable options. One is a compile-time error.
The second is to treat the call exactly as if it had been written:
max(left: 20, right: 12);
Everything else is bike-shedding. People disagree on the syntax for the
declaration, or if the parameter information should be part of the
mangled name of the function, or if it should be possible to have
different names for the "named parameters" and the "formal parameter" in
the declaration or definition of the function. Some people want to
complicate matters with using names to overload functions, others want
to keep it simpler.
The fact is that most other good, modern programming languages have
named parameters. They can make the code clearer, and reduce errors.
It can be done in a simple, optional manner that will suffice for the
great majority of cases. And it is a frustrating thing to see people
arguing about the number of angels that can dance on the head of this
pin, instead of just making the clear and obvious solution that people
can use today.
Post by Henry MillerIn a real program where the
variables come from someplace and are used in multiple locations it
is much more likely that either it fails to compile, or at least
someone catches the error in review. Haskell has a reputation of if
it compiles it is right. It would be nice to have the same reputation
without the downsides of haskell (which are subjective so let's not
argue about them)
Ada has that reputation too - and it manages named parameters in a
simple manner without strong types.
You talk about "real programs". In "real programs", people are not
going to go out of their way to make strong types for parameters except
in a few extreme cases. When you try to make a solution that requires
extra effort on the part of programmers, people will not use it! Make
it simple, make it optional, make it work with today's code, and it will
be used.
Post by Henry MillerPost by David BrownA great many people want a simple, clean and optional method of
naming parameters. It could be nothing more than a compile-time
check, but it needs a convenient syntax. More advanced
requirements - re-ordering parameters, forcing the use of names,
etc., gets more controversial.
Yes, but why? If you can get the same benefit from something else that might be better.
"Better" for this means simpler to use, with clear syntax and little
extra effort.
Let those that want strong typing use that - there are cases where it is
a good idea, it works today (with lots of boilerplate and ugly code),
and no one is taking it away.
And for the majority of cases, use a simple system.
Post by Henry MillerPost by David BrownParameter naming is not an alternative to strong types, nor are
strong types an alternative to parameter naming - they are
complements.
Post by Henry MillerWhy not
max(left_t left, right_t right)
This does everything you wanted, plus as a user I can use my own names.
It most certainly does not do what /I/ want.
Post by Henry Millervoid fub() { left_t foo(99); right_t bar(getFuzzSize); max(bar,
foo) ; }
This separates the declarations from the call site, spoiling the
max(right_t(getFussSize), left_t(99));
I figured that was obvious, but it fails to show the power of types
vs parameters: types follow to other contexts in a often useful way
that named parameters do not.
I don't care.
Really, I don't.
What I care about is being able to make a function call in a manner the
same as today, with the /option/ of being able to include the parameter
names in some way as self-documentation for the code and as an extra
check that I have got the order right.
Post by Henry MillerPost by David Brown(Giving the same compile-time error.)
But let us be more realistic. Suppose "max" is in the namespace
"stuff". Types "left_t" and "right_t" are specific to the
function "max" here, and should be in a nested namespace
"max_params" so that they are independent from "left_t" and
stuff::max( stuff::max_params::right_t(getFussSize),
stuff::max_params::left_t(99) );
Should be stuff::right_t.
No, it should not.
"max" is a silly example here, as are "right" and "left".
A better example would be:
guilib::drawbox(int x1, int y1, int x2, int y2);
Are you telling me you think "x1_t", "x2_t", "y1_t" and "y2_t" should
all be types within the "guilib" namespace? Are you telling me that
there should a type within the "guilib" namespace for each of the
parameters for each of the hundred functions in that namespace? Are you
telling me that the "x2_t" type for parameter "x2" in the "drawbox" call
should be the same as the type for parameter "x2" in the "beziercurve"
call where it means a subtly different thing? What about in the
"sheartransform" call in which "x2" is now a floating point type rather
than an integer type?
Post by Henry MillerThat max takes this isn't a factor. The
very name max implies there is a min which should use the same types.
Most likely stuff is a larger name space with lots of functions that
take or return left_t and/or right_t. They are conceptually the same
type and it would make the library hard to use if they were not the
same type all the way through.
You are talking about a different thing entirely.
You are not talking about using strong types for parameter naming - you
are talking about using strong types in programming in general.
Strong types are, of course, a good idea. (The C++ language today makes
it too difficult to make them - it takes too much manual coding. Some
standardised libraries for the purpose would be a good idea, but maybe
it should wait until metaclasses are in place.)
But strong types of the sort you are describing are /not/ an alternative
to named parameters - they are a complement.
So for the "guilib::drawbox" example, it would be better to have type
such as "guilib::pixel_coordinate_t", used for the parameters in
"drawbox". (Perhaps this should be split into horizontal and vertical
types, or combined as a point type - that's a minor detail.)
But that does not help in the slightest to get the parameter order
correct. It helps distinguish between a two-point style "drawbox" and a
point plus height/width style "drawbox". But it does not help avoid
mistakes such as "drawbox(x1, x2, y1, y2)".
To do that using strong types, you need a new strong type for each
parameter. For each parameter, in each function call. This is doable,
but would need the kind of changes I proposed in order to be manageable.
Post by Henry MillerPost by David Brownstuff::max(right: getFussSize, left: 99);
There is simply no contest.
A simple using can bring right_t into the current scope and solve
that. Now we have the same thing as below.
I don't want to have to add "using" clauses for every parameter of every
function call. Such extra code makes the program harder to read, which
is always a bad thing.
But I /do/ want to be able to add parameter names to every parameter of
every function call, if I feel it makes the code clearer or safer.
Post by Henry MillerPost by David BrownIf there is to be a sane use of strong types as a way of
implementing named parameters, we need two things.
First, we need a "function parameter scope" for lookups, so that
within function parameters the identifier lookup starts with a
scope for function. This should also include scopes related to the
parameters (if a function takes an enum parameter, you should be
able to use enum constants of that type directly without giving the
scope details).
stuff::max(right_t(getFussSize), left_t(99));
A proposal to make function call parameters follow different type
resolution rules from the outside scope probably is a good idea.
There are some tricky areas in some of the details that need to be
worked out, but it seems realistic. I'm not thinking about it, but I
see the use.
I am confident that there would be tricky areas - there are /always/
tricky areas :-) But I am also confident that it could make code
simpler to write and simpler to read.
Post by Henry MillerPost by David BrownSecondly, we need syntactic sugar so that when declaring
stuff::max, we don't need to define the parameter types and scopes
manually.
That is the downside to strong types in current c++. They require
something ugly (very subjective, some people are happy with their way
of overcoming the problem some are not)
Yes.
As I mentioned above, I think it might be best to wait until metaclasses
are in place before "solving" this one. I suspect that metaclasses
could be used to give a much neater solution, both from the users'
viewpoint and from the implementers (it would just be a new standard
header or module, rather than changes to the core language), and it
would be a shame to standardise on one method when a better one is
around the corner.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/prbrqm%24p6o%241%40blaine.gmane.org.