www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Pointer vs Ref

reply confuzzled <con fuzzled.com> writes:
Hello community,

Is it possible to accomplish the following using ref instead of 
pointers? If so, please share an example.

import std.stdio;

// Represents our large, external data source (like TimeSeries)
struct DataSource
{
     int[3] data;
}

// Represents our Backtester engine
struct Engine
{
     // It STORES a pointer to its data source. This is its "memory".
     const(DataSource)* dataSource;

     // The run method USES the stored pointer.
     void run()
     {
         writeln("Engine running...");
         if (dataSource is null)
         {
             writeln("  Error: Data source not configured!");
             return;
         }

         // We access the data through the remembered pointer.
         foreach (i, val; dataSource.data)
         {
             writef("  Processing data point %d: %d\n", i, val);
         }
     }
}

void main()
{
     writeln("--- Running Pointer Member Example ---");

     // 1. Create our data. It lives here in main.
     auto myData = DataSource([10, 20, 30]);

     // 2. Create our engine. It starts empty.
     auto myEngine = Engine();
     writeln("Engine created. Has it been configured yet?");
     myEngine.run(); // Will fail because the pointer is null

     // 3. Configure the engine. We give it the ADDRESS of our data.
     //    The engine stores this address in its pointer member.
     writeln("\nConfiguring engine...");
     myEngine.dataSource = &myData;

     // 4. Later, we run the engine. It can now work because it
     //    remembered the address of myData.
     writeln("\nRunning configured engine...");
     myEngine.run();
}

Thanks,
-- confuzzled
Jun 09
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Monday, 9 June 2025 at 07:24:41 UTC, confuzzled wrote:
 Hello community,

 Is it possible to accomplish the following using ref instead of 
 pointers? If so, please share an example.

 import std.stdio;

 // Represents our large, external data source (like TimeSeries)
 struct DataSource
 {
     int[3] data;
 }

 // Represents our Backtester engine
 struct Engine
 {
     // It STORES a pointer to its data source. This is its 
 "memory".
     const(DataSource)* dataSource;

     // The run method USES the stored pointer.
     void run()
     {
         writeln("Engine running...");
         if (dataSource is null)
         {
             writeln("  Error: Data source not configured!");
             return;
         }

         // We access the data through the remembered pointer.
         foreach (i, val; dataSource.data)
         {
             writef("  Processing data point %d: %d\n", i, val);
         }
     }
 }

 void main()
 {
     writeln("--- Running Pointer Member Example ---");

     // 1. Create our data. It lives here in main.
     auto myData = DataSource([10, 20, 30]);

     // 2. Create our engine. It starts empty.
     auto myEngine = Engine();
     writeln("Engine created. Has it been configured yet?");
     myEngine.run(); // Will fail because the pointer is null

     // 3. Configure the engine. We give it the ADDRESS of our 
 data.
     //    The engine stores this address in its pointer member.
     writeln("\nConfiguring engine...");
     myEngine.dataSource = &myData;

     // 4. Later, we run the engine. It can now work because it
     //    remembered the address of myData.
     writeln("\nRunning configured engine...");
     myEngine.run();
 }

 Thanks,
 -- confuzzled
The hard part is the `foreach` the simple answer is throw a ref before `val`. Define your data to impliment ranges... but then you lose indexing on foreach You can then use enumerate... but then you lose ref Drop range entirely and you can interface with foreach with opApply, but then you dont get map/reduce. --- Ranges do not support indexing in truth(enumerate is fundamentally incorrect after a filter) and foreach is opinionated about ranges. the tradeoffs as I understand them: 1. use raw arrays, `foreach(i, ref v` is discouraged(there was a stupid breaking change) but the community will fight tooth and nail on the subject 2. make your own enumerate with a ref index(refness on tuples) 3. define opApply with 2 arguments(delegates dont share the shared refness issues of tuples)
Jun 09
parent confuzzled <con fuzzled.com> writes:
On 6/9/25 11:16 PM, monkyyy wrote:
 On Monday, 9 June 2025 at 07:24:41 UTC, confuzzled wrote:
 Hello community,

 Is it possible to accomplish the following using ref instead of 
 pointers? If so, please share an example.
The hard part is the `foreach` the simple answer is throw a ref before `val`. Define your data to impliment ranges... but then you lose indexing on foreach You can then use enumerate... but then you lose ref Drop range entirely and you can interface with foreach with opApply, but then you dont get map/reduce. --- Ranges do not support indexing in truth(enumerate is fundamentally incorrect after a filter) and foreach is opinionated about ranges. the tradeoffs as I understand them: 1. use raw arrays, `foreach(i, ref v` is discouraged(there was a stupid breaking change) but the community will fight tooth and nail on the subject 2. make your own enumerate with a ref index(refness on tuples) 3. define opApply with 2 arguments(delegates dont share the shared refness issues of tuples)
Thank you very much monkyyy.
Jun 11
prev sibling parent reply =?UTF-8?Q?Ali_=C3=87ehreli?= <acehreli yahoo.com> writes:
On 6/9/25 12:24 AM, confuzzled wrote:

 Is it possible to accomplish the following using ref instead of
 pointers?
Your example is a good case for a pointer. Was there a reason why a reference should be used? Having said that, you can even drop the pointer and use a DataSource as-is: struct Engine { DataSource dataSource; // ... } However, that would be preferable only if DataSource did not have a static array but I assume you wrote int[3] just as an example. Otherwise: struct DataSource { int[] data; // <-- Now a slice } That works because DataSource.data is a *reference* to your external data. Ali
Jun 09
parent confuzzled <con fuzzled.com> writes:
On 6/10/25 2:17 AM, Ali Çehreli wrote:
 On 6/9/25 12:24 AM, confuzzled wrote:
 
  > Is it possible to accomplish the following using ref instead of
  > pointers?
 
 Your example is a good case for a pointer. Was there a reason why a 
 reference should be used?
Just exploring the realm of possibilities. I thought they could accomplish the same things as pointers but safer. And since we now have auto ref in the global space... well, by brain got away from me. Why is auto ref illegal inside UDTs anyway?
 Having said that, you can even drop the pointer and use a DataSource as-is:
 
 struct Engine
 {
      DataSource dataSource;
      // ...
 }
 
 However, that would be preferable only if DataSource did not have a 
 static array but I assume you wrote int[3] just as an example. Otherwise:
The size is an example but it is indeed a static array.
 struct DataSource
 {
      int[] data;    // <-- Now a slice
 }
 
 That works because DataSource.data is a *reference* to your external data.
 
 Ali
 
Thanks Ali
Jun 11