View mode: basic / threaded / horizontal-split · Log in · Help
September 08, 2012
string to thread
In C++ (not C), when you wanted to parse a string, you were 
supposed to put the string inside a stream (std::stringstream), 
and then parse that new stream stream.

As a general rule, stringstream also allowed abstracting a string 
into a more generic stream.

I did not find anything equivalent in D. Did I just miss it?

How is a user supposed to parse a string in D?

I thought I was supposed to use "formattedRead", but was told 
that was actually more meant for library writers. Is there an 
alternative? Just trying to learn.
September 08, 2012
Re: string to thread
On Saturday, September 08, 2012 11:01:50 monarch_dodra wrote:
> In C++ (not C), when you wanted to parse a string, you were
> supposed to put the string inside a stream (std::stringstream),
> and then parse that new stream stream.
> 
> As a general rule, stringstream also allowed abstracting a string
> into a more generic stream.
> 
> I did not find anything equivalent in D. Did I just miss it?
> 
> How is a user supposed to parse a string in D?
> 
> I thought I was supposed to use "formattedRead", but was told
> that was actually more meant for library writers. Is there an
> alternative? Just trying to learn.

If you were to operate on a string in a manner similar to a stream, you'd be 
operating on it as a range, and there are a lot of range-based functions in 
Phobos. But if you want to specifically parse a range of characters, then use 
std.conv.parse:

http://dlang.org/phobos/std_conv.html#parse

If you want to know more about ranges, then this is currently the best 
tutorial on them:

http://ddili.org/ders/d.en/ranges.html

- Jonathan M Davis
September 09, 2012
Re: string to thread
On Saturday, 8 September 2012 at 09:10:30 UTC, Jonathan M Davis 
wrote:
>
> If you were to operate on a string in a manner similar to a 
> stream, you'd be
> operating on it as a range, and there are a lot of range-based 
> functions in
> Phobos. But if you want to specifically parse a range of 
> characters, then use
> std.conv.parse:
>
> http://dlang.org/phobos/std_conv.html#parse
>
> If you want to know more about ranges, then this is currently 
> the best
> tutorial on them:
>
> http://ddili.org/ders/d.en/ranges.html
>
> - Jonathan M Davis

Hum, parse. Looks useful. No need to create a temp stream like in 
C++ then. Good. Thanks for the info.

That said, is the "abstraction" itself available? Say *someone* 
wrote an xml parser, and the public interface expects to operate 
on a "File". Now, supposing I don't have a file, but all I have 
is a string, is it possible for someone pass that string the the 
function?
September 09, 2012
Re: string to thread
On Sunday, September 09, 2012 12:21:59 monarch_dodra wrote:
> Hum, parse. Looks useful. No need to create a temp stream like in
> C++ then. Good. Thanks for the info.
> 
> That said, is the "abstraction" itself available? Say *someone*
> wrote an xml parser, and the public interface expects to operate
> on a "File". Now, supposing I don't have a file, but all I have
> is a string, is it possible for someone pass that string the the
> function?

So, your asking if you can pass a string to a function which requires a file? 
Is that what you're asking? I don't see why that would work, given that the 
function expects a file. So, I must be misunderstanding something...

But one of the key design philosophies in Phobos is to use range-based APIs 
for just about everything. So, we wouldn't have an XML parser which operated 
on a file. It would operate on a range, and if you wanted to operate on a file, 
you'd get a range over the file and pass it in rather than the file. That's 
actually one key area that std.io should improve over std.stdio once Steven 
finally finishes it (since right now, it's kind of hard to have a good range 
interface on a file - you've can operate on it as a range of lines or chunks or 
whatnot but not as a range of characters or bytes without creating some sort 
of wrapper). But by using ranges everywhere, it becomes a lot like the *nix 
command-line where you can take the output of any program and pipe it as input 
to another program, allowing you to chain programs and mix and match them, but 
it's with ranges and functions rather than pipes and programs.

- Jonathan M Davis
September 09, 2012
Re: string to thread
On Sunday, 9 September 2012 at 10:36:14 UTC, Jonathan M Davis 
wrote:
> On Sunday, September 09, 2012 12:21:59 monarch_dodra wrote:
>> Hum, parse. Looks useful. No need to create a temp stream like 
>> in
>> C++ then. Good. Thanks for the info.
>> 
>> That said, is the "abstraction" itself available? Say *someone*
>> wrote an xml parser, and the public interface expects to 
>> operate
>> on a "File". Now, supposing I don't have a file, but all I have
>> is a string, is it possible for someone pass that string the 
>> the
>> function?
>
> So, your asking if you can pass a string to a function which 
> requires a file?
> Is that what you're asking? I don't see why that would work, 
> given that the
> function expects a file. So, I must be misunderstanding 
> something...

No, not like that, that'd be stupid.

In C++, a functions that can parse/unparse 
(serialize/deserialize) take a "stream" as an argument. That is 
c++'s paradigm. A stream, more often than not, is a filestream, 
or a standard input/output stream.

Now every once in a while, you'd like to parse/print a string. To 
do this, you create a "stringstream". That's what I was asking 
about.

More below:

> But one of the key design philosophies in Phobos is to use 
> range-based APIs
> for just about everything. So, we wouldn't have an XML parser 
> which operated
> on a file. It would operate on a range, and if you wanted to 
> operate on a file,
> you'd get a range over the file and pass it in rather than the 
> file. That's
> actually one key area that std.io should improve over std.stdio 
> once Steven
> finally finishes it (since right now, it's kind of hard to have 
> a good range
> interface on a file - you've can operate on it as a range of 
> lines or chunks or
> whatnot but not as a range of characters or bytes without 
> creating some sort
> of wrapper). But by using ranges everywhere, it becomes a lot 
> like the *nix
> command-line where you can take the output of any program and 
> pipe it as input
> to another program, allowing you to chain programs and mix and 
> match them, but
> it's with ranges and functions rather than pipes and programs.
>
> - Jonathan M Davis

Okay, that makes a sense to me. In c++, the paradigm is:
*Streams for formating.
*Iterators for algorithms.

Two paradigms => object to go from string(pointer/iterator) to 
stream.

And you are telling me that in D, everything is ranges, so there 
is no such need for a string stream. Everything operates on 
ranges, and you can (or should be able) to scare an range out of 
a stream, is this correct?

--------
What bothers me though (and is the source of my confusion) is 
that in that case, shouldn't stdin and stdout also be ranges? Or 
at least, shouldn't there be a global equivalent symbol that is a 
range?

Imagine teaching a program that asks a user his age, and prints 
it. This is what you would teach: (qualified names for making a 
point)

--------
import std.stdio;
void main()
{
    int age;
    //What is your age?
    std.stdio.stdin.readf("%s", &age);
    std.stdio.stdout.writefln("Your age is %s", age);
}
--------

Now, the next logical step in the lesson, is to make things more 
generic with a function, right? Why stop at std[in|out]?

--------
import std.stdio;
import std.array;
import std.format;

void askAge(RangeIn, RangeOut)(RangeIn ri, RangeOut ro)
{
    int age;
    //What is your age?
    ri.formattedRead("%s", &age); //This changed
    ro.formattedWrite("Your age is %s\n", age); //So did this

}

void main()
{
    auto input = "42";
    auto output = appender!string();
    askAge(input, output);
    writeln(output.data);
}
--------

Instead of using std[in|out], I create an InputRange (a string), 
and an output range (an Appender!string). However, the methods 
readf/writefln have been changed!

This is what is confusing me: I have been taught to work on 
streams, but I can't use that interface on strings/ranges :/
September 09, 2012
Re: string to thread
On Sunday, September 09, 2012 14:13:26 monarch_dodra wrote:
> Okay, that makes a sense to me. In c++, the paradigm is:
> *Streams for formating.
> *Iterators for algorithms.
> 
> Two paradigms => object to go from string(pointer/iterator) to
> stream.
> 
> And you are telling me that in D, everything is ranges, so there
> is no such need for a string stream. Everything operates on
> ranges, and you can (or should be able) to scare an range out of
> a stream, is this correct?

Pretty much. Some functions will never operate on ranges, and in some cases it 
may make sense to have a way to do something with ranges and a way to do it 
without them, but in general, things are going to be range based, and we may 
not even _have_ streams, since a stream is effectively a range.

> What bothers me though (and is the source of my confusion) is
> that in that case, shouldn't stdin and stdout also be ranges? Or
> at least, shouldn't there be a global equivalent symbol that is a
> range?

More likely, there will be a way to get a range over stdin or stdout. That's 
pretty much how we deal with it now (stdin and stdout are Files and get 
whatever functions File has). It's just that we need a better range type on 
Files (something which is forward range of bytes or characters rather than 
ranges of lines or chunks). That'll come with std.io, but Steven has been too 
busy to finish it yet.

> Instead of using std[in|out], I create an InputRange (a string),
> and an output range (an Appender!string). However, the methods
> readf/writefln have been changed!

I'd point out that formattedRead and formattedWrite aren't really meant to be 
used directly in your typical program, so they're not a terribly great 
example. Regardless, _some_ functions will make more sense to _not_ be range-
based, and even if something works better if it's range-based, some older stuff 
which was created before we started using ranges is going to stick around for 
backwards compatibility if nothing else. So, some things may get range-based 
replacements but still have the old versions around. Exactly what happens with 
input and output will depend heavily on what happens with std.io.

> This is what is confusing me: I have been taught to work on
> streams, but I can't use that interface on strings/ranges :/

I don't understand this remark. You mean that the ranges for operating on 
input and output properly don't exist yet? That's definitely true, but it will 
be fixed. If you mean something else, I don't know what you mean. Streams 
pretty much _are_ ranges.

- Jonathan M Davis
Top | Discussion index | About this forum | D home