Re: dmd 2.049 bug with take and SList?
On Thu, 14 Oct 2010 06:54:17 +, Lars T. Kyllingstad wrote: > On Wed, 13 Oct 2010 18:06:15 +, Lars T. Kyllingstad wrote: > >> On Wed, 13 Oct 2010 16:46:09 +, Nick Treleaven wrote: >> >>> Hi, >>> I'm new to D2 ranges but have been following D for some time. I'm >>> posting here because I want to check if I'm doing anything wrong >>> before filing a bug. >>> >>> The code below is a test case I made after hitting the problem in real >>> code. Basically the pyramid recursive function should print out: [1, >>> 2, 3] >>> [1, 2] >>> [1] >>> >>> This works fine when calling with an int[] range, but calling with >>> SList!int seems to make the compiler hang, eating up memory. >>> >>> Should I file a bug? >>> >>> >>> import std.stdio; >>> import std.range; >>> import std.container; >>> >>> void pyramid(Range)(Range items) >>> { >>> if (items.empty) >>> return; >>> writeln(items); >>> auto len = walkLength(items); >>> auto r = take(items, len - 1); >>> pyramid(r); >>> } >>> >>> void main() >>> { >>> /* array version is fine */ >>> int[] arr = [1, 2, 3]; >>> pyramid(arr[]); >>> >>> SList!int list = [1, 2, 3]; >>> pyramid(list[]);/* infinite loop with dmd 2.049 */ >>> } >> >> >> You are creating an infinite recursion of templates. For an array the >> return type of take() is the same array type. For other ranges, the >> return type of take() is Take!Range. So when you instantiate pyramid! >> Range, it instantiates pyramid!(Take!Range), and then >> pyramid!(Take!(Take! Range)), and so on ad infinitum. >> >> A solution could be to make take!(Take!Range)() just return another >> Take! Range. I can look into that, but you should file a bug report on >> it so it's not forgotten. >> >> -Lars > > http://d.puremagic.com/issues/show_bug.cgi?id=5052 Fixed. http://www.dsource.org/projects/phobos/changeset/2102
writing
Hello, write and writeln just write; writef and writefln first format: seems clear. But the latter do not work properly with D strings, and the former do not work without format. Is there a practical way to just write anything to the terminal (without caring of its type)? Is there some rationale about this? Would it be possible to automatically add \0 to D strings passed to write/writeln (can a programmer define a custom func doing this before delegating to builtin funcs, or is it necessarily a job for the compiler?)? And/or what about having writef/writefln use "%s" as default format (when the first arg is not a string)? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: writing
On Thu, 14 Oct 2010 09:58:36 +0200, spir wrote: > Hello, > > write and writeln just write; writef and writefln first format: seems > clear. But the latter do not work properly with D strings, and the > former do not work without format. Is there a practical way to just > write anything to the terminal (without caring of its type)? > > Is there some rationale about this? > Would it be possible to automatically add \0 to D strings passed to > write/writeln (can a programmer define a custom func doing this before > delegating to builtin funcs, or is it necessarily a job for the > compiler?)? And/or what about having writef/writefln use "%s" as default > format (when the first arg is not a string)? I don't understand what you mean. This works just fine: import std.stdio; void main() { string s = "Hello world!"; writeln(s); } If I'm misunderstanding you, please explain, or perhaps give a code example. -Lars
Re: What sorts of things cause cyclic dependencies?
Jonathan M Davis: > Well, just knowing that it involves module constructors is definitely useful, > though the error message really needs to be improved. Thanks. You may file a bug report, with an example, asking for a better error message (with a better wording), or a much better error message (that lists the cycle too). Bye, bearophile
Re: GC interpreting integer values as pointers
On Sat, 09 Oct 2010 15:51:37 -0400, Ivo Kasiuk wrote: Hi! In my D programs I am having problems with objects not getting finalised although there is no reference anymore. It turned out that this is caused by integers which happen to have values corresponding to pointers into the heap. So I wrote a test program to check the GC behaviour concerning integer values: [snip] So in most but not all situations the integer value keeps the object from getting finalised. This observation corresponds to the effects I saw in my programs. I find this rather unfortunate. Is this known, documented behaviour? In a typical program there are such integer values all over the place. How should such values be stored to avoid unwanted interaction with the GC? Yes, D's garbage collector is a conservative garbage collector. One which doesn't have this problem is called a precise garbage collector. There are two problems here. First, D has unions, so it is impossible for the GC to determine if a union contains an integer or a pointer. Second problem is the granularity of scanning. A memory block is scanned as if every n bits (n being your architecture) is a pointer, or there are no pointers. This is determined by a bit associated with the block (the NO_SCAN bit). If you allocate a memory block that contains at least one pointer, then all the words in the memory block are considered to be pointers by the GC. There is a (continually updated) patch which allows the GC to be semi-precise. That is, the type information of the memory block will be linked to it. This will allow precise scanning except for unions. Once this is integrated, the false pointer problem will be much less prevalent. -Steve
Re: dmd 2.049 bug with take and SList?
On Thu, 14 Oct 2010 07:18:48 +, Lars T. Kyllingstad wrote: >>> You are creating an infinite recursion of templates. For an array the >>> return type of take() is the same array type. For other ranges, the >>> return type of take() is Take!Range. So when you instantiate pyramid! >>> Range, it instantiates pyramid!(Take!Range), and then >>> pyramid!(Take!(Take! Range)), and so on ad infinitum. OK, makes sense. >>> A solution could be to make take!(Take!Range)() just return another >>> Take! Range. I can look into that, but you should file a bug report >>> on it so it's not forgotten. >>> >>> -Lars >> >> http://d.puremagic.com/issues/show_bug.cgi?id=5052 > > Fixed. > http://www.dsource.org/projects/phobos/changeset/2102 Thanks!
Re: mutable reference to const object
On Tue, 12 Oct 2010 18:54:49 -0400, Jonathan M Davis wrote: On Tuesday, October 12, 2010 15:27:41 Jesse Phillips wrote: Jonathan M Davis Wrote: > Unfortunately, at this point, tail const has pretty much been decided to > be too difficult implement and/or too difficult to do cleanly, so it's > not in D and likely never will be. If it's mentioned in the online docs, > the docs need to be updated. It's been a long time since there was any > kind of tail const in D. > > - Jonathan M Davis What I have heard is that it can't be done syntactically for references. As Denis shows you can do it with points (and arrays) but not object references. There are many syntax suggestion threads so I suggest search for them before bring it up again. Yes, you can do it with pointers, but not with references, and it causes problems for stuff like ranges. There have been several discussions on it over time, and Walter has pretty much said that it's not a feature that's going to happen. He spent too much time on it before without success to want to try at it again. If someone were to do the work, and the syntax was bearable, it might be considered. I think Walter no longer wants to accept any ideas without proof that they will work -- he's already worked enough on trying to implement tail-const. I personally think tail const is going to be a very important feature that will not be solvable via the library. Tail-const ranges are going to be very important when it comes to things like collections. -Steve
Re: What sorts of things cause cyclic dependencies?
On Thu, 14 Oct 2010 02:31:23 -0400, Jonathan M Davis wrote: On Wednesday 13 October 2010 23:03:05 Lars T. Kyllingstad wrote: On Thu, 14 Oct 2010 05:53:51 +, Lars T. Kyllingstad wrote: > On Wed, 13 Oct 2010 21:25:15 -0700, Jonathan M Davis wrote: >> Okay. in the code that I'm working on at the moment, I get an exception >> saying that a cyclic dependency was detected but no information >> whatsoever as to where it is or what it means. I haven't been able to >> find much information on them other than some discussions of making it >> so that the compiler detects them at compile time. I have yet to figure >> out _what_ it is that is causes such errors. Could someone clue me in? >> It's really hard to track down a bug when the error only tells you that >> there's a bug and doesn't say anything about where it happens, and I >> have no clue what sort of things can be cyclically dependent. > > Say you have two modules, a and b. Both have static constructors, and a > > imports b: > // a.d > module a; > import b; > static this() { ... } > > // b.d > module b; > static this() { ... } > > The language is then defined so that b's constructor is run before a's, > since a depends on b. But what happens if b imports a as well? There > is no way to determine which constructor to run first, so the runtime > throws a "cyclic dependency" exception. I should mention that this can happen with larger cycles as well, i.e. "a imports b, b imports c, c imports ..., ... imports a". This can make some cyclic dependencies very hard to track down. There was a discussion about this on the Phobos mailing list a few months ago: http://lists.puremagic.com/pipermail/phobos/2010-June/thread.html#949 -Lars Well, just knowing that it involves module constructors is definitely useful, though the error message really needs to be improved. Thanks. I had mostly implemented a cyclic dependency improvement that actually printed the cycle. However, I never committed it because I found there was a huge hole in the algorithm that needed to be addressed. Essentially certain cycles are allowed (even today). I think it can be done with an O(n^2) space and an O(n) algorithm, but I need to work on it. BTW, there is a bug report for this problem: http://d.puremagic.com/issues/show_bug.cgi?id=4384 -Steve
How to use tango's FileScan correctly?
Hello! I'm trying out some things in D (with tango) and tried to build a *very* primitive indexing program. One function requires to run through a directory (without recursion) and get me all the files/folders in there. So after reading the documentation I found that tango.io.FileScan basically does what I need. It's just that I can't get it to work. All examples there use some filter, but I don't need one. And the other stuff I tried (and which compiled) gives me either a wrong number of files in my debug output, or none at all. Here's (part of) my code: FileScan scan = new FileScan(); // only one of those was used at a time, the others are commented // dir is a char[] with an existing (absolute) directory: scan(dir, "*"); scan(dir, ".*"); scan(dir, "*.*"); scan(dir, ""); scan = scan.sweep(dir, false); FilePath[] myFolders = scan.folders(); FilePath[] myFiles = scan.files(); char[][] err = scan.errors(); Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files : ")(myFiles.length)("\n")(); Stdout("errors:\n")(); foreach (char[] e; err) Stdout(e)("\n")(); The result was always: found folders: 0 found files : 0 errors: % _ I think I'm doing something very wrong here. And it's possibly because I don't understand the documentation. Can you help me get this to work? Regards qwesx
Re: Am I doing this right? (File byChunk)
I'll be sure to check it out once I get my phone line back (forgot to pay the bills..). I'm currently on expensive wireless (Why is wireless so expensive anyway? What's so special about radiowaves that were invented half a century ago?..) Thanks for the heads up! On 9/14/10, Jonathan M Davis wrote: > gmx.com seems to deal with mailing list e-mails correctly (by actually > putting > the ones you sent to the list in your inbox when they come from the list), > and > it has free imap and lots of disk space just like gmail (not to mention that > it > uses proper folders instead of labels), so I've switched over to it. It's > much > more pleasant to deal with (at least when using it from an e-mail client; > whether the user interface for the site itself is better is more debatable). > And > switching e-mail addresses gives me a chance to reduce the spam that I get. > :) > > - Jonathan M Davis >
Re: GC interpreting integer values as pointers
Steven Schveighoffer: > There are two problems here. First, D has unions, so it is impossible for > the GC to determine if a union contains an integer or a pointer. D has unions, and sometimes normal C-style unions are useful. But in many situations when you have a union you also keep a tag that represents the type, so in many of those situations you may use the tagged union of Phobos, std.variant.Algebraic (if the Phobos implementation is good enough, currently unfinished and not good enough yet) and the D GC may be aware and read and use the tag of an Algebraic union to know at runtime what's the type. This improves the GC precision a little. Bye, bearophile
Passing multidimensional D arrays to C (sorry if duplicate)
I don't have a minimal working example right now so I'll just have to show you the client code and the C function prototype. I have a C++ DLL with a C interface for some of its functions and I am dynamically loading it in my D application. Here's some code with the usual DLL loading bits left out: alias extern(C) void function(float** inputs) ProcessProc; // Some code that loads the DLL, calls Windows' GetProcAddress.. and now we have a function pointer processFunc: ProcessProc processFunc; I have no trouble passing single pointer parameters to C functions, and even callback functions. But I haven't figured out an elegant way of passing multidimensional arrays to functions expecting pointers to pointers. I've tried forcing a 2-dimensional array with a cast, or even changing the function pointer signature to *fake* that it takes a 2-dimensional array and not a ptr-2-ptr, but that doesn't work properly as the C code ends up working only partially and I get back an access violation. So my calling code looks like the following. Disregard that I'm using GC's malloc and not std.c.stdlib.malloc for now please :) : float[][] _inputs; float** inputs; enum numInputs = 4; enum kBlockSize = 512; _inputs = new float[][](numInputs, kBlockSize); // we would now fill the inputs with some random data inputs = cast(float**)GC.malloc((float*).sizeof * numInputs); foreach (index; 0 .. numInputs) { inputs[index] = _inputs[index].ptr; } // some loop that runs for a number of cycles, im using while true just for demonstration while (true) { processFunc(inputs); } I don't want to leave you in the dark, so let me explain. I'm using the popular VST plugin standard, which is used for digital audio plugin effects. The loaded DLL can be any DLL file that conforms to this standard and has a certain number and type of functions ready to be called from the client code. Basically how it's used is: I send a pointer to a number of buffers to the DLL's processing function, and the effect does some processing on the data and writes it back to the buffers. If it's necessary I'll try to write a simplified C DLL and calling code to show what's wrong. P.S. (for those in the know) I have a fully working Host example that can load VST instruments/effects, check their capabilities, do some processing, and load their GUI (if they have one). I have not ported any VST classes used to build the VST instruments yet. P.P.S. I also have a working ASIO Host, however it's only a wrapper around the C++ classes. I'm currently having huge issues with COM, and I'm not yet sure if there's a bug in DMD or in my implementation. P.P.P.S. Hopefully I'll be able to provide a clean implementation of both VST and ASIO, and after the necessary registration at Steinberg I'll create a repository for the projects. Wish me luck. :>
[import,module] got biting again :(
Yay, free access to a! I searched for this bug in the bug-reports.. Why are there so many basic import bugs? -- module main; import b; void main(){ a.write(); } -- module a; import std.stdio; void write(){ writefln("a"); } -- module b; import a; //also with static --
Re: How to use tango's FileScan correctly?
I suspect there is a bug. You could use FilePath.toList() as an alternative for now. foreach(path; FilePath(".").toList()) { if(path.isFolder) folder_counter++; else file_counter++; } On Thu, 14 Oct 2010 15:31:47 +, qwesx wrote: > Hello! > > I'm trying out some things in D (with tango) and tried to build a *very* > primitive indexing program. One function requires to run through a > directory (without recursion) and get me all the files/folders in there. > > So after reading the documentation I found that tango.io.FileScan > basically does what I need. It's just that I can't get it to work. All > examples there use some filter, but I don't need one. And the other > stuff I tried (and which compiled) gives me either a wrong number of > files in my debug output, or none at all. > > Here's (part of) my code: > > FileScan scan = new FileScan(); > // only one of those was used at a time, the others are commented // dir > is a char[] with an existing (absolute) directory: scan(dir, "*"); > scan(dir, ".*"); > scan(dir, "*.*"); > scan(dir, ""); > scan = scan.sweep(dir, false); > > > FilePath[] myFolders = scan.folders(); FilePath[] myFiles = > scan.files(); > char[][] err = scan.errors(); > Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files > : ")(myFiles.length)("\n")(); Stdout("errors:\n")(); > foreach (char[] e; err) > Stdout(e)("\n")(); > > > The result was always: > > found folders: 0 > found files : 0 > errors: > % _ > > I think I'm doing something very wrong here. And it's possibly because I > don't understand the documentation. > > Can you help me get this to work? > > > > Regards > qwesx
Re: Passing multidimensional D arrays to C (sorry if duplicate)
Andrej Mitrovic: > But I haven't figured out an elegant way of passing multidimensional arrays > to functions expecting pointers to pointers. In D there are no nD dynamic arrays. nD arrays in D may be fixed-sized. The fixed-sized ones are just a contiguous sequence of values (so their rows may be not aligned to 16 bytes). The dynamic arrays may contain other dynamic arrays, so a 2D dynamic array is a 2-word struct that points to an array of 2-word structs, each of them points to an array of the items (so if the row lengths are all the same you are wasting memory). There are few different ways to allocate 2D arrays in C, if your C function expects a pointer to pointers, then it wants an array of pointers to the row, so the D structure is not fit, you need to build an array of pointers: void main() { enum int side = 10; alias int T; auto m = new T[][](side, side); auto m2 = new T*[side]; foreach (i, ref p; m2) p = m[i].ptr; // now you may read m2.ptr from C } Bye, bearophile
Re: [import,module] got biting again :(
%u: > Why are there so many basic import bugs? Module system bugs are among the most voted in Bugzilla. True modules are absent in C/C++, so maybe Walter thinks assuring their semantics is correct is not so important compared to other kinds of bugs, or maybe such bugs are hard to fix, I don't know. Bye, bearophile
Foreach and string to string assignment (maybe a bug..)
I'm not sure if this is a legitimate bug or one of my brainfarts. I know that if I'm using a foreach loop with a char array as a reusable datatype I definitely have to create a copy if I want to store it to a string. But this code is a little more subtle, check it out (This is Windows only because it uses the registry, sorry): module mymodule; import std.stdio : writeln, write; import std.windows.registry; void main() { Key HKLM = Registry.localMachine; Key SFW = HKLM.getKey("software"); string[] names; foreach (Key key; SFW.keys()) { string name = key.name(); // string name = key.name().idup; // workaround for the issue names ~= name; } writeln("results:"); foreach (name; names) { write(name, ", "); } } The results are quite unexpected. The strings get overwritten with each other, and in my case the results are similar to this: Sun Microsystems, Sun Micros, Sun , Sun Micr, Sun, Sun Mic,... And it goes like that for a hundred or so values, then switches to the next name and writes more garbage like that. If I use .idup, the problem goes away. What I don't understand is why assigning a string to a string isn't safe in this case? They're both immutable, so I was expecting the contents of the strings never to change. If it's not a bug, it certainly is a subtle issue. The original foreach loop was quite big, and it took some time to figure out the problem. Are we *always* supossed to be using .idup in a foreach loop? Of course, the Key key variable is reused in the foreach loop, so I guess this has something to do with the results.
Overloading Generic and non-generic functions
AFAIK the following should be allowed, but it's not (v2.048): void test(uint) { } void test(T)(T value) { } void main() { test(42); test("hello"); } These end up conflicting with each other. From what I've read in TDPL we should be able to overload generic and nongeneric functions, there's an example in the book similar to this one, but it doesn't work. Has this been filed as a bug already?
Order of interface implementations affects code
Should the order in which you implement interfaces have an effect in your code? It seems to be that way when you have two functions with the same name in the different interfaces. Here's an example: import std.stdio : writeln; interface Foo { final void run() { writeln("foo"); } } interface Bar { final void run() { writeln("bar"); } } class One : Foo, Bar { } class Two : Bar, Foo { } void main() { with (new One) { run(); // writes foo } with (new Two) { run(); // writes bar } } Bug? Or legitimate working code?
Re: How to use tango's FileScan correctly?
Here is the bug report (patch proposal included): http://dsource.org/projects/tango/ticket/2003 On Thu, 14 Oct 2010 15:31:47 +, qwesx wrote: > Hello! > > I'm trying out some things in D (with tango) and tried to build a *very* > primitive indexing program. One function requires to run through a > directory (without recursion) and get me all the files/folders in there. > > So after reading the documentation I found that tango.io.FileScan > basically does what I need. It's just that I can't get it to work. All > examples there use some filter, but I don't need one. And the other > stuff I tried (and which compiled) gives me either a wrong number of > files in my debug output, or none at all. > > Here's (part of) my code: > > FileScan scan = new FileScan(); > // only one of those was used at a time, the others are commented // dir > is a char[] with an existing (absolute) directory: scan(dir, "*"); > scan(dir, ".*"); > scan(dir, "*.*"); > scan(dir, ""); > scan = scan.sweep(dir, false); > > > FilePath[] myFolders = scan.folders(); FilePath[] myFiles = > scan.files(); > char[][] err = scan.errors(); > Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files > : ")(myFiles.length)("\n")(); Stdout("errors:\n")(); > foreach (char[] e; err) > Stdout(e)("\n")(); > > > The result was always: > > found folders: 0 > found files : 0 > errors: > % _ > > I think I'm doing something very wrong here. And it's possibly because I > don't understand the documentation. > > Can you help me get this to work? > > > > Regards > qwesx
Re: Order of interface implementations affects code
On Thursday, October 14, 2010 10:14:25 Andrej Mitrovic wrote: > Should the order in which you implement interfaces have an effect in your > code? It seems to be that way when you have two functions with the same > name in the different interfaces. Here's an example: > > import std.stdio : writeln; > > interface Foo > { > final void run() { writeln("foo"); } > } > > interface Bar > { > final void run() { writeln("bar"); } > } > > class One : Foo, Bar > { > } > > class Two : Bar, Foo > { > } > > void main() > { > with (new One) > { > run(); // writes foo > } > > with (new Two) > { > run(); // writes bar > } > } > > Bug? Or legitimate working code? I'd have to pull out my copy of TDPL, but IIRC, it should not be legal to call run() directly because it's ambiguous. Assuming that dmd was working correctly on this issue, it wouldn't let this code compile. I believe that you'd have to do something like Foo.run() and Bar.run() to call run(). I'd have to check TDPL to be completely sure of the syntax though. - Jonathan M Davis
Re: What sorts of things cause cyclic dependencies?
On Thu, 14 Oct 2010 06:03:05 + (UTC) "Lars T. Kyllingstad" wrote: > On Thu, 14 Oct 2010 05:53:51 +, Lars T. Kyllingstad wrote: > > > On Wed, 13 Oct 2010 21:25:15 -0700, Jonathan M Davis wrote: > > > >> Okay. in the code that I'm working on at the moment, I get an exception > >> saying that a cyclic dependency was detected but no information > >> whatsoever as to where it is or what it means. I haven't been able to > >> find much information on them other than some discussions of making it > >> so that the compiler detects them at compile time. I have yet to figure > >> out _what_ it is that is causes such errors. Could someone clue me in? > >> It's really hard to track down a bug when the error only tells you that > >> there's a bug and doesn't say anything about where it happens, and I > >> have no clue what sort of things can be cyclically dependent. > > > > > > Say you have two modules, a and b. Both have static constructors, and a > > imports b: > > > > // a.d > > module a; > > import b; > > static this() { ... } > > > > // b.d > > module b; > > static this() { ... } > > > > The language is then defined so that b's constructor is run before a's, > > since a depends on b. But what happens if b imports a as well? There > > is no way to determine which constructor to run first, so the runtime > > throws a "cyclic dependency" exception. > > > I should mention that this can happen with larger cycles as well, i.e. "a > imports b, b imports c, c imports ..., ... imports a". This can make > some cyclic dependencies very hard to track down. > > There was a discussion about this on the Phobos mailing list a few months > ago: > > http://lists.puremagic.com/pipermail/phobos/2010-June/thread.html#949 > > -Lars I'm totally new to D, but have some real-life experience with circular imports. A typical case is with unit testing. Say you design a parsing lib, with (among others) a module defining Pattern types and another for (parse tree) Nodes, wich are thee results of successful pattern matches. To test Patterns, no issue, since it already imports Nodes for normal process. But testing Nodes introduces a circular dependance, only for testing, because the ordinary way to produce a node, and thus to be able to test its functionality, is to create a Pattern and run its match method against source text. 2 solutions I know of: * create fake Pattern types inside the Nodes module, just for testing * export Nodes' test routines into a third module that imports both Patterns and Nodes, but is not import. That's probably why many libraries have loads of separated test* unittest modules. But I prefere to have tests locally written in the module itself (which well seems to be the intention of D's testing features). Some static languages (eg freepascal) allow mutual dependance as long as at least one module (M1) uses imported elements of the other (M2) on the implementation side only (not in the interface). This allows the compiler initially constructing the interface of M1 (without any mention of M2), to be imported by M2. Then, M2 can be fully constructed, and imported into M1 for the needs of its implementation only. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: Overloading Generic and non-generic functions
Andrej Mitrovic wrote: AFAIK the following should be allowed, but it's not (v2.048): void test(uint) { } void test(T)(T value) { } void main() { test(42); test("hello"); } These end up conflicting with each other. From what I've read in TDPL we should be able to overload generic and nongeneric functions, there's an example in the book similar to this one, but it doesn't work. Has this been filed as a bug already? http://d.puremagic.com/issues/show_bug.cgi?id=2972 -- Simen
Re: GC interpreting integer values as pointers
On Thu, 14 Oct 2010 12:39:33 -0400, bearophile wrote: Steven Schveighoffer: There are two problems here. First, D has unions, so it is impossible for the GC to determine if a union contains an integer or a pointer. D has unions, and sometimes normal C-style unions are useful. But in many situations when you have a union you also keep a tag that represents the type, so in many of those situations you may use the tagged union of Phobos, std.variant.Algebraic (if the Phobos implementation is good enough, currently unfinished and not good enough yet) and the D GC may be aware and read and use the tag of an Algebraic union to know at runtime what's the type. This improves the GC precision a little. Unions are rare enough that I think this may not be worth doing. But yes, it could be had. -Steve
Re: GC interpreting integer values as pointers
> On Sat, 09 Oct 2010 15:51:37 -0400, Ivo Kasiuk wrote: > > > Hi! > > > > In my D programs I am having problems with objects not getting finalised > > although there is no reference anymore. It turned out that this is > > caused by integers which happen to have values corresponding to pointers > > into the heap. So I wrote a test program to check the GC behaviour > > concerning integer values: > > > > [snip] > > > So in most but not all situations the integer value keeps the object > > from getting finalised. This observation corresponds to the effects I > > saw in my programs. > > > > I find this rather unfortunate. Is this known, documented behaviour? In > > a typical program there are such integer values all over the place. How > > should such values be stored to avoid unwanted interaction with the GC? > > Yes, D's garbage collector is a conservative garbage collector. One which > doesn't have this problem is called a precise garbage collector. > > There are two problems here. First, D has unions, so it is impossible for > the GC to determine if a union contains an integer or a pointer. > > Second problem is the granularity of scanning. A memory block is scanned > as if every n bits (n being your architecture) is a pointer, or there are > no pointers. This is determined by a bit associated with the block (the > NO_SCAN bit). > > If you allocate a memory block that contains at least one pointer, then > all the words in the memory block are considered to be pointers by the > GC. There is a (continually updated) patch which allows the GC to be > semi-precise. That is, the type information of the memory block will be > linked to it. This will allow precise scanning except for unions. Once > this is integrated, the false pointer problem will be much less prevalent. > > -Steve Thanks! This absolutely makes sense. It is basically a trade-off between precision and efficiency of the GC. Slowly, I am learning all the little details of D's garbage collection. It is more complicated than it seems at first, but understanding it better greatly helps to write better programs in terms of memory management. There is one case though that I am still not sure about: associative arrays. It seems that keys as well as values in AAs are scanned for pointers even if both are integer types. How can I tell the GC that I do not want them to be scanned? I know about the NO_SCAN flag but what memory region should it be applied to in this case? BTW: considering the "conservative" scanning, the implementation of Object.toHash() is somewhat interesting: hash_t toHash() { // BUG: this prevents a compacting GC from working, needs to be fixed return cast(hash_t)cast(void*)this; } So an object's hash value will keep the GC from freeing the object, if that value is scanned. But as the comment indicates, this implementation needs to be changed anyway (I am eager to see the result). A compacting GC probably gives rise to some whole new problems. Ivo
Re: Foreach and string to string assignment (maybe a bug..)
On Thu, 14 Oct 2010 13:01:36 -0400, Andrej Mitrovic wrote: I'm not sure if this is a legitimate bug or one of my brainfarts. I know that if I'm using a foreach loop with a char array as a reusable datatype I definitely have to create a copy if I want to store it to a string. But this code is a little more subtle, check it out (This is Windows only because it uses the registry, sorry): module mymodule; import std.stdio : writeln, write; import std.windows.registry; void main() { Key HKLM = Registry.localMachine; Key SFW = HKLM.getKey("software"); string[] names; foreach (Key key; SFW.keys()) { string name = key.name(); // string name = key.name().idup; // workaround for the issue names ~= name; } writeln("results:"); foreach (name; names) { write(name, ", "); } } The results are quite unexpected. The strings get overwritten with each other, and in my case the results are similar to this: Sun Microsystems, Sun Micros, Sun , Sun Micr, Sun, Sun Mic,... And it goes like that for a hundred or so values, then switches to the next name and writes more garbage like that. If I use .idup, the problem goes away. What I don't understand is why assigning a string to a string isn't safe in this case? They're both immutable, so I was expecting the contents of the strings never to change. If it's not a bug, it certainly is a subtle issue. The original foreach loop was quite big, and it took some time to figure out the problem. Are we *always* supossed to be using .idup in a foreach loop? Of course, the Key key variable is reused in the foreach loop, so I guess this has something to do with the results. I'm not familiar with std.windows.registry, but there are two things here. First, unequivocally, this is a bug. If key.name is returning an immutable(char)[], and later on that value is being overwritten, this is a violation of the type system (immutable data must never change again). Second, I think the bug may not be that it's violating immutability, but rather that it's typed key.name as string. It could probably be const(char)[]. Essentially, I think from the behavior described that the foreach loop is reusing the name buffer for each iteration of the loop. This is probably to save extra heap allocations in case you don't use them after the foreach loop is over. I think your workaround is the correct way to deal with it. This is a common problem in defining an opApply loop which streams data -- do you make things safe or efficient? The only reasonable solution IMO is to make them efficient, because safety can be had by duping the data. -Steve
Re: GC interpreting integer values as pointers
On Thu, 14 Oct 2010 13:35:13 -0400, Ivo Kasiuk wrote: There is one case though that I am still not sure about: associative arrays. It seems that keys as well as values in AAs are scanned for pointers even if both are integer types. How can I tell the GC that I do not want them to be scanned? I know about the NO_SCAN flag but what memory region should it be applied to in this case? This is a common problem. I am not intimately familiar with AAs, but it may have something to do with the fact that it's not a templated type. That means the runtime is responsible for allocating AA nodes. I think at the moment there is no way to do this. I also think there is likely a bug report to this effect, and that others may have implemented better AAs to fix the issue. Try searching the bug database for AA and NO_SCAN. -Steve
Re: Foreach and string to string assignment (maybe a bug..)
Steven Schveighoffer: > This is a common problem in defining an opApply loop which streams data -- > do you make things safe or efficient? The only reasonable solution IMO is > to make them efficient, because safety can be had by duping the data. The only reasonable solution is to make it safe, and then allow the unsafe and more efficient behaviour only on explicit request. This follows D philosophy and in practice it's the only design that allows you to write programs that actually work, instead of being just a nest for bugs. Bye, bearophile
Re: Foreach and string to string assignment (maybe a bug..)
So do I file this as a bug? The current behavior is way too subtle imo, at least the compiler could issue a warning if this behavior is intended. On 10/14/10, bearophile wrote: > Steven Schveighoffer: > >> This is a common problem in defining an opApply loop which streams data -- >> >> do you make things safe or efficient? The only reasonable solution IMO is >> >> to make them efficient, because safety can be had by duping the data. > > The only reasonable solution is to make it safe, and then allow the unsafe > and more efficient behaviour only on explicit request. This follows D > philosophy and in practice it's the only design that allows you to write > programs that actually work, instead of being just a nest for bugs. > > Bye, > bearophile >
Re: writing
On Thu, 14 Oct 2010 08:05:09 + (UTC) "Lars T. Kyllingstad" wrote: > On Thu, 14 Oct 2010 09:58:36 +0200, spir wrote: > > > Hello, > > > > write and writeln just write; writef and writefln first format: seems > > clear. But the latter do not work properly with D strings, and the > > former do not work without format. Is there a practical way to just > > write anything to the terminal (without caring of its type)? > > > > Is there some rationale about this? > > Would it be possible to automatically add \0 to D strings passed to > > write/writeln (can a programmer define a custom func doing this before > > delegating to builtin funcs, or is it necessarily a job for the > > compiler?)? And/or what about having writef/writefln use "%s" as default > > format (when the first arg is not a string)? > > > I don't understand what you mean. This works just fine: > > import std.stdio; > > void main() > { > string s = "Hello world!"; > writeln(s); > } > > If I'm misunderstanding you, please explain, or perhaps give a code > example. > > -Lars Sorry, seems I just mistake the various C & D ways of coping with strings (too many forms of char arrays and functions that deal with them). I'll just stick with D funcs. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: Order of interface implementations affects code
Jonathan M Davis: > I believe that you'd have to > do something like Foo.run() and Bar.run() to call run(). I'd have to check > TDPL > to be completely sure of the syntax though. I think that's a compiler bug, regardless what the TDPL-Bible says :-) Bye, bearophile
Re: How to use tango's FileScan correctly?
Ok, as I've found out, FileScan is only for locating a set of files. the preferred way is to use the virtual file system (VFS): http://dsource.org/projects/tango/wiki/ChapterVFS Examples: http://www.dsource.org/projects/tango/wiki/VfsZipAndLinesExample http://dsource.org/projects/tango/browser/trunk/doc/example/vfs/vfscan.d http://dsource.org/projects/tango/browser/trunk/doc/example/vfs But I think FilePath.toList() is enough for your plans. On Thu, 14 Oct 2010 15:31:47 +, qwesx wrote: > Hello! > > I'm trying out some things in D (with tango) and tried to build a *very* > primitive indexing program. One function requires to run through a > directory (without recursion) and get me all the files/folders in there. > > So after reading the documentation I found that tango.io.FileScan > basically does what I need. It's just that I can't get it to work. All > examples there use some filter, but I don't need one. And the other > stuff I tried (and which compiled) gives me either a wrong number of > files in my debug output, or none at all. > > Here's (part of) my code: > > FileScan scan = new FileScan(); > // only one of those was used at a time, the others are commented // dir > is a char[] with an existing (absolute) directory: scan(dir, "*"); > scan(dir, ".*"); > scan(dir, "*.*"); > scan(dir, ""); > scan = scan.sweep(dir, false); > > > FilePath[] myFolders = scan.folders(); FilePath[] myFiles = > scan.files(); > char[][] err = scan.errors(); > Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files > : ")(myFiles.length)("\n")(); Stdout("errors:\n")(); > foreach (char[] e; err) > Stdout(e)("\n")(); > > > The result was always: > > found folders: 0 > found files : 0 > errors: > % _ > > I think I'm doing something very wrong here. And it's possibly because I > don't understand the documentation. > > Can you help me get this to work? > > > > Regards > qwesx
Re: How to use tango's FileScan correctly?
On Thu, 14 Oct 2010 18:07:20 +, Moritz Warning wrote: > Ok, > > as I've found out, FileScan is only for locating a set of files. the > preferred way is to use the virtual file system (VFS): > > http://dsource.org/projects/tango/wiki/ChapterVFS > > Examples: > http://www.dsource.org/projects/tango/wiki/VfsZipAndLinesExample > http://dsource.org/projects/tango/browser/trunk/doc/example/vfs/vfscan.d > http://dsource.org/projects/tango/browser/trunk/doc/example/vfs > > But I think FilePath.toList() > is enough for your plans. I'll take a look at it. Thank all three of you, I got it working with toList() :-) Regards qwesx
Re: Foreach and string to string assignment (maybe a bug..)
On Thu, 14 Oct 2010 13:49:13 -0400, bearophile wrote: Steven Schveighoffer: This is a common problem in defining an opApply loop which streams data -- do you make things safe or efficient? The only reasonable solution IMO is to make them efficient, because safety can be had by duping the data. The only reasonable solution is to make it safe, and then allow the unsafe and more efficient behaviour only on explicit request. This follows D philosophy and in practice it's the only design that allows you to write programs that actually work, instead of being just a nest for bugs. How do you request in a foreach loop that it doesn't dup? That's why I think the only one which allows both is the by default unsafe version. Note also, by "unsafe" we just mean surprising :) It's still safe in terms of memory safety. On Thu, 14 Oct 2010 13:55:38 -0400, Andrej Mitrovic wrote: So do I file this as a bug? The current behavior is way too subtle imo, at least the compiler could issue a warning if this behavior is intended. Well, at the very least, this violates immutability. You can file a bug based on those grounds alone. Whether the foreach loop should auto-dup for you is another question, I think it's fine to require you to dup each key's name if you plan on using it later, but this should be in the documentation. -Steve
Re: Foreach and string to string assignment (maybe a bug..)
Steven Schveighoffer: > How do you request in a foreach loop that it doesn't dup? There are several ways to do this. You may add a boolean value in the struct/class template, that switches the safe/unsafe behaviour (defaults to safe), or you may let the basic opApply to dup, plus you add another method with a name that warns against its non-copying behaviour that doesn't dup. In my dlibs1 I have used the first solution for the lazy xpermutations/xcombinations. > Whether the foreach loop should auto-dup for you is another question, I > think it's fine to require you to dup each key's name if you plan on using > it later, but this should be in the documentation. D Zen follows another design philosophy, documentation is not enough, people forget things. > Note also, by "unsafe" we just mean surprising :) It's still safe in > terms of memory safety. "Safe" has many different meanings. Something that on default acts in a bug-prone way is not "safe". Bye, bearophile
Re: Foreach and string to string assignment (maybe a bug..)
On Thursday 14 October 2010 12:20:06 bearophile wrote: > Steven Schveighoffer: > > How do you request in a foreach loop that it doesn't dup? > > There are several ways to do this. You may add a boolean value in the > struct/class template, that switches the safe/unsafe behaviour (defaults > to safe), or you may let the basic opApply to dup, plus you add another > method with a name that warns against its non-copying behaviour that > doesn't dup. In my dlibs1 I have used the first solution for the lazy > xpermutations/xcombinations. > > > Whether the foreach loop should auto-dup for you is another question, I > > think it's fine to require you to dup each key's name if you plan on > > using it later, but this should be in the documentation. > > D Zen follows another design philosophy, documentation is not enough, > people forget things. > > > Note also, by "unsafe" we just mean surprising :) It's still safe in > > terms of memory safety. > > "Safe" has many different meanings. Something that on default acts in a > bug-prone way is not "safe". > > Bye, > bearophile The "safe" that Walter and Andrei are almost always concerned with is memory safety. That doesn't mean that other types of safety aren't important, but it does mean that that's the sort of safety that dmd and Phobos is generally concerned about. - Jonathan M Davis
Re: Foreach and string to string assignment (maybe a bug..)
Jonathan M Davis: > The "safe" that Walter and Andrei are almost always concerned with is memory > safety. Please help me help Walter understand that for a modern system language memory safety isn't the only safety worth having :-) Bye, bearophile
about pointer syntax
Hello, As a way to start learning D by practicing, I'm trying to implement a symbol table as linked list: see prototype code of the structs below. (Hints about good D coding welcome :-) 2 little questions about pointers: 1. To please the compiler, I had to wrap dereferencing in parens, like in "(*symbol).name". Is this just normal (for disambiguation)? 2. Just noticed the compiler accepts "symbol.name", while symbol is a pointer: is there implicit dereferencing of pointers to structs? If yes, does this also apply to pointers to arrays (for information, this what Oberon does). And a note: had forgotten to add an empty main(), just for compiling: the linker produced a rather big amount of error text without any hint to the actual issue. Maybe dmd could cope with that before calling gcc? Finally: the reference is rather harsh for me, esp there are very few example (I have few practice of C, and none of C++); the bits of tutorials I found are too light or just started (toc points to empty pages). Is there anywhere online a kind of D programming guide, even not polished or possibly unfinished (I know about the book; maybe I'll order it, but in meantime...). Thank you, Denis == code == struct Symbol { string name = "" ; int element = 0 ; Symbol* next = null ; } struct List { Symbol* first = null ; int element(string name) { Symbol* symbol = this.first ; while (symbol) { if ((*symbol).name == name) {return (*symbol).element ;} ; symbol = (*symbol).next ; } return 0 ; } } == -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: about pointer syntax
spir: > As a way to start learning D by practicing, I'm trying to implement a symbol > table as linked list: see prototype code of the structs below. (Hints about > good D coding welcome :-) I have modified your code a little: struct Symbol { string name; int element; Symbol* next; this(string n, int e, Symbol* s=null) { name = n; element = e; next = s; } } struct List { Symbol* first; int element(string name) { for (auto symbol = this.first; symbol != null; symbol = symbol.next) if (symbol.name == name) return symbol.element; return 0; } } void main() { auto l = List(new Symbol("baz", 3, new Symbol("bar", 2, new Symbol("foo", 1; assert(l.element("bar") == 2); } - There's no need to initialize int to 0, string to "", pointers to null, etc, the compiler does it for you on default. Each type has a default init value (for floating point values it uses a NaN). - Generally don't put a space before the ending semicolon. - Four spaces indent and no space before the "*" of the pointer, as you have done, is OK. - Using a while loop as you have done is OK, I have used a for loop just to show a shorter alternative. - It's generally better to put one or two blank lines before structs, functions, etc - (*symbol).name is written symbol.name in D. - After an { generally a \n is used, there's no need to use the ; after the } - using 0 as error return value is sometimes OK, but also keep in mind that exceptions are present. - while(symbol) is acceptable, but some people prefer to put an explicit comparison to make the code more readable. - sometimes using "auto" helps. - In D linked lists are doable, but much less used, think about using a dynamic array, or even in this case an associative array: void main() { auto aa = ["foo": 1, "bar": 2, "baz": 3]; assert(aa["bar"] == 2); } > 1. To please the compiler, I had to wrap dereferencing in parens, like in > "(*symbol).name". Is this just normal (for disambiguation)? > 2. Just noticed the compiler accepts "symbol.name", while symbol is a > pointer: is there implicit dereferencing of pointers to structs? If yes, does > this also apply to pointers to arrays (for information, this what Oberon > does). Generally the field dereferencing doesn't require the "(*symbol).name", in D you use "symbol.name". Pointers to arrays are possible, but quite uncommon in D. > And a note: had forgotten to add an empty main(), just for compiling: the > linker produced a rather big amount of error text without any hint to the > actual issue. Maybe dmd could cope with that before calling gcc? I agree, I have bug report 4680 open on something similar: http://d.puremagic.com/issues/show_bug.cgi?id=4680 > Finally: the reference is rather harsh for me, esp there are very few example > (I have few practice of C, and none of C++); the bits of tutorials I found > are too light or just started (toc points to empty pages). Is there anywhere > online a kind of D programming guide, even not polished or possibly > unfinished (I know about the book; maybe I'll order it, but in meantime...). The D2 documentation isn't abundant yet :-) Bye, bearophile
Re: Order of interface implementations affects code
On 14/10/2010 18:14, Andrej Mitrovic wrote: Should the order in which you implement interfaces have an effect in your code? No. It seems to be that way when you have two functions with thesame name in the different interfaces. If they are normal interface functions, then if they have the same signature then they should resolve to the same function in any class that implements both. If they have the same parameters but different return types, or are final functions with the same signature, the compiler should reject any class that implements both. If one's final and the other isn't ... I guess I just don't know what's meant to happen. Stewart.
Any usable parsers for D2 around?
Hey, I've been looking for a D2 parser.. there seems to be a few D1 lexers, parsers, and even some minimal semantic analysis tools but I can't find much of anything for D2. Perhaps Goldie will be D2 compatible some day soon. :) There's a "CodeAnalyzer" lexer/parser with some minimal semantics, but it's D1 only and kind of dead for some years. The Poseidon author added some D2 support for it in his editor, so I have kept an eye on that. But interfacing with D1 code from D2 is kind of complicated, and I need to use it from D2. (I guess I could get away with writing a DLL with a simple interface for D2 or something..). I had a visit on the prowiki site and most of the parser projects there are either D1-only or dead. So is there anything usable for D2? Specifically I need these tools for use with an editor/IDE, which is something I'm working on for fun atm. But working on a parser is probably a ton of work, + the whole thing screams NIH to me. Luckily enough I don't have to reinvent a GUI and an editing control, there's DFL and Scintilla which are pretty awesome for my needs. Maybe I should take a look at how Descent/DDT and VisualD do their parsing.. :)
Re: about pointer syntax
On Thu, 14 Oct 2010 17:16:23 -0400 bearophile wrote: > spir: > > > As a way to start learning D by practicing, I'm trying to implement a > > symbol table as linked list: see prototype code of the structs below. > > (Hints about good D coding welcome :-) > > I have modified your code a little: > > struct Symbol { > string name; > int element; > Symbol* next; > > this(string n, int e, Symbol* s=null) { > name = n; > element = e; > next = s; > } > } > > struct List { > Symbol* first; > > int element(string name) { > for (auto symbol = this.first; symbol != null; symbol = symbol.next) > if (symbol.name == name) > return symbol.element; > return 0; > } > } > > void main() { > auto l = List(new Symbol("baz", 3, new Symbol("bar", 2, new Symbol("foo", > 1; > assert(l.element("bar") == 2); > } Thank you very much! That's exactly what I need to learn good practice, even more with comments below. (Hope you don't mind if I send other bits of code to be improved that way?) > - There's no need to initialize int to 0, string to "", pointers to null, > etc, the compiler does it for you on default. Each type has a default init > value (for floating point values it uses a NaN). Right. I think at keeping explicit defaults like "int element = 0" for documentation. It means "that's precisely what I want as default value", as opposed to just the language's "init". (So, for Symbol fields, I would only write element & next defaults explicitely, since name has no meaningful default: it must be provided.) > - Generally don't put a space before the ending semicolon. > - Four spaces indent and no space before the "*" of the pointer, as you have > done, is OK. > - It's generally better to put one or two blank lines before structs, > functions, etc (About ';', I like to separate actual code from grammatical separators, which are just noise to my eyes. If I ever write a lib for public use, I'll follow such styling guidelines ;-) > - Using a while loop as you have done is OK, I have used a for loop just to > show a shorter alternative. Thanks, as I said I'm not used to PLs of the C family. Wouldn't have ever thought that the "stepping" statement of a for loop can be something else as incrementation. > - (*symbol).name is written symbol.name in D. Very good. > - After an { generally a \n is used, there's no need to use the ; after the } Right. > - using 0 as error return value is sometimes OK, but also keep in mind that > exceptions are present. ;-) Was just a placeholder before I decide how to cope with "finding failure". > - while(symbol) is acceptable, but some people prefer to put an explicit > comparison to make the code more readable. Right, guess you mean while(symbol != null)? > - sometimes using "auto" helps. I need to explore this further (what's the actual purpose of "auto"). > - In D linked lists are doable, but much less used, think about using a > dynamic array, or even in this case an associative array: > > void main() { > auto aa = ["foo": 1, "bar": 2, "baz": 3]; > assert(aa["bar"] == 2); > } Yes, it was just an exercise. For curiosity, I intend to benchmark lists vs sequential arrays vs associative arrays, for various element counts. (Did that already in another language (freepascal), to know what kind of data structures were suited for symbol tables representing the content of record-like objects, which number of entries is typically small since hand-written by the programmer: sophisticated structures like associative arrays and tries started to perform better than plain sequences for counts >> 100.) > > 1. To please the compiler, I had to wrap dereferencing in parens, like in > > "(*symbol).name". Is this just normal (for disambiguation)? > > 2. Just noticed the compiler accepts "symbol.name", while symbol is a > > pointer: is there implicit dereferencing of pointers to structs? If yes, > > does this also apply to pointers to arrays (for information, this what > > Oberon does). > > Generally the field dereferencing doesn't require the "(*symbol).name", in D > you use "symbol.name". > Pointers to arrays are possible, but quite uncommon in D. Sure, there are builtin dynamic arrays :-) I'll check whether manually pointed arrays also silently dereferencing (on element access, on attribute access)? > > And a note: had forgotten to add an empty main(), just for compiling: the > > linker produced a rather big amount of error text without any hint to the > > actual issue. Maybe dmd could cope with that before calling gcc? > > I agree, I have bug report 4680 open on something similar: > http://d.puremagic.com/issues/show_bug.cgi?id=4680 Good. > > Finally: the reference is rather harsh for me, esp there are very few > > example (I have few practice of C, and none of C++); the bits of tutorials > > I found are too light or just started (toc p
Re: about pointer syntax
On 10/14/10, bearophile wrote: > Generally the field dereferencing doesn't require the "(*symbol).name", in D > you use "symbol.name". > Pointers to arrays are possible, but quite uncommon in D. I'm not sure, but I think function pointers (the C syntax ones, not variables declared with function/delegate) still need parenthesis for dereferencing? IIRC I was getting back some weird errors a few days ago when I was trying it out. I might be wrong though..
Re: about pointer syntax
spir: > (Hope you don't mind if I send other bits of code to be improved that way?) Feel free to show them, if I am busy other people may give you an answer. The worst that may happen is that no one answers you. > Right. I think at keeping explicit defaults like "int element = 0" for > documentation. Not putting a value, unless it's different from the standard initializator, is a very common idiom in D. It's easy to remember the inits: zero, empty string, NaN, null, invalid Unicode chars. > If I ever write a lib for public use, I'll follow such styling guidelines ;-) The D style: http://www.digitalmars.com/d/2.0/dstyle.html > Wouldn't have ever thought that the "stepping" statement of a for loop can be > something else as incrementation. This is a kind of incrementation: symbol = symbol.next; In C-derived languages this line of code: symbol = symbol + 5; May be written: symbol += 5; In the same way you may think of this (this is not D syntax): symbol .= next; As a compact version of: symbol = symbol.next; > Right, guess you mean while(symbol != null)? Right. But some people don't like that. > I need to explore this further (what's the actual purpose of "auto"). It just asks the compiler to use the default type, it performs a bit of local type inferencing. > For curiosity, I intend to benchmark lists vs sequential arrays vs > associative arrays, for various element counts. Good, it's a way to understand the language better. In the lists vs dynamic array I suggest you to also take a look at the produced (dis)assembly. > to know what kind of data structures were suited for symbol tables > representing the content of record-like objects, which number of entries is > typically small since hand-written by the programmer: sophisticated > structures like associative arrays and tries started to perform better than > plain sequences for counts >> 100.)< D dynamic arrays are not bad, but they are not very efficient, so a sequential scan in a small array of integer numbers is faster than an hash search. You may also try a "perfect hash", for your purpose. Around you may find C code (that's easy to translate to D) to create a perfect hash out of a sequence of strings. A binary search in an array of strings-int pairs is an easy option too. If your symbol are names are short you may also put your string+int pairs in a single flat data structure (even keeping a fixed length for each one of them), to increase CPU cache locality a bit, something like: struct Pair { char[10] name; int element; } Pair[20] data; In C/C++/D languages usually there are *many* complicated ways to speed up code :-) You generally want to use them only in the spots where the profiler tells you you need performance. The profiler is used with the DMD -profile switch. It's also good if you learn D to start using unittests and design by contract from the beginning. They help a lot avoid bugs. And the more hairy (pointers, etc) your code is, the more useful they are. Bye, bearophile
Re: about pointer syntax
> D dynamic arrays are not bad, but they are not very efficient, I meant associative array, sorry.
broken link: http://d-programming-language.org/phobos/phobos.html
Is it just me or there's a broken link to the library reference in the official site ? I'm currently using the doc shipped with DMD, but I found this broken link and I thought it's worth to signal. Best Gianluigi
Re: broken link: http://d-programming-language.org/phobos/phobos.html
On Thursday, October 14, 2010 16:12:40 Gianluigi Rubino wrote: > Is it just me or there's a broken link to the library reference in the > official site ? I'm currently using the doc shipped with DMD, but I > found this broken link and I thought it's worth to signal. > > Best > Gianluigi It's probably there because at some point that will be the correct link, but d- programming-language.org hasn't been completed yet, so the link doesn't work. - Jonathan M Davis
Re: Any usable parsers for D2 around?
On Fri, 15 Oct 2010 02:47:28 +0400, Andrej Mitrovic wrote: Hey, I've been looking for a D2 parser.. there seems to be a few D1 lexers, parsers, and even some minimal semantic analysis tools but I can't find much of anything for D2. Perhaps Goldie will be D2 compatible some day soon. :) There's a "CodeAnalyzer" lexer/parser with some minimal semantics, but it's D1 only and kind of dead for some years. The Poseidon author added some D2 support for it in his editor, so I have kept an eye on that. But interfacing with D1 code from D2 is kind of complicated, and I need to use it from D2. (I guess I could get away with writing a DLL with a simple interface for D2 or something..). I had a visit on the prowiki site and most of the parser projects there are either D1-only or dead. So is there anything usable for D2? Specifically I need these tools for use with an editor/IDE, which is something I'm working on for fun atm. But working on a parser is probably a ton of work, + the whole thing screams NIH to me. Luckily enough I don't have to reinvent a GUI and an editing control, there's DFL and Scintilla which are pretty awesome for my needs. Maybe I should take a look at how Descent/DDT and VisualD do their parsing.. :) You can try using ddmd (dsource.org/projects/ddmd).