How about "auto" parameters?

Jonathan M Davis jmdavisProg at gmx.com
Wed Jun 8 19:56:49 PDT 2011


On 2011-06-08 19:27, Ary Manzana wrote:
> On 6/8/11 11:56 PM, Jonathan M Davis wrote:
> > On 2011-06-08 02:20, Ary Manzana wrote:
> >> On 6/7/11 9:50 PM, Andrei Alexandrescu wrote:
> >>> On 6/7/11 5:35 AM, Ary Manzana wrote:
> >>>> Well, in Ruby every parameter type is auto. And it works pretty well.
> >>>> 
> >>>> :-)
> >>>> 
> >>>> When you invoke a method and something goes wrong, like the auto
> >>>> parameter doesn't have a method, it gives a sensible error message.
> >>> 
> >>> It does, just at run time. The way dynamic languages and static
> >>> languages set up computation is very different and as such difficult to
> >>> compare something as core as function call resolution as equals for
> >>> equals.
> >>> 
> >>>> So:
> >>>> 
> >>>> void foo(auto parameter) {
> >>>> return parameter * 2;
> >>>> }
> >>>> 
> >>>> could just be the same as
> >>>> 
> >>>> void foo(T)(T parameter) {
> >>>> return parameter * 2;
> >>>> }
> >>>> 
> >>>> just with a nicer syntax (but I understand it doesn't add much).
> >>> 
> >>> The counterpoint is that you seldom want to write foo() as written
> >>> above. You want to clarify what family of types it is intended for.
> >> 
> >> Why? Note that in Ruby you *NEVER* say the family of types, and that is
> >> a huge bennefit. Good tests and good documentation are better than
> >> restricting the time. Look at this:
> >> 
> >> ======================================================
> >> import std.stdio;
> >> 
> >> // This is Ruby :-)
> >> auto foo(T)(T param) {
> >> return param * 2;
> >> }
> >> 
> >> class MyClass {
> >> int value;
> >> 
> >> this(int value) {
> >> this.value = value;
> >> }
> >> 
> >> int opBinary(string op)(int other) if (op == "*") {
> >> return value * other;
> >> }
> >> }
> >> 
> >> int main() {
> >> auto x = foo(3);
> >> auto y = foo(6L);
> >> auto z = foo(new MyClass(10));
> >> 
> >> writefln("%s", x);
> >> writefln("%s", y);
> >> writefln("%s", z);
> >> return 0;
> >> }
> >> ======================================================
> >> 
> >> This function:
> >> 
> >> auto foo(T)(T param) {
> >> return param * 2;
> >> }
> >> 
> >> Could be just as well:
> >> 
> >> auto foo(auto param) {
> >> return param * 2;
> >> }
> >> 
> >> Yes, in Ruby it is checked on runtime, on D it is checked on
> >> compile-time.
> >> 
> >> What's cool about "auto param"? I have written a function once and it
> >> will work for everything that can be multiplied and it will be compiled
> >> efficiently for every type that I pass that complies to the function.
> >> Why you find it useless? Why do I have to restrict the type? I can
> >> restrict the type just for the operations being performed on it and then
> >> my function is open to any param that accepts those operations.
> >> 
> >> I know, I know. This is the same as just a template, but with a
> >> different syntax. I just don't understand why you think you will almost
> >> always would like to restrict the type you pass to the function. If you
> >> do, you limit your code. If you don't, you open your code and you have
> >> to write less code.
> > 
> > You want to restrict it for several reasons, including the fact that if
> > you don't, you get hideous error messages when you use a type with a
> > template that it doesn't work with.
> 
> That's not the reason I shouldn't be using it. The compiler should give
> precise error messages.
> 
> For instance, first I wrote this code:
> 
> void foo(T)(T param) {
>    return param * 2;
> }
> 
> I got these messages back:
> 
> main.d(4): Error: * has no effect in expression (param * 2)
> main.d(20): Error: template instance main.foo!(int) error instantiating
> main.d(20): Error: variable main.main.x voids have no value
> main.d(20): Error: expression foo(3) is void and has no value
> 
> Umm... can't it just tell me "foo's return type is void and you are
> trying to return an int"?

There are definitely things that can be done to improve error messages, but 
providing good error messages for templates is notoriously hard. C++ has been 
at it for years, and its error messages are still pretty awful regardless of 
the compiler you're using. Remember that when you're dealing with templates, 
you're compiling generated code, which complicates things a fair bit. If it 
gives you error messages like it does if you had written the code by hand 
(which is what it frequently ends up doing, if not always), then the messages 
tend to be incredibly obtuse, because you may not have written the code which 
is failing, and there's a good chance that error message means nothing to you. 
And if it doesn't treat the templates as normal code when dealing with errors, 
then that complicates template compilation a fair bit, because you have to 
duplicate all kinds of error checking and error reporting stuff. And how does 
the compiler know whether it's an error in the template itself or if it's an 
error simply because you gave it a template argument which just doesn't work 
with that template?

I don't think that there's any question that template error messages could be 
improved, and they likely will be, but by their very nature, reporting 
template-related errors seems to be a difficult task to adequately solve. It's 
one of the things that many people complain about with C++. Template 
constraints improve the situation considerably.

- Jonathan M Davis


More information about the Digitalmars-d mailing list