www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Phobos packages a bit confusing

reply retard <re tard.com.invalid> writes:
Hi

after using D1 and Tango for couple of years we decided to experiment 
with D2 and Phobos in a small scale project. For some reason the mostly 
flat package hierarchy seemed rather confusing.

For instance, it took two of us 15 minutes to build a program that reads 
a line from user, converts the string to a natural number, adds one, and 
finally prints it to the screen. Entities like 'stdin' seem to have no 
documentation at all. What should I import to get it, what interfaces 
does it implement etc.

When writing this, I already forgot what package contained the to! 
template. My intuition says it should be in
 * std.stdint [int related operations]
 * std.format [number formats?]
 * std.typecons [we're constructing a int from a string]
 * std.string [the input was a string, maybe toInt is a string operation]
 * std.numeric [it's a numeric operation, isn't it]

I admit using higher level languages has made major damage to my brain 

intuitive, but in Phobos the set of packages and their contents feels 
more or less arbitrary. Is there anything that can be done?
Nov 29 2009
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
retard Wrote:

 Hi
 
 after using D1 and Tango for couple of years we decided to experiment 
 with D2 and Phobos in a small scale project. For some reason the mostly 
 flat package hierarchy seemed rather confusing.
 
 For instance, it took two of us 15 minutes to build a program that reads 
 a line from user, converts the string to a natural number, adds one, and 
 finally prints it to the screen. Entities like 'stdin' seem to have no 
 documentation at all. What should I import to get it, what interfaces 
 does it implement etc.
That's an interesting example considering how Tango IO is way more complex. Comparatively speaking, 15 minutes is great! That being said, there probably are ways to make D2 Phobos easier to use.
 When writing this, I already forgot what package contained the to! 
 template. 
std.conv (for conversions)
 My intuition says it should be in
  * std.stdint [int related operations]
  * std.format [number formats?]
  * std.typecons [we're constructing a int from a string]
  * std.string [the input was a string, maybe toInt is a string operation]
  * std.numeric [it's a numeric operation, isn't it]
 
 I admit using higher level languages has made major damage to my brain 

 intuitive, but in Phobos the set of packages and their contents feels 
 more or less arbitrary. Is there anything that can be done?
Any massively used language is easier to use because a google search turns up similar code. I've found both D2 Phobos and Tango to be easy to use once you start. Tango was easier to find where most things were, but was amazingly tough to assemble generic pieces for IO. I remember reading line buffered text from standard in was way simpler with D2 Phobos.
Nov 29 2009
parent retard <re tard.com.invalid> writes:
Sun, 29 Nov 2009 14:36:24 -0500, Jason House wrote:

 retard Wrote:
 
 Hi
 
 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the mostly
 flat package hierarchy seemed rather confusing.
 
 For instance, it took two of us 15 minutes to build a program that
 reads a line from user, converts the string to a natural number, adds
 one, and finally prints it to the screen. Entities like 'stdin' seem to
 have no documentation at all. What should I import to get it, what
 interfaces does it implement etc.
That's an interesting example considering how Tango IO is way more complex. Comparatively speaking, 15 minutes is great! That being said, there probably are ways to make D2 Phobos easier to use.
 When writing this, I already forgot what package contained the to!
 template.
std.conv (for conversions)
 My intuition says it should be in
  * std.stdint [int related operations] * std.format [number formats?]
  * std.typecons [we're constructing a int from a string] * std.string
  [the input was a string, maybe toInt is a string operation] *
  std.numeric [it's a numeric operation, isn't it]
 
 I admit using higher level languages has made major damage to my brain

 rather intuitive, but in Phobos the set of packages and their contents
 feels more or less arbitrary. Is there anything that can be done?
Any massively used language is easier to use because a google search turns up similar code. I've found both D2 Phobos and Tango to be easy to use once you start. Tango was easier to find where most things were, but was amazingly tough to assemble generic pieces for IO. I remember reading line buffered text from standard in was way simpler with D2 Phobos.
Agreed. Also, once you start memorizing stuff, it doesn't matter that much anymore what the functions are called and where they can be found. I found the tutorials on Tango's site very helpful when learning it. I also agree that doing common tasks is more straightforward with Phobos and the resulting code is also a bit shorter, but using Tango was a bit more intuitive.
Nov 29 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
retard wrote:
 Hi
 
 after using D1 and Tango for couple of years we decided to experiment 
 with D2 and Phobos in a small scale project. For some reason the mostly 
 flat package hierarchy seemed rather confusing.
 
 For instance, it took two of us 15 minutes to build a program that reads 
 a line from user, converts the string to a natural number, adds one, and 
 finally prints it to the screen. Entities like 'stdin' seem to have no 
 documentation at all. What should I import to get it, what interfaces 
 does it implement etc.
 
 When writing this, I already forgot what package contained the to! 
 template. My intuition says it should be in
  * std.stdint [int related operations]
  * std.format [number formats?]
  * std.typecons [we're constructing a int from a string]
  * std.string [the input was a string, maybe toInt is a string operation]
  * std.numeric [it's a numeric operation, isn't it]
 
 I admit using higher level languages has made major damage to my brain 

 intuitive, but in Phobos the set of packages and their contents feels 
 more or less arbitrary. Is there anything that can be done?
These are great points. I personally consider import files a necessary evil. There are a couple of things that make me hopeful about simplifying the situation: a) D parses fast enough to allow importing extensive modules; b) The "no-hijack" approach allows liberal importing of modules without fear of serious name clashes. Walter and I discussed quite a few times the possibility of defining std.all that publically imports all of std. My experiments show that a short script importing std.all will compile slower, but not too slow, compared to a script that only import a few modules. One other possibility would be to define some generic modules that group together useful lower-level modules. The question is of course how to name those aggregation modules (std.common?) and what they should include. Some PR or tips on how to search the documentation may also be helpful. If you navigate to Phobos' homepage http://digitalmars.com/d/2.0/phobos/phobos.html and then enter conversion in the search box, std.conv comes up first. Also, the same module comes up first if you search this with google: d programming language conversion It would be great to improve D and Phobos accessibility for first-time users. (To my personal satisfaction, searching google for std::algorithm puts D's std.algorithm in the third or fifth position (depending how you count), after the obligatory C++ reference sites.) Andrei
Nov 29 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 Walter and I discussed quite a few times the possibility of defining
 std.all that publically imports all of std. My experiments show that a
 short script importing std.all will compile slower, but not too slow,
 compared to a script that only import a few modules.
Vote++. This would be a nice little convenience when writing small scripts in D, which I actually do quite often because I already know where basic APIs like file I/O are in Phobos and I don't want to learn another API just for small scripts. This goes along with the scaling down thing I was talking about a few days ago. A well-designed language and library should be good for both big projects (making complicated things possible) and small projects (making things simple). std.all would be a trivial addition that wouldn't clash with anything else and would really help Phobos scale down better.
Nov 29 2009
next sibling parent reply retard <re tard.com.invalid> writes:
Sun, 29 Nov 2009 20:26:07 +0000, dsimcha wrote:

 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s
 article
 Walter and I discussed quite a few times the possibility of defining
 std.all that publically imports all of std. My experiments show that a
 short script importing std.all will compile slower, but not too slow,
 compared to a script that only import a few modules.
Vote++. This would be a nice little convenience when writing small scripts in D, which I actually do quite often because I already know where basic APIs like file I/O are in Phobos and I don't want to learn another API just for small scripts. This goes along with the scaling down thing I was talking about a few days ago. A well-designed language and library should be good for both big projects (making complicated things possible) and small projects (making things simple). std.all would be a trivial addition that wouldn't clash with anything else and would really help Phobos scale down better.
When writing small scripts, I use bpython: http://www.bpython-interpreter.org/screenshots/ Nicely integrated apidocs.
Nov 29 2009
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from retard (re tard.com.invalid)'s article
 Sun, 29 Nov 2009 20:26:07 +0000, dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s
 article
 Walter and I discussed quite a few times the possibility of defining
 std.all that publically imports all of std. My experiments show that a
 short script importing std.all will compile slower, but not too slow,
 compared to a script that only import a few modules.
Vote++. This would be a nice little convenience when writing small scripts in D, which I actually do quite often because I already know where basic APIs like file I/O are in Phobos and I don't want to learn another API just for small scripts. This goes along with the scaling down thing I was talking about a few days ago. A well-designed language and library should be good for both big projects (making complicated things possible) and small projects (making things simple). std.all would be a trivial addition that wouldn't clash with anything else and would really help Phobos scale down better.
When writing small scripts, I use bpython: http://www.bpython-interpreter.org/screenshots/ Nicely integrated apidocs.
Yeah, I like Python, especially for things where I need tons of libraries that have simple APIs and are just there, or where I really need a dynamic language and even D templates aren't a good substitute. I do most of my coding in D, with Python as my second language for when D is just the wrong tool for the job. However, 1. I'm more used to D and it's almost as easy to use as Python. Therefore I tend to use D more for the "grab the quickest thing available and get it working" kind of programming. 2. I sometimes need to write tiny but fast programs, such as simple monte carlo simulations that I want to be able to tweak and run with as little thumb twiddling in between as possible, or utility programs that do some specific operation to a large amount of data. Since D's build times are negligible for these programs and D code runs much faster than Python, D is the better tool here. 3. I've built up a whole bunch of custom libraries in D that I like (the better/more universally useful ones I've released under various projects, the more quick and dirty or niche ones I haven't) and I want access to them even in very small scripts.
Nov 29 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 Walter and I discussed quite a few times the possibility of defining
 std.all that publically imports all of std. My experiments show that a
 short script importing std.all will compile slower, but not too slow,
 compared to a script that only import a few modules.
Vote++. This would be a nice little convenience when writing small scripts in D, which I actually do quite often because I already know where basic APIs like file I/O are in Phobos and I don't want to learn another API just for small scripts. This goes along with the scaling down thing I was talking about a few days ago. A well-designed language and library should be good for both big projects (making complicated things possible) and small projects (making things simple). std.all would be a trivial addition that wouldn't clash with anything else and would really help Phobos scale down better.
Sounds great. I'm even more encouraged by some brief measurement results. I timed dmd against this program: void main(){} Then against this program: import std.stdio; void main(){} Then against this program: import std.stdio; void main(){} For convenience of other testers I'm pasting std.all after this message. The test machine is a 2.5 years old bottom-of-the-line Ubuntu laptop that seems to be in possession of the secret of immortality. Quiescent average run times: * 0.23 seconds for the first program * 0.64 seconds for the second program * 0.98 seconds for the third program I assume any program or script would have to include at least one module, and the marginal cost of including all other modules is low enough to be encouraging. Andrei module std.all; public import std.algorithm; public import std.array; //public import std.atomics; public import std.base64; public import std.bigint; public import std.bitmanip; public import std.boxer; public import std.compiler; public import std.complex; public import std.contracts; public import std.conv; public import std.cpuid; public import std.cstream; public import std.ctype; public import std.date; public import std.datebase; public import std.dateparse; public import std.demangle; public import std.encoding; public import std.file; public import std.format; public import std.functional; public import std.getopt; public import std.intrinsic; public import std.iterator; public import std.json; //public import std.loader; public import std.math; public import std.md5; public import std.metastrings; public import std.mmfile; public import std.numeric; public import std.outbuffer; public import std.path; public import std.perf; public import std.process; public import std.random; public import std.range; public import std.regex; public import std.regexp; public import std.signals; public import std.socket; public import std.socketstream; public import std.stdint; public import std.stdio; public import std.stdiobase; public import std.stream; public import std.string; public import std.syserror; public import std.system; public import std.traits; public import std.typecons; public import std.typetuple; public import std.uni; public import std.uri; public import std.utf; public import std.variant; public import std.xml; public import std.zip; public import std.zlib;
Nov 29 2009
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sun, Nov 29, 2009 at 07:12:50PM +0000, retard wrote:
 after using D1 and Tango for couple of years we decided to experiment 
 with D2 and Phobos in a small scale project. For some reason the mostly 
 flat package hierarchy seemed rather confusing.
Are you familiar with C's standard library? Phobos is loosely based on it, so if you can think of where you'd find it in C, it won't be far off in phobos.
 Entities like 'stdin' seem to have no 
 documentation at all. What should I import to get it, what interfaces 
 does it implement etc.
http://digitalmars.com/d/2.0/phobos/std_stdio.html#File stdin is just an instance of that struct - directly analogous to how stdin in C is a FILE*. (D actually used C's FILE* directly for the longest time.)
  * std.string [the input was a string, maybe toInt is a string operation]
That's where it used to be, but now the generic to!() template does it all, including non string types, so it gets its own module.
 I admit using higher level languages has made major damage to my brain 

 intuitive, but in Phobos the set of packages and their contents feels 
 more or less arbitrary. Is there anything that can be done?
I do think some more big picture overview like documentation pages would be a good idea. If I had more time, I'd write some of them myself. -- Adam D. Ruppe http://arsdnet.net
Nov 29 2009
parent retard <re tard.com.invalid> writes:
Sun, 29 Nov 2009 15:30:14 -0500, Adam D. Ruppe wrote:

 On Sun, Nov 29, 2009 at 07:12:50PM +0000, retard wrote:
 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the mostly
 flat package hierarchy seemed rather confusing.
Are you familiar with C's standard library? Phobos is loosely based on it, so if you can think of where you'd find it in C, it won't be far off in phobos.
 
 Entities like 'stdin' seem to have no documentation at all. What should
 I import to get it, what interfaces does it implement etc.
http://digitalmars.com/d/2.0/phobos/std_stdio.html#File
 stdin is just an instance of that struct - directly analogous to how
 stdin in C is a FILE*. (D actually used C's FILE* directly for the
 longest time.)
I got it now. Note that stdin and stdout aren't defined anywhere. They're mentioned only briefly in the examples of the informal documentation.
Nov 29 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"retard" <re tard.com.invalid> wrote in message 
news:heuh3h$o71$3 digitalmars.com...
 Hi

 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the mostly
 flat package hierarchy seemed rather confusing.

 For instance, it took two of us 15 minutes to build a program that reads
 a line from user, converts the string to a natural number, adds one, and
 finally prints it to the screen. Entities like 'stdin' seem to have no
 documentation at all. What should I import to get it, what interfaces
 does it implement etc.
I actually find that kind of ironic, because that's pretty much how I feel about tango's ultra-separation-mania. I use tango all the time and I still can't do a single IO operation without spending at least ten minutes hunting blindly through the docs and finally finding what I need (including the necessary documentation) is spread out across at least three different modules.
Nov 29 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Nick Sabalausky (a a.a)'s article
 "retard" <re tard.com.invalid> wrote in message
 news:heuh3h$o71$3 digitalmars.com...
 Hi

 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the mostly
 flat package hierarchy seemed rather confusing.

 For instance, it took two of us 15 minutes to build a program that reads
 a line from user, converts the string to a natural number, adds one, and
 finally prints it to the screen. Entities like 'stdin' seem to have no
 documentation at all. What should I import to get it, what interfaces
 does it implement etc.
I actually find that kind of ironic, because that's pretty much how I feel about tango's ultra-separation-mania. I use tango all the time and I still can't do a single IO operation without spending at least ten minutes hunting blindly through the docs and finally finding what I need (including the necessary documentation) is spread out across at least three different modules.
Yeah, I dislike Tango's (and Java's) I/O design. I think it's a classic example of overengineering. I don't care how efficient, flexible, complete, etc. it is if it doesn't "just work" for the simple stuff. By far the two most important pieces of I/O functionality I need are: 1. Read a text file line-by-line. 2. Read a whole file into an array of bytes. These are common, simple I/O operations that just about everyone needs fairly often. It's ridiculous if I have to use three different modules or whatever it takes to accomplish something so simple. I'm convinced that this is one thing that turns a lot of people off to programming if they get past the first hurdle of understanding variable assignment. File I/O is required for almost any program complicated enough to be worth writing. When a beginner who doesn't necessarily even understand the concept of a class hierarchy well sees a huge overengineered API for basic file I/O, he/she is bound to think (wrongly) that programming is much harder than it really is and that he/she is just inept at it.
Nov 29 2009
parent reply retard <re tard.com.invalid> writes:
Mon, 30 Nov 2009 04:51:19 +0000, dsimcha wrote:

 == Quote from Nick Sabalausky (a a.a)'s article
 "retard" <re tard.com.invalid> wrote in message
 news:heuh3h$o71$3 digitalmars.com...
 Hi

 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the
 mostly flat package hierarchy seemed rather confusing.

 For instance, it took two of us 15 minutes to build a program that
 reads a line from user, converts the string to a natural number, adds
 one, and finally prints it to the screen. Entities like 'stdin' seem
 to have no documentation at all. What should I import to get it, what
 interfaces does it implement etc.
I actually find that kind of ironic, because that's pretty much how I feel about tango's ultra-separation-mania. I use tango all the time and I still can't do a single IO operation without spending at least ten minutes hunting blindly through the docs and finally finding what I need (including the necessary documentation) is spread out across at least three different modules.
Yeah, I dislike Tango's (and Java's) I/O design. I think it's a classic example of overengineering. I don't care how efficient, flexible, complete, etc. it is if it doesn't "just work" for the simple stuff.
Are you sure you know what you're talking about?
 By
 far the two most important pieces of I/O functionality I need are:
 
 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
 2.  Read a whole file into an array of bytes.
new File("foobar.bin").read() Java isn't that bad IMO - you just have to remember the buffer: BufferedReader input = new BufferedReader(new FileReader("foo")); try { String line = null; while (( line = input.readLine()) != null) { } } finally { input.close(); }
 
 These are common, simple I/O operations that just about everyone needs
 fairly often.  It's ridiculous if I have to use three different modules
 or whatever it takes to accomplish something so simple.
 
 I'm convinced that this is one thing that turns a lot of people off to
 programming if they get past the first hurdle of understanding variable
 assignment.  File I/O is required for almost any program complicated
 enough to be worth writing.  When a beginner who doesn't necessarily
 even understand the concept of a class hierarchy well sees a huge
 overengineered API for basic file I/O, he/she is bound to think
 (wrongly) that programming is much harder than it really is and that
 he/she is just inept at it.
Well, that's not the only problem a novice meets during the first minutes / hours with a new language. If you write e.g. console apps for win32, you need to teach them what code pages are, why do you need to convert between utf-8 and windows-1252 etc. since the default console i/o routines are not unicode aware under windows.
Nov 29 2009
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Nov 30, 09 14:02, retard wrote:
 Mon, 30 Nov 2009 04:51:19 +0000, dsimcha wrote:

 == Quote from Nick Sabalausky (a a.a)'s article
 "retard"<re tard.com.invalid>  wrote in message
 news:heuh3h$o71$3 digitalmars.com...
 Hi

 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the
 mostly flat package hierarchy seemed rather confusing.

 For instance, it took two of us 15 minutes to build a program that
 reads a line from user, converts the string to a natural number, adds
 one, and finally prints it to the screen. Entities like 'stdin' seem
 to have no documentation at all. What should I import to get it, what
 interfaces does it implement etc.
I actually find that kind of ironic, because that's pretty much how I feel about tango's ultra-separation-mania. I use tango all the time and I still can't do a single IO operation without spending at least ten minutes hunting blindly through the docs and finally finding what I need (including the necessary documentation) is spread out across at least three different modules.
Yeah, I dislike Tango's (and Java's) I/O design. I think it's a classic example of overengineering. I don't care how efficient, flexible, complete, etc. it is if it doesn't "just work" for the simple stuff.
Are you sure you know what you're talking about?
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
 2.  Read a whole file into an array of bytes.
new File("foobar.bin").read() Java isn't that bad IMO - you just have to remember the buffer: BufferedReader input = new BufferedReader(new FileReader("foo")); try { String line = null; while (( line = input.readLine()) != null) { } } finally { input.close(); }
yuck yuck yuck.
 These are common, simple I/O operations that just about everyone needs
 fairly often.  It's ridiculous if I have to use three different modules
 or whatever it takes to accomplish something so simple.

 I'm convinced that this is one thing that turns a lot of people off to
 programming if they get past the first hurdle of understanding variable
 assignment.  File I/O is required for almost any program complicated
 enough to be worth writing.  When a beginner who doesn't necessarily
 even understand the concept of a class hierarchy well sees a huge
 overengineered API for basic file I/O, he/she is bound to think
 (wrongly) that programming is much harder than it really is and that
 he/she is just inept at it.
Well, that's not the only problem a novice meets during the first minutes / hours with a new language. If you write e.g. console apps for win32, you need to teach them what code pages are, why do you need to convert between utf-8 and windows-1252 etc. since the default console i/o routines are not unicode aware under windows.
Nov 30 2009
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
Nov 30 2009
next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
I wouldn't go as far as saying "yuck" to the above, but I like the Phobos way better: foreach (line; File("foobar.txt").byLine) { ... } -Lars
Nov 30 2009
parent Leandro Lucarella <llucax gmail.com> writes:
Lars T. Kyllingstad, el 30 de noviembre a las 12:16 me escribiste:
 Ary Borenszweig wrote:
KennyTM~ wrote:
By
far the two most important pieces of I/O functionality I need are:

1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
I wouldn't go as far as saying "yuck" to the above, but I like the Phobos way better: foreach (line; File("foobar.txt").byLine) { ... }
I think you need a few more imports in Tango too. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Come on, now, I hear you're feeling down. Well I can ease your pain Get you on your feet again.
Nov 30 2009
prev sibling next sibling parent reply retard <re tard.com.invalid> writes:
Mon, 30 Nov 2009 12:01:22 +0100, Ary Borenszweig wrote:

 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
I guess something like this: JustDoItWith("foobar.txt") { ... }
Nov 30 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
retard wrote:
 Mon, 30 Nov 2009 12:01:22 +0100, Ary Borenszweig wrote:
 
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
I guess something like this: JustDoItWith("foobar.txt") { ... }
foreach (char[] line; File("text.txt").byLine()) { ... } Efficient, flexible, convenient. Closes automatically the file, too, which Tango seems doesn't. Andrei
Nov 30 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 30 Nov 2009 18:25:41 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 retard wrote:
 Mon, 30 Nov 2009 12:01:22 +0100, Ary Borenszweig wrote:

 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
I guess something like this: JustDoItWith("foobar.txt") { ... }
foreach (char[] line; File("text.txt").byLine()) { ... } Efficient, flexible, convenient. Closes automatically the file, too, which Tango seems doesn't. Andrei
If it closes file automatically, then why do you close it explicitly in slurp? The code is almost the same except that "Lines" class works with any Input Stream (memory stream, file stream, network stream, pipe, i/o device etc).
Nov 30 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Mon, 30 Nov 2009 18:25:41 +0300, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 retard wrote:
 Mon, 30 Nov 2009 12:01:22 +0100, Ary Borenszweig wrote:

 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
I guess something like this: JustDoItWith("foobar.txt") { ... }
foreach (char[] line; File("text.txt").byLine()) { ... } Efficient, flexible, convenient. Closes automatically the file, too, which Tango seems doesn't. Andrei
If it closes file automatically, then why do you close it explicitly in slurp?
Because a compiler bug prevented the destructor from functioning correctly. The manual close does no harm now but of course should be removed.
 The code is almost the same except that "Lines" class works with any 
 Input Stream (memory stream, file stream, network stream, pipe, i/o 
 device etc).
I hope we'd be able to add such streams to Phobos too, perhaps using your networking library for transport. Andrei
Nov 30 2009
prev sibling next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Nov 30, 09 19:01, Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1. Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
Python do it like this: for line in open("foobar.txt"): print(line) How many things you need to explain for that elegant code? Line? File? Cout? .newline?
Nov 30 2009
parent reply retard <re tard.com.invalid> writes:
Mon, 30 Nov 2009 21:06:21 +0800, KennyTM~ wrote:

 On Nov 30, 09 19:01, Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1. Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
Python do it like this: for line in open("foobar.txt"): print(line) How many things you need to explain for that elegant code? Line? File? Cout? .newline?
Your argumentation is getting ridiculous. Reading and printing lines of a text file isn't by any means a good measure of standard library quality. I could define something like void printFileLines(string fn) { ... } in my code and use it like this: printFileLines("foobar.txt"); When I'm programming with a systems programming language, I really do want to know if it reads the whole 100 GB file into memory before iterating or if not, what kind of buffer it is using. I often also need to work with endianess issues, codepage conversions, file system exceptions etc. If I only need to write simple code (== programming in the small) I might want to use some scripting language instead. It's really hard to please both audiences without cluttering the stdlib api.
Nov 30 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
retard wrote:
 Mon, 30 Nov 2009 21:06:21 +0800, KennyTM~ wrote:
 
 On Nov 30, 09 19:01, Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1. Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
Python do it like this: for line in open("foobar.txt"): print(line) How many things you need to explain for that elegant code? Line? File? Cout? .newline?
Your argumentation is getting ridiculous. Reading and printing lines of a text file isn't by any means a good measure of standard library quality. I could define something like void printFileLines(string fn) { ... } in my code and use it like this: printFileLines("foobar.txt"); When I'm programming with a systems programming language, I really do want to know if it reads the whole 100 GB file into memory before iterating or if not, what kind of buffer it is using. I often also need to work with endianess issues, codepage conversions, file system exceptions etc. If I only need to write simple code (== programming in the small) I might want to use some scripting language instead. It's really hard to please both audiences without cluttering the stdlib api.
I don't have much time to spend on std.stdio nowadays, but the clear intent there is to provide range-based access that satisfies both audiences by using a good abstraction instead of cluttering the API. Andrei
Nov 30 2009
prev sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from retard (re tard.com.invalid)'s article
 Mon, 30 Nov 2009 21:06:21 +0800, KennyTM~ wrote:
 On Nov 30, 09 19:01, Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1. Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
Python do it like this: for line in open("foobar.txt"): print(line) How many things you need to explain for that elegant code? Line? File? Cout? .newline?
Your argumentation is getting ridiculous. Reading and printing lines of a text file isn't by any means a good measure of standard library quality. I could define something like void printFileLines(string fn) { ... } in my code and use it like this: printFileLines("foobar.txt"); When I'm programming with a systems programming language, I really do want to know if it reads the whole 100 GB file into memory before iterating or if not, what kind of buffer it is using. I often also need to work with endianess issues, codepage conversions, file system exceptions etc. If I only need to write simple code (== programming in the small) I might want to use some scripting language instead. It's really hard to please both audiences without cluttering the stdlib api.
Right, but I do scientific work. I've never written a polished app that's designed to be used by non-programmers or to be internationalized, where caring about things like unicode is important. Most of my programming is very algorithm-centric and CPU-bound. Anything I/O is generally regarded as just a means of getting data in to process it with your algorithms. The algorithms are where I want to spend about 99% of my coding efforts, but I need a systems language here for performance reasons. For I/O I just want the quickest, simplest thing available. If the character set supports A, C, T, G, and U (the five characters of DNA and RNA), it's good enough for me. I'm sure other niches have similar things: Dead simple requirements in one dimension, but need for a full-fledged systems language to fulfill requirements in another dimension. For example, I work with huge datasets and need to tune memory management pretty frequently. Someone writing business software might care more about unicode and "proper" I/O than I do, but probably wouldn't care at all about the ability to tune memory management. Maybe their need for a systems language is because they want native binaries or an easy way to interface with C code.
Nov 30 2009
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from dsimcha (dsimcha yahoo.com)'s article
 == Quote from retard (re tard.com.invalid)'s article
 Mon, 30 Nov 2009 21:06:21 +0800, KennyTM~ wrote:
 On Nov 30, 09 19:01, Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1. Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
Python do it like this: for line in open("foobar.txt"): print(line) How many things you need to explain for that elegant code? Line? File? Cout? .newline?
Your argumentation is getting ridiculous. Reading and printing lines of a text file isn't by any means a good measure of standard library quality. I could define something like void printFileLines(string fn) { ... } in my code and use it like this: printFileLines("foobar.txt"); When I'm programming with a systems programming language, I really do want to know if it reads the whole 100 GB file into memory before iterating or if not, what kind of buffer it is using. I often also need to work with endianess issues, codepage conversions, file system exceptions etc. If I only need to write simple code (== programming in the small) I might want to use some scripting language instead. It's really hard to please both audiences without cluttering the stdlib api.
Right, but I do scientific work. I've never written a polished app that's designed to be used by non-programmers or to be internationalized, where caring about things like unicode is important. Most of my programming is very algorithm-centric and CPU-bound. Anything I/O is generally regarded as just a means of getting data in to process it with your algorithms. The algorithms are where I want to spend about 99% of my coding efforts, but I need a systems language here for performance reasons. For I/O I just want the quickest, simplest thing available. If the character set supports A, C, T, G, and U (the five characters of DNA and RNA), it's good enough for me. I'm sure other niches have similar things: Dead simple requirements in one dimension, but need for a full-fledged systems language to fulfill requirements in another dimension. For example, I work with huge datasets and need to tune memory management pretty frequently. Someone writing business software might care more about unicode and "proper" I/O than I do, but probably wouldn't care at all about the ability to tune memory management. Maybe their need for a systems language is because they want native binaries or an easy way to interface with C code.
I guess the idea here is that the beauty of D2/Phobos is that it's a systems programming language/lib, but one that only makes you care that it's a systems programming language for the parts of your code where you really need the power of a systems language. For the parts of your code where that power is overkill, you can seamlessly shift into a more scripting language style of programming, without any messy glue layers, inter-language interfaces, etc. getting in the way.
Nov 30 2009
prev sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
Ary Borenszweig wrote:
 KennyTM~ wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
yuck.
Yuck?? I find that code very elegant. How would you like it to be?
foreach (line; open("foobar.txt")) { writeln(line); } I find the .newline idea rather hackish.
Nov 30 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Pelle Månsson:

 foreach (line; open("foobar.txt")) {
    writeln(line);
 }
With the xio module of my dlibs: import d.xio: xfile; foreach (line; xfile("foobar.txt")) putr(line); xfile is optimized to reduce memory rellocations as much as possible in the most common case of about 90 chars long lines. There is an xstdin too. Bye, bearophile
Nov 30 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Pelle Månsson:
 
 foreach (line; open("foobar.txt")) {
    writeln(line);
 }
With the xio module of my dlibs: import d.xio: xfile; foreach (line; xfile("foobar.txt")) putr(line); xfile is optimized to reduce memory rellocations as much as possible in the most common case of about 90 chars long lines. There is an xstdin too.
Why not just reuse the same buffer as the previous line? That approach is inherently adaptive. And why is there a need for xstdin vs. xfile? Stdin _is_ a file. Andrei
Nov 30 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 Why not just reuse the same buffer as the previous line? That approach 
 is inherently adaptive.
That approach is unsafe. xfile yields byte strings, in D1. When I write 10 lines long scripts I usually don't need every bit of optimization, I need the less bug-prone code as possible, because the thing I have to optimize is my coding time. In D1 strings are mutable, so if you put them in an AA as keys you must dup them to avoid bugs if you reuse the same buffer.
And why is there a need for xstdin vs. xfile? Stdin _is_ a file.<
I use it like this: foreach (line; xstdin) { ... } line is a string with newline at the end. I know this isn't the best design, but it's the most handy for my purposes. I need to do a limited number of things in those scripts and iterating over the lines of a fine and over the lines of the stdin are the only two that matter. Bye, bearophile
Nov 30 2009
parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
bearophile wrote:
 Andrei Alexandrescu:
 Why not just reuse the same buffer as the previous line? That approach 
 is inherently adaptive.
That approach is unsafe. xfile yields byte strings, in D1. When I write 10 lines long scripts I usually don't need every bit of optimization, I need the less bug-prone code as possible, because the thing I have to optimize is my coding time. In D1 strings are mutable, so if you put them in an AA as keys you must dup them to avoid bugs if you reuse the same buffer.
You'll have to .dup them if you want to use them as non-views always. I for one like that approach more. Why call it xfile and not just open?
 And why is there a need for xstdin vs. xfile? Stdin _is_ a file.<
I use it like this: foreach (line; xstdin) { ... } line is a string with newline at the end. I know this isn't the best design, but it's the most handy for my purposes. I need to do a limited number of things in those scripts and iterating over the lines of a fine and over the lines of the stdin are the only two that matter. Bye, bearophile
Dec 01 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 01 Dec 2009 15:22:23 +0300, Pelle M=C3=A5nsson  =

<pelle.mansson gmail.com> wrote:

 bearophile wrote:
 Andrei Alexandrescu:
 Why not just reuse the same buffer as the previous line? That approa=
ch =
 is inherently adaptive.
That approach is unsafe. xfile yields byte strings, in D1. When I =
 write 10 lines long scripts I usually don't need every bit of  =
 optimization, I need the less bug-prone code as possible, because the=
=
 thing I have to optimize is my coding time. In D1 strings are mutable=
, =
 so if you put them in an AA as keys you must dup them to avoid bugs i=
f =
 you reuse the same buffer.
You'll have to .dup them if you want to use them as non-views always. =
I =
 for one like that approach more.

 Why call it xfile and not just open?

 And why is there a need for xstdin vs. xfile? Stdin _is_ a file.<
I use it like this: foreach (line; xstdin) { ... } line is a string with newline at the end. I know this isn't the best design, but it's the most handy for my =
 purposes. I need to do a limited number of things in those scripts an=
d =
 iterating over the lines of a fine and over the lines of the stdin ar=
e =
 the only two that matter.
  Bye,
 bearophile
In his notation, xfoo is a lazy version of foo (i.e. it reads file in = chunks as opposed to reading the whole file at once). So you are essentially asking, "why file instead of open?". What's the = difference? It's a bikeshed discussion, but I believe file("filename") i= s = more clear than open("filename"). Besides, I'm used to "close" everythin= g = I "open", which is not suitable here.
Dec 01 2009
parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
Denis Koroskin wrote:
 On Tue, 01 Dec 2009 15:22:23 +0300, Pelle Månsson 
 <pelle.mansson gmail.com> wrote:
 
 bearophile wrote:
 Andrei Alexandrescu:
 Why not just reuse the same buffer as the previous line? That 
 approach is inherently adaptive.
That approach is unsafe. xfile yields byte strings, in D1. When I write 10 lines long scripts I usually don't need every bit of optimization, I need the less bug-prone code as possible, because the thing I have to optimize is my coding time. In D1 strings are mutable, so if you put them in an AA as keys you must dup them to avoid bugs if you reuse the same buffer.
You'll have to .dup them if you want to use them as non-views always. I for one like that approach more. Why call it xfile and not just open?
 And why is there a need for xstdin vs. xfile? Stdin _is_ a file.<
I use it like this: foreach (line; xstdin) { ... } line is a string with newline at the end. I know this isn't the best design, but it's the most handy for my purposes. I need to do a limited number of things in those scripts and iterating over the lines of a fine and over the lines of the stdin are the only two that matter. Bye, bearophile
In his notation, xfoo is a lazy version of foo (i.e. it reads file in chunks as opposed to reading the whole file at once). So you are essentially asking, "why file instead of open?". What's the difference? It's a bikeshed discussion, but I believe file("filename") is more clear than open("filename"). Besides, I'm used to "close" everything I "open", which is not suitable here/.
File looks like a constructor. You are not constructing a file you open for reading. Also, saying that you close everything you open, are you deallocating everything you allocate as well? I feel we have moved past such symmetry.
Dec 01 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Pelle Månsson wrote:
 File looks like a constructor. You are not constructing a file you open
 for reading.
"open" by itself is ambiguous. What are you opening? A window? A network port? I think the word "file" needs to be in there somewhere to disambiguate. -- Rainer Deyke - rainerd eldwood.com
Dec 01 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Rainer Deyke:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere to
 disambiguate.
When you program in Python you remember that open is a built-in function to open files :-) When you want to open other things you import other names from some module. So this ambiguity usually doesn't introduce bugs. It' a well known convention. Few well chosen conventions (sensible defaults) save you from a lot of useless coding. Bye, bearophile
Dec 01 2009
parent reply retard <re tard.com.invalid> writes:
Tue, 01 Dec 2009 18:58:25 -0500, bearophile wrote:

 Rainer Deyke:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere
 to disambiguate.
When you program in Python you remember that open is a built-in function to open files :-) When you want to open other things you import other names from some module. So this ambiguity usually doesn't introduce bugs. It' a well known convention. Few well chosen conventions (sensible defaults) save you from a lot of useless coding.
These default values are sometimes very annoying. For instance almost in every game you have a game object hierarchy and the super class of game objects usually conflicts with built-in 'Object'. If I write an adventure game and some event opens a dungeon door, open() suddenly deals with files. Also IIRC Python has built-in print() command. What if I want to redefine this to mean printing to a graphical quake like game console. Namespaces in general seem rather useful. I hate the php like 'there's a flat global scope and everything is a free function approach'. It's annoying me each time I use phobos.
Dec 01 2009
next sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
retard wrote:
 Tue, 01 Dec 2009 18:58:25 -0500, bearophile wrote:
 
 Rainer Deyke:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere
 to disambiguate.
When you program in Python you remember that open is a built-in function to open files :-) When you want to open other things you import other names from some module. So this ambiguity usually doesn't introduce bugs. It' a well known convention. Few well chosen conventions (sensible defaults) save you from a lot of useless coding.
These default values are sometimes very annoying. For instance almost in every game you have a game object hierarchy and the super class of game objects usually conflicts with built-in 'Object'. If I write an adventure game and some event opens a dungeon door, open() suddenly deals with files. Also IIRC Python has built-in print() command. What if I want to redefine this to mean printing to a graphical quake like game console. Namespaces in general seem rather useful. I hate the php like 'there's a flat global scope and everything is a free function approach'. It's annoying me each time I use phobos.
door.open() ? In python, you can just override what open does if you need open(door).
Dec 01 2009
parent reply retard <re tard.com.invalid> writes:
Wed, 02 Dec 2009 08:38:29 +0100, Pelle Månsson wrote:

 retard wrote:
 Tue, 01 Dec 2009 18:58:25 -0500, bearophile wrote:
 
 Rainer Deyke:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere
 to disambiguate.
When you program in Python you remember that open is a built-in function to open files :-) When you want to open other things you import other names from some module. So this ambiguity usually doesn't introduce bugs. It' a well known convention. Few well chosen conventions (sensible defaults) save you from a lot of useless coding.
These default values are sometimes very annoying. For instance almost in every game you have a game object hierarchy and the super class of game objects usually conflicts with built-in 'Object'. If I write an adventure game and some event opens a dungeon door, open() suddenly deals with files. Also IIRC Python has built-in print() command. What if I want to redefine this to mean printing to a graphical quake like game console. Namespaces in general seem rather useful. I hate the php like 'there's a flat global scope and everything is a free function approach'. It's annoying me each time I use phobos.
door.open() ? In python, you can just override what open does if you need open(door).
In internal class methods the door.open can be written as this.open() or just open(). In that case you need to worry about other symbols, if they are globally available built-ins.
Dec 01 2009
parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
retard wrote:
 Wed, 02 Dec 2009 08:38:29 +0100, Pelle Månsson wrote:
 
 retard wrote:
 Tue, 01 Dec 2009 18:58:25 -0500, bearophile wrote:

 Rainer Deyke:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere
 to disambiguate.
When you program in Python you remember that open is a built-in function to open files :-) When you want to open other things you import other names from some module. So this ambiguity usually doesn't introduce bugs. It' a well known convention. Few well chosen conventions (sensible defaults) save you from a lot of useless coding.
These default values are sometimes very annoying. For instance almost in every game you have a game object hierarchy and the super class of game objects usually conflicts with built-in 'Object'. If I write an adventure game and some event opens a dungeon door, open() suddenly deals with files. Also IIRC Python has built-in print() command. What if I want to redefine this to mean printing to a graphical quake like game console. Namespaces in general seem rather useful. I hate the php like 'there's a flat global scope and everything is a free function approach'. It's annoying me each time I use phobos.
door.open() ? In python, you can just override what open does if you need open(door).
In internal class methods the door.open can be written as this.open() or just open(). In that case you need to worry about other symbols, if they are globally available built-ins.
Not in python you can't. Also, in D, this wouldn't be a problem, since if it is ambiguous, the compiler will tell you so.
Dec 02 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
retard wrote:
 Namespaces in general seem rather useful. I hate the php like 'there's a 
 flat global scope and everything is a free function approach'. It's 
 annoying me each time I use phobos.
If you have the same name declared in multiple imports, you cannot refer to it without qualification (unless the function arguments are clearly distinct). I don't see the problem you are. Can you explain?
Dec 01 2009
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
retard:
 Also IIRC Python has built-in print() command. What if I want to 
 redefine this to mean printing to a graphical quake like game console.
In Python3 there is a built-in print function, that is a reference to a callable object. So you just need to redefine it, like this: def print(...): Or just: def foo(): ... print = foo Bye, bearophile
Dec 02 2009
prev sibling parent reply =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
Rainer Deyke wrote:
 Pelle Månsson wrote:
 File looks like a constructor. You are not constructing a file you open
 for reading.
"open" by itself is ambiguous. What are you opening? A window? A network port? I think the word "file" needs to be in there somewhere to disambiguate.
Something like new BufferedReader(new FileReader("foo.txt"))? It's quite unambiguous. I'll rather have open as a file-opening function.
Dec 01 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Pelle Månsson wrote:
 Rainer Deyke wrote:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere to
 disambiguate.
Something like new BufferedReader(new FileReader("foo.txt"))? It's quite unambiguous.
No, like 'file("foo.txt")' or 'fopen("foo.txt")'. There's always a trade-off between verbosity and clarity, but names that are both reasonably short and reasonably unambiguous exist. -- Rainer Deyke - rainerd eldwood.com
Dec 02 2009
parent =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Rainer Deyke wrote:
 Pelle M=C3=A5nsson wrote:
 Rainer Deyke wrote:
 "open" by itself is ambiguous.  What are you opening?  A window?  A
 network port?  I think the word "file" needs to be in there somewhere=
to
 disambiguate.
Something like new BufferedReader(new FileReader("foo.txt"))? It's qui=
te
 unambiguous.
=20 No, like 'file("foo.txt")' or 'fopen("foo.txt")'. There's always a trade-off between verbosity and clarity, but names that are both reasonably short and reasonably unambiguous exist. =20
Note that 'open ("foo.txt", O_RDONLY)' is perfectly valid C code=20 for opening a file (unbuffered). Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Dec 02 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"retard" <re tard.com.invalid> wrote in message 
news:hevn56$2to1$1 digitalmars.com...
 Mon, 30 Nov 2009 04:51:19 +0000, dsimcha wrote:
 Yeah, I dislike Tango's (and Java's) I/O design.  I think it's a classic
 example of overengineering.  I don't care how efficient, flexible,
 complete, etc. it is if it doesn't "just work" for the simple stuff.
Are you sure you know what you're talking about?
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
 2.  Read a whole file into an array of bytes.
new File("foobar.bin").read()
Sure, once you actually know that and remember it. But trying to discover them in the first place (and discover what modules to import, and how many of the problem is that there's about million different classes, modules, structs, functions, whatever all dealing with accessing a file. So I have to figure out which method to use, which is made extra painful by the fact that each way of going about it is spread out across at least three different modules out of a total of I-don't-even-want-to-count. And of course there are zero "all" modules which just leaves me bouncing back up to the imports section of my code every time I make an edit. "But it's right there in the tutorials, don't go looking through the API ref for it!" Well, ok, but there have been a lot of things I've needed to find (such as more in depth details) that the tuts don't tell me, and that I've had to look through the API ref or even source to find. So now I have to worry about not only what module to look in for what I want, but also which set of docs.
Nov 30 2009
prev sibling next sibling parent torhu <no spam.invalid> writes:
On 30.11.2009 7:02, retard wrote:
 foreach (line; new Lines!(char) (new File ("foobar.txt")))
    Cout (line).newline;
 }
To be fair, it's a bit simpler than that in Tango: foreach (line; new TextFileInput("foobar.txt")) Cout (line).newline; }
  2.  Read a whole file into an array of bytes.
new File("foobar.bin").read()
This one too: auto contents = File.get("foobar.bin"); get is a static method in the File class. But I won't pretend that I think Tango I/O is easy to use. There's a lot of interfaces and classes, and usually several ways to accomplish the same thing. Some classes are just thin wrappers over others, which can be confusing.
Dec 01 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
retard wrote:
 Mon, 30 Nov 2009 04:51:19 +0000, dsimcha wrote:
 By
 far the two most important pieces of I/O functionality I need are:

 1.  Read a text file line-by-line.
foreach (line; new Lines!(char) (new File ("foobar.txt"))) Cout (line).newline; }
 2.  Read a whole file into an array of bytes.
new File("foobar.bin").read() Java isn't that bad IMO - you just have to remember the buffer: BufferedReader input = new BufferedReader(new FileReader("foo")); try { String line = null; while (( line = input.readLine()) != null) { } } finally { input.close(); }
Wouldn't you need a try/finally around the D code too? Andrei
Dec 05 2009
prev sibling next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from retard (re tard.com.invalid)'s article
 Hi
 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the mostly
 flat package hierarchy seemed rather confusing.
 For instance, it took two of us 15 minutes to build a program that reads
 a line from user, converts the string to a natural number, adds one, and
 finally prints it to the screen.
While I agree that the docs for Phobos should be improved after the language stabilizes, I honestly don't think 15 minutes is too bad if you're completely unfamiliar with the API. Using Java's file I/O API, for example, practically requires a Ph.D. in object-oriented design. It's just a fact of life that every API has its quirks that take time to learn, and anything that's not what you're used to is going to seem quirky at first.
Nov 29 2009
parent reply retard <re tard.com.invalid> writes:
Mon, 30 Nov 2009 04:55:29 +0000, dsimcha wrote:

 == Quote from retard (re tard.com.invalid)'s article
 Hi
 after using D1 and Tango for couple of years we decided to experiment
 with D2 and Phobos in a small scale project. For some reason the mostly
 flat package hierarchy seemed rather confusing. For instance, it took
 two of us 15 minutes to build a program that reads a line from user,
 converts the string to a natural number, adds one, and finally prints
 it to the screen.
While I agree that the docs for Phobos should be improved after the language stabilizes, I honestly don't think 15 minutes is too bad if you're completely unfamiliar with the API. Using Java's file I/O API, for example, practically requires a Ph.D. in object-oriented design. It's just a fact of life that every API has its quirks that take time to learn, and anything that's not what you're used to is going to seem quirky at first.
Well, they have been teaching the Java i/o stuff to first year students for a while now. I completely agree that it's a bit too complicated for novices, but it's not the only bad thing: public static void main(String[] args) { System.out.println("Hello world!"); } Wtf. They used to learn Scheme: (print "Hello World") I guess the PhD requirement is a bit exaggerating. Of course you do need to learn some basic concepts first. OTOH I know a handful of C programmers who just don't get why their (unbuffered) i/o routines always perform badly, and use libraries instead.
Nov 29 2009
parent "Nick Sabalausky" <a a.a> writes:
"retard" <re tard.com.invalid> wrote in message 
news:hevo45$2to1$2 digitalmars.com...
 Mon, 30 Nov 2009 04:55:29 +0000, dsimcha wrote:

 Well, they have been teaching the Java i/o stuff to first year students
 for a while now. I completely agree that it's a bit too complicated for
 novices, but it's not the only bad thing:

 public static void main(String[] args)
 { System.out.println("Hello world!"); }
Correction: class Main { public static void main(String[] args) { System.out.println("Hello world!"); } } (Or something like that anyway, been forever since I touched Java.)
 Wtf. They used to learn Scheme:

 (print "Hello World")

 I guess the PhD requirement is a bit exaggerating. Of course you do need
 to learn some basic concepts first. OTOH I know a handful of C
 programmers who just don't get why their (unbuffered) i/o routines always
 perform badly, and use libraries instead. 
Nov 30 2009
prev sibling parent reply Roman Ivanov <isroman km.ru> writes:
retard Wrote:
 Java isn't that bad IMO - you just have to remember the buffer:
 
 BufferedReader input = new BufferedReader(new FileReader("foo"));
 try {
   String line = null;
 
   while (( line = input.readLine()) != null) {
   }
 }
 finally {
   input.close();
 }
One of the important factors in API quality is feature discoverability. That is, the amount of time you need to find a sane way to do something, provided that you know the language. Java has very low discoverability. The code above is extremely unintuitive, because the abstractions you are required to use have nothing to do with the task at hand. FileReader? BufferedReader? string[] readText = File.ReadAllLines(path, Encoding.UTF8); Or PHP: $file = file_get_contents($path); Yes, the alternatives store the entire file in memory. That's perfectly fine for 95% of use cases. Good APIs provide several levels of abstraction. If 95% of the people don't care about the way a file is read, then a good API would provide a simple function that just works for those people. Nobody stops it from providing a low-level API with finer control as well.
 
 These are common, simple I/O operations that just about everyone needs
 fairly often.  It's ridiculous if I have to use three different modules
 or whatever it takes to accomplish something so simple.
 
 I'm convinced that this is one thing that turns a lot of people off to
 programming if they get past the first hurdle of understanding variable
 assignment.  File I/O is required for almost any program complicated
 enough to be worth writing.  When a beginner who doesn't necessarily
 even understand the concept of a class hierarchy well sees a huge
 overengineered API for basic file I/O, he/she is bound to think
 (wrongly) that programming is much harder than it really is and that
 he/she is just inept at it.
Well, that's not the only problem a novice meets during the first minutes / hours with a new language.
I'd say most of the programmers learn new APIs all the time. If every one requires you to jump though hoops, you will end up with a significant and constant overhead.
Nov 30 2009
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Roman Ivanov (isroman km.ru)'s article
 retard Wrote:
 Java isn't that bad IMO - you just have to remember the buffer:

 BufferedReader input = new BufferedReader(new FileReader("foo"));
 try {
   String line = null;

   while (( line = input.readLine()) != null) {
   }
 }
 finally {
   input.close();
 }
One of the important factors in API quality is feature discoverability. That is,
the amount of time you need to find a sane way to do something, provided that you know the language. Java has very low discoverability. The code above is extremely unintuitive, because the abstractions you are required to use have nothing to do with the task at hand. FileReader? BufferedReader? Right, very well said. Bringing this discussion full circle to where it started, IMHO very fine grained modules hurt discoverability. In D, namespace pollution isn't a major problem because hijacking can't happen. If you know everything related to file I/O is in one module (basic functionality common to all forms of I/O can just be publicly imported and the important stuff demonstrated in the example docs), it's a lot easier to browse through the docs for that module and understand the API's concept of file I/O than if the logic is spread across a zillion files w/o any obvious relationship between them. This was my main gripe against Tango. Once you figure out what modules you needs, it's pretty easy. The problem is that there are an overwhelming number of I/O modules, each of which, by itself, does practically nothing. Of course Java is even worse because iterating over the lines of a text file isn't even consistent with Java's standard way of iterating over other stuff (it doesn't use iterators), so it's much more non-discoverable.
Nov 30 2009