January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | >> Please stop explain me how fun3() works. I know that. > > This is first problem. You are being explained what is the *purpose* of the fun3() but you repeatedly fail to accept it. > No odds. >> One of the main idea of D is that things must work as planned, or would not compile at all. > > Outcryingly wrong. Study bugzilla which shows how some things go wrong and read DIPs to learn that there are some issues in the language for which the communitty still struggles to formulate good solution. > Now I am trying to speak ideally. What ideal language should be, not the practical implementation. >> First and second variants follow this idea. But fun3() can work not as planned on the caller side (depends on fun3() body's implementation). > > Many things can work not as intended. Please read forums, bugzilla, etc. I bet passing array will not be the only thing you find confusing. > Again - don't look back. Consider how we can make D better. >> The question again - may be prohibit fun3() variant? > > Prohibiting code like: > void foo(int[] arr) {} > > would break hell of a code and pose doubts on what happens with arrays if so simple construction is prohibited. In addition, I mentioned that "don't care" is probably sometimes an option. Emitting warning here has some merits but it would be consitently ignored (I expect). Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors. |
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Cooler | Cooler:
> Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors.
I think functions like void fun(int[] a){} are bug prone, because you seem to change the length of the array inside the function, or if you perform an append you modify a new memory zone, but such changes are invisible from the caller. Some times this is what you want, and in some cases this is a programmer mistake (this bug happened to me several times).
But I don't know what to change and if this situation can be improved now. Perhaps all that's left to improve is to add tests to a D lint that warns against this possible source of bugs.
Bye,
bearophile
|
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Cooler | On Thursday, 30 January 2014 at 10:49:42 UTC, Cooler wrote: > Now I am trying to speak ideally. What ideal language should be, not the practical implementation. > ... > Again - don't look back. Consider how we can make D better. > ... > Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors. Looks like you are overestimating yourself. Now, try: 1) write pull request to reject the code 2) convince developers somehow that your proposal is good 3) convince Walter to accept the change 4) after merging pull convince angry maintainers that it is good idea to reject unqualified array passing because Cooler tries to make the language better |
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On Thursday, 30 January 2014 at 11:06:03 UTC, Maxim Fomin wrote:
> On Thursday, 30 January 2014 at 10:49:42 UTC, Cooler wrote:
>> Now I am trying to speak ideally. What ideal language should be, not the practical implementation.
>>
> ...
>> Again - don't look back. Consider how we can make D better.
>>
> ...
>> Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors.
>
> Looks like you are overestimating yourself.
>
> Now, try:
> 1) write pull request to reject the code
> 2) convince developers somehow that your proposal is good
> 3) convince Walter to accept the change
> 4) after merging pull convince angry maintainers that it is good idea to reject unqualified array passing because Cooler tries to make the language better
Agree. As a first step I post this topic in the forum. If I found understanding I will follow all steps you mention :)
|
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | >> Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors.
>
> I think functions like void fun(int[] a){} are bug prone, because you seem to change the length of the array inside the function, or if you perform an append you modify a new memory zone, but such changes are invisible from the caller. Some times this is what you want, and in some cases this is a programmer mistake (this bug happened to me several times).
>
> But I don't know what to change and if this situation can be improved now. Perhaps all that's left to improve is to add tests to a D lint that warns against this possible source of bugs.
>
> Bye,
> bearophile
You wrote "this bug happened to me several times" :) This bug also happened with me :)
I know that everybody uses variant of fun(int[] a){} everywhere. I understand that nobody will rewrite it source code. I just want to follow rule "Correct things must be simple. Wrong things must be difficult." As an example we can mark such usage as "deprecated", to push all programmers use more error prone variants.
|
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Cooler | On Wednesday, 29 January 2014 at 14:34:54 UTC, Cooler wrote:
> Here is ambiguity.
> void fun3(int[] x){ x ~= 5; ... }
> auto a = new int[10];
> fun3(a); // Here content of "a" may be changed or may be not changed. Depends on the buffer size that system will allocate for "a" array.
You use very subjective meaning for "ambiguity", one that is never normally used in programming language context. Normally term "ambiguity" is applied only when _compiler_ can't reliably decide meaning of the code snippet and needs to resort to special casing.
You are correct in notion that you can't make any reasonable judgement yourself about content of a after `fun3` call but same applies to `fun2` - it can be or not be modified. It is expected - to express all semantics of function body in function signature one would have needed to make it of comparable length and complexity.
In practice you need always to assume the worst - everything is modified and nothing can be trusted unless explicitly qualified other way around.
|
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Thursday, 30 January 2014 at 12:47:56 UTC, Dicebot wrote: > On Wednesday, 29 January 2014 at 14:34:54 UTC, Cooler wrote: >> Here is ambiguity. >> void fun3(int[] x){ x ~= 5; ... } >> auto a = new int[10]; >> fun3(a); // Here content of "a" may be changed or may be not changed. Depends on the buffer size that system will allocate for "a" array. > > You use very subjective meaning for "ambiguity", one that is never normally used in programming language context. Normally term "ambiguity" is applied only when _compiler_ can't reliably decide meaning of the code snippet and needs to resort to special casing. > > You are correct in notion that you can't make any reasonable judgement yourself about content of a after `fun3` call but same applies to `fun2` - it can be or not be modified. It is expected - to express all semantics of function body in function signature one would have needed to make it of comparable length and complexity. If I use fun2() I expect that fun2() will change the content of my array, and all changes I will see. If I don't want any change to my array, I will use fun1(). What should I want to use fun3()? As many people writes to me in the post - "You may want that fun3() change content of an array, but can't change length of array". I cannot imagine such use case. void fun3(int[] x){ x[0] = 5; x ~= 6; writeln(x); } // What caller will get? auto a = new int[10]; fun3(a); // What I must want here to call fun3(). If I want fun3() will change my array, I should prefer fun2() variant which will guarantee me that I will get all changes. If i just want send array to fun() for it internal use I should prefer fun1(). If I call fun3() the contents of array after the call is not predictable - it can be changed or may not. What must push me to use fun3()? > > In practice you need always to assume the worst - everything is modified and nothing can be trusted unless explicitly qualified other way around. In practice if function declared as fun(in int[] a){} I can be sure that call fun(x) will not change 'x', until the compiler has a bug, or fun() author don't play with c-like pointers. |
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Cooler | kOn Wed, 29 Jan 2014 05:55:56 -0500, Cooler <kulkin@hotbox.ru> wrote: > Consider 3 functions taking array as an argument: > > void fun1(in int[] x){...} > void fun2(ref int[] x){...} > void fun3( int[] x){...} > > auto a = new int[10]; > > fun1(a); // Guaranteed that "a" will not be changed > fun2(a); // Guaranteed that we will see any change to "a", made in fun2() > fun3(a); // Changes to "a" in fun3() may be or may be not visible to the caller > > In case of fun3() we have ambiguous behaviour, depending on the body of the function. > > Am I right? Yes. > Is that intentional? Yes. I read the rest of the discussion. Arrays are hard to understand in D, especially if you have preconceived notions from other languages. But I would point out that fun2 does not "guarantee" anything more than fun3: void fun2(ref int [] x) { fun3(x); } It is an intrinsic property of slices that they do not own the data pointed at. You cannot guarantee that one slice's changes will affect another slice, AS LONG AS one slice is increasing its length. If you avoid increasing the length, then the results are deterministic. As I said in the article, avoid increasing the length, and THEN changing the original data. If you do that, you should have quite predictable results. If your code must do otherwise, explain in the documentation what should happen (i.e. don't use the passed-in slice after the function), and use some of the tricks to avoid it (use ref, or return the new slice data). -Steve |
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 30 January 2014 at 13:44:39 UTC, Steven Schveighoffer wrote: > kOn Wed, 29 Jan 2014 05:55:56 -0500, Cooler <kulkin@hotbox.ru> wrote: > >> Consider 3 functions taking array as an argument: >> >> void fun1(in int[] x){...} >> void fun2(ref int[] x){...} >> void fun3( int[] x){...} >> >> auto a = new int[10]; >> >> fun1(a); // Guaranteed that "a" will not be changed >> fun2(a); // Guaranteed that we will see any change to "a", made in fun2() >> fun3(a); // Changes to "a" in fun3() may be or may be not visible to the caller >> >> In case of fun3() we have ambiguous behaviour, depending on the body of the function. >> >> Am I right? > > Yes. > >> Is that intentional? > > Yes. > > I read the rest of the discussion. Arrays are hard to understand in D, especially if you have preconceived notions from other languages. But I would point out that fun2 does not "guarantee" anything more than fun3: > > void fun2(ref int [] x) > { > fun3(x); > } If I don't want that fun() will change my array, i have to use fun1() variant. If I want fun() will change my array, i have to use fun2() variant. What fun2() do with it's argument inside it's body - not my business. > > It is an intrinsic property of slices that they do not own the data pointed at. You cannot guarantee that one slice's changes will affect another slice, AS LONG AS one slice is increasing its length. If you avoid increasing the length, then the results are deterministic. As I said in the article, avoid increasing the length, and THEN changing the original data. If you do that, you should have quite predictable results. If your code must do otherwise, explain in the documentation what should happen (i.e. don't use the passed-in slice after the function), and use some of the tricks to avoid it (use ref, or return the new slice data). > > -Steve 1. For example somebody already implemented fun1() and fun2() variants, as in my first post. This variants understandable and predictable. What can push me to ask another person for fun3() implementation, while it result is unpredictable, until you know fun3() body? 2. You wrote "If your code must do otherwise, explain in the documentation what should happen". That exactly what I am trying to discuss here. Instead of writing some documentation, just warn (and may be prohibit in far-far future) about such possible unpredictability during compilation. |
January 30, 2014 Re: Array as an argument, ambiguous behaviour. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Cooler | Forgot to mention :)
>> I read the rest of the discussion. Arrays are hard to understand in D, especially if you have preconceived notions from other languages. But I would point out that fun2 does not "guarantee" anything more than fun3:
>>
>> void fun2(ref int [] x)
>> {
>> fun3(x);
>> }
"But I would point out that fun2 does not guarantee anything more than fun3:" - fun2() cannot guarantee anything because it calls fun3() which in turn cannot guarantee anything.
|
Copyright © 1999-2021 by the D Language Foundation