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 :/