Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 09:14:43 UTC, Cooler wrote: Please stop explain me how fun3() works. I know that. One of the main idea of D is that things must work as planned, or would not compile at all. First and second variants follow this idea. But fun3() can work not as planned on the caller side (depends on fun3() body's implementation). The question again - may be prohibit fun3() variant? If we prohibit it, what use cases we could not implement with fun1() and fun2()? Goodness... You've been shown this use case like a zillion times already: the caller manages her buffer, fun3() is allowed to change contents, but not reallocate caller's buffer. fun1() can't provide that (const), fun2() cannot either, because it explicitly allows reallocation (ref). This behavior is only provided by fun3(). So it's either that, or indeed cases of I don't care about this array, which Maxim Fomin has mentioned.
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 09:14:43 UTC, Cooler wrote: If you want to modify the slice and make changes visible in caller, you should use ref. If you don't care whether changes are visible in caller, you can omit any attributes and use plain array. This belongs to the case you are asking about. If you don't want to change array in callee, pass it as const qualified. Now, after rethinking the issue I am inclining that don't care whether changes are visible for caller is not very wrong, but not very good design. Ideally it should be specified to avoid unexpected problems to pop up. So yes, it is better to qualify array. Another point. This casino games of whether changes would be visible or not is direct consequence of how slices are implemented (and how runtime service them). Remember, that many features in D work in a strange way not because of wise design but as a consequence of not fully thought design (like array). As a result, some features work in not best way they should. Although many folks in newsgroups would eagerly say that you don't understand the lang, it wouldn't make a bad design a good one. 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. 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. 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. 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).
Re: Array as an argument, ambiguous behaviour.
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
Re: Array as an argument, ambiguous behaviour.
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
Re: Array as an argument, ambiguous behaviour.
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.
Re: Array as an argument, ambiguous behaviour.
kOn Wed, 29 Jan 2014 05:55:56 -0500, Cooler kul...@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
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 09:18:40 -0500, Cooler kul...@hotbox.ru wrote: 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. Right, but you said this: fun2(a); // Guaranteed that we will see any change to a, made in fun2() Which is false. That was my point. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 09:07:14 -0500, Cooler kul...@hotbox.ru wrote: 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. No. You can use fun3 variant as well: void fun3(int[] x) { x[] = 0; // guaranteed to be seen by caller. } 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? The only reason to have both fun2 and fun3 variants is if you want to handle both l-value and r-value options differently. There would be very few use cases which make sense AND return void. You usually want one or the other. 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. No, because you are not understanding the effect of the attributes, and who is responsible for what. 1. Banning such signatures does NOT accomplish what you want. 2. Such signatures do NOT guarantee what happens inside the function. Having the compiler ban the problem where you expect the caller to see your changes, but they don't, is akin to just making the compiler able to detect all logic bugs. It's not possible (NP complete). The compiler just doesn't know what you really want to do. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 10:24:14 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 14:40:36 UTC, Dicebot wrote: On Thursday, 30 January 2014 at 13:42:53 UTC, Cooler wrote: 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()? For changes to content of array but not array itself. I agree. I just want that the case can be expressed in language syntax more obvious - something like fun(int[] const x){} to emphasize that I understand that fun() can change content of array, and cannot change the {pointer,size} pair. That's what fun(int[] x) does :) -Steve
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 15:49:35 UTC, Cooler wrote: I agree. I just want that the case can be expressed in language syntax more obvious - something like fun(int[] const x){} to emphasize that I understand that fun() can change content of array, and cannot change the {pointer,size} pair. That's what fun(int[] x) does :) -Steve Again... void fun(int[] x){ x ~= 5; } auto a = new int[10]; fun(a); // Can you predict the content of 'a'? It's [0, 0, 0, 0, 0, 0, 0, 0, 0, 0].
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 10:49:34 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 15:29:50 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 10:24:14 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 14:40:36 UTC, Dicebot wrote: I agree. I just want that the case can be expressed in language syntax more obvious - something like fun(int[] const x){} to emphasize that I understand that fun() can change content of array, and cannot change the {pointer,size} pair. That's what fun(int[] x) does :) -Steve Again... void fun(int[] x){ x ~= 5; } auto a = new int[10]; fun(a); // Can you predict the content of 'a'? I suspect you mean: void fun(int[] x) {x.length += 1; x[0] = 5;} I cannot predict what the caller will see. But this is not a problem of *signatures*. The caller will not see ANY changes to {pointer,size} pair of x. That is the point -- it's passed by value. Note that this implementation is completely predictable: void fun(int[] x) {x[0] = 5; x.length += 1;} I want to stress that just because you can find an implementation that has a bug doesn't mean that there is an opportunity for the compiler to detect that bug, especially a logic bug. The compiler simply cannot know what you are thinking. In your case: void fun(int[] x){ x = [1, 2]; } // Compilation ok. Implementation's error. The fun() implementer made error and think that caller will get new array. But it will get it only at runtime! If we for example (just for example) have void fun(int[] const x){ x = [1, 2]; } // Compilation error. I see very little value in that. We don't need to obliterate a tremendous amount of slice usage (not mentioning how much code will have to be updated) in order to help newbies understand how slices work. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 11:48:50 -0500, Cooler kul...@hotbox.ru wrote: Please understand - I am not against void foo(int[] x){} From an earlier post by you: May be just prohibit at language level the case of fun3() function, to do not allow unpredictable behavior? I thought that this meant you were against it? I am for predictability of behavior. You suggest to describe function's behavior in documentation - quotation from your article It is a good idea to note in the documentation how the passed in slice might or might not be overwritten. My idea is that all potential errors must be detected as soon as possible. You cannot eradicate all errors. The intentions of a function are not apparent to the compiler. Maybe the intention is to use the argument as a buffer, and the caller should not care what happens to the buffer inside the function. Adding yet another attribute is going to increase language complexity for almost no benefit. It does not guarantee unambiguity because you have no idea what the author of the function is going to do. The D principle - The program compile and runs as expected, or not compile at all. This is a fantasy. The compiler cannot know what you expect. If you really need to call function that can change content of an array, but cannot change size of an array the language syntax should allow express it in function signature. I consider void fun(int[] const x){} more error prone than void fun(int[] x){} and for the caller and for implemeter. Not sure if something is mixed up there. I think void fun(int[] x) is sufficient to describe what you say. The function cannot alter x's array bounds at all, and can alter it's data. I see very little value in that. We don't need to obliterate a tremendous amount of slice usage (not mentioning how much code will have to be updated) in order to help newbies understand how slices work. Any idea can be rejected by this sentence. No, only ideas that force people to change millions of lines of code, and provide scant benefits instead of taking 5 minutes to explain no, just use x[0..2] = [1, 2] or just use ref int[] x depending on the goal. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 12:07:07 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 16:18:33 UTC, Steven Schveighoffer wrote: void foo(int x) { x = 5; } hey, why doesn't that work! Setting a parameter to another value should be illegal! Difference is here. void foo(int x){} - the caller will NEVER see any change to 'x'. void foo(int[] x){} - the caller MAY or MAY NOT see changes to 'x'. This is incorrect: foo(int[] x){} - The caller will see changes to data 'x' references. A slice is a reference type, it references a specific block of data. It's more akin to a pointer than an int. I could change my example: void foo(int *x) { int n = 3; x = n; } hey, why doesn't x now point to 3? Should be illegal! -Steve
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 16:48:51 UTC, Cooler wrote: On Thursday, 30 January 2014 at 16:18:33 UTC, Steven Schveighoffer wrote: void foo(int x) { x = 5; } hey, why doesn't that work! Setting a parameter to another value should be illegal! -Steve Please understand - I am not against void foo(int[] x){} I am for predictability of behavior. Predictability of behavior is not a principle of D and even if it would be, it can't be applied blindly. D is not a formal mathematic system. You suggest to describe function's behavior in documentation - quotation from your article It is a good idea to note in the documentation how the passed in slice might or might not be overwritten. My idea is that all potential errors must be detected as soon as possible. It is impossible to detect all errors in D per se, let alone taking into account separate compilation model. In some circumstances compiler can guess possible ways, but particular case we discussing is so common, that nothing can be done to 'fix' it. By the way, this case is not strictly speaking an error. It is error in context when caller cares about changes but this can be hardly verified at compile time (compiler need to read brain to know it). The D principle - The program compile and runs as expected, or not compile at all. It is all talk. Trying to apply this 'principle' in all cases is too naive. If you really need to call function that can change content of an array, but cannot change size of an array the language syntax should allow express it in function signature. I consider void fun(int[] const x){} more error prone than void fun(int[] x){} and for the caller and for implemeter. Personally this syntax is awful. By the way, there is another similar issue in D: import std.stdio; void foo(int[int] aa) { aa[1] = 1; } void main() { int[int] aa; foo(aa); writeln(aa); // [] aa[0] = 0; foo(aa); writeln(aa); // [0:0, 1:1] aa = null; foo(aa); writeln(aa); // [] } Here changes in AA array will be visible conditional that array is non null. If it is null, changes will be lost. This is another example of situation of the caller MAY or MAY NOT see changes to (citing your post above). In general, such semivalue-semireference semantic is produced when there is pointer wrapped into struct (doesn't matter whether it is opaque lang type or user defined). This happens in some language types, but may be also in user defined types. I don't think that verifying arbitrary semantic is compiler job.
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 12:38:57 -0500, Cooler kul...@hotbox.ru wrote: The D principle - The program compile and runs as expected, or not compile at all. This is a fantasy. The compiler cannot know what you expect. The language is needed to express your intentions to the compiler. Anything that the compiler cannot enforce is just documentation. Does it matter whether the documentation is in a comment or part of the signature? The language should be expressive as possible. My point is to push programmers to write correct software. I just ask these forum to think about topic. If everybody satisfied by void fun(int[] x){} behavior, then I just go... I'm not trying to be a bully or anything, but you are not understanding that what you want is a guarantee of logic, that the compiler cannot possibly enforce. Your example (setting a variable to another value) being rejected is easy to work around, just use another variable that doesn't have that restriction. There are so many examples of behavior-enforcing features that result in something that the creator of the feature didn't want or expect. Keep in mind there are years of projects that have been written assuming that you can use a standard slice in the signature of a function, we don't want to invalidate all that code just because programmers sometimes write buggy code. But I encounter a bug in my program that was due to my misusing of such signature. Here's where the gray area is. If you make this error once or twice, but never again, is it worth changing the language over? Probably not. But if you make this error every day, even KNOWING what will happen, it's worth looking into. But any changes have to avoid a negative impact on existing code as much as possible. Think of the person who knows how slices work, who very seldom makes this mistake, and who now has to go through all his code and make this change, never finding an instance where it makes a difference. At this point, I'm not sure what you are proposing, but I don't think there is much value in changing the way slice passing works. If you really need to call function that can change content of an array, but cannot change size of an array the language syntax should allow express it in function signature. I consider void fun(int[] const x){} more error prone than void fun(int[] x){} and for the caller and for implemeter. Not sure if something is mixed up there. I think void fun(int[] x) is sufficient to describe what you say. The function cannot alter x's array bounds at all, and can alter it's data. Here is the reason why i post the topic on this forum. You think one way, I think another way. I wanted to discuss what think other people. But looks like still nobody can understand my point, or may be I cannot express it... By mixed up, I meant that you seemed to be valuing the int[] x version over the int[] const x version. Other than that, what I stated is an indisputable fact -- the function cannot alter x's bounds. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 13:58:55 -0500, Cooler kul...@hotbox.ru wrote: The D principle - The program compile and runs as expected, or not compile at all. This is a fantasy. The compiler cannot know what you expect. The language is needed to express your intentions to the compiler. Anything that the compiler cannot enforce is just documentation. Does it matter whether the documentation is in a comment or part of the signature? Why we need const keyword, while we can just put I promise do not change it in the documentation? const is only useful in cases where references are involved. In this case, you want to make the *copied* data constant, in hopes that you then can't accidentally stop referencing the original. In another example, there is little to be gained from a signature such as: void foo(const int x); What does this say about foo? Nothing. I can pass in a mutable, const, or immutable int, because a copy is made. It doesn't provide any more guarantees to the caller than: void foo(int x); Likewise, your proposed int[] const would not guarantee anything extra to the caller beyond int[], because both are copies put onto the stack. The function has no access to the original values. Arrays in D are hard to understand. They don't behave like arrays in most other languages. But they foster a different mindset I think, that results in some of the fastest code on the planet. But one has to understand the semantics of syntax if they want to properly use the language. For functions which append/extend and then write data to the prior piece (the only non-deterministic case), special care has to be taken to explain this to the caller. I would think a mechanism to attempt detecting this and flagging it would be a worthy lint tool feature. But not a language or compiler feature. There is just simply no way to say that is always bad or that you know what the intentions of the author are. The other case you specified, when the author re-assigns a slice and expects it to be a memcpy or to re-bind the calling parameter, the result is deterministically the wrong result, and the coder will notice it right away (and hopefully correct their understanding). I don't think we need a language feature for that, just documentation (which I think we have). Let me also suggest you use scope statements to verify at runtime that the case you intend to prevent doesn't actually happen: void foo(int[] x) { const origx = x; scope(exit) assert(origx.ptr == x.ptr); ... } While not perfect, and not static, it should at least avoid subtle bugs (and can be turned off in release mode). -Steve
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 10:55:57 UTC, Cooler 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? Is that intentional? I believe what you are asking for is head const. D does not do this, search for head const dlang and you'll probably find some discussion in it.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 10:55:57 UTC, Cooler 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? Is that intentional? Arrays are a pair of pointer and length. fun1 marks the pointer, the length and the data pointed as const. fun3 marks nothing const, but since pointer and length are passed by value, you'll only see changes to the content of x. fun2 is like fun3, but pointer and length are itself passed by reference.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 11:46:23 UTC, Cooler wrote: Thank you for detailed explanation. But the question is - Is that correct that language allows ambiguous behavior? Could you expand your example? fun(int[] a) {} is passing a by value, that is, the pointer and length is copied over to fun. Any changes to the elements of a will be visible, but if you reassign a directly or indirectly (expanding it so it needs to be copied to a new memory location), the changes are not visible.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 11:46:23 UTC, Cooler wrote: Thank you for detailed explanation. But the question is - Is that correct that language allows ambiguous behavior? Where is it ambiguous?
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 13:15:30 UTC, Cooler wrote: On Wednesday, 29 January 2014 at 12:40:00 UTC, Tobias Pankrath wrote: On Wednesday, 29 January 2014 at 11:46:23 UTC, Cooler wrote: Thank you for detailed explanation. But the question is - Is that correct that language allows ambiguous behavior? Where is it ambiguous? Ambiguity is here... When I call fun1() or fun2() I know the behavior directly from function signature (read the comments in my first post). For fun3() case the caller side don't know the behavior directly from function signature. To know what will happen with array a, the caller must see to fun3() body. Ambiguity is - in first and second cases the caller knows what happens with a, but in third case the caller does not know what happens with a. 'in' is a shorthard for 'const scope'. 'const' means that the callee cannot change the passed in parameter in any way, including anything available through that type (for example x[0]) 'scope' means it cannot leave the scope of the callee - that it cannot be stored away anywhere. 'ref' means that the parameter is passed by reference, and thus might be reassigned or changed in any way. No parameters means that it's mutable, but the reference cannot change. I don't see any ambiguities here.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 13:15:30 UTC, Cooler wrote: On Wednesday, 29 January 2014 at 12:40:00 UTC, Tobias Pankrath wrote: On Wednesday, 29 January 2014 at 11:46:23 UTC, Cooler wrote: Thank you for detailed explanation. But the question is - Is that correct that language allows ambiguous behavior? Where is it ambiguous? Ambiguity is here... When I call fun1() or fun2() I know the behavior directly from function signature (read the comments in my first post). For fun3() case the caller side don't know the behavior directly from function signature. To know what will happen with array a, the caller must see to fun3() body. Ambiguity is - in first and second cases the caller knows what happens with a, but in third case the caller does not know what happens with a. I believe you encounter an array reallocation. If fun3 doesn't change the size of the array - you will see every change made by fun3 to the contents of `a` (but the `a` itself cannot be changed - only the contents). No other way around. If, however, in fun3 you change the size of the array - it may reallocate. Like, if you're appending to `x` - it will allocate a new array and make x point to it. Now `a` and `x` point to distinct arrays. And any change you do using `x` won't be seen by `a`. And, yes, this is the intended behavior.
Re: Array as an argument, ambiguous behaviour.
On 01/29/2014 02:55 AM, Cooler 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? Is that intentional? Yes, that is how slices work in D. The following article explains the non-determinism that you mention: http://dlang.org/d-array-article.html Ali
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 15:11:33 UTC, Cooler wrote: Yes, that is how slices work in D. The following article explains the non-determinism that you mention: http://dlang.org/d-array-article.html Ali Thank you for the article. Quotation from the article It is a good idea to note in the documentation how the passed in slice might or might not be overwritten. May be just prohibit at language level the case of fun3() function, to do not allow unpredictable behavior? This behavior is just a consequence of the deliberate decision on how arrays should be implemented. Any decision would be a trade-off. Like, if you just disallow this signature, you will have to use .dup at the caller side if you want the semantics of fun3. And often this copy might be unnecessary. It's really like a ball under the carpet. You make it flat in one place, but the ball pops up in the other. The trade-off that D chooses is pretty reasonable. You just have to accept that and get used to it.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 15:11:33 UTC, Cooler wrote: Yes, that is how slices work in D. The following article explains the non-determinism that you mention: http://dlang.org/d-array-article.html Ali Thank you for the article. Quotation from the article It is a good idea to note in the documentation how the passed in slice might or might not be overwritten. May be just prohibit at language level the case of fun3() function, to do not allow unpredictable behavior? It's not unpredictable, at least not more unpredictable then fun2. Should we dissallow this two? int[] a = [1,2,3,4]; b = a; b ~= [5, 6, 7, 8];
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 15:38:34 UTC, Cooler wrote: It's not unpredictable, at least not more unpredictable then fun2. Should we dissallow this two? int[] a = [1,2,3,4]; b = a; b ~= [5, 6, 7, 8]; You don't understand me. You consider that I am author of the fun() and the caller side. Read two post above http://forum.dlang.org/post/dxqxlhyhmdfuashhm...@forum.dlang.org I consider that author of fun() and author of caller side are different persons. They must agree between them how to provide some functionality. If I fun()'s author why do I need to provide fun3() if I already provided fun1() and fun2()? I I caller's author - why may I require fun3() variant, if I already have fun1() and fun2()? Oh, I guess I understood quite well. I just don't see a special problem with arrays, it's just the same as any other aliasing issue. Take this for example: void funS(S* s); // S is a struct, maybe containing a ptr and a length member :-) Should we disallow this as well? When I give a unqualified pointer to a function, the only guarantee I get is that it's pointing to the same location after the call. It's the same with arrays. And since we have this problem every time we pass a pointer to function I don't see why arrays should get special treatment.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 16:01:08 UTC, Cooler wrote: Do you read my post? I am answering... why do I need fun3() if I already have fun1() and fun2(). fun3 guarantees that the argument has the same length for example.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 16:26:05 UTC, Cooler wrote: Where argument has the same length? After function call, or inside function? I don't understand what my intention should be to push me to use fun3()? Gosh. To allow the function to modify the contents, but not the size of the array.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 16:54:27 UTC, Cooler wrote: On Wednesday, 29 January 2014 at 16:36:44 UTC, Stanislav Blinov wrote: On Wednesday, 29 January 2014 at 16:26:05 UTC, Cooler wrote: Where argument has the same length? After function call, or inside function? I don't understand what my intention should be to push me to use fun3()? Gosh. To allow the function to modify the contents, but not the size of the array. Сам то понял чего написал??? :) Yes I did.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 16:26:05 UTC, Cooler wrote: On Wednesday, 29 January 2014 at 16:15:36 UTC, Tobias Pankrath wrote: On Wednesday, 29 January 2014 at 16:01:08 UTC, Cooler wrote: Do you read my post? I am answering... why do I need fun3() if I already have fun1() and fun2(). fun3 guarantees that the argument has the same length for example. Where argument has the same length? After function call, or inside function? I don't understand what my intention should be to push me to use fun3()? If you want to modify the slice and make changes visible in caller, you should use ref. If you don't care whether changes are visible in caller, you can omit any attributes and use plain array. This belongs to the case you are asking about. If you don't want to change array in callee, pass it as const qualified. Now, after rethinking the issue I am inclining that don't care whether changes are visible for caller is not very wrong, but not very good design. Ideally it should be specified to avoid unexpected problems to pop up. So yes, it is better to qualify array. Another point. This casino games of whether changes would be visible or not is direct consequence of how slices are implemented (and how runtime service them). Remember, that many features in D work in a strange way not because of wise design but as a consequence of not fully thought design (like array). As a result, some features work in not best way they should. Although many folks in newsgroups would eagerly say that you don't understand the lang, it wouldn't make a bad design a good one.