digitalmars.D - Private default arguments?
- bearophile (58/58) Dec 28 2012 Often recursive functions need some "bookkeeping" default
- Gor Gyolchanyan (6/63) Dec 28 2012 I like the idea. I really don't like having the overhead of inner functi...
- Nick Treleaven (16/28) Dec 28 2012 I think the feature is more useful/flexible if private still means
- bearophile (6/9) Dec 28 2012 I see, and I understand. I find it a little funny that I suggest
- monarch_dodra (22/24) Dec 28 2012 What's wrong with:
- bearophile (7/22) Dec 28 2012 That's what I do in languages that don't allow nested functions,
- Maxim Fomin (40/43) Dec 28 2012 What happens when function with private argument is stored in a
- bearophile (14/20) Dec 28 2012 You have to supply all arguments. I've written this in the
- Maxim Fomin (7/27) Dec 28 2012 I see. Another ideas how to use it:
- Peter Alexander (2/7) Dec 28 2012 I don't think it is, given how easy it is to work around.
- Jonathan M Davis (6/15) Dec 28 2012 Agreed. All you need to do is create an inner function which holds the
- bearophile (9/10) Dec 28 2012 It's not a necessary feature, but it helps make the code more
- Jonathan M Davis (8/17) Dec 29 2012 AFAIK, not even functional languages where recursion is what you always ...
- bearophile (9/14) Dec 30 2012 The little enhancement request discussed here requires default
- F i L (1/1) Dec 28 2012 Good idea, but honestly what we really need is a "static foreach"
- bearophile (6/8) Dec 28 2012 I opened this time ago, but this is another topic, and it's
Often recursive functions need some "bookkeeping" default arguments that aren't meant to be used by the user, they are meant to be used only by recursive calls: void radixSort(uint[] items, in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } } void main() { auto array = new uint[n]; ... array.radixSort(); } So this call is a bug: void main() { ... array.radixSort(26); } To avoid bugs and to not expose such private arguments I sometimes define an inner function (or a private function in a struct/class). Now the only argument of the outer function is 'items', and no mistakes can happen using radixSort2(): void radixSort2(uint[] items) { void radix(in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } } radix(); } This has some disadvantages. An alternative idea (that I maybe I proposed years ago in a weaker form) is to introduce 'private' default arguments (they must have a default value): void radixSort3(uint[] items, private in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } } The 'private' means that only radixSort3 is allowed to set a shiftBits argument value. So this is reported as compilation error: void main() { ... array.radixSort(26); } A more detailed proposal, almost a DEP: http://d.puremagic.com/issues/show_bug.cgi?id=9229 Is this little feature worth the amount of language complexity increase it causes? Bye, bearophile
Dec 28 2012
I like the idea. I really don't like having the overhead of inner functions just for compile-time enforcement. On Fri, Dec 28, 2012 at 2:58 PM, bearophile <bearophileHUGS lycos.com>wrote:Often recursive functions need some "bookkeeping" default arguments that aren't meant to be used by the user, they are meant to be used only by recursive calls: void radixSort(uint[] items, in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } } void main() { auto array = new uint[n]; ... array.radixSort(); } So this call is a bug: void main() { ... array.radixSort(26); } To avoid bugs and to not expose such private arguments I sometimes define an inner function (or a private function in a struct/class). Now the only argument of the outer function is 'items', and no mistakes can happen using radixSort2(): void radixSort2(uint[] items) { void radix(in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } } radix(); } This has some disadvantages. An alternative idea (that I maybe I proposed years ago in a weaker form) is to introduce 'private' default arguments (they must have a default value): void radixSort3(uint[] items, private in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } } The 'private' means that only radixSort3 is allowed to set a shiftBits argument value. So this is reported as compilation error: void main() { ... array.radixSort(26); } A more detailed proposal, almost a DEP: http://d.puremagic.com/issues/**show_bug.cgi?id=9229<http://d.puremagic.com/issues/show_bug.cgi?id=9229> Is this little feature worth the amount of language complexity increase it causes? Bye, bearophile-- Bye, Gor Gyolchanyan.
Dec 28 2012
On 28/12/2012 10:58, bearophile wrote:An alternative idea (that I maybe I proposed years ago in a weaker form) is to introduce 'private' default arguments (they must have a default value): void radixSort3(uint[] items, private in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSort(array[...], shiftBits - 8); } }I like the idea, it's intuitive.The 'private' means that only radixSort3 is allowed to set a shiftBits argument value.I think the feature is more useful/flexible if private still means module visibility. I realize you would lose the benefit when using radixSort3 from the same module, but then the feature has more potential applications. (Ideally D would have both module-private and local-private qualifiers, but that's another topic). The feature might be useful for things like logging: void log(T...)(T args, private string file = __FILE__, private size_t line = __LINE__); That could allow the compiler to distinguish variadic arguments from non-overridable default arguments (for calls outside private scope). It's also nice to prevent the user accidentally overriding file and line. To allow wrapping log(), another function can be provided, without any default arguments: void logWrapped(string s, string file, size_t line);
Dec 28 2012
Nick Treleaven:The feature might be useful for things like logging: void log(T...)(T args, private string file = __FILE__, private size_t line = __LINE__);I see, and I understand. I find it a little funny that I suggest a feature for recursive functions, and the first proposal for alternative usage is for logging :o) Bye, bearophile
Dec 28 2012
On Friday, 28 December 2012 at 14:10:01 UTC, bearophile wrote:[SNIP] bearophileWhat's wrong with: //---- void radixSort(uint[] items) { radixSortRecurse(items); } private void radixSortRecurse(uint[] items, in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSortRecurse(array[...], shiftBits - 8); } } //---- I know I never write recursive functions with a public entry point anyways: You *always* end up with "test only the first time" or "countdown the number of iterations" or some other problem that will force you onto this scheme sooner or later anyways. As mentioned, this also allows module level sharing.
Dec 28 2012
monarch_dodra:What's wrong with: //---- void radixSort(uint[] items) { radixSortRecurse(items); } private void radixSortRecurse(uint[] items, in uint shiftBits=24) { ... if (shiftBits > 0) { ... radixSortRecurse(array[...], shiftBits - 8); } }That's what I do in languages that don't allow nested functions, like ANSI C, etc. It's very similar to defining a static inner function in D. You end with two functions, two names, more code, etc. Bye, bearophile
Dec 28 2012
On Friday, 28 December 2012 at 10:58:59 UTC, bearophile wrote:Often recursive functions need some "bookkeeping" default arguments that aren't meant to be used by the user, they are meant to be used only by recursive calls:What happens when function with private argument is stored in a function pointer? Currently (2.061 beta) if you do so with a function with default argument, you have to supply all default arguments (it seems that some information is lost when making function pointer from function). So, declaring some default argument as private makes function pointer useless: on the one hand, you have to supply all arguments when calling from pointer, on the other hand it is forbidden to supply default private arguments. I don't like a name for this feature because it breaks logic that private is accessible within module. Perhaps a new name? I also against some simple and dummy constraints (like one-path-constructor call restriction) which can be easily avoided and does not really prevent from making mistakes. class A { this(int i) { } this() { int x; // it is rejected // Error: one path skips constructor // Error: return without calling constructor // if (x) // this(1); if (x) // it works __ctor(1); } } void main() { A a = new A; } I think your private argument constraint can be as easily broken: D is a system language and there is no way to prevent it from calling arbitrary code. IMHO it does make sense to apply restrictions which prevent from doing danger things - this reduces space for mistakes, but constraints like you propose and above are not that serious as others.
Dec 28 2012
Maxim Fomin:What happens when function with private argument is stored in a function pointer?You have to supply all arguments. I've written this in the detailed proposal: http://d.puremagic.com/issues/show_bug.cgi?id=9229I don't like a name for this feature because it breaks logic that private is accessible within module. Perhaps a new name?I understand. I think proposing a new keyword, or a keyword, in infeasible, because all this stuff not important enough :-(I think your private argument constraint can be as easily broken:I am not concerned by ways to force the usage of those private arguments (like taking the address and using it to call the function). It's like the yellow-black plastic strips you see around. They are there to tell you to not go forward, for a real danger or a legal danger, but they don't actually stop you. Thank you, bye, bearophile
Dec 28 2012
On Friday, 28 December 2012 at 15:42:03 UTC, bearophile wrote:Maxim Fomin:I see. Another ideas how to use it: void radixSort3(uint[] items, private in uint shiftBits=24) // original void radixSort3(uint[] items, uint shiftBits is 24) void radixSort3(uint[] items, uint shiftBits=24 const) void radixSort3(uint[] items, static uint shiftBits=24)What happens when function with private argument is stored in a function pointer?You have to supply all arguments. I've written this in the detailed proposal: http://d.puremagic.com/issues/show_bug.cgi?id=9229I don't like a name for this feature because it breaks logic that private is accessible within module. Perhaps a new name?I understand. I think proposing a new keyword, or a keyword, in infeasible, because all this stuff not important enough :-(I think your private argument constraint can be as easily broken:I am not concerned by ways to force the usage of those private arguments (like taking the address and using it to call the function). It's like the yellow-black plastic strips you see around. They are there to tell you to not go forward, for a real danger or a legal danger, but they don't actually stop you. Thank you, bye, bearophile
Dec 28 2012
On Friday, 28 December 2012 at 10:58:59 UTC, bearophile wrote:An alternative idea (that I maybe I proposed years ago in a weaker form) is to introduce 'private' default arguments (they must have a default value): Is this little feature worth the amount of language complexity increase it causes?I don't think it is, given how easy it is to work around.
Dec 28 2012
On Friday, December 28, 2012 19:17:45 Peter Alexander wrote:On Friday, 28 December 2012 at 10:58:59 UTC, bearophile wrote:Agreed. All you need to do is create an inner function which holds the majority of the function's body or a private function which does the same (and it can even have exactly the same if you want it to avoiding the need to come up with another name). I really think that this is a non-issue. - Jonathan M DavisAn alternative idea (that I maybe I proposed years ago in a weaker form) is to introduce 'private' default arguments (they must have a default value): Is this little feature worth the amount of language complexity increase it causes?I don't think it is, given how easy it is to work around.
Dec 28 2012
Jonathan M Davis:I really think that this is a non-issue.It's not a necessary feature, but it helps make the code more readable, shorter, keeping it safe. I write several recursive functions, and I'd like a way to refer to the function inside the function without using its real name, something like self(), or even __function(). Private default arguments help further the use of recursion. Bye, bearophile
Dec 28 2012
On Saturday, December 29, 2012 07:01:42 bearophile wrote:Jonathan M Davis:AFAIK, not even functional languages where recursion is what you always do have anything like what you're suggesting. I really don't see it as any real cost to do recursion use the function's name. So, feel free to bring it up as a feature that you'd like, but I really think that it's trying to solve something that really isn't a problem in the first place. And this is coming from someone who used to program in haskell quite a bit. - Jonathan M DavisI really think that this is a non-issue.It's not a necessary feature, but it helps make the code more readable, shorter, keeping it safe. I write several recursive functions, and I'd like a way to refer to the function inside the function without using its real name, something like self(), or even __function(). Private default arguments help further the use of recursion.
Dec 29 2012
Jonathan M Davis:AFAIK, not even functional languages where recursion is what you always do have anything like what you're suggesting. ... And this is coming from someone who used to program in haskell quite a bit.The little enhancement request discussed here requires default arguments. Function languages like Haskell don't have default arguments (despite there are some ways to have them http://neilmitchell.blogspot.it/2008/04/optional-parameters-in-haskell.html ), so you can't compare well the two situations. Bye, bearophile
Dec 30 2012
Good idea, but honestly what we really need is a "static foreach"
Dec 28 2012
F i L:Good idea, but honestly what we really need is a "static foreach"I opened this time ago, but this is another topic, and it's better to keep threads separate: http://d.puremagic.com/issues/show_bug.cgi?id=4085 Bye, bearophile
Dec 28 2012