www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can you fix this code to avoid using pointers?

reply XavierAP <n3minis-git yahoo.es> writes:
I do not really think it's a bad solution, to check several 
scalar arguments that must obey the same condition; just 
wondering if you have better ideas. Try to avoid modifying the 
function's signature and defining custom types, unless you have a 
really terrific idea.

void calc(double in1, double in2, double in3, double in4)
in {
    foreach(const p; [&in1, &in2, &in3, &in4])
       enforce(*p > 0);
}
body { /* ... */ }
Mar 11
next sibling parent XavierAP <n3minis-git yahoo.es> writes:
Oh... please forget it
What a terrible example :p I forgot why I was using pointers at 
all... I must have had a reason to write this in the past ???
Mar 11
prev sibling next sibling parent reply XavierAP <n3minis-git yahoo.es> writes:
On Saturday, 11 March 2017 at 12:35:42 UTC, XavierAP wrote:
 I do not really think it's a bad solution, to check several 
 scalar arguments that must obey the same condition; just 
 wondering if you have better ideas. Try to avoid modifying the 
 function's signature and defining custom types, unless you have 
 a really terrific idea.

 void calc(double in1, double in2, double in3, double in4)
 in {
    foreach(const p; [&in1, &in2, &in3, &in4])
       enforce(*p > 0);
 }
 body { /* ... */ }
Please imagine double is a type that I wanted to avoid copying, just check by ref. Same question :p
Mar 11
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Sat, Mar 11, 2017 at 12:45:10PM +0000, XavierAP via Digitalmars-d-learn
wrote:
 On Saturday, 11 March 2017 at 12:35:42 UTC, XavierAP wrote:
 I do not really think it's a bad solution, to check several scalar
 arguments that must obey the same condition; just wondering if you
 have better ideas. Try to avoid modifying the function's signature
 and defining custom types, unless you have a really terrific idea.
 
 void calc(double in1, double in2, double in3, double in4)
 in {
    foreach(const p; [&in1, &in2, &in3, &in4])
       enforce(*p > 0);
 }
 body { /* ... */ }
Please imagine double is a type that I wanted to avoid copying, just check by ref. Same question :p
What about just: foreach (const ref p; [in1, in2, in3, in4]) ... ? T -- Stop staring at me like that! It's offens... no, you'll hurt your eyes!
Mar 11
parent reply XavierAP <n3minis-git yahoo.es> writes:
On Saturday, 11 March 2017 at 19:15:59 UTC, H. S. Teoh wrote:
 What about just:

 	foreach (const ref p; [in1, in2, in3, in4])
I would think there will be already one copy from the local parameter variables to the in situ array. Then from that one into the for each element it's ref'd all right. But I'm afk and can't test. Like the other copy I missed and Adam spotted when passing the arguments with missing ref qualifiers.. I realized that the code that sparked the question made no sense and should be done in a different way... As is always the case when these questions come up. But I still like the version with pointers ;)
Mar 11
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Sat, Mar 11, 2017 at 08:07:39PM +0000, XavierAP via Digitalmars-d-learn
wrote:
[...]
 I realized that the code that sparked the question made no sense and
 should be done in a different way... As is always the case when these
 questions come up.
 But I still like the version with pointers ;)
There's nothing wrong with using pointers in D. The fact that D alleviates most cases of (explicit) pointers is a testament to just how awesome it is. ;-) But that shouldn't deter anyone from using (explicit) pointers once in a while. In fact, D makes it such that it's a lot safer using pointers than in C/C++, mainly because it alleviates most of the dangerous use cases for pointers so what's left is generally harmless stuff. Unless your code for whatever reason is involved in heavy pointer hackery (like OS writing), but that's not a typical use case. T -- All problems are easy in retrospect.
Mar 13
parent XavierAP <n3minis-git yahoo.es> writes:
On Monday, 13 March 2017 at 14:47:20 UTC, H. S. Teoh wrote:
 On Sat, Mar 11, 2017 at 08:07:39PM +0000, XavierAP via 
 Digitalmars-d-learn wrote: [...]
 But I still like the version with pointers ;)
There's nothing wrong with using pointers in D. The fact that D alleviates most cases of (explicit) pointers is a testament to just how awesome it is. ;-) But that shouldn't deter anyone from using (explicit) pointers once in a while. In fact, D makes it such that it's a lot safer using pointers than in C/C++, mainly because it alleviates most of the dangerous use cases for pointers so what's left is generally harmless stuff. Unless your code for whatever reason is involved in heavy pointer hackery (like OS writing), but that's not a typical use case.
I did it again ;) enum params = [ "Radius of disk in m", "Integration step size along radius", "Total integration time in s", "Integration step size along time", "Time step size for output", "Initial temperature in C", "Edge temperature in C", "Flow temperature in C", "2D conductivity in W K^-1", "2D diffusivity in m^2 s^-1", "Convective coefficient in W m^-2 K^-1" ]; real*[params.length] vals = [ &R, &dr, &T, &dt, &dtOut, &u0, &uc, &ug, &k, &a, &h ]; import std.conv: to; /* ... */ foreach(i, param; params) { /* ... */ *vals[i] = to!real(val); } I had the same requirement to make separate named scalars instead of an array; but also an array was handier to assign the values inside a loop; and I needed a readable and simple way to map between them. An array of pointers is perfect I think. And the only dangerous thing I could do with the pointers is arithmetic on them instead of the pointed values, but: "pointer arithmetic not allowed in safe functions." So all is good :)
Mar 13
prev sibling parent reply Satoshi <satoshi rikarin.org> writes:
On Saturday, 11 March 2017 at 12:35:42 UTC, XavierAP wrote:
 I do not really think it's a bad solution, to check several 
 scalar arguments that must obey the same condition; just 
 wondering if you have better ideas. Try to avoid modifying the 
 function's signature and defining custom types, unless you have 
 a really terrific idea.

 void calc(double in1, double in2, double in3, double in4)
 in {
    foreach(const p; [&in1, &in2, &in3, &in4])
       enforce(*p > 0);
 }
 body { /* ... */ }
void calc(in double[] array...) { foreach (x; array) { } }
Mar 11
parent reply XavierAP <n3minis-git yahoo.es> writes:
On Saturday, 11 March 2017 at 13:44:30 UTC, Satoshi wrote:
 void calc(in double[] array...) {
 foreach (x; array) { }
 }
To do what I want it should be foreach(ref x; array) -- or const ref. But also I don't want to modify the function signature, certainly in this way. In another situation yes, but the arguments are very different magnitudes, for example temperatures, conductivity, heat power, etc. They should be separate arguments with self-documenting names. And it's not worth the bother to define a struct type for them as a set. Specially since this is an internal implementation "problem" that shouldn't affect the outer interface. I know there's something in std.algorithm for this, but afaik it would be relatively bloated compared to this pointer solution. In C++ I would use a &reference instead of a *pointer, but I actually think C++ references are redundant with pointers, not much safer, and plain confusing. I guess it's a not a common case because if a type is non trivial to copy it should probably be a class, which is already assigned by reference so I wouldn't need the pointer/ref.
Mar 11
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 11 March 2017 at 14:49:42 UTC, XavierAP wrote:
 But also I don't want to modify the function signature, 
 certainly in this way.
It is already copied by the time you get in to the function though because of the signature (unless they are constructed in-place at the call site). But you can also do an unrolled loop with AliasSeq http://dpldocs.info/experimental-docs/std.meta.AliasSeq.html import std.meta; import std.exception; void calc(double in1, double in2, double in3, double in4) in { foreach(ref item; AliasSeq!(in1, in2, in3, in4)) enforce(item > 0); } body { /* ... */ } Note that if the loop body is large, this could bloat the code slightly since a foreach over AliasSeq is always an unrolled loop. But that's probably irrelevant to you.
Mar 11