About std.stdio.File.writef
With dmd 2.048 this code: import std.stdio: File; void main() { auto f = File("TEST.ppm", "w"); f.writef("%c", 50); } Prints at run-time: std.format.FormatError: std.format integral So to write a char I've had to use: f.write(cast(char)50); Partially unrelated: is is possible to perform something like f.readfln()? Do I have to use std.conv.parse for it? Bye and thank you, bearophile
RosettaCode: Echo Server
Hello, I decided to exercise my skills in D a bit and wrote an implementation for an echo server using D. I figure before I post it to the site, I'd post it here for comments as I'd like to get the best possible version on the site vs. something that's half-assed. Considering I'm very new to socket programming, I'm guessing this may not be the best possible version. Attached are two files: a client and a server. Let me know what you think. Casey import std.socket; import std.stdio; import std.string; void main() { Socket sock = new TcpSocket(new InternetAddress("localhost", 12321)); string[4] messages = ["Hello world.", "Hello\nworld.", "\tHello world.", "Goodby cruel world..."]; ubyte buff[1]; int bytesRead; foreach (msg; messages) { sock.send(msg); for (int i = 0; i < msg.length; i++) { bytesRead = sock.receive(buff); write(cast(char)buff[0]); } /* string temp = cast(string)buff; writeln(temp, "\n"); */ write("\n"); } sock.close(); } import std.socket; import std.array; void main() { Socket listener = new TcpSocket; assert(listener.isAlive); listener.bind(new InternetAddress(12321)); listener.listen(10); Socket currSock; uint bytesRead; ubyte buff[1]; while(1) { currSock = listener.accept(); while ((bytesRead = currSock.receive(buff)) > 0) { currSock.send(buff); } currSock.close(); buff.clear(); } }
Re: How to name things [Was: Re: SO rotate question]
On Friday 03 September 2010 10:14:24 bearophile wrote: > Jonathan M Davis: > > Still, naming functions is a bit of an art and most function names are > > debatable as to how good they are, so you're bound to have functions > > in any API that aren't named the way that you think they should be. > > I don't like what you say. > > If you take a look at how in the last ten years every small feature was > designed by Python devs, you see how much care they have for naming > things. For each name of feature/built-in all people of the development > mailing list propose their names and the rationale behind those names. > Then they write down a list of all the ideas, and they vote for each name. > The name with most votes usually gets accepted, and then they start over > with the next name to choose. This is a bit time consuming, but one of the > most important qualities of Python its refined and natural design. > > You are right that good names are purpose-specific, and often a name that > is good for me is not good for you. > > Every single person has some quirks, so if you let a single person choose a > name, there's some risk the name will reflect only the specific quirks of > that person. > > On the other hand the good names for a specific feature are not totally > random. If you take 100 smart persons, and you ask them what name to use > to define a certain feature, you will often receive something like 15-20 > answers, and among them one or two answers are the most common. The most > common choice is the the right name choice. > > It's true that this most common name is not always the same name that each > person is willing to chose, but such average process smooths out the > quirks each single person has, and very often the names chosen by this > process are simple to remember and natural. > > This is how I'd like Phobos names to be chosen. Andrei is smart and > intelligent, but as everyone else he has quirks (and his usage of English > is not the most common you may find), so letting the choice of many names > to any single person is bad. I didn't say anything that contradicts what you just said. All I said was that picking a function name is an art, and there _are_ going to be function names in an API that people aren't going to like simply because they think differently. Heck, you could really like one of your own names when you first create the function, and then later decide that it was a poor choice. What you're proposing is a way to reduce the odds that the average programmer will think that a name is bad, because more people will have input. I have no problem with that, and I didn't suggest that the way that names in Phobos is picked is perfect. I didn't even say anything about whether having one person pick the names was good or bad. So, I really don't know why you're unhappy with what I said. In any case, it looks like Andrei is looking to have more of a review process for stuff entering Phobos - akin to what Boost does. That review process would likely be the time to suggest better names for functions if they are poorly named. - Jonathan M Davis
ubyte[] -> immutable(ubyte)[]
This is from TDPL page 407: import std.algorithm, std.concurrency, std.stdio; void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (immutable(ubyte)[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer); } } void fileWriter() { // write loop while (true) { auto buffer = receiveOnly!(immutable(ubyte)[])(); tgt.write(buffer); } } Error: C:\DMD\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(1943): Error: cannot implicitly convert expression (buffer) of type ubyte[] to immutable(ubyte)[] Yet interestingly I can't use type inference: foreach (buffer; stdin.byChunk(bufferSize)) { send(tid, buffer); } Error: stdin_stdout_copy.d(11): Error: cannot infer type for buffer But in the original code I get back a mutable ubyte[] which I can't implicitly convert to immutable (I'd need a copy first). There's no .dup or .idup property for stdin.byChunk. So what am I supossed to do here?
Re: Threading errors.
So what's the word on this? Will we have simple indexing of tuples via T[] or do we still need T.field[] and T._1 ? The situations is the same in 2.048 as it was in 2.047. There are more examples of tuples being used via T[] in some Phobos code examples (which don't compile and I've reported that). Otherwise if it stays the way it is I'll send Andrei a message to add the corrections to the errata. Philippe Sigaud Wrote: > On Tue, Jul 27, 2010 at 19:03, Sean Kelly wrote: > > > The next release, 2.048, should bring things in line with TDPL. I had > > meant to do this for 2.047, but was too busy with other work to finish in > > time. > > > > Do you mean, indexing tuples directly by a CT value as in msg[1]? Because > that was the only error here, I think. > > On Tue, Jul 27, 2010 at 19:03, Sean Kelly dir="ltr">< href="mailto:s...@invisibleduck.org";>s...@invisibleduck.org> > wrote: > The next release, 2.048, should bring things in line with TDPL. I had meant > to do this for 2.047, but was too busy with other work to finish in time. > Do you mean, indexing tuples directly by a CT > value as in msg[1]? Because that was the only error here, I > think. >
How to name things [Was: Re: SO rotate question]
Jonathan M Davis: > Still, naming functions is a bit of an art and most function names are > debatable as to how good they are, so you're bound to have functions > in any API that aren't named the way that you think they should be. I don't like what you say. If you take a look at how in the last ten years every small feature was designed by Python devs, you see how much care they have for naming things. For each name of feature/built-in all people of the development mailing list propose their names and the rationale behind those names. Then they write down a list of all the ideas, and they vote for each name. The name with most votes usually gets accepted, and then they start over with the next name to choose. This is a bit time consuming, but one of the most important qualities of Python its refined and natural design. You are right that good names are purpose-specific, and often a name that is good for me is not good for you. Every single person has some quirks, so if you let a single person choose a name, there's some risk the name will reflect only the specific quirks of that person. On the other hand the good names for a specific feature are not totally random. If you take 100 smart persons, and you ask them what name to use to define a certain feature, you will often receive something like 15-20 answers, and among them one or two answers are the most common. The most common choice is the the right name choice. It's true that this most common name is not always the same name that each person is willing to chose, but such average process smooths out the quirks each single person has, and very often the names chosen by this process are simple to remember and natural. This is how I'd like Phobos names to be chosen. Andrei is smart and intelligent, but as everyone else he has quirks (and his usage of English is not the most common you may find), so letting the choice of many names to any single person is bad. - I have also added this one: http://d.puremagic.com/issues/show_bug.cgi?id=4803 Bye, bearophile
Re: Understanding isInfinite(Range)
Ah, you're right. Whenever I see the square brackets my brain automatically things "we're indexing something". I'll blame that on C. :p Thanks. Steven Schveighoffer Wrote: > On Fri, 03 Sep 2010 11:12:29 -0400, Andrej Mitrovic > wrote: > > > I was reading about the various range templates in std.range and I found > > this: > > > > http://www.digitalmars.com/d/2.0/phobos/std_range.html#isInfinite > > > > Seems simple enough. But I dont understand it's implementation, this > > from range.d: > > > > template isInfinite(Range) > > { > > static if (isInputRange!Range && is(char[1 + Range.empty])) > > enum bool isInfinite = !Range.empty; > > else > > enum bool isInfinite = false; > > } > > > > What does char[1 + Range.empty] do? It looks rather cryptic.. > > char[1+Range.empty] is a type. If Range.empty is a compile-time constant, > then this type is valid, otherwise it's not valid (the is expression > results to true if the argument is a valid type). > > If it's valid, then Range.empty never changes. If it never changes and > it's always false, then it's infinite. > > -Steve
Re: Understanding isInfinite(Range)
On Fri, 03 Sep 2010 11:12:29 -0400, Andrej Mitrovic wrote: I was reading about the various range templates in std.range and I found this: http://www.digitalmars.com/d/2.0/phobos/std_range.html#isInfinite Seems simple enough. But I dont understand it's implementation, this from range.d: template isInfinite(Range) { static if (isInputRange!Range && is(char[1 + Range.empty])) enum bool isInfinite = !Range.empty; else enum bool isInfinite = false; } What does char[1 + Range.empty] do? It looks rather cryptic.. char[1+Range.empty] is a type. If Range.empty is a compile-time constant, then this type is valid, otherwise it's not valid (the is expression results to true if the argument is a valid type). If it's valid, then Range.empty never changes. If it never changes and it's always false, then it's infinite. -Steve
Understanding isInfinite(Range)
I was reading about the various range templates in std.range and I found this: http://www.digitalmars.com/d/2.0/phobos/std_range.html#isInfinite Seems simple enough. But I dont understand it's implementation, this from range.d: template isInfinite(Range) { static if (isInputRange!Range && is(char[1 + Range.empty])) enum bool isInfinite = !Range.empty; else enum bool isInfinite = false; } What does char[1 + Range.empty] do? It looks rather cryptic..
Re: SO rotate question
On Friday 03 September 2010 04:35:30 bearophile wrote: > > canFind isn't really the best possible name, is it? > > Some name/APIs of Phobos are not the best possible, they were often > invented by a single person. I don't know if contains() or isIn() are > better. It used to be that all you had was find(), and you had to check whether the result was empty if you were looking to see whether what you were trying to find was in the range or not. I pointed out that that was overly verbose and less efficient in cases where all you cared about was whether the item or items was in the range rather than getting the range starting at the point where the item was found. I probably suggested contains() for the new function name, but I'd have go look at the bug report. In either case, Andrei agreed that it was a good idea and added the function. However, he named it canFind() - presumably because that's what you're trying to do. You're seeing whether you could find it with find(). So, from that perspective, it's a perfect name. However, I don't think that's really how people think about it. They're looking for whether an element is in a range, not whether they can find it there. So, from that perspective, it's a poor name. Personally, I think that contains() would be better, but canFind() does make sense depending on how you look at it. Now, canFind() might be going away. I opened a bug report asking for all() and any() (all() returning whether all of the elements of a range satisfied a predicate, and and any() returning whether any of them did) and pointed out that while there is no function in std.algorithm which does all(), the version of canFind() which takes a predicate and a haystack but no needle is effectively any(). Andrei thought that any() was better and decided that canFind() should be replaced with any(). After that, I pointed out that while any() is definitely better for the case where it's a just a predicate and a haystack, the other cases would still make more sense as canFind(), and he didn't say anything further on that bug report, so I don't know what he intends to do, and canFind() may or may not be going away. Regardless, contains() is definitely a better name for the other versions of canFind(), so perhaps a bug report should be opened on the matter. Still, naming functions is a bit of an art and most function names are debatable as to how good they are, so you're bound to have functions in any API that aren't named the way that you think they should be. - Jonathan M Davis
Re: SO rotate question
Pelle: > bool isRotated(T)(T[] a, T[] b) { > return a.length == b.length && (a.length == 0 || > canFind(chain(a,a), b)); > } Nice clean solution. I suggest to add "pure" and two "const" in the signature. > canFind isn't really the best possible name, is it? Some name/APIs of Phobos are not the best possible, they were often invented by a single person. I don't know if contains() or isIn() are better. Bye, bearophile
Re: SO rotate question
On 09/03/2010 01:35 PM, bearophile wrote: Pelle: bool isRotated(T)(T[] a, T[] b) { return a.length == b.length&& (a.length == 0 || canFind(chain(a,a), b)); } Nice clean solution. I suggest to add "pure" and two "const" in the signature. canFind isn't really the best possible name, is it? Some name/APIs of Phobos are not the best possible, they were often invented by a single person. I don't know if contains() or isIn() are better. Bye, bearophile Heh, I actually tried that before posting, but chain doesn't seem to support const. :-) Should probably be two forward ranges, not two arrays, as well.
Re: SO rotate question
simendsjo: > I agree that's much simpler, but s1 ~ s1 doesn't perform too well I > think. Always creates a new heap allocation and copies the array.. The version written by Pelle is better. On the other hand performance is not an absolute thing, it's "good enough" or "not good enough", and in many situations you don't need a high-performance rotate test function. Bye, bearophile
Re: SO rotate question
Pelle wrote: On 09/02/2010 10:24 PM, bearophile wrote: simendsjo: Suggestions for D-ifying the code is welcome. Your unit tests are not good enough, they miss some important corner cases. This my first version in D2: import std.string: indexOf; /// return True if s1 is a rotated version of s2 bool isRotated(T)(T[] s1, T[] s2) { return (s1.length + s2.length == 0) || (s1.length == s2.length&& indexOf(s1 ~ s1, s2) != -1); } unittest { // of isRotated assert(isRotated("", "")); assert(!isRotated("", "x")); assert(!isRotated("x", "")); assert(isRotated("x", "x")); string s = "rotato"; assert(isRotated(s, "rotato")); assert(isRotated(s, "otator")); assert(isRotated(s, "tatoro")); assert(isRotated(s, "atorot")); assert(isRotated(s, "torota")); assert(isRotated(s, "orotat")); assert(!isRotated(s, "rotator")); assert(!isRotated(s, "rotat")); assert(!isRotated(s, "rotata")); } void main() {} Bye, bearophile This is what I wrote: bool isRotated(T)(T[] a, T[] b) { return a.length == b.length && (a.length == 0 || canFind(chain(a,a), b)); } Use chain to avoid allocation. canFind isn't really the best possible name, is it? Sweet! Thats what I was looking for!