Creating InputRanges from strings, files etc.

Steven Schveighoffer schveiguy at gmail.com
Thu Nov 8 16:41:50 UTC 2018


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


More information about the Digitalmars-d-learn mailing list