www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to detect if an array if dynamic or static

reply mahdi <xemailpro yahoo.co.uk> writes:
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
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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
parent reply mahdi <xemailpro yahoo.co.uk> writes:
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:
 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?
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?
Feb 24 2016
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 02/24/2016 08:44 PM, mahdi wrote:
 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:
 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?
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?
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. Ali
Feb 24 2016
parent reply mahdi <xemailpro yahoo.co.uk> writes:
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
next sibling parent Kagamin <spam here.lot> writes:
void diss(int n)(ref int[n] array) { }

But to consume array of any size, just take dynamic array as 
parameter.
Feb 25 2016
prev sibling parent reply sigod <sigod.mail gmail.com> writes:
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
parent reply mahdi <xemailpro yahoo.co.uk> writes:
On Thursday, 25 February 2016 at 11:50:02 UTC, sigod wrote:
 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
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?
Feb 25 2016
next sibling parent sigod <sigod.mail gmail.com> writes:
On Thursday, 25 February 2016 at 12:18:07 UTC, mahdi wrote:
 On Thursday, 25 February 2016 at 11:50:02 UTC, sigod wrote:
 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
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?
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: http://dlang.org/phobos/std_array.html#.Appender
Feb 25 2016
prev sibling parent reply sigod <sigod.mail gmail.com> writes:
On Thursday, 25 February 2016 at 12:18:07 UTC, mahdi wrote:
 On Thursday, 25 February 2016 at 11:50:02 UTC, sigod wrote:
 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
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?
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])
Feb 25 2016
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
prev sibling next sibling parent reply Chris Wright <dhasenan gmail.com> writes:
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
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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
next sibling parent Chris Wright <dhasenan gmail.com> writes:
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:
 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
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.
Feb 25 2016
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 2/24/16 9:08 PM, Adam D. Ruppe wrote:
 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 )
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. -Steve
Feb 25 2016
prev sibling next sibling parent asdf <a b.c> writes:
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
prev sibling parent jmh530 <john.michael.hall gmail.com> writes:
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