Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn
On Thursday, 8 November 2018 at 16:41:50 UTC, Steven 
Schveighoffer wrote:

I did this in a run.dlang.org playground:

pragma(msg, ElementType!(typeof(b)));
pragma(msg, ElementType!(typeof(d)));

I get:
immutable(ubyte)
ubyte

Which means they aren't the same type, and they don't define 
the same interface (InputRange!(ubyte) is not the same as 
InputRange!(immutable(ubyte)) ).


Other than simply using compile-time functions, and dropping 
the object interface as Alex suggests, the easiest thing I can 
recommend is wrapping representation into a casting input range 
such as map:


auto b = inputRangeObject(a.representation.map!(b => ubyte(b)));

You can see all this here:

https://run.dlang.io/is/1E6Uqj

-Steve


Thanks, guys, those are helpful pointers.


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Steven Schveighoffer via Digitalmars-d-learn

On 11/8/18 11:15 AM, Vinay Sajip wrote:

On Thursday, 8 November 2018 at 14:38:37 UTC, Paul Backus wrote:
To pass these ranges around using the `InputRange` interface, use 
`inputRangeObject` to wrap them:


    InputRange!ubyte r3 = inputRangeObject(r1);
    InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


I did a bit more digging, and it seems to work for strings but not for 
files: The program


import std.algorithm.iteration;
import std.format;
import std.range;
import std.stdio;
import std.string;

void somefn(InputRange!(immutable(ubyte)) r) {
     writeln(format!"%s"(r));
}

void main()
{
     auto a = "Hello, world!";
     auto b = inputRangeObject(a.representation);
     somefn(b);
     auto c = stdin.byChunk(1024).joiner;
     auto d = inputRangeObject(c);
     //somefn(d);
}

compiles as given above, but if the somefn(d) line is uncommented, I get 
an error:


function onlineapp.somefn(InputRange!(immutable(ubyte)) r) is not 
callable using argument types (InputRangeObject!(Result))
onlineapp.d(18):    cannot pass argument d of type 
std.range.interfaces.InputRangeObject!(Result) to parameter 
InputRange!(immutable(ubyte)) r


Do I need to do an explicit cast? If so, can someone tell me the precise 
incantation? How come it doesn't figure out that the underlying range is 
a ubyte range, or is it to do with immutability, or something else 
altogether?


A cool feature of D is to have it tell you something about your code at 
compile time.


I did this in a run.dlang.org playground:

pragma(msg, ElementType!(typeof(b)));
pragma(msg, ElementType!(typeof(d)));

I get:
immutable(ubyte)
ubyte

Which means they aren't the same type, and they don't define the same 
interface (InputRange!(ubyte) is not the same as 
InputRange!(immutable(ubyte)) ).


Other than simply using compile-time functions, and dropping the object 
interface as Alex suggests, the easiest thing I can recommend is 
wrapping representation into a casting input range such as map:


auto b = inputRangeObject(a.representation.map!(b => ubyte(b)));

You can see all this here:

https://run.dlang.io/is/1E6Uqj

-Steve


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Alex via Digitalmars-d-learn

On Thursday, 8 November 2018 at 16:15:25 UTC, Vinay Sajip wrote:

On Thursday, 8 November 2018 at 14:38:37 UTC, Paul Backus wrote:
To pass these ranges around using the `InputRange` interface, 
use `inputRangeObject` to wrap them:


InputRange!ubyte r3 = inputRangeObject(r1);
InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


I did a bit more digging, and it seems to work for strings but 
not for files: The program


import std.algorithm.iteration;
import std.format;
import std.range;
import std.stdio;
import std.string;

void somefn(InputRange!(immutable(ubyte)) r) {
writeln(format!"%s"(r));
}

void main()
{
auto a = "Hello, world!";
auto b = inputRangeObject(a.representation);
somefn(b);
auto c = stdin.byChunk(1024).joiner;
auto d = inputRangeObject(c);
//somefn(d);
}

compiles as given above, but if the somefn(d) line is 
uncommented, I get an error:


function onlineapp.somefn(InputRange!(immutable(ubyte)) r) is 
not callable using argument types (InputRangeObject!(Result))
onlineapp.d(18):cannot pass argument d of type 
std.range.interfaces.InputRangeObject!(Result) to parameter 
InputRange!(immutable(ubyte)) r


Do I need to do an explicit cast? If so, can someone tell me 
the precise incantation? How come it doesn't figure out that 
the underlying range is a ubyte range, or is it to do with 
immutability, or something else altogether?


you could use a template for somefn definition:

´´´
void somefn(T)(T r) {
writeln(format!"%s"(r));
}
´´´


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn

On Thursday, 8 November 2018 at 14:38:37 UTC, Paul Backus wrote:
To pass these ranges around using the `InputRange` interface, 
use `inputRangeObject` to wrap them:


InputRange!ubyte r3 = inputRangeObject(r1);
InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


I did a bit more digging, and it seems to work for strings but 
not for files: The program


import std.algorithm.iteration;
import std.format;
import std.range;
import std.stdio;
import std.string;

void somefn(InputRange!(immutable(ubyte)) r) {
writeln(format!"%s"(r));
}

void main()
{
auto a = "Hello, world!";
auto b = inputRangeObject(a.representation);
somefn(b);
auto c = stdin.byChunk(1024).joiner;
auto d = inputRangeObject(c);
//somefn(d);
}

compiles as given above, but if the somefn(d) line is 
uncommented, I get an error:


function onlineapp.somefn(InputRange!(immutable(ubyte)) r) is not 
callable using argument types (InputRangeObject!(Result))
onlineapp.d(18):cannot pass argument d of type 
std.range.interfaces.InputRangeObject!(Result) to parameter 
InputRange!(immutable(ubyte)) r


Do I need to do an explicit cast? If so, can someone tell me the 
precise incantation? How come it doesn't figure out that the 
underlying range is a ubyte range, or is it to do with 
immutability, or something else altogether?


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn

On Thursday, 8 November 2018 at 14:38:37 UTC, Paul Backus wrote:
You can iterate through a file one ubyte at a time using 
`byChunk` and `joiner`:


auto r1 = stdin.byChunk(1024).joiner;
assert(is(typeof(r1.front) == ubyte));

You can iterate through a string one ubyte at a time using 
`representation`:


auto r2 = "To be or not to be".representation;
assert(is(typeof(r2.front) == immutable(ubyte)));

To pass these ranges around using the `InputRange` interface, 
use `inputRangeObject` to wrap them:


InputRange!ubyte r3 = inputRangeObject(r1);
InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


Aha - inputRangeObject was the thing I was missing. Thanks!


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 8 November 2018 at 13:58:55 UTC, Vinay Sajip wrote:
Excuse my ignorance, but from looking at the documentation on 
std.range and a quick skim of the guides mentioned there near 
the top, I can't see what the simple way is of creating an 
InputRange!(ubyte) from strings, files etc. I would have 
expected to find something in the DLang Tour about this, but 
couldn't find anything. Please can someone tell me how to do 
it? Just to be clear, I want to create an object which is an 
InputRange!(ubyte) and pass that around, rather than e.g. 
iterate over a string or a file.


You can iterate through a file one ubyte at a time using 
`byChunk` and `joiner`:


auto r1 = stdin.byChunk(1024).joiner;
assert(is(typeof(r1.front) == ubyte));

You can iterate through a string one ubyte at a time using 
`representation`:


auto r2 = "To be or not to be".representation;
assert(is(typeof(r2.front) == immutable(ubyte)));

To pass these ranges around using the `InputRange` interface, use 
`inputRangeObject` to wrap them:


InputRange!ubyte r3 = inputRangeObject(r1);
InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread rikki cattermole via Digitalmars-d-learn

On 09/11/2018 2:58 AM, Vinay Sajip wrote:
Excuse my ignorance, but from looking at the documentation on std.range 
and a quick skim of the guides mentioned there near the top, I can't see 
what the simple way is of creating an InputRange!(ubyte) from strings, 
files etc. I would have expected to find something in the DLang Tour 
about this, but couldn't find anything. Please can someone tell me how 
to do it? Just to be clear, I want to create an object which is an 
InputRange!(ubyte) and pass that around, rather than e.g. iterate over a 
string or a file.


TLDR of how to write an input range:

struct MyInputRange {
ubyte[] input;

@property {
ubyte front() {
return this.input[0];
}

bool empty() {
return this.input.length == 0;
}
}

void popFront() {
this.input = this.input[1 .. $];
}
}

import std.stdio;

void main() {
foreach(b; MyInputRange([1, 2, 3])) {
writeln(b);
}
}


Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn
Excuse my ignorance, but from looking at the documentation on 
std.range and a quick skim of the guides mentioned there near the 
top, I can't see what the simple way is of creating an 
InputRange!(ubyte) from strings, files etc. I would have expected 
to find something in the DLang Tour about this, but couldn't find 
anything. Please can someone tell me how to do it? Just to be 
clear, I want to create an object which is an InputRange!(ubyte) 
and pass that around, rather than e.g. iterate over a string or a 
file.