www.digitalmars.com         C & C++   DMDScript  

D - Functions in default args

reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
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))) ]
Nov 07 2001
parent reply "Walter" <walter digitalmars.com> writes:
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))) ]

Nov 08 2001
next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"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?
Nov 08 2001
parent reply Roland <rv ronetech.com> writes:
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?

Nov 09 2001
parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Roland" <rv ronetech.com> wrote in message
news:3BEBD5A0.B7D7D9DF ronetech.com...

 Default argument can be put in the same categorie as operator overloading:

 "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,

 new code.
 I think default argument is a good way to make mistake: you forget an

 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!
Nov 09 2001
parent reply Roland <rv ronetech.com> writes:
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
Nov 09 2001
parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Roland" <rv ronetech.com> wrote in message
news:3BEC408C.839137B3 ronetech.com...

 The ideal would be: "if default argument behaviour is absolutely clear"

 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 =)
Nov 09 2001
prev sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
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))) ]


Nov 08 2001
parent reply "Walter" <walter digitalmars.com> writes:
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

 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

 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

 the function declaration, not the definition, and D merges those two

 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


     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))) ]



Nov 08 2001
parent a <a b.c> writes:
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
Nov 08 2001