digitalmars.D.learn - How to detect if an array if dynamic or static
- mahdi (4/4) Feb 24 2016 Suppose we have a function like this:
- Adam D. Ruppe (4/6) Feb 24 2016 `array` there is always dynamic because it is not of a fixed size
- mahdi (10/16) Feb 24 2016 I thought we can simply denote `int[] x` in case we have an array
- =?UTF-8?Q?Ali_=c3=87ehreli?= (21/36) Feb 24 2016 Yes.
- mahdi (6/6) Feb 25 2016 Thanks.
- Kagamin (3/3) Feb 25 2016 void diss(int n)(ref int[n] array) { }
- sigod (16/22) Feb 25 2016 Static array can be accepted in place of dynamic:
- mahdi (6/29) Feb 25 2016 My question: If in your `bar` function, the code tries to add a
- sigod (10/42) Feb 25 2016 I'm not sure if this is an error at all. Append sees that array
- sigod (8/40) Feb 25 2016 Also, if you need to append elements to an array inside of a
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/9) Feb 25 2016 To qualify further, static arrays cannot be passed as slice references
- Chris Wright (14/20) Feb 24 2016 Static arrays point to memory on the stack, inside an aggregate type on
- Adam D. Ruppe (13/14) Feb 24 2016 The GC is easy, you can simply ask it:
- Chris Wright (8/14) Feb 25 2016 I saw that method, and I saw that it returned the base address of a Pool...
- Steven Schveighoffer (9/22) Feb 25 2016 Just a slight nit -- it will only return 0 if the array slice doesn't
- asdf (10/14) Feb 25 2016 I don't understand what I'm doing but got a proof of concept for
- jmh530 (4/8) Feb 25 2016 I don't see that anyone has mentioned it but:
Suppose we have a function like this: void diss(int[] array) ... How can we detect is `array` is static (fixed size) or dynamic, inside the function body?
Feb 24 2016
On Wednesday, 24 February 2016 at 21:48:14 UTC, mahdi wrote:How can we detect is `array` is static (fixed size) or dynamic, inside the function body?`array` there is always dynamic because it is not of a fixed size type. Why do you want to know though?
Feb 24 2016
On Wednesday, 24 February 2016 at 22:38:04 UTC, Adam D. Ruppe wrote:On Wednesday, 24 February 2016 at 21:48:14 UTC, mahdi wrote:I thought we can simply denote `int[] x` in case we have an array argument in D functions. So according to your answer if a function expects a static array, it has to specify size of array in parameter declaration: void diss(int[3] array) ... //this expects a static array of size 3 void diss(int[] array) ... //this expects a dynamic array is this correct?How can we detect is `array` is static (fixed size) or dynamic, inside the function body?`array` there is always dynamic because it is not of a fixed size type. Why do you want to know though?
Feb 24 2016
On 02/24/2016 08:44 PM, mahdi wrote:On Wednesday, 24 February 2016 at 22:38:04 UTC, Adam D. Ruppe wrote:Yes. Note that static arrays are value types. So, if the parameter is int[3], then the argument will be copied. However, you can still take it by reference (with the ref keyword): import std.stdio; void diss(ref int[3] array) { writeln(typeof(array).stringof); } void diss(int[] array) { writeln(typeof(array).stringof); } void main() { int[3] arr; diss(arr); } Prints: int[3] And a reminder that rvalues cannot be bound to ref in D. So, 'ref int[3]' may not be usable in your case. AliOn Wednesday, 24 February 2016 at 21:48:14 UTC, mahdi wrote:I thought we can simply denote `int[] x` in case we have an array argument in D functions. So according to your answer if a function expects a static array, it has to specify size of array in parameter declaration: void diss(int[3] array) ... //this expects a static array of size 3 void diss(int[] array) ... //this expects a dynamic array is this correct?How can we detect is `array` is static (fixed size) or dynamic, inside the function body?`array` there is always dynamic because it is not of a fixed size type. Why do you want to know though?
Feb 24 2016
Thanks. So when we define the function, we MUST specify the array size to be able to accept a static array? Can't we just define a function which can accept any static array with any size? (e.g. a function to calculate average of a static int array of any size)?
Feb 25 2016
void diss(int n)(ref int[n] array) { } But to consume array of any size, just take dynamic array as parameter.
Feb 25 2016
On Thursday, 25 February 2016 at 10:03:08 UTC, mahdi wrote:Thanks. So when we define the function, we MUST specify the array size to be able to accept a static array? Can't we just define a function which can accept any static array with any size? (e.g. a function to calculate average of a static int array of any size)?Static array can be accepted in place of dynamic: void foo() { int[3] arr = [1, 2, 3]; bar(arr); } void bar(scope int[] arr) { import std.stdio : writeln; writeln(arr); // [1, 2, 3] } But be careful not to escape such variables. Demonstration: http://dpaste.dzfl.pl/613e04d4fe3f
Feb 25 2016
On Thursday, 25 February 2016 at 11:50:02 UTC, sigod wrote:On Thursday, 25 February 2016 at 10:03:08 UTC, mahdi wrote:My question: If in your `bar` function, the code tries to add a new element to the dynamic array, it will be completely ok because array is dynamic. BUT if we pass a static array to this function, can this error be detected at compile time (and prevent a runtime error)? If so, how?Thanks. So when we define the function, we MUST specify the array size to be able to accept a static array? Can't we just define a function which can accept any static array with any size? (e.g. a function to calculate average of a static int array of any size)?Static array can be accepted in place of dynamic: void foo() { int[3] arr = [1, 2, 3]; bar(arr); } void bar(scope int[] arr) { import std.stdio : writeln; writeln(arr); // [1, 2, 3] } But be careful not to escape such variables. Demonstration: http://dpaste.dzfl.pl/613e04d4fe3f
Feb 25 2016
On Thursday, 25 February 2016 at 12:18:07 UTC, mahdi wrote:On Thursday, 25 February 2016 at 11:50:02 UTC, sigod wrote:I'm not sure if this is an error at all. Append sees that array doesn't have any available space and allocates new array. writeln(arr.ptr); // 7FBFC45AA0 arr ~= 1; writeln(arr.ptr); // 4002E000 I would say that you have poor code design if your function must be able to accept static arrays and append elements to it. You might find this useful:On Thursday, 25 February 2016 at 10:03:08 UTC, mahdi wrote:My question: If in your `bar` function, the code tries to add a new element to the dynamic array, it will be completely ok because array is dynamic. BUT if we pass a static array to this function, can this error be detected at compile time (and prevent a runtime error)? If so, how?Thanks. So when we define the function, we MUST specify the array size to be able to accept a static array? Can't we just define a function which can accept any static array with any size? (e.g. a function to calculate average of a static int array of any size)?Static array can be accepted in place of dynamic: void foo() { int[3] arr = [1, 2, 3]; bar(arr); } void bar(scope int[] arr) { import std.stdio : writeln; writeln(arr); // [1, 2, 3] } But be careful not to escape such variables. Demonstration: http://dpaste.dzfl.pl/613e04d4fe3f
Feb 25 2016
On Thursday, 25 February 2016 at 12:18:07 UTC, mahdi wrote:On Thursday, 25 February 2016 at 11:50:02 UTC, sigod wrote:Also, if you need to append elements to an array inside of a function, then you need to mark function arguments as `ref`: void bar(ref int[] arr) Code wouldn't compile if you try to pass static array as `ref` argument. Error: function f436.bar (ref int[] arr) is not callable using argument types (int[3])On Thursday, 25 February 2016 at 10:03:08 UTC, mahdi wrote:My question: If in your `bar` function, the code tries to add a new element to the dynamic array, it will be completely ok because array is dynamic. BUT if we pass a static array to this function, can this error be detected at compile time (and prevent a runtime error)? If so, how?Thanks. So when we define the function, we MUST specify the array size to be able to accept a static array? Can't we just define a function which can accept any static array with any size? (e.g. a function to calculate average of a static int array of any size)?Static array can be accepted in place of dynamic: void foo() { int[3] arr = [1, 2, 3]; bar(arr); } void bar(scope int[] arr) { import std.stdio : writeln; writeln(arr); // [1, 2, 3] } But be careful not to escape such variables. Demonstration: http://dpaste.dzfl.pl/613e04d4fe3f
Feb 25 2016
On 02/25/2016 04:47 AM, sigod wrote:void bar(ref int[] arr) Code wouldn't compile if you try to pass static array as `ref` argument.To qualify further, static arrays cannot be passed as slice references because although there is an automatic slicing of static arrays, such slices are rvalues and rvalues cannot be bound to 'ref' parameters:Error: function f436.bar (ref int[] arr) is not callable using argument types (int[3])Ali
Feb 25 2016
On Wed, 24 Feb 2016 21:48:14 +0000, mahdi wrote:Suppose we have a function like this: void diss(int[] array) ... How can we detect is `array` is static (fixed size) or dynamic, inside the function body?Static arrays point to memory on the stack, inside an aggregate type on the heap, or inside the static data area. In the stack case, you can use this strategy: extern (C) void* thread_stackBottom(); bool isLocatedOnStack(T)(T[] arr) { int i; void* top = &i; auto bottom = thread_stackBottom(); return arr.ptr >= min(top, bottom) && arr.ptr <= max(top, bottom); } When you get to GC-allocated stuff, there's no way to tell. Static data, I'm not sure. This probably isn't what you want, though.
Feb 24 2016
On Thursday, 25 February 2016 at 01:31:17 UTC, Chris Wright wrote:When you get to GC-allocated stuff, there's no way to tell.The GC is easy, you can simply ask it: http://dpldocs.info/experimental-docs/core.memory.GC.addrOf.1.html "If p references memory not originally allocated by this garbage collector, if p is null, or if the garbage collector does not support this operation, null will be returned." The append operator uses this kind of logic to determine if it is safe to append. The `capacity` property on slices can query, though it is zero in some cases where the GC owns it, but it still needs reallocation to be appended to (e.g. when the array is already at the max length of the allocated block, or when the stomping protection kicks in. See: http://dlang.org/d-array-article.html )
Feb 24 2016
On Thu, 25 Feb 2016 02:08:18 +0000, Adam D. Ruppe wrote:On Thursday, 25 February 2016 at 01:31:17 UTC, Chris Wright wrote:I saw that method, and I saw that it returned the base address of a Pool. From the name, fields, and Gcx invocation, I guessed that Pool represented a bundle of multiple values. It's got about ten or twelve words of overhead, which would be a bit heavy to have one for each allocated object. (And that's on top of the bookkeeping malloc has to do, since the GC uses malloc under the hood.) Or maybe it's just got that much overhead.When you get to GC-allocated stuff, there's no way to tell.The GC is easy, you can simply ask it: http://dpldocs.info/experimental-docs/core.memory.GC.addrOf.1.html
Feb 25 2016
On 2/24/16 9:08 PM, Adam D. Ruppe wrote:On Thursday, 25 February 2016 at 01:31:17 UTC, Chris Wright wrote:Just a slight nit -- it will only return 0 if the array slice doesn't end at the end of valid data as defined by the metadata. If it ends exactly at the max length of the block, then arr.capacity == arr.length. It will also return 0 if the memory block in question wasn't allocated via the array allocation routine (and therefore has no metadata). The correct answer is what you said, to use the GC to look up whether it's part of the GC. -SteveWhen you get to GC-allocated stuff, there's no way to tell.The GC is easy, you can simply ask it: http://dpldocs.info/experimental-docs/core.memory.GC.addrOf.1.html "If p references memory not originally allocated by this garbage collector, if p is null, or if the garbage collector does not support this operation, null will be returned." The append operator uses this kind of logic to determine if it is safe to append. The `capacity` property on slices can query, though it is zero in some cases where the GC owns it, but it still needs reallocation to be appended to (e.g. when the array is already at the max length of the allocated block, or when the stomping protection kicks in. See: http://dlang.org/d-array-article.html )
Feb 25 2016
On Wednesday, 24 February 2016 at 21:48:14 UTC, mahdi wrote:Suppose we have a function like this: void diss(int[] array) ... How can we detect is `array` is static (fixed size) or dynamic, inside the function body?I don't understand what I'm doing but got a proof of concept for you. This https://dlang.org/phobos/std_traits.html page helped. import std.stdio; void main() { int[] a; int[1] b; writeln(is(typeof(a) == int[])); // true writeln(is(typeof(b) == int[])); // false }
Feb 25 2016
On Wednesday, 24 February 2016 at 21:48:14 UTC, mahdi wrote:Suppose we have a function like this: void diss(int[] array) ... How can we detect is `array` is static (fixed size) or dynamic, inside the function body?I don't see that anyone has mentioned it but: https://dlang.org/phobos/std_traits.html#isStaticArray https://dlang.org/phobos/std_traits.html#isDynamicArray
Feb 25 2016