Thread overview | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 28, 2012 Private default arguments? | ||||
---|---|---|---|---|
| ||||
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 |
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile Attachments:
| 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. |
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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); |
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | 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
|
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Friday, 28 December 2012 at 14:10:01 UTC, bearophile wrote:
> [SNIP]
> bearophile
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);
}
}
//----
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.
|
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 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
|
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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.
|
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | 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=9229 > I 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 |
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Friday, 28 December 2012 at 15:42:03 UTC, bearophile wrote:
> 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=9229
>
>
>> I 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
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)
|
December 28, 2012 Re: Private default arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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.
|
Copyright © 1999-2021 by the D Language Foundation