June 05

On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote:

>

foreach (i, row; maze)
slices[i] = row;

Sorry that assignment was wrong (edited at last minute). Fixed:

import std.stdio;
alias s_cell = int;

void main()
{  writeln("Maze generation demo");

   s_cell [5][5] maze;
   int n;
   foreach (i, row; maze)
        foreach (j, col; row)
            maze[i][j] = n++;

   s_cell[][5] slices;
   foreach (i, _; maze)
       slices[i] = maze[i];

   print_maze (slices);
}

void print_maze ( s_cell [][] maze )
{
    foreach (a; maze)
        a.writeln();
}
June 05

On Wednesday, 5 June 2024 at 09:24:23 UTC, evilrat wrote:

>

for simple cases like this it might work, but 2d array is not even contiguous,

A 2D static array is contiguous:
https://dlang.org/spec/arrays.html#rectangular-arrays

>

D static arrays, while using the same syntax, are implemented as a fixed rectangular layout in a contiguous block of memory

June 05

On Wednesday, 5 June 2024 at 11:27:32 UTC, Nick Treleaven wrote:

>

On Wednesday, 5 June 2024 at 09:24:23 UTC, evilrat wrote:

>

for simple cases like this it might work, but 2d array is not even contiguous,

A 2D static array is contiguous:
https://dlang.org/spec/arrays.html#rectangular-arrays

>

D static arrays, while using the same syntax, are implemented as a fixed rectangular layout in a contiguous block of memory

Yeah ok, i might have messed up with columns last time, but it works.

    int[5][5] test;

    foreach(i; 0..5) {
        foreach(j; 0..5) {
            test[i][j] = i * 5 + j;
        }
    }

    foreach(i; 0..25) {
        assert(test[0].ptr[i] == i);
    }
June 05

On Wednesday, 5 June 2024 at 06:22:34 UTC, Eric P626 wrote:

>

I tried the following signatures with the ref keyword and it did not change anything:

void print_maze ( ref s_cell maze )
void print_maze ( ref s_cell [][] maze )

From what I found, arrays passed in parameters are always passed by reference. So the ref keyword seems pointless.

There is one useful functionality about the ref keyword when passing arrays, it is that you can change the original array reference to another array reference.

Ex.

void foo(ref int[] x)
{
    x = [1,2,3];
}

void bar(int[] y)
{
    y = [1,2,3];
}

void main()
{
    auto x = [0,0,0];
    auto y = [1,1,1];

    foo(x);
    bar(y);

    writeln(x);
    writeln(y);
}

The output of the program is:

[1, 2, 3]
[1, 1, 1]

Of course in your case this doesn't matter, but just wanted to point out that adding ref to array parameters actually pose a function.

June 06

On Wednesday, 5 June 2024 at 10:36:50 UTC, Nick Treleaven wrote:

>
import std.stdio;
alias s_cell = int;

void main()
{  writeln("Maze generation demo");

   s_cell [5][5] maze;
   int n;
   foreach (i, row; maze)
        foreach (j, col; row)
            maze[i][j] = n++;

   s_cell[][5] slices;
   foreach (i, _; maze)
       slices[i] = maze[i];

   print_maze (slices);
}

void print_maze ( s_cell [][] maze )
{
    foreach (a; maze)
        a.writeln();
}

Thanks for the feedback

Almost all my projects works intensively with multiple dimensions arrays. So I want to know the best way to manage multi dimensional arrays. I guess the best solution so far are:

  1. Only use dynamic arrays.
  2. Use a single dimension array, and compute the index value from x,y,z coordinates (Makes dynamic allocation easier). This solution could work well with pointers too.
  3. Make my own data structure or class containing the array. Allowing to pass the structure/class by reference. Could allow encapsulating single or multi dimensional arrays.

About .ptr, the documentation page state that:

The .ptr property for static and dynamic arrays will give the address of the first element in the array:

So I assumed that the following expressions where equivalent, but I guess the multiple dimensions do complicate things:

array.ptr == &array == &array[0]

So ommitting the "ref" keyword it's like if the data was read only even if the variable is not passed by value. That means that this signature cannot modify the content of the 2D array:

void print_maze ( s_cell [][] maze )

For the create_maze() function, I would need to use the follwing signature since it changes the content of the array.

void print_maze ( ref s_cell [][] maze )

I imagine a.writeln(); is the same as writeln(a); ?

Your foreach loops look better than mine. Here is the code I have been using to print the maze.

void print_maze ( s_cell [][] maze )
{
   //print top row, assume full
   foreach ( cell; maze[0] ) write("+---");
   writeln("+");
   for ( int y = 0; y < maze.length; y++)
   {  //print content
      write("|"); //assume edge is always full
      for ( int x = 0; x < maze[y].length; x++)
      {  write("   ");
         write( maze[y][x].east ? "|": " ");
      }
      writeln();
      foreach ( cell; maze[y] ) write( cell.south ? "+---" : "    " );
      writeln("+");
   }
}

your iteration version is more neat:

foreach (i, row; maze)
        foreach (j, col; row)
            maze[i][j] = n++;

I like that using 2 variables (i,row) or (j,col) allow to access the variable later as a element in a collection or as an index. It's more flexible. I'll guess I'll need to read more code to avoid programming too much old school (^_^).

June 06

On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote:

>

I am currently trying to learn how to program in D. I thought that I could start by trying some maze generation algorithms. I have a maze stored as 2D array of structure defined as follow which keep tracks of wall positions:

struct s_cell
{
   bool north = true;
   bool east = true;
   bool south = true;
   bool west = true;
}

I try to create a 2D array of fixed length and pass it in parameter as a reference. Normally, in C, I would have used a pointer as parameter, and pass the address of the array. Here, I thought it would have been easier just to pass a slice of the array, since a slice is a reference to the original array. So I wrote the signature like this:

void main()
{  writeln("Maze generation demo");

   s_cell [5][5] maze;
   print_maze (maze);

}

void print_maze ( s_cell [][] maze )
{
}

My idea is that print_maze use a slice of what ever is sent in parameter. Unfortunately, I get the following error message:

Error: function `mprmaze.print_maze(s_cell[][] maze)` is not callable using argument types `(s_cell[5][5])`
  cannot pass argument `maze` of type `s_cell[5][5]` to parameter `s_cell[][] maze`

I tried to find a solution on the internet, but could not find anything, I stumble a lot on threads about Go or Rust language even if I specify "d language" in my search.

Else is there other ways to pass an array as reference using parameter modifiers like: ref,in,out ...

Else, can it be done the C way using pointers?

Thank you.

First things first, put @safe: on the top of the file or put @safe at the end of every function declarator. It makes anything that could be undefined behavior an error:

void main() @safe
{
    writeln("Maze generation demo");

    s_cell [5][5] maze;
    print_maze (maze);

}

// change to: ( const ref s_cell [5][5] maze )
void print_maze ( s_cell [][] maze ) @safe
{
}

A T[] is a pointer–length pair, aka. a slice. A T[n] is a block of n values of type T. Assuming you know a thing or two about C, a T[n] converts to a T[] like an int converts to a long: It’s lossless and safe, but not pointer compatible.

For the same reason an int* can’t convert to a long*, a T[m][n] can’t convert to a T[][].

Also, if you’re new, be aware some people call slices “dynamic arrays,” which is really misleading sometimes.

  • If a function writes a maze, pass the maze by ref. Note that ref is not part of the parameter’s type (as in C++), but a property of the parameter akin to its type.
  • If a function only reads a maze, pass the maze by const ref; or in using the command-line option -preview=in which: allows rvalues and doesn’t bind by reference if the object bound is small and trivial to copy.
1 2
Next ›   Last »