digitalmars.D.learn - Pointer vs Ref
- confuzzled (50/50) Jun 09 Hello community,
- monkyyy (19/71) Jun 09 The hard part is the `foreach` the simple answer is throw a ref
- confuzzled (2/33) Jun 11 Thank you very much monkyyy.
- =?UTF-8?Q?Ali_=C3=87ehreli?= (17/19) Jun 09 Your example is a good case for a pointer. Was there a reason why a
- confuzzled (7/33) Jun 11 Just exploring the realm of possibilities. I thought they could
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
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, -- confuzzledThe 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
On 6/9/25 11:16 PM, monkyyy wrote:On Monday, 9 June 2025 at 07:24:41 UTC, confuzzled wrote:Thank you very much monkyyy.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)
Jun 11
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
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. AliThanks Ali
Jun 11