Re: map question

2022-01-23 Thread Stanislav Blinov via Digitalmars-d-learn
On Sunday, 23 January 2022 at 09:38:57 UTC, Siarhei Siamashka 
wrote:
On Sunday, 23 January 2022 at 09:08:46 UTC, Stanislav Blinov 
wrote:
Using `iota` here incurs additional computation and argument 
copies that are actually never used, i.e. wasted work. So I'd 
say go with `generate`, as that seems the intent.


Isn't this normally a compiler's job to eliminate all unused 
computations and copies?


It is the programmer's job long before it is the compiler's. It 
can do wonders on your "minimal" code but it's not its job to 
read your mind.



```D
auto foobar1(size_t n)
{
return n.iota.map!(_ => 123).array;
}

auto foobar2(size_t n)
{
return generate!(() => 123).take(n).array;
}
```

LDC with "-O -release" command line options generates pretty 
much identical code for foobar1 and foobar2 (I'm only showing 
the main loop, but the rest is also the same):

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar1FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar1FNaNbNfmZAi+0x20>

```

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar2FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar2FNaNbNfmZAi+0x20>

```

Do you have a better example to demonstrate `generate`'s 
superiority?


Try actual work instead of returning a literal :) Like e.g. 
calling dice(50, 50).


One thing to note though - `generate` will always eagerly call 
its function at least once. Which of course should also be 
considered in choosing the desired implementation. I.e. if your 
`n` comes from user and is allowed to be 0, then `generate` 
becomes an inferior choice.


Re: map question

2022-01-23 Thread Siarhei Siamashka via Digitalmars-d-learn
On Sunday, 23 January 2022 at 09:08:46 UTC, Stanislav Blinov 
wrote:
Using `iota` here incurs additional computation and argument 
copies that are actually never used, i.e. wasted work. So I'd 
say go with `generate`, as that seems the intent.


Isn't this normally a compiler's job to eliminate all unused 
computations and copies?


```D
auto foobar1(size_t n)
{
return n.iota.map!(_ => 123).array;
}

auto foobar2(size_t n)
{
return generate!(() => 123).take(n).array;
}
```

LDC with "-O -release" command line options generates pretty much 
identical code for foobar1 and foobar2 (I'm only showing the main 
loop, but the rest is also the same):

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar1FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar1FNaNbNfmZAi+0x20>

```

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar2FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar2FNaNbNfmZAi+0x20>

```

Do you have a better example to demonstrate `generate`'s 
superiority?


Re: map question

2022-01-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 22 January 2022 at 23:54:27 UTC, forkit wrote:
On Saturday, 22 January 2022 at 19:55:43 UTC, Stanislav Blinov 
wrote:




thanks for the explanation. That really helped :-)

writeln( generate!(() => dice(0.6, 1.4)).take(howManyTimes) );
[1, 1, 1, 1, 0]

(or after reading Ali's response - getting rid of rnd, and 
using _ )


writeln( howManyTimes.iota.map!(_ => dice(0.6, 1.4)) );
[1, 0, 1, 1, 1]

They produce exactly the same thing, so I guess it comes down 
to personal choice now.


Using `iota` here incurs additional computation and argument 
copies that are actually never used, i.e. wasted work. So I'd say 
go with `generate`, as that seems the intent.


Re: map question

2022-01-22 Thread forkit via Digitalmars-d-learn
On Saturday, 22 January 2022 at 19:55:43 UTC, Stanislav Blinov 
wrote:




thanks for the explanation. That really helped :-)

writeln( generate!(() => dice(0.6, 1.4)).take(howManyTimes) );
[1, 1, 1, 1, 0]

(or after reading Ali's response - getting rid of rnd, and using 
_ )


writeln( howManyTimes.iota.map!(_ => dice(0.6, 1.4)) );
[1, 0, 1, 1, 1]

They produce exactly the same thing, so I guess it comes down to 
personal choice now.




Re: map question

2022-01-22 Thread Ali Çehreli via Digitalmars-d-learn

On 1/22/22 11:32, forkit wrote:
> trying to make sense of the below:

The generate() solution shown by Stanislav Blinov is suitable here.

>  auto rnd = Random(unpredictableSeed);

Somebody else mentioned this before but none of the programs we've seen 
so far seemed to need a special random number generator. So, the default 
one, which is already randomized, would suffice. Just drop the line above.


>  // ok - using 'e =>' makes sense
>  writeln(howManyTimes.iota.map!(e => rnd.dice(0.6,
> 1.4)).format!"%(%s,%)");

When there is a syntactic need for a variable but that variable is not 
used, the idiomatic way of naming that variable is '_':


howManyTimes.iota.map!(_ => dice(0.6, 1.4))

(Note: I did not write rnd.dice.)

Ali



Re: map question

2022-01-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 22 January 2022 at 19:32:07 UTC, forkit wrote:

trying to make sense of the below:


// ---
module test;

import std;

void main()
{
auto rnd = Random(unpredictableSeed);

int howManyTimes = 5;

// ok - using 'e =>' makes sense
writeln(howManyTimes.iota.map!(e => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");


// ok - though using 'howManyTimes =>' doesn't make much 
sense??
writeln(howManyTimes.iota.map!(howManyTimes => 
rnd.dice(0.6, 1.4)).format!"%(%s,%)");


// NOT ok - using '5 =>' - but isn't this effectively the 
same as above line?
//writeln(howManyTimes.iota.map!(5 => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");

}

// ---


No, it's not the same. 'Tis not really a "map question", looks 
more like a question about


https://dlang.org/spec/expression.html#function_literals (see 
#10).


In the second case, you're defining a lambda with single 
parameter named `howManyTimes`, which is not at all related to 
your local variable of the same name. Third case is invalid, as 
you're effectively trying to do this:


auto func(T)(T 5) { return rnd.dice(0.6, 1.4); }

Which, of course, doesn't make any sense, does it? :)

Given your use case (call a function N times), I think `generate` 
would be more appropriate here:


```d
import std.random;
import std.stdio;
import std.range : generate, take;

void main()
{
auto rnd = Random(unpredictableSeed);
int howManyTimes = 5;
generate!(() => rnd.dice(0.6, 
1.4)).take(howManyTimes).writeln;

}

```


map question

2022-01-22 Thread forkit via Digitalmars-d-learn

trying to make sense of the below:


// ---
module test;

import std;

void main()
{
auto rnd = Random(unpredictableSeed);

int howManyTimes = 5;

// ok - using 'e =>' makes sense
writeln(howManyTimes.iota.map!(e => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");


// ok - though using 'howManyTimes =>' doesn't make much 
sense??
writeln(howManyTimes.iota.map!(howManyTimes => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");


// NOT ok - using '5 =>' - but isn't this effectively the 
same as above line?
//writeln(howManyTimes.iota.map!(5 => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");

}

// ---