Thread overview
Functions in default args
Nov 08, 2001
Russ Lewis
Nov 08, 2001
Walter
Nov 09, 2001
Roland
Nov 09, 2001
Roland
Nov 08, 2001
Sean L. Palmer
Nov 08, 2001
Walter
Nov 09, 2001
a
November 08, 2001
What is/will be the D standard for how function calls as default arguments?  Will the function be evaluated once, then saved, or re-called each time, or what?

I tried this on gcc, and got some very weird results:



SOURCE:
#include <stdio.h>

class X
{
public:
   X() { printf("X::X %p\n",this); };
  ~X() { printf("X::~X %p\n",this); };
};
class FOO
{
public:
  FOO(X *ptr = new X) { printf("FOO::FOO(%p) %p\n",ptr,this); };
  ~FOO() { printf("FOO::~FOO %p\n",this); };
};

int main()
{
  FOO a;
  FOO b;
  X   c;
  FOO d(&c);

  return 0;
};



OUTPUT (compiled by gcc):
X::X 0x8049c08
FOO::FOO(0x8049c08) 0xbffffc17
X::X 0x8049c08
FOO::FOO(0x8049c08) 0xbffffc16
X::X 0xbffffc15
FOO::FOO(0xbffffc15) 0xbffffc14
FOO::~FOO 0xbffffc14
X::~X 0xbffffc15
FOO::~FOO 0xbffffc16
FOO::~FOO 0xbffffc17

That is *really* bad.  That's why I don't use function in default arguments in C++.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


November 08, 2001
Default arguments are not allowed in D. To achieve the same effect as C++:

    void foo(int i, int j = 3);

in D:

    void foo(int i, int j);
    void foo(int i) { foo(i, 3); }

Inlining and optimization will produce the same code, without the ambiguities and surprising behavior (as you discovered) of C++.


"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3BE9DF39.D513D6BE@deming-os.org...
> What is/will be the D standard for how function calls as default arguments?  Will the function be evaluated once, then saved, or re-called each time, or what?
>
> I tried this on gcc, and got some very weird results:
>
>
>
> SOURCE:
> #include <stdio.h>
>
> class X
> {
> public:
>    X() { printf("X::X %p\n",this); };
>   ~X() { printf("X::~X %p\n",this); };
> };
> class FOO
> {
> public:
>   FOO(X *ptr = new X) { printf("FOO::FOO(%p) %p\n",ptr,this); };
>   ~FOO() { printf("FOO::~FOO %p\n",this); };
> };
>
> int main()
> {
>   FOO a;
>   FOO b;
>   X   c;
>   FOO d(&c);
>
>   return 0;
> };
>
>
>
> OUTPUT (compiled by gcc):
> X::X 0x8049c08
> FOO::FOO(0x8049c08) 0xbffffc17
> X::X 0x8049c08
> FOO::FOO(0x8049c08) 0xbffffc16
> X::X 0xbffffc15
> FOO::FOO(0xbffffc15) 0xbffffc14
> FOO::~FOO 0xbffffc14
> X::~X 0xbffffc15
> FOO::~FOO 0xbffffc16
> FOO::~FOO 0xbffffc17
>
> That is *really* bad.  That's why I don't use function in default arguments in C++.
>
> --
> The Villagers are Online! villagersonline.com
>
> .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> .[ (a version.of(English).(precise.more)) is(possible) ]
> ?[ you want.to(help(develop(it))) ]
>
>


November 08, 2001
"Walter" <walter@digitalmars.com> wrote in message news:9sdc1v$2167$2@digitaldaemon.com...
> Default arguments are not allowed in D. To achieve the same effect as C++:

Why? =(

> Inlining and optimization will produce the same code, without the ambiguities and surprising behavior (as you discovered) of C++.

Um... why not restrict default arguments to be compile-time constants
only? This would resolve any "surprising behaviour" unclearance.
As for ambiguity... that's something that we have to live with if
we use function overloading, optional arguments don't actually add
much to it, but they can be so damn useful. Yes, they can be emulated
by overloading, as you've stated, but why not throw a bit of
(syntactic) sugar in?


November 08, 2001
I'm with Pavel... I can understand limiting default arguments to compile-time constant expressions only, but are you sure you want to replace the default syntax by a requirement that the programmer make 'n' copies of the function which all forward to the one with the most parameters (maintenance headache) or forward to the one with one more parameter (the optimizer will have to do more work), where 'n' is the number of default parameters?  If you were maintaining a piece of code, and you came across one of these, which would you rather it look like:?

class A
{
  this(int a=0, int b=1, int c=2, int d=3) { PaintByNumbers(a,b,c,d); }
}

or this:

class B
{
  this() { this(0,1,2,3); }
  this(int a) { this(a,1,2,3); }
  this(int a, int b) { this(a,b,2,3); }
  this(int a, int b, int c) { this(a,b,c,3); }
  this(int a, int b, int c, int d) { PaintByNumbers(a,b,c,d); }
}

I'm sure you can extrapolate out a bit based on past experiences.  ;)

Surely any ambiguities with conflicting signatures can be resolved.  This is one feature C++ has I don't get troubled by often.  It sure is convenient though... extra convenient since in C++ you could only have the defaults in the function declaration, not the definition, and D merges those two things.

Sean

"Walter" <walter@digitalmars.com> wrote in message news:9sdc1v$2167$2@digitaldaemon.com...
> Default arguments are not allowed in D. To achieve the same effect as C++:
>
>     void foo(int i, int j = 3);
>
> in D:
>
>     void foo(int i, int j);
>     void foo(int i) { foo(i, 3); }
>
> Inlining and optimization will produce the same code, without the ambiguities and surprising behavior (as you discovered) of C++.
>
>
> "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3BE9DF39.D513D6BE@deming-os.org...
> > What is/will be the D standard for how function calls as default arguments?  Will the function be evaluated once, then saved, or re-called each time, or what?
> >
> > I tried this on gcc, and got some very weird results:
> >
> >
> >
> > SOURCE:
> > #include <stdio.h>
> >
> > class X
> > {
> > public:
> >    X() { printf("X::X %p\n",this); };
> >   ~X() { printf("X::~X %p\n",this); };
> > };
> > class FOO
> > {
> > public:
> >   FOO(X *ptr = new X) { printf("FOO::FOO(%p) %p\n",ptr,this); };
> >   ~FOO() { printf("FOO::~FOO %p\n",this); };
> > };
> >
> > int main()
> > {
> >   FOO a;
> >   FOO b;
> >   X   c;
> >   FOO d(&c);
> >
> >   return 0;
> > };
> >
> >
> >
> > OUTPUT (compiled by gcc):
> > X::X 0x8049c08
> > FOO::FOO(0x8049c08) 0xbffffc17
> > X::X 0x8049c08
> > FOO::FOO(0x8049c08) 0xbffffc16
> > X::X 0xbffffc15
> > FOO::FOO(0xbffffc15) 0xbffffc14
> > FOO::~FOO 0xbffffc14
> > X::~X 0xbffffc15
> > FOO::~FOO 0xbffffc16
> > FOO::~FOO 0xbffffc17
> >
> > That is *really* bad.  That's why I don't use function in default arguments in C++.
> >
> > --
> > The Villagers are Online! villagersonline.com
> >
> > .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> > .[ (a version.of(English).(precise.more)) is(possible) ]
> > ?[ you want.to(help(develop(it))) ]
> >
> >
>
>


November 08, 2001
There's also the issue of what do you do with the default argument when the function is overridden in a derived class. I'd rather just avoid the complexity and the special rules. I don't like looking at the function call, and then having to look at the derived class to see what the function does, and then look at the base class to see what the arguments are, ...

I admit it's a matter of personal taste.

"Sean L. Palmer" <spalmer@iname.com> wrote in message news:9sdoi0$2app$1@digitaldaemon.com...
> I'm with Pavel... I can understand limiting default arguments to compile-time constant expressions only, but are you sure you want to
replace
> the default syntax by a requirement that the programmer make 'n' copies of the function which all forward to the one with the most parameters (maintenance headache) or forward to the one with one more parameter (the optimizer will have to do more work), where 'n' is the number of default parameters?  If you were maintaining a piece of code, and you came across one of these, which would you rather it look like:?
>
> class A
> {
>   this(int a=0, int b=1, int c=2, int d=3) { PaintByNumbers(a,b,c,d); }
> }
>
> or this:
>
> class B
> {
>   this() { this(0,1,2,3); }
>   this(int a) { this(a,1,2,3); }
>   this(int a, int b) { this(a,b,2,3); }
>   this(int a, int b, int c) { this(a,b,c,3); }
>   this(int a, int b, int c, int d) { PaintByNumbers(a,b,c,d); }
> }
>
> I'm sure you can extrapolate out a bit based on past experiences.  ;)
>
> Surely any ambiguities with conflicting signatures can be resolved.  This
is
> one feature C++ has I don't get troubled by often.  It sure is convenient though... extra convenient since in C++ you could only have the defaults
in
> the function declaration, not the definition, and D merges those two
things.
>
> Sean
>
> "Walter" <walter@digitalmars.com> wrote in message news:9sdc1v$2167$2@digitaldaemon.com...
> > Default arguments are not allowed in D. To achieve the same effect as
C++:
> >
> >     void foo(int i, int j = 3);
> >
> > in D:
> >
> >     void foo(int i, int j);
> >     void foo(int i) { foo(i, 3); }
> >
> > Inlining and optimization will produce the same code, without the ambiguities and surprising behavior (as you discovered) of C++.
> >
> >
> > "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3BE9DF39.D513D6BE@deming-os.org...
> > > What is/will be the D standard for how function calls as default arguments?  Will the function be evaluated once, then saved, or re-called each time, or what?
> > >
> > > I tried this on gcc, and got some very weird results:
> > >
> > >
> > >
> > > SOURCE:
> > > #include <stdio.h>
> > >
> > > class X
> > > {
> > > public:
> > >    X() { printf("X::X %p\n",this); };
> > >   ~X() { printf("X::~X %p\n",this); };
> > > };
> > > class FOO
> > > {
> > > public:
> > >   FOO(X *ptr = new X) { printf("FOO::FOO(%p) %p\n",ptr,this); };
> > >   ~FOO() { printf("FOO::~FOO %p\n",this); };
> > > };
> > >
> > > int main()
> > > {
> > >   FOO a;
> > >   FOO b;
> > >   X   c;
> > >   FOO d(&c);
> > >
> > >   return 0;
> > > };
> > >
> > >
> > >
> > > OUTPUT (compiled by gcc):
> > > X::X 0x8049c08
> > > FOO::FOO(0x8049c08) 0xbffffc17
> > > X::X 0x8049c08
> > > FOO::FOO(0x8049c08) 0xbffffc16
> > > X::X 0xbffffc15
> > > FOO::FOO(0xbffffc15) 0xbffffc14
> > > FOO::~FOO 0xbffffc14
> > > X::~X 0xbffffc15
> > > FOO::~FOO 0xbffffc16
> > > FOO::~FOO 0xbffffc17
> > >
> > > That is *really* bad.  That's why I don't use function in default arguments in C++.
> > >
> > > --
> > > The Villagers are Online! villagersonline.com
> > >
> > > .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> > > .[ (a version.of(English).(precise.more)) is(possible) ]
> > > ?[ you want.to(help(develop(it))) ]
> > >
> > >
> >
> >
>
>


November 09, 2001
Walter wrote:
> 
> There's also the issue of what do you do with the default argument when the function is overridden in a derived class. I'd rather just avoid the complexity and the special rules. I don't like looking at the function call, and then having to look at the derived class to see what the function does, and then look at the base class to see what the arguments are, ...
> 
> I admit it's a matter of personal taste.

Given that, you have to be aware that it will almost certainly be an
'extension' in the first open source compiler anyway.
	As far as not wanting to look at the derived class, if a person is
already going to need specialized tools and editors to extract a
stripped down/opaque interface for a class (no header files) then the
same tools can be made to determine which version of the function is
being called.  Granted I hate when a language requires the use of
specialized editors or IDE, but other decisions have already been made
make it necessary to use such beasts with D.  Put this feature in that
category.  We all like to program in a word processor anyway, right?

Dan
November 09, 2001
Default argument can be put in the same categorie as operator overloading: the
"sugar" categorie.
Personaly, i don't know how i can live without operator overloading sugar.
But the more i get experienced, the less i use default argument sugar, never for
new code.
I think default argument is a good way to make mistake: you forget an argument
and the compiler
put one that is not good.

Roland


Pavel \"EvilOne\" Minayev a écrit :

> "Walter" <walter@digitalmars.com> wrote in message news:9sdc1v$2167$2@digitaldaemon.com...
> > Default arguments are not allowed in D. To achieve the same effect as C++:
>
> Why? =(
>
> > Inlining and optimization will produce the same code, without the ambiguities and surprising behavior (as you discovered) of C++.
>
> Um... why not restrict default arguments to be compile-time constants
> only? This would resolve any "surprising behaviour" unclearance.
> As for ambiguity... that's something that we have to live with if
> we use function overloading, optional arguments don't actually add
> much to it, but they can be so damn useful. Yes, they can be emulated
> by overloading, as you've stated, but why not throw a bit of
> (syntactic) sugar in?

November 09, 2001
"Roland" <rv@ronetech.com> wrote in message news:3BEBD5A0.B7D7D9DF@ronetech.com...

> Default argument can be put in the same categorie as operator overloading:
the
> "sugar" categorie.
> Personaly, i don't know how i can live without operator overloading sugar.
> But the more i get experienced, the less i use default argument sugar,
never for
> new code.
> I think default argument is a good way to make mistake: you forget an
argument
> and the compiler
> put one that is not good.

If it is an issue, why use default arguments in your programs at all? Sometimes, however, they can be useful. Imagine a File class which has Seek method, similar to fseek():

    function Seek(int offset, int whence = SEEK_SET);

Now when you simply want to move to some position in file (which is 90% of all uses), you use a simple and logical Seek(123) syntax. In other words, a generic rule for optional arguments, "use them only when the default behaviour is absolutely clear" - like in case with Seek(). Of course, using this feature improperly may result in poor reliability and readability, but the same problem is with function overloading, heck, even OOP!


November 09, 2001

Pavel \"EvilOne\" Minayev a écrit :

>
> If it is an issue, why use default arguments in your programs at all? Sometimes, however, they can be useful. Imagine a File class which has Seek method, similar to fseek():
>
>     function Seek(int offset, int whence = SEEK_SET);
>
> Now when you simply want to move to some position in file (which is 90% of all uses), you use a simple and logical Seek(123) syntax. In other words, a generic rule for optional arguments, "use them only when the default behaviour is absolutely clear" - like in case with Seek(). Of course, using this feature improperly may result in poor reliability and readability, but the same problem is with function overloading, heck, even OOP!

In fact i agree with you.
But one issue of D is to force programmer to make standardized code,
understandable, easy to maintant.
One ultimate goal as far as i understand is: one thing to do, only one way to
write the code.
So it is a question of balance. If compiler is too restrictive, few will use it
or people will create preprocessor for
it. If it is too flexible, why not keep C++ ?

The ideal would be: "if default argument behaviour is absolutely clear" then
compile else throw a compiler error.
A lot of work for Walter..

Roland



November 10, 2001
"Roland" <rv@ronetech.com> wrote in message news:3BEC408C.839137B3@ronetech.com...

> The ideal would be: "if default argument behaviour is absolutely clear"
then
> compile else throw a compiler error.
> A lot of work for Walter..

Yeah, writing an AI system to determine the expected default behaviour from function names =)