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