www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Metaprog can be abstruse

reply user1234 <user1234 12.de> writes:
Example:

```d
auto genDecimalRanks()
{
     import std.conv;
     auto r = 1;
     auto result = "[";
     foreach (i; 1 .. 11)
     {
         result ~= to!string(r);
         if (i < 10)
             result ~= ", ";
         r *= 10;
     }
     result ~= "]";
     return result;
}

/// like 
[1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000]
immutable decimalRanks = mixin(genDecimalRanks);
```

It takes much more space and time to write DDOC + the generator 
than the space + time required to write the equivalent explicit 
declaration without comments, i.e "self documenting".

So metaprog is not the panacea, do you think to that before 
"meta-progrogramming", or do you "meta-prog" just because it's 
nice ?
Jul 04
next sibling parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Monday, 4 July 2022 at 08:24:01 UTC, user1234 wrote:
 Example:

 ```d
 auto genDecimalRanks()
 {
     import std.conv;
     auto r = 1;
     auto result = "[";
     foreach (i; 1 .. 11)
     {
         result ~= to!string(r);
         if (i < 10)
             result ~= ", ";
         r *= 10;
     }
     result ~= "]";
     return result;
 }

 /// like 
 [1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000]
 immutable decimalRanks = mixin(genDecimalRanks);
 ```

 It takes much more space and time to write DDOC + the generator 
 than the space + time required to write the equivalent explicit 
 declaration without comments, i.e "self documenting".

 So metaprog is not the panacea, do you think to that before 
 "meta-progrogramming", or do you "meta-prog" just because it's 
 nice ?
Not necessarily. ```d immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array; ``` -- Bastiaan.
Jul 04
next sibling parent reply user1234 <user1234 12.de> writes:
On Monday, 4 July 2022 at 09:40:45 UTC, Bastiaan Veelo wrote:
 Not necessarily.
 ```d
 immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array;
 ```

 -- Bastiaan.
Hi, to this alternative I'd say that it's not self documenting. So it still has 50% of the initial problem.
Jul 04
next sibling parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Monday, 4 July 2022 at 09:43:11 UTC, user1234 wrote:
 On Monday, 4 July 2022 at 09:40:45 UTC, Bastiaan Veelo wrote:
 Not necessarily.
 ```d
 immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array;
 ```

 -- Bastiaan.
Hi, to this alternative I'd say that it's not self documenting. So it still has 50% of the initial problem.
I can see your point, but it depends on how used you are to reading chains of range algorithms. I read this as "given the integers 0 to 9, use them as the powers of ten and put them in an array". There is a point to be made that this is more self-documenting than the hand-written alternative: Here it is obvious that the ranks cover all powers of 10 from 0 to 9 in order. In the hand-written alternative you'd either assume that is the case, or have to meticulously count all the zero's to be sure. -- Bastiaan.
Jul 04
parent reply Dom Disc <dominikus scherkl.de> writes:
On Monday, 4 July 2022 at 10:19:36 UTC, Bastiaan Veelo wrote:
 On Monday, 4 July 2022 at 09:43:11 UTC, user1234 wrote:
 On Monday, 4 July 2022 at 09:40:45 UTC, Bastiaan Veelo wrote:
 Not necessarily.
 ```d
 immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array;
 ```
Hi, to this alternative I'd say that it's not self documenting. So it still has 50% of the initial problem.
There is a point to be made that this is more self-documenting than the hand-written alternative: Here it is obvious that the ranks cover all powers of 10 from 0 to 9 in order.
This advantage becomes much more clear in, let's say: ```d immutable long powersOfThree = iota(27).map!(p => 3.pow(p)).array; ``` Handwritten this is a very long chain of arbitrary numbers and you have to put a very close look, that those are indeed the powers of three.
Jul 04
parent reply kdevel <kdevel vogtner.de> writes:
On Monday, 4 July 2022 at 13:03:55 UTC, Dom Disc wrote:
[...]
 This advantage becomes much more clear in, let's say:
 ```d
 immutable long powersOfThree = iota(27).map!(p => 
 3.pow(p)).array;
 ```
 Handwritten this is a very long chain of arbitrary numbers and 
 you have to put a very close look, that those are indeed the 
 powers of three.
Really? ``` immutable long [] powersOfThree = [ 1, 3, 3 * 3, 3 * 3 * 3, 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, ]; ```
Jul 05
parent Dom Disc <dominikus scherkl.de> writes:
On Wednesday, 6 July 2022 at 00:11:58 UTC, kdevel wrote:
 On Monday, 4 July 2022 at 13:03:55 UTC, Dom Disc wrote:
 [...]
 This advantage becomes much more clear in, let's say:
 ```d
 immutable long powersOfThree = iota(27).map!(p => 
 3.pow(p)).array;
 ```
 Handwritten this is a very long chain of arbitrary numbers and 
 you have to put a very close look, that those are indeed the 
 powers of three.
Really? ``` immutable long [] powersOfThree = [ 1, 3, 3 * 3, 3 * 3 * 3, 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, ]; ```
Ok, but with this, you can't see where the overflow will occur. So you have the same problem as with the one-liner (and it is indeed very much longer).
Jul 06
prev sibling next sibling parent bauss <jj_1337 live.dk> writes:
On Monday, 4 July 2022 at 09:43:11 UTC, user1234 wrote:
 On Monday, 4 July 2022 at 09:40:45 UTC, Bastiaan Veelo wrote:
 Not necessarily.
 ```d
 immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array;
 ```

 -- Bastiaan.
Hi, to this alternative I'd say that it's not self documenting. So it still has 50% of the initial problem.
I think that depends on your expertise. It's self-document if you understand the functionality of iota, map, pow and array. Saying it's not self documenting is the same as saying: `writeln("Hello World!")` isn't self documenting, but I do believe we can both agree on that it pretty much is. It's self documenting for the same reason, you understand the functionality behind writeln and thus knows what it is doing. The same can be said about the above function chain. It's very much straight-forward in what it's doing and it's only when one doesn't understand these "basic" functions that one don't find it self-documenting.
Jul 04
prev sibling parent drug007 <drug2004 bk.ru> writes:
On 7/4/22 12:43, user1234 wrote:
 On Monday, 4 July 2022 at 09:40:45 UTC, Bastiaan Veelo wrote:
 Not necessarily.
 ```d
 immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array;
 ```

 -- Bastiaan.
Hi, to this alternative I'd say that it's not self documenting. So it still has 50% of the initial problem.
As for me it is self documenting. And it is more readable than your hand written imperative version.
Jul 04
prev sibling parent reply kdevel <kdevel vogtner.de> writes:
On Monday, 4 July 2022 at 09:40:45 UTC, Bastiaan Veelo wrote:
 [...]
 Not necessarily.
 ```d
 immutable decimalRanks = iota(10).map!(p => 10.pow(p)).array;
 ```
Your example requires ``` import std.range; // for iota import std.algorithm; // for map import std.math; // for pow of int ``` Then your example is prone to errors: ``` immutable decimalRanks = iota(13).map!(p => 10.pow(p)).array; // silent wrap around ``` (unit)test to the rescue: ``` auto make_decimal_rank () { import std.range; import std.algorithm; import std.math; return iota (13).map!(p => 10.pow (p)).array; } void main () { import std.stdio; immutable decimalRank = make_decimal_rank; decimalRank.writeln; typeof (decimalRank).stringof.writeln; } unittest { enum ar13 = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000 ]; pragma (msg, typeof (ar13)); assert (make_decimal_rank == ar13); } ``` Running: ``` dmd -checkaction=context -unittest -run decrank long[] decrank.d(35): [unittest] [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 1410065408, 1215752192, -727379968] != [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000] 1/1 modules FAILED unittests ```
Jul 04
parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Monday, 4 July 2022 at 23:19:27 UTC, kdevel wrote:
 Then your example is prone to errors:

 ```
 immutable decimalRanks = iota(13).map!(p => 10.pow(p)).array; 
 // silent wrap around
 ```

 (unit)test to the rescue:
To be fair, original example also requires some testing.
Jul 05
parent kdevel <kdevel vogtner.de> writes:
On Tuesday, 5 July 2022 at 07:37:35 UTC, Alexandru Ermicioi wrote:
[...]
 To be fair, original example also requires some testing.
Sure, but user1234 was never in favor of it. It is prone to the same wrap around which have been avoided by using strings in the first place: ``` auto sgenDecimalRanks() { auto r = "1"; auto result = "["; foreach (i; 1 .. 13) { result ~= r; if (i < 12) result ~= ", "; r ~= '0'; } result ~= "]"; return result; } ```
Jul 05
prev sibling next sibling parent reply bauss <jj_1337 live.dk> writes:
On Monday, 4 July 2022 at 08:24:01 UTC, user1234 wrote:
 Example:

 ```d
 auto genDecimalRanks()
 {
     import std.conv;
     auto r = 1;
     auto result = "[";
     foreach (i; 1 .. 11)
     {
         result ~= to!string(r);
         if (i < 10)
             result ~= ", ";
         r *= 10;
     }
     result ~= "]";
     return result;
 }

 /// like 
 [1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000]
 immutable decimalRanks = mixin(genDecimalRanks);
 ```

 It takes much more space and time to write DDOC + the generator 
 than the space + time required to write the equivalent explicit 
 declaration without comments, i.e "self documenting".

 So metaprog is not the panacea, do you think to that before 
 "meta-progrogramming", or do you "meta-prog" just because it's 
 nice ?
If you don't like the iota version then you can just do this: (Modified version of yours.) ```d auto genDecimalRanks() { import std.conv; auto r = 1; int[] result = []; foreach (i; 1 .. 11) { result ~= r; r *= 10; } return result; } /// like [1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000] static immutable decimalRanks = genDecimalRanks(); ``` Everything at compile-time doesn't have to be strings and mixin :) static and enum will trigger ctfe.
Jul 04
parent reply user1234 <user1234 12.de> writes:
On Monday, 4 July 2022 at 10:29:24 UTC, bauss wrote:
 On Monday, 4 July 2022 at 08:24:01 UTC, user1234 wrote:
 [...]
If you don't like the iota version then you can just do this: (Modified version of yours.) ```d auto genDecimalRanks() { import std.conv; auto r = 1; int[] result = []; foreach (i; 1 .. 11) { result ~= r; r *= 10; } return result; } /// like [1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000] static immutable decimalRanks = genDecimalRanks(); ``` Everything at compile-time doesn't have to be strings and mixin :) static and enum will trigger ctfe.
still the same problems as the initial version (even if yes I know it's absurd code)
Jul 04
parent bauss <jj_1337 live.dk> writes:
On Monday, 4 July 2022 at 10:37:14 UTC, user1234 wrote:
 still the same problems as the initial version (even if yes I 
 know it's absurd code)
I'm actually not sure what you're even trying to achieve or what problem you're trying to solve tbh. Could you perhaps give an example of what your expectations are and how exactly this differs from your expectations of runtime? Because my modified version of yours works both at ctfe and runtime, so it has nothing to do with ctfe really. The only thing ctfe about is that it's statically initialized, but you can use it for runtime arrays too, where the function will be executed at runtime. So there's really no metaprogramming involved in that.
Jul 04
prev sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
I personally only use metaprogramming for tasks i will know will 
become repetitive

For your example it is not worth it, you only would write that 
code once anyways

For my case here, it perfectly worth it, adding new packet 
handler is a matter of an attribute

The complexity of the code added should be relative to its 
benefits, no need to over do it

![screenshot](https://i.imgur.com/gLvENTY.png)
Jul 04