Thread overview
Inconsistent chain (implicitly converts to int)
Apr 05
rkompass
Apr 06
rkompass
April 05

Hi everyone,

Technically r1 and r2 are different types of range. Isn't it inconsistent to chain both? If not, why is the char type converted to int?

import std.stdio,
       std.range;

void main() {
  auto r1 = N!size_t(10, 1, 1);
  auto r2 = N!real(15, .5, 10);

  r1.chain(r2).writeln;
  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5]

  auto a = [97, 98, 99];
  auto b = ['d', 'e', 'f'];

  a.chain(b).writeln;
  // [97, 98, 99, 100, 101, 102]
}

struct N(T)
{
  T last, step, first;
  bool empty() => first >= last;
  T front() => first;
  auto popFront() => first += step;
}
void main() {
  auto r1 = N!size_t(10, 1, 1);
  auto r2 = N!real(15, .5, 10);

  r1.chain(r2).writeln;
  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5]

  auto a = [97, 98, 99];
  auto b = ['d', 'e', 'f'];

  a.chain(b).writeln;
  // [97, 98, 99, 100, 101, 102]
}

struct N(T)
{
  T last, step, first;
  bool empty() => first >= last;
  T front() => first;
  auto popFront() => first += step;
}

SDB@79

April 05
On Fri, Apr 05, 2024 at 03:18:09PM +0000, Salih Dincer via Digitalmars-d-learn wrote:
> Hi everyone,
> 
> Technically r1 and r2 are different types of range. Isn't it inconsistent to chain both? If not, why is the char type converted to int?
[...]

It's not inconsistent if there exists a common type that both range element types implicit convert to.

The real problem is the implicit conversion of char to int, which I have been against for a long time.  Walter, however, disagrees.


T

-- 
What's worse than raining cats and dogs?  Hailing taxis!
April 05
On Friday, 5 April 2024 at 16:05:20 UTC, H. S. Teoh wrote:
> On Fri, Apr 05, 2024 at 03:18:09PM +0000, Salih Dincer via Digitalmars-d-learn wrote:
>> Hi everyone,
>> 
>> Technically r1 and r2 are different types of range. Isn't it inconsistent to chain both? If not, why is the char type converted to int?
> [...]
>
> It's not inconsistent if there exists a common type that both range element types implicit convert to.
>

In the first example the int's are converted to doubles (also common type).
But they appear as int's because writeln does not write a trailing .0.
April 05

On Friday, 5 April 2024 at 16:05:20 UTC, H. S. Teoh wrote:

>

On Fri, Apr 05, 2024 at 03:18:09PM +0000, Salih Dincer via Digitalmars-d-learn wrote:

>

Hi everyone,

Technically r1 and r2 are different types of range. Isn't it inconsistent to chain both? If not, why is the char type converted to int?
[...]

It's not inconsistent if there exists a common type that both range element types implicit convert to.

The real problem is the implicit conversion of char to int, which I have been against for a long time. Walter, however, disagrees.

T

  auto a = [97, 98, 99];
  auto b = ['d', 'e', 'f'];

  a.chain(b).map!(chr => chr.to!char).writeln;
  // abcdef

Nice, there is a solution that requires memory allocation, but it still makes you think!

However, they can fix this in Phobos3 because now we have this too: https://dlang.org/changelog/2.108.0.html#range_predicate_element

PS. I think I unintentionally made a chain by repeating the source code above, sorry :)

SDB@79

April 05
On Friday, 5 April 2024 at 21:16:42 UTC, rkompass wrote:
>
> In the first example the int's are converted to doubles (also common type).
> But they appear as int's because writeln does not write a trailing .0.

But it doesn't work as you say! I even tried it on an older version and got the same result.

SDB@79
April 06

On Friday, 5 April 2024 at 21:26:10 UTC, Salih Dincer wrote:

>

On Friday, 5 April 2024 at 21:16:42 UTC, rkompass wrote:

>

In the first example the int's are converted to doubles (also common type).
But they appear as int's because writeln does not write a trailing .0.

But it doesn't work as you say! I even tried it on an older version and got the same result.

SDB@79

I checked:

import std.stdio,
       std.range,
       std.algorithm;

struct N(T)
{
  T last, step, first;
  bool empty() => first >= last;
  T front() => first;
  auto popFront() => first += step;
}

void main() {
  auto r1 = N!size_t(10, 1, 1);
  auto r2 = N!real(15, .5, 10);

  // r1.chain(r2).writeln;
  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5]
  r1.chain(r2).map!(x => typeid(x)).writeln;
  // [real, real, . . . , real]
}

and it seems to work as I said.

April 06

On Saturday, 6 April 2024 at 09:21:34 UTC, rkompass wrote:

>

I checked:

import std.stdio,
       std.range,
       std.algorithm;

struct N(T)
{
  T last, step, first;
  bool empty() => first >= last;
  T front() => first;
  auto popFront() => first += step;
}

void main() {
  auto r1 = N!size_t(10, 1, 1);
  auto r2 = N!real(15, .5, 10);

and it seems to work as I said.

Thank you for checking again, but it is important to be solution oriented. How about Tuple?

Yes, it might be wise to use a tuple in this case:

  //...
  auto tuple = a.zip(b);
  tuple.writeln;
  // [Tuple!(int, dchar)(97, 'd'), Tuple!(int, dchar)(98, 'e'), Tuple!(int, dchar)(99, 'f')]

  tuple.map!(num => num[0].to!dchar).write;
  tuple.map!"a[1]".writeln; // abcdef
}

SDB@79