Re: The Thermopylae excerpt of TDPL available online
Pelle Månsson wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Your Hallå Värd! should be Hallå Värld!, to be Swedish. D: Thanks! Ouch, two mistakes in one word. Also, should I put a comma in between the words? Also, I am wondering, why is the undefined behavior of opCatAssign kept? Couldn't every T[] know if it is the owner of the memory in question? Sorry if I bring outdated discussions up unnecessarily. We don't know how to do that cheaply. Andrei
Re: The Thermopylae excerpt of TDPL available online
Ellery Newcomer wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Maybe I haven't been paying attention lately, but shouldn't assert(x == 0) be assert(x[] == 0) ? Where does the former occur? Thanks, Andrei
Re: The Thermopylae excerpt of TDPL available online
Also, no mention about .dup not being a deep dup.
Re: The Thermopylae excerpt of TDPL available online
crp p20. 40 words? those where for myself, to check
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: Ellery Newcomer wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Maybe I haven't been paying attention lately, but shouldn't assert(x == 0) be assert(x[] == 0) ? Where does the former occur? Thanks, Andrei top of page 102
Re: The Thermopylae excerpt of TDPL available online
Robert Jacques wrote: On Thu, 29 Oct 2009 00:38:33 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Still reading, but here's a quick comment. I found it odd that the syntax for element-wise copying (4.1.7) comes sections after the section on copying (4.1.4). Perhaps a sentence mentioning where element-wise copying can be found would be appropriate. (Props though on including a memory layout figure. It may not seem like much, but I've seen Java students have no idea what an array is in memory.) Good point, thanks. Andrei
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Thanks for the excerpt! I've only had the time to give it a brief skim so far, but it's looking good. This is what I found: p16: int quadrupeds[100], int legs[4 * quadrupeds.length] - is the C-style array declaration syntax intended? p20: No mention of the new T[][](rows, cols) syntax? p26 (User-Defined Types as Keys): No need for opEquals? -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Re: LLVM 2.6 Release!
bearophile wrote: Andrei Alexandrescu: [snip] You can see an example of this from the missing videos/PDFs of the last conference, they were not allowed to show them, because Apple is sometimes even more corporative than Microsoft: http://llvm.org/devmtg/2009-10/ Bye, bearophile Bearophile Thanks for the link. By the way there is quite a interesting talk from David Greene from CRAY using LLVM titled LLVM on 180k Cores. cheers Nick B.
Re: ICE: template.c:806: failed assertion `i parameters-dim'
grauzone wrote: Don wrote: Jacob Carlborg wrote: On 10/28/09 16:32, Don wrote: Jacob Carlborg wrote: I have quite a big project and when I compile it I get this internal compiler error: template.c:806: failed assertion `i parameters-dim'. I don't know what could cause that error so I don't know where to look in my code to try to produce a small test case and report an issue. I'm using quite a lot of templates, template mixins and string mixins. Bugzilla 2229. Was fixed in DMD1.049. There have been about 60 ICE bugs fixed since 1.045. I want to find out what the regressions are that are stopping people from using the latest DMD -- it's time for the ICE age to end. I haven't been using any later version because of various known regressions, I think they've been solved know. I tried to compile Tango trunk with DMD trunk and it failed with: /Users/doob/development/d/tango-trunk/build/user/../../user/tango/io/compress/BzipStream.d(270): Error: var has no effect in expression (w) It's returning a value in a void function. I don't know if it's a regression that hasn't been solved or if it's something wrong with Tango. The compiler now catches a few bugs that used to slip past before. Just change the return w; into return;. I thought that was a feature? It's OK for a void function to return another void function, and it's OK if the expression has side-effects. The situations which have been disallowed are ones where the compiler used to completely ignore the expression, generating no code at all. It's now treated exactly the same as if you wrote: w; return; The bug was that although the compiler has always done that transformation, it wasn't running the semantic pass on it.
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei It's a very pleasant read, and it looks good. I guess I'll have to buy the book. :) I just have two comments: Code snippet in 4.2.1: Why do you suddenly use postfix array declaration here? Code snippet just before 4.4.3: (yowza !in aa) doesn't work, at least not with DMD 2.035. It has to be !(yowza in aa). Very annoying.
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: dsimcha wrote: == Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Given that new is all over the place, does this mean we're not getting rid of new before D2 goes gold? I guess we need to compromise. Andrei I got the impression from previous discussions that this would be a rather simple thing to implement. Also, the community mostly seemed to agree that ditching new would be a good thing. What are the obstacles? -Lars
Re: What Does Haskell Have to Do with C++?
Andrei Alexandrescu wrote: Don wrote: Jeremie Pelletier wrote: http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-with-c/ Bartosz's second part of 'Template Metaprogramming Made Easy (Huh?)', its quite a read :) Yes, it is excellent. Two comments: (1) Bartosz's D examples make me seriously question 'static foreach' which is scheduled for implementation (bugzilla 3377). If implemented, it will be a source of frustration, since it will not be very usable inside templates. The ability to exit from a 'static foreach' is something which is possible with a 'return'-style syntax, but is not possible with the 'eponymous template hack'. I think breaking early out of a static foreach is not necessary (but indeed convenient) for writing good loops. (2) It seems pretty clear that we need to allow the eponymous trick to continue to work when more than one template member is present. I think everyone who's ever attempted template metaprogramming in D has proposed it! Yes, that was on the list for a long time. Bartosz even has participated to many related discussions. I'm surprised the article made it seem an unescapable matter of principles, when it clearly is a trivially fixable bug in the language definition. Yes, looking at the compiler source, it doesn't look too difficult. The fact that something like this works: template foo(int X) { static if (bar!(X)) { const int foo = 57; } else { const char [] foo = abc; } } makes it pretty clear that the difficult part has already been done. I don't know what happens with template mixins, though. I hate template mixins (and I'm not convinced they're useful for anything, either). We discussed using this instead of the template's name, but that has a few ambiguity problems. Currently, we want to allow a template to define private symbols in addition to the eponymous trick (a term that Bartosz shouldn't have implied paternity of, sigh). Those private members would be accessible from inside the template's definition, but not from the outside. That would effectively remove the issue. Andrei
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Your Hallå Värd! should be Hallå Värld!, to be Swedish. D: Also, I am wondering, why is the undefined behavior of opCatAssign kept? Couldn't every T[] know if it is the owner of the memory in question? Sorry if I bring outdated discussions up unnecessarily.
Re: What Does Haskell Have to Do with C++?
Don Wrote: I don't know what happens with template mixins, though. I hate template mixins (and I'm not convinced they're useful for anything, either). Sometimes in C macros are used like template mixins in D.
Re: Shared Hell
Walter Bright Wrote: A function that accesses shared data has to put in fences. There's no way to have the same code deal with shared and unshared code. Shared code perfectly deals with unshared data (it's not guaranteed that shared data is accessed by more than one thread). In other words unshared data is implicitly castable to shared.
Re: Shared Hell
Kagamin Wrote: Walter Bright Wrote: A function that accesses shared data has to put in fences. There's no way to have the same code deal with shared and unshared code. Shared code perfectly deals with unshared data (it's not guaranteed that shared data is accessed by more than one thread). In other words unshared data is implicitly castable to shared. Uh... this post was a little fast, ignore it, please.
Re: Shared Hell
Christopher Wright Wrote: A function that accesses shared data has to put in fences. There's no way to have the same code deal with shared and unshared code. Acquiring a lock on a non-shared instance is safe, just an unnecessary expense. I would have looked into optimizing this expense away rather than punting the problem to the programmer. Shared code can put data into *really* shared environment, which must not happen for unshared data.
Re: What Does Haskell Have to Do with C++?
On Thu, Oct 29, 2009 at 1:47 AM, Don nos...@nospam.com wrote: Andrei Alexandrescu wrote: Don wrote: Jeremie Pelletier wrote: http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-with-c/ Bartosz's second part of 'Template Metaprogramming Made Easy (Huh?)', its quite a read :) Yes, it is excellent. Two comments: (1) Bartosz's D examples make me seriously question 'static foreach' which is scheduled for implementation (bugzilla 3377). If implemented, it will be a source of frustration, since it will not be very usable inside templates. The ability to exit from a 'static foreach' is something which is possible with a 'return'-style syntax, but is not possible with the 'eponymous template hack'. I think breaking early out of a static foreach is not necessary (but indeed convenient) for writing good loops. (2) It seems pretty clear that we need to allow the eponymous trick to continue to work when more than one template member is present. I think everyone who's ever attempted template metaprogramming in D has proposed it! Yes, that was on the list for a long time. Bartosz even has participated to many related discussions. I'm surprised the article made it seem an unescapable matter of principles, when it clearly is a trivially fixable bug in the language definition. Yes, looking at the compiler source, it doesn't look too difficult. The fact that something like this works: template foo(int X) { static if (bar!(X)) { const int foo = 57; } else { const char [] foo = abc; } } makes it pretty clear that the difficult part has already been done. I don't know what happens with template mixins, though. I hate template mixins (and I'm not convinced they're useful for anything, either). I don't think there's a problem with template mixins. Templates for mixin purposes are not generally the eponymous variety. I don't think any of the eponymous magic comes into play when you mix-in a template. At least I don't see why it would. And I do think template mixins are useful. I've seen some pretty nifty things done where you pass in a template as an alias template parameter to a class, and then mix that in. That can be a pretty powerful way to create extensible classes (or structs even) without inheritance. --bb
Re: GC Precision
dsimcha: A moving GC, one that doesn't stop the world on collection, and one that's fully precise including stack would be nice, but they're several orders of magnitude less important and would also have more ripple effects. I agree that here doing something simple now is better than doing nothing or doing something very refined in an unknown future. And in future things may be improved. In D objects are always managed by reference, and I think that most programs don't alter or cast such references to something else (objects allocated on memory specified by the programmer, and scoped objects allocated on the stack may be excluded from this). So I think that it can be safe to move objects, to compact the heap. So you may have 5 memory zones: - C heap. (The type system of the D compiler may see the C-heap pointers and D-heap pointers as two different types, as I have proposed in the past. So you need casts if you want to mix them, and the compiler can use the D moving heap in a safer way). - Pinned D heap for everything can't be moved, like structs managed by pointers (eventually a D compiler can infer at compile time that some structs too may be moved around, because their pointer is used only in clean ways (you don't need to introduce struct references for this)). I think SafeD modules will not use this heap a lot (but they can use unsafe modules that may use pinned objects. Is D safety transitive? I think it is not, so from a SafeD module you can call and use an unsafe module); - Old object generation managed with compaction (I think there's no need for the permanent objects zone in D); - Two from and to zones for the young generation, that don't use a true compaction strategy, young objects bounce between them; - New generation Eden where new object allocations happen managed as a memory arena. All this has the disadvantage of requiring a more complex GC, and probably requiring 2-4 times more RAM at runtime. It hopefully has the advantage of allowing new programmers, that have learnt Java at university, to program in almost like in Java. (I have found a not-synthetic Java benchmark program that converted to D is something like 18 times slower on LDC. I'll put the code in my site in the following days). Bye, bearophile
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu: http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! So far I've just taken a look, I'll read it when I can. I can see several warnings in red. The look of the text is really nice! Elegant, and the images are good and necessary. Are you going to write a book with all pages coloured? If true this will increase the book price, I think. I have seen that you use a nice fount for the nonproportional text (like code), it looks similar to the Consolas. You may try this one too (but it's not a professional product, it may have some rough details): http://www.fantascienza.net/leonardo/ar/inconsolatag/inconsolata-g_font.zip Bye, bearophile
Re: associative arrays: iteration is finally here
Andrei Alexandrescu: I'll make aa.remove(key) always work and return a bool that tells you whether there was a mapping or not. I think that's a small design mistake. In a high level language you want things to not fail silently. You want them to fail in an explicit way because programmers often forget to read and use return values. So AAs may have two methods, remove and drop (Python sets use remove and discard for this). The remove can be the safer one and used by default in D programs (especially in SafeD modules, safety is in things like this too), that raises an exception when you try to remove a missing key. drop/discard is faster and silent, it removes the key if it's present, as you want. Bye, bearophile
Re: Shared Hell
Kagamin wrote: Christopher Wright Wrote: A function that accesses shared data has to put in fences. There's no way to have the same code deal with shared and unshared code. Acquiring a lock on a non-shared instance is safe, just an unnecessary expense. I would have looked into optimizing this expense away rather than punting the problem to the programmer. Shared code can put data into *really* shared environment, which must not happen for unshared data. Okay, but the compiler can try copying the method, removing the 'shared' storage class, and running semantic on the result. If that succeeds, you're guaranteed not to be doing anything that would be unsafe unless you're casting, and you can call the shared method on a local instance. This lets you avoid whole program analysis and blacklisting unsafe operations. In this case, the compiler can also point to the line of code that prevents the method from being marked not shared.
Re: What Does Haskell Have to Do with C++?
Don wrote: Andrei Alexandrescu wrote: Don wrote: Jeremie Pelletier wrote: http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-with-c/ Bartosz's second part of 'Template Metaprogramming Made Easy (Huh?)', its quite a read :) Yes, it is excellent. Two comments: (1) Bartosz's D examples make me seriously question 'static foreach' which is scheduled for implementation (bugzilla 3377). If implemented, it will be a source of frustration, since it will not be very usable inside templates. The ability to exit from a 'static foreach' is something which is possible with a 'return'-style syntax, but is not possible with the 'eponymous template hack'. I think breaking early out of a static foreach is not necessary (but indeed convenient) for writing good loops. (2) It seems pretty clear that we need to allow the eponymous trick to continue to work when more than one template member is present. I think everyone who's ever attempted template metaprogramming in D has proposed it! Yes, that was on the list for a long time. Bartosz even has participated to many related discussions. I'm surprised the article made it seem an unescapable matter of principles, when it clearly is a trivially fixable bug in the language definition. Yes, looking at the compiler source, it doesn't look too difficult. The fact that something like this works: template foo(int X) { static if (bar!(X)) { const int foo = 57; } else { const char [] foo = abc; } } makes it pretty clear that the difficult part has already been done. I don't know what happens with template mixins, though. I hate template mixins (and I'm not convinced they're useful for anything, either). My mock object library http://dsource.org/projects/dmocks/ uses: mixin(method!(name, returnType, arguments...)); The implementation is a long and ugly string mixin. There's a bug that prevents you from implementing interface methods with aliases. If this were removed, I could replace the long and ugly string mixin with a very short string mixin and a short template mixin. Due to problems with .stringof, my current system usually fails for methods with templated arguments or return types (eg void filter(HashSet!(int) integers). Now that I think of it, I could probably make things better by using a forwarding function.
Re: GC Precision
On 10/29/09 11:47, bearophile wrote: dsimcha: A moving GC, one that doesn't stop the world on collection, and one that's fully precise including stack would be nice, but they're several orders of magnitude less important and would also have more ripple effects. I agree that here doing something simple now is better than doing nothing or doing something very refined in an unknown future. And in future things may be improved. In D objects are always managed by reference, and I think that most programs don't alter or cast such references to something else (objects allocated on memory specified by the programmer, and scoped objects allocated on the stack may be excluded from this). So I think that it can be safe to move objects, to compact the heap. The current implementation of toHash in Object does that: return cast(hash_t)cast(void*)this; So you may have 5 memory zones: - C heap. (The type system of the D compiler may see the C-heap pointers and D-heap pointers as two different types, as I have proposed in the past. So you need casts if you want to mix them, and the compiler can use the D moving heap in a safer way). - Pinned D heap for everything can't be moved, like structs managed by pointers (eventually a D compiler can infer at compile time that some structs too may be moved around, because their pointer is used only in clean ways (you don't need to introduce struct references for this)). I think SafeD modules will not use this heap a lot (but they can use unsafe modules that may use pinned objects. Is D safety transitive? I think it is not, so from a SafeD module you can call and use an unsafe module); - Old object generation managed with compaction (I think there's no need for the permanent objects zone in D); - Two from and to zones for the young generation, that don't use a true compaction strategy, young objects bounce between them; - New generation Eden where new object allocations happen managed as a memory arena. All this has the disadvantage of requiring a more complex GC, and probably requiring 2-4 times more RAM at runtime. It hopefully has the advantage of allowing new programmers, that have learnt Java at university, to program in almost like in Java. (I have found a not-synthetic Java benchmark program that converted to D is something like 18 times slower on LDC. I'll put the code in my site in the following days). Bye, bearophile
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu Wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! I still think is expressions are a glaring problem. Somewhere in the text, you use assert(!is(typeof(... as support for what you're talking about. That particular construct feels more like a hack someone stumbled into than clean, easy to read code. It's the type of thing a programmer will get wring unless they use it frequently. Even you've screwed it up in past Phobos releases! IMHO all is(...) expressions should be revisited. Have you written the section(s) on them yet? Also, on page 8? a code comment says average of a and b even though the variables don't exist.
Re: GC Precision
Jacob Carlborg: The current implementation of toHash in Object does that: return cast(hash_t)cast(void*)this; I agree, such things will have to change when D wants a moving GC. Bye, bearophile
Re: The Thermopylae excerpt of TDPL available online
Jason House wrote: Andrei Alexandrescu Wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! I still think is expressions are a glaring problem. Somewhere in the text, you use assert(!is(typeof(... as support for what you're talking about. That particular construct feels more like a hack someone stumbled into than clean, easy to read code. It's the type of thing a programmer will get wring unless they use it frequently. Even you've screwed it up in past Phobos releases! IMHO all is(...) expressions should be revisited. Have you written the section(s) on them yet? I don't think he uses is(typeof(...)) in the text. The code snippets in question are marked Note: normally the code below would not be included..., and I suppose he's put them there as a reminder for himself and Walter on what needs to be fixed before the book comes out. I agree with you, though, is(typeof(...)) is quite often misused, or at least used in an ugly way. Why not use __traits(compiles, ...) instead? -Lars
Re: The Thermopylae excerpt of TDPL available online
On Thu, 29 Oct 2009 15:12:51 +0300, Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote: Jason House wrote: Andrei Alexandrescu Wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! I still think is expressions are a glaring problem. Somewhere in the text, you use assert(!is(typeof(... as support for what you're talking about. That particular construct feels more like a hack someone stumbled into than clean, easy to read code. It's the type of thing a programmer will get wring unless they use it frequently. Even you've screwed it up in past Phobos releases! IMHO all is(...) expressions should be revisited. Have you written the section(s) on them yet? I don't think he uses is(typeof(...)) in the text. The code snippets in question are marked Note: normally the code below would not be included..., and I suppose he's put them there as a reminder for himself and Walter on what needs to be fixed before the book comes out. I agree with you, though, is(typeof(...)) is quite often misused, or at least used in an ugly way. Why not use __traits(compiles, ...) instead? -Lars ... which is at least as ugly.
Re: The Thermopylae excerpt of TDPL available online
Denis Koroskin wrote: On Thu, 29 Oct 2009 15:12:51 +0300, Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote: Jason House wrote: Andrei Alexandrescu Wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! I still think is expressions are a glaring problem. Somewhere in the text, you use assert(!is(typeof(... as support for what you're talking about. That particular construct feels more like a hack someone stumbled into than clean, easy to read code. It's the type of thing a programmer will get wring unless they use it frequently. Even you've screwed it up in past Phobos releases! IMHO all is(...) expressions should be revisited. Have you written the section(s) on them yet? I don't think he uses is(typeof(...)) in the text. The code snippets in question are marked Note: normally the code below would not be included..., and I suppose he's put them there as a reminder for himself and Walter on what needs to be fixed before the book comes out. I agree with you, though, is(typeof(...)) is quite often misused, or at least used in an ugly way. Why not use __traits(compiles, ...) instead? -Lars ... which is at least as ugly. I disagree. Pretend you are just learning D, and you are presented with the following two lines of code: static assert (is(typeof(XXX)); static assert (__traits(compiles, XXX)); Which of these would you most likely assume to be a check on whether XXX is compilable code? What I cannot for the life of me understand is WHY the double underscores? What's wrong with just traits? -Lars
Re: The Thermopylae excerpt of TDPL available online
Denis Koroskin Wrote: On Thu, 29 Oct 2009 15:12:51 +0300, Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote: I don't think he uses is(typeof(...)) in the text. The code snippets in question are marked Note: normally the code below would not be included..., and I suppose he's put them there as a reminder for himself and Walter on what needs to be fixed before the book comes out. I agree with you, though, is(typeof(...)) is quite often misused, or at least used in an ugly way. Why not use __traits(compiles, ...) instead? -Lars ... which is at least as ugly. I disagree. Code that isn't readily understandable is uglier than readable code. Certainly, __traits is ugly, but it is easier to understand when readig code and easier to write.
Re: GC Sentinel
On Tue, 27 Oct 2009 19:41:24 -0400, dsimcha dsim...@yahoo.com wrote: I'm looking at the GC implementation and starting my hacking. I noticed that the ends of blocks are already being used in some creative ways in the sentinel version. This looks like a debugging feature, though I don't understand it completely. Can one of the original implementors (Walter, Sean) explain to me what the heck version(SENTINEL) in gcx.d does at a high level, whether it conflicts with storing bit masks for precise heap scanning at the ends of memory blocks, and whether we still even need it? IIRC, the sentinel byte is to prevent pointers from leaking into the next block. For example, if you did: byte[] x = new byte[16]; // GC allocates 16 byte block. x = x[$..$]; Now, if there is no sentinel byte, the pointer in x points to the *next* memory block. It is an interesting problem, there might be a better solution. -Steve
Re: associative arrays: iteration is finally here
bearophile wrote: Andrei Alexandrescu: I'll make aa.remove(key) always work and return a bool that tells you whether there was a mapping or not. I think that's a small design mistake. In a high level language you want things to not fail silently. You want them to fail in an explicit way because programmers often forget to read and use return values. So AAs may have two methods, remove and drop (Python sets use remove and discard for this). The remove can be the safer one and used by default in D programs (especially in SafeD modules, safety is in things like this too), that raises an exception when you try to remove a missing key. drop/discard is faster and silent, it removes the key if it's present, as you want. Bye, bearophile I agree with this. I usually want exceptions.
Re: associative arrays: iteration is finally here
On Wed, 28 Oct 2009 20:08:34 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Denis Koroskin wrote: On Wed, 28 Oct 2009 23:18:08 +0300, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I'd also like you to add a few things in an AA interface. First, opIn should not return a pointer to Value, but a pointer to a pair of Key and Value, if possible (i.e. if this change won't sacrifice performance). I'm coy about adding that because it forces the implementation to hold keys and values next to each other. I think that was a minor mistake of STL - there's too much exposure of layout details. It doesn't have to be the case: key and value are both properties (i.e. methods), and they doesn't have to be located next to each other. I see. So you want a pointer to an elaborate type featuring a key and a value. It could return a struct holding both pointers, instead of a pointer to a struct. I don't see this as unreasonable (in fact, it's what I do in dcollections, see the cursor types). An implementation which stores the two close together in actuality may only require one pointer. The only drawback of this is it can't be part of a formal interface, since the return type is defined by the derived type. -Steve
Re: The Thermopylae excerpt of TDPL available online
On Thu, 29 Oct 2009 15:32:51 +0300, Jason House jason.james.ho...@gmail.com wrote: Denis Koroskin Wrote: On Thu, 29 Oct 2009 15:12:51 +0300, Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote: I don't think he uses is(typeof(...)) in the text. The code snippets in question are marked Note: normally the code below would not be included..., and I suppose he's put them there as a reminder for himself and Walter on what needs to be fixed before the book comes out. I agree with you, though, is(typeof(...)) is quite often misused, or at least used in an ugly way. Why not use __traits(compiles, ...) instead? -Lars ... which is at least as ugly. I disagree. Code that isn't readily understandable is uglier than readable code. Certainly, __traits is ugly, but it is easier to understand when readig code and easier to write. I was talking about ugliness, not readability. There are only 2 places where is(typeof(...)) feature is used: assert(is(typeof(somePrimes) == int[])); // perfectly fine IMO static assert(!is(typeof(a[length - 1]))); // misused, yes BTW, typeof is a bit inconsistent with .stringof, .alignof, .sizeof etc (typeof(foo) but foo.sizeof). Any chance this inconsistency is going to be fixed? Either assert(typeof(x + y) == int); - assert(is((x + y).typeof == int)); Or assert((x + y).sizeof == 4); - assert(is(sizeof(x + y) == 4);
Re: associative arrays: iteration is finally here
On Wed, 28 Oct 2009 10:22:00 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Walter has magically converted his work on T[new] into work on making associative arrays true templates defined in druntime and not considered very special by the compiler. This is very exciting because it opens up or simplifies a number of possibilities. One is that of implementing true iteration. I actually managed to implement last night something that allows you to do: int[int] aa = [ 1:1 ]; auto iter = aa.each; writeln(iter.front.key); writeln(iter.front.value); Two other iterations are possible: by key and by value (in those cases iter.front just returns a key or a value). One question is, what names should these bear? I am thinking of makign opSlice() a universal method of getting the all iterator, a default that every container must implement. For AAs, there would be a iterate keys and iterate values properties or functions. How should they be called? This is one of the benefits of opApply. Rather than define some new names to make up for the deficiencies of range-foreach (especially so near the release of D2), why not focus on fixing the deficiencies? i.e. here is my desired interface: foreach(key, value; aa) // iterate both keys and values foreach(value; aa) // default to iterating values (to be consistent with arrays) foreach(key; aa.keys) // iterate keys lazily. If ranges cannot support this interface, I think the range paradigm needs some work. opApply works great for this since the delegate type defines the desired interface. The problem with ranges is the potential opRange method in it's natural form should overload on the return value, and have no parameters. Here's a possible idea: make foreach(X x, Y y, Z z,...; container) translate to foreach(X x, Y y, Z z,...; container.opRange!(X, Y, Z, ...)()). In the case of inferred types, maybe you can do something like: opRange!(T : keytype, U : valuetype)() and have the compiler infer types for x and y as keytype and valuetype. The only drawback I see is opRange can't be virtual. However, how does one define a virtual range return, when a range is invariably a struct? It might be a moot issue. Of course, you could always meet the virtual requirement by naming your range-generating method... So with my scheme, the AA becomes: struct AA(Key, Val) { ... // implementation auto opRange(T : Key, U : Val)() { ... } auto opRange(T : Val)() { ... } auto keys() { ... } } One other thing left to define is what foreach calls to get the key(s) in the case of multiple arguments to foreach. The value is generally accessed via front(). Might as well tackle the ref possibilities too :) -Steve
Re: The Thermopylae excerpt of TDPL available online
Lars T. Kyllingstad wrote: Denis Koroskin wrote: On Thu, 29 Oct 2009 15:12:51 +0300, Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote: Jason House wrote: Andrei Alexandrescu Wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! I still think is expressions are a glaring problem. Somewhere in the text, you use assert(!is(typeof(... as support for what you're talking about. That particular construct feels more like a hack someone stumbled into than clean, easy to read code. It's the type of thing a programmer will get wring unless they use it frequently. Even you've screwed it up in past Phobos releases! IMHO all is(...) expressions should be revisited. Have you written the section(s) on them yet? I don't think he uses is(typeof(...)) in the text. The code snippets in question are marked Note: normally the code below would not be included..., and I suppose he's put them there as a reminder for himself and Walter on what needs to be fixed before the book comes out. I agree with you, though, is(typeof(...)) is quite often misused, or at least used in an ugly way. Why not use __traits(compiles, ...) instead? -Lars ... which is at least as ugly. I disagree. Pretend you are just learning D, and you are presented with the following two lines of code: static assert (is(typeof(XXX)); static assert (__traits(compiles, XXX)); Which of these would you most likely assume to be a check on whether XXX is compilable code? What I cannot for the life of me understand is WHY the double underscores? What's wrong with just traits? -Lars Also is(typeof(XXX)) *doesn't* currently check that XXX is compilable, just that it has a type. OTOH __traits(compiles, XXX) is ugly. traits(compiles, XXX) would be better; but I think we need to do better than that. It's the bread-and-butter of metaprogramming in D. Using the ugly syntax, it has well and truly proved its value. I've counted 20 uses in what I've seen of Andrei's book -- it appears about as often as (say) 'delegate'! It does a beautiful thing, it deserves a beautiful syntax. Something at least as good as __compiles(XXX), I reckon.
Re: Shared Hell
On Thu, 29 Oct 2009 07:25:20 -0400, Christopher Wright dhase...@gmail.com wrote: Kagamin wrote: Christopher Wright Wrote: A function that accesses shared data has to put in fences. There's no way to have the same code deal with shared and unshared code. Acquiring a lock on a non-shared instance is safe, just an unnecessary expense. I would have looked into optimizing this expense away rather than punting the problem to the programmer. Shared code can put data into *really* shared environment, which must not happen for unshared data. Okay, but the compiler can try copying the method, removing the 'shared' storage class, and running semantic on the result. If that succeeds, you're guaranteed not to be doing anything that would be unsafe unless you're casting, and you can call the shared method on a local instance. This lets you avoid whole program analysis and blacklisting unsafe operations. In this case, the compiler can also point to the line of code that prevents the method from being marked not shared. Let's say your shared method your attempting to analyze calls an obscure shared method: int foo(shared C c); How do you determine if it can be called without the 'shared' qualifier? This is one of the problems with not importing from compiled interface files. -Steve
More PC Precision Stuff
I've gotten underway hacking the GC to add precise heap scanning, but I thought of one really annoying corner case that really would make things an order of magnitude more complicated if it were handled properly: Structs and classes that have large static arrays embedded. For example: class Foo { Foo next; void*[4 * 1024 * 1024] hugeArray; } The problem here is that scanning this precisely would require me to either generate a megabyte bitmask that explicitly says scan every element of hugeArray or to change my bitmask data structure from a flat array to something nested and an order of magnitude more complex to generate at compile time. Since this is such a rare case in practice, I'm tempted to just say that any object with size above some arbitrary limit, say 1 kb, just gets scanned conservatively and be done with it. For arrays, this would be a limit on the size of the element, i.e. for a T[], it would be a limit on T.sizeof, *not* T.sizeof * length. I'd like to get the community's input on this: Is this enough of a corner case that I have permission to cop out of solving it properly for the sake of simplicity?
Re: The Thermopylae excerpt of TDPL available online
Jason House wrote: Andrei Alexandrescu Wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! I still think is expressions are a glaring problem. Somewhere in the text, you use assert(!is(typeof(... as support for what you're talking about. That particular construct feels more like a hack someone stumbled into than clean, easy to read code. It's the type of thing a programmer will get wring unless they use it frequently. Even you've screwed it up in past Phobos releases! IMHO all is(...) expressions should be revisited. Have you written the section(s) on them yet? Also, on page 8? a code comment says average of a and b even though the variables don't exist. Thanks, fixed. I also would like to see is expressions improved, but so far we couldn't find a good solution. There is a proposal currently in Bugzilla which may improve things. Andrei
Re: The Thermopylae excerpt of TDPL available online
bearophile wrote: Andrei Alexandrescu: http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! So far I've just taken a look, I'll read it when I can. I can see several warnings in red. The look of the text is really nice! Elegant, and the images are good and necessary. Are you going to write a book with all pages coloured? If true this will increase the book price, I think. Thanks. Unlike most authors, I provide camera-free to the publisher and carried all of the page design myself. I'm very glad I did. The book will be in black and white. Notice how every use of color is also accompanied by a color-independent cue (e.g. bold/slanted). But the book will also sell in electronic format, which will be color. I have seen that you use a nice fount for the nonproportional text (like code), it looks similar to the Consolas. You may try this one too (but it's not a professional product, it may have some rough details): http://www.fantascienza.net/leonardo/ar/inconsolatag/inconsolata-g_font.zip I did consider Inconsolata seriously, but I had to reject it (I forgot why; all I can remember was that it was a good reason). Andrei
Re: The Thermopylae excerpt of TDPL available online
Pelle Månsson wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Your Hallå Värd! should be Hallå Värld!, to be Swedish. D: Thanks! Ouch, two mistakes in one word. Also, should I put a comma in between the words? Also, I am wondering, why is the undefined behavior of opCatAssign kept? Couldn't every T[] know if it is the owner of the memory in question? Sorry if I bring outdated discussions up unnecessarily. We don't know how to do that cheaply. Andrei
Re: What Does Haskell Have to Do with C++?
Don wrote: Andrei Alexandrescu wrote: Don wrote: Jeremie Pelletier wrote: http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-with-c/ Bartosz's second part of 'Template Metaprogramming Made Easy (Huh?)', its quite a read :) Yes, it is excellent. Two comments: (1) Bartosz's D examples make me seriously question 'static foreach' which is scheduled for implementation (bugzilla 3377). If implemented, it will be a source of frustration, since it will not be very usable inside templates. The ability to exit from a 'static foreach' is something which is possible with a 'return'-style syntax, but is not possible with the 'eponymous template hack'. I think breaking early out of a static foreach is not necessary (but indeed convenient) for writing good loops. (2) It seems pretty clear that we need to allow the eponymous trick to continue to work when more than one template member is present. I think everyone who's ever attempted template metaprogramming in D has proposed it! Yes, that was on the list for a long time. Bartosz even has participated to many related discussions. I'm surprised the article made it seem an unescapable matter of principles, when it clearly is a trivially fixable bug in the language definition. Yes, looking at the compiler source, it doesn't look too difficult. The fact that something like this works: template foo(int X) { static if (bar!(X)) { const int foo = 57; } else { const char [] foo = abc; } } makes it pretty clear that the difficult part has already been done. That sounds great. If you could operate the changes, that would be awesome. Walter and I had already agreed about the feature. Andrei
Re: The Thermopylae excerpt of TDPL available online
Lars T. Kyllingstad wrote: Andrei Alexandrescu wrote: dsimcha wrote: == Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Given that new is all over the place, does this mean we're not getting rid of new before D2 goes gold? I guess we need to compromise. Andrei I got the impression from previous discussions that this would be a rather simple thing to implement. Also, the community mostly seemed to agree that ditching new would be a good thing. What are the obstacles? Walter prefers that allocations have a cue. You'd need to convince him. Andrei
Re: More PC Precision Stuff
dsimcha: Since this is such a rare case in practice, I don't think this is a so uncommon case, I use something similar for my memory pools. But if handling this makes your code too much complex, then it may be acceptable to ignore it anyway. Two persons have shown the need for D benchmarks that stress the GC, so I am translating the Olden benchmarks to D. You can find two of them already in D on my site (in several variants) and I'll add more (but some of those variants use memory pools that you will not scan if you adopt that simplification). Such benchmarks (and other ones I have already) can be used to test your changes to the GC. Bye, bearophile
Re: The Thermopylae excerpt of TDPL available online
Lars T. Kyllingstad wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei It's a very pleasant read, and it looks good. I guess I'll have to buy the book. :) Thanks! Very glad to hear you like it. I just have two comments: Code snippet in 4.2.1: Why do you suddenly use postfix array declaration here? Oops... I'd planned to simply pretend it doesn't exist. Thanks, I fixed that now. Code snippet just before 4.4.3: (yowza !in aa) doesn't work, at least not with DMD 2.035. It has to be !(yowza in aa). Very annoying. Walter is planning to effect that change. By publishing time, there won't be any red and any pink in the book! (One nice thing about the book is that it gives us a good idea on what to work on. Walter has been on an incredible streak lately, and Don adds amazing value.) Andrei
Re: associative arrays: iteration is finally here
Pelle Månsson: I agree with this. I usually want exceptions. A problem with this is that currently exceptions are very slow in D compiled with DMD (something like up to 11 times slower than Java exceptions, about 2-4 times slower than Python exceptions. I have a benchmark for this on my site). Bye, bearophile
Re: More PC Precision Stuff
== Quote from bearophile (bearophileh...@lycos.com)'s article dsimcha: Since this is such a rare case in practice, I don't think this is a so uncommon case, I use something similar for my memory pools. Why not dynamic arrays? Wouldn't it make more sense to do: class MemoryPool { // other stuff uint[] memory; this() { memory = new uint[someHugeNumber]; } } This would have negligible additional overhead and would allow you to change the size of the memory pool at runtime. I personally find that I almost never use static arrays, either on the stack or inside heap-allocated objects because the fact that their size is fixed at compile time is just too restrictive. About my only use for them is to store compile-time constants in the static data segment.
Re: associative arrays: iteration is finally here
Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Y no es el centro del Universo! El sol gira alrededor de la tierra! Miles de girasoles no pueden estar equivocados! -- Inodoro Pereyra
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu: I did consider Inconsolata seriously, but I had to reject it (I forgot why; all I can remember was that it was a good reason). A problem with Inconsolata that I have forgotten to tell you is that there isn't a true bold version yet, so the bold characters don't have the same width. So if your code highlighting converts some words to bold, the alignments break. This is quite so bad that I have disabled bold highlighting in my Python editor where I use that font. In the future I'll create a bold version of Inconsolata-g to solve this problem, it requires some tedious work, because it seems there are no automatic tools to do this. Bye, bearophile
Re: associative arrays: iteration is finally here
Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? I think this all is overdoing it. First, I disagree that remove should ever throw an exception. It's not a code that the user is supposed to check (with dire consequences if she doesn't), it's just additional information just in case you need it. I think bool remove(key) is better than all other designs suggested so far. Andrei
Re: The Thermopylae excerpt of TDPL available online
bearophile wrote: Andrei Alexandrescu: I did consider Inconsolata seriously, but I had to reject it (I forgot why; all I can remember was that it was a good reason). A problem with Inconsolata that I have forgotten to tell you is that there isn't a true bold version yet, so the bold characters don't have the same width. I think that was it indeed. Andrei
Re: The Thermopylae excerpt of TDPL available online
Ellery Newcomer wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Maybe I haven't been paying attention lately, but shouldn't assert(x == 0) be assert(x[] == 0) ? Where does the former occur? Thanks, Andrei
Re: associative arrays: iteration is finally here
On Thu, Oct 29, 2009 at 8:39 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? I think this all is overdoing it. First, I disagree that remove should ever throw an exception. It's not a code that the user is supposed to check (with dire consequences if she doesn't), it's just additional information just in case you need it. I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. So the advice would be to always check to make sure the key you remove got removed to be on the safe side. If that's the case I'd rather just have the darn thing throw an exception so I don't have to bother to write things like if (!aa.remove(theKey)) assert(false); everywhere just to be on the safe side. --bb
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Makes me want to read the rest! Will we get the electronic version with the paper version? p2. typo: eenlists p9. Is it ok to expect the order of an array expression to be like in foreach ? Maybe mention a[] = b. p11. typo: no(t) palindrome p12. Should in a safe module ~= always create a new array? p14. further expansions reads as if expansions have been made especially because the comment is maybe that obvious that I was looking for something else to be there. p16. Is there anything other than the random values, unsafe about void assignment? When you write something to be unsafe, I expect it to not be allowed safe modules. p18. What is unsafe about implicit conversion of static to dynamic array? Meaning getting a dynamic array pointing to a stack allocated array. Any operation changing its size could copy the array to the heap. What am I missing p20. An alternative to figure 4.5 could display row/column properties. p20. change 1,000,000 to 1_000_000 :D to me the comma is a decimal separator anyways. p20. 40 words? p21. Why use enum iso immutable? Probably in the previous chapters explained :) p21. Second paragraph reads as a solution to the above p22. typo: array!literal p25. Expected to read about ref in foreach That's all :)
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! It looks very nice. A small error in 4.1.7 first code block: auto a = new double[4]; // must be already allocated auto a1 = [ 0.5, -0.5, 1.5, 2 ]; auto a2 = [ 3.5, 5.5, 4.5, -1 ]; a[] = (a1[] + a2[]) / 2; // take the average of b and c ^^^ take the average of a1 and a2? (I think it would be easier to follow using b and c though ;) -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Cuando intenté arrimarle mi brazo Se puso a hablar de Miller, de Anais Nin y Picasso Y si osaba intentar robarle un beso Se ponía a leer de Neruda unos versos Me hizo mucho mal la cumbiera intelectual
Re: associative arrays: iteration is finally here
Andrei Alexandrescu Wrote: Two other iterations are possible: by key and by value (in those cases iter.front just returns a key or a value). Well, AA already has properties keys and values and you can already iterate over them. I think, it's ok to restrict to opApply(int delegate(ref KeyType, ref ValueType)).
Re: The Thermopylae excerpt of TDPL available online
Leandro Lucarella, el 29 de octubre a las 13:21 me escribiste: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! It looks very nice. A small error in 4.1.7 first code block: auto a = new double[4]; // must be already allocated auto a1 = [ 0.5, -0.5, 1.5, 2 ]; auto a2 = [ 3.5, 5.5, 4.5, -1 ]; a[] = (a1[] + a2[]) / 2; // take the average of b and c ^^^ take the average of a1 and a2? (I think it would be easier to follow using b and c though ;) BTW, it looks like array literals will be dynamic arrays, from the code in your book. Can you or Walter explain why this is better to make array literals statically stored immutable memory like strings (which adds an inconsistency to the language)? Is this just to avoid [1,2,3].dup; when you want to get a dynamic array from an array literal or is there other reasons? -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- En la calle me crucé con un señor muy correcto, que habitualmente anda en Falcon; iba corriendo con dos valijas en la mano y dijo: Voy para Miami, tiene algún mensaje o ... y le dije: No, no, no... -- Extra Tato (1983, Triunfo de Alfonsín)
Re: The Thermopylae excerpt of TDPL available online
Also, no mention about .dup not being a deep dup.
Re: The Thermopylae excerpt of TDPL available online
Saaa wrote Also, no mention about .dup not being a deep dup. Sorry, should've been attached to my response
Re: The Thermopylae excerpt of TDPL available online
On Thu, Oct 29, 2009 at 9:31 AM, Leandro Lucarella llu...@gmail.com wrote: Leandro Lucarella, el 29 de octubre a las 13:21 me escribiste: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! It looks very nice. A small error in 4.1.7 first code block: auto a = new double[4]; // must be already allocated auto a1 = [ 0.5, -0.5, 1.5, 2 ]; auto a2 = [ 3.5, 5.5, 4.5, -1 ]; a[] = (a1[] + a2[]) / 2; // take the average of b and c ^^^ take the average of a1 and a2? (I think it would be easier to follow using b and c though ;) BTW, it looks like array literals will be dynamic arrays, from the code in your book. Can you or Walter explain why this is better to make array literals statically stored immutable memory like strings (which adds an inconsistency to the language)? Is this just to avoid [1,2,3].dup; when you want to get a dynamic array from an array literal or is there other reasons? It's in the chapter. Basically static arrays just aren't the common use case. It is a bit of a bummer that there's no way to get a static array with the elements counted for you. Some folks suggested things like int[auto] = [1,2,3]; or int[$] = [1,2,3]; Something like that would be nice. --bb
Re: associative arrays: iteration is finally here
On Oct 29, 09 23:59, Bill Baxter wrote: On Thu, Oct 29, 2009 at 8:39 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? I think this all is overdoing it. First, I disagree that remove should ever throw an exception. It's not a code that the user is supposed to check (with dire consequences if she doesn't), it's just additional information just in case you need it. I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. Um what? aa[theKey] = 1 doesn't fail, why should aa.remove(theKey) be special? (Meanwhile, C++'s map::erase returns the number of elements removed, C#'s (CLR in general) Dictionary.Remove returns a bool, Javascript's delete x[y] returns a bool, Perl, Ruby, Objective-C, Java, etc. all won't throw exceptions (Python being the only exceptional case). Do all languages clutter up with checks?) So the advice would be to always check to make sure the key you remove got removed to be on the safe side. If that's the case I'd rather just have the darn thing throw an exception so I don't have to bother to write things like if (!aa.remove(theKey)) assert(false); everywhere just to be on the safe side. void discard(K,V)(ref V[K] aa, in K key) { if (!aa.remove(key)) assert(false); } ... aa.discard(theKey); --bb
Re: The Thermopylae excerpt of TDPL available online
crp p20. 40 words? those where for myself, to check
Re: associative arrays: iteration is finally here
KennyTM~: Um what? aa[theKey] = 1 doesn't fail, why should aa.remove(theKey) be special? That's a different situation. You probably meant to say: If aa[theKey]++; doesn't fail, why should aa.remove(theKey) be special? void discard(K,V)(ref V[K] aa, in K key) { if (!aa.remove(key)) assert(false); } This is stupid. Part of the point of built-in AAs is to avoid to import things. If I need to import (or worse define) that discard template in all programs where I use an AA, then I will create my own AAs and I'll just import and use them in the first place. Bye, bearophile
Re: associative arrays: iteration is finally here
On Thu, Oct 29, 2009 at 9:57 AM, KennyTM~ kenn...@gmail.com wrote: On Oct 29, 09 23:59, Bill Baxter wrote: On Thu, Oct 29, 2009 at 8:39 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? I think this all is overdoing it. First, I disagree that remove should ever throw an exception. It's not a code that the user is supposed to check (with dire consequences if she doesn't), it's just additional information just in case you need it. I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. Um what? aa[theKey] = 1 doesn't fail, why should aa.remove(theKey) be special? Huh? aa[theKey] also doesn't delete entries, so why should it have any bearing on what remove does? The closest analogy would be the case where aa[theKey]=1 can't do what you ask it to, which would be an out-of-memory error, which does generate an error of some kind, I think. (Meanwhile, C++'s map::erase returns the number of elements removed, Erase is also used for multimaps, so it's not exactly apples to apples. Your other examples are ok AFAIK. void discard(K,V)(ref V[K] aa, in K key) { if (!aa.remove(key)) assert(false); } ... aa.discard(theKey); Yep, that would be perfect if it were part of the standard AA interface. That would actually be my preferred solution, to have two methods for removing elements from AAs. One that throws and one that doesn't. --bb
Re: The Thermopylae excerpt of TDPL available online
Saaa wrote: Will we get the electronic version with the paper version? I'm not exactly sure how things will roll out. Probably yes. p2. typo: eenlists p9. Is it ok to expect the order of an array expression to be like in foreach ? Maybe mention a[] = b. p11. typo: no(t) palindrome p12. Should in a safe module ~= always create a new array? p14. further expansions reads as if expansions have been made especially because the comment is maybe that obvious that I was looking for something else to be there. p16. Is there anything other than the random values, unsafe about void assignment? When you write something to be unsafe, I expect it to not be allowed safe modules. p18. What is unsafe about implicit conversion of static to dynamic array? Meaning getting a dynamic array pointing to a stack allocated array. Any operation changing its size could copy the array to the heap. What am I missing p20. An alternative to figure 4.5 could display row/column properties. p20. change 1,000,000 to 1_000_000 :D to me the comma is a decimal separator anyways. p20. 40 words? p21. Why use enum iso immutable? Probably in the previous chapters explained :) p21. Second paragraph reads as a solution to the above p22. typo: array!literal p25. Expected to read about ref in foreach That's all :) Thanks much! Andrei
Re: The Thermopylae excerpt of TDPL available online
Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! It looks very nice. A small error in 4.1.7 first code block: auto a = new double[4]; // must be already allocated auto a1 = [ 0.5, -0.5, 1.5, 2 ]; auto a2 = [ 3.5, 5.5, 4.5, -1 ]; a[] = (a1[] + a2[]) / 2; // take the average of b and c ^^^ take the average of a1 and a2? (I think it would be easier to follow using b and c though ;) Thanks! I fixed that to have a and b as sources and c as destination. Andrei
Re: The Thermopylae excerpt of TDPL available online
Saaa wrote: Also, no mention about .dup not being a deep dup. I've put this on my todo list, but it's difficult. At this point people only know about statements and expressions, so it would be a bit difficult to introduce the subtleties of shallow vs. deep copying. I guess I'll have to do it. Andrei
Re: The Thermopylae excerpt of TDPL available online
Leandro Lucarella wrote: Leandro Lucarella, el 29 de octubre a las 13:21 me escribiste: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! It looks very nice. A small error in 4.1.7 first code block: auto a = new double[4]; // must be already allocated auto a1 = [ 0.5, -0.5, 1.5, 2 ]; auto a2 = [ 3.5, 5.5, 4.5, -1 ]; a[] = (a1[] + a2[]) / 2; // take the average of b and c ^^^ take the average of a1 and a2? (I think it would be easier to follow using b and c though ;) BTW, it looks like array literals will be dynamic arrays, from the code in your book. Can you or Walter explain why this is better to make array literals statically stored immutable memory like strings (which adds an inconsistency to the language)? Is this just to avoid [1,2,3].dup; when you want to get a dynamic array from an array literal or is there other reasons? I don't have a better explanation than the excerpt: Beware, however: if you replace @int[3]@ above with @auto@, @a@'s type will be deduced as @int[]@, not @int...@. Although it seems logical that the type of \cc{[1, 2, 3]} should be @int[3]@ which in a way is more ``precise'' than @int[]@, it turns out that dynamically-sized arrays are used much more often than fixed-size arrays, so insisting on fixed-size array literals would have been a usability impediment and a source of unpleasant surprises. Effectively, the use of literals would have prevented the gainful use of @a...@. As it is, array literals are @T[]@ by default, and @T[n]@ if you \emph{ask} for that specific type and if @n@ matches the number of values in the literal (as the code above shows). Andrei
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: Ellery Newcomer wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Maybe I haven't been paying attention lately, but shouldn't assert(x == 0) be assert(x[] == 0) ? Where does the former occur? Thanks, Andrei top of page 102
Re: associative arrays: iteration is finally here
Bill Baxter wrote: On Thu, Oct 29, 2009 at 8:39 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? I think this all is overdoing it. First, I disagree that remove should ever throw an exception. It's not a code that the user is supposed to check (with dire consequences if she doesn't), it's just additional information just in case you need it. I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. I don't find this reasonable. If you know removal must have succeeded, just type enforce(aa.remove(theKey)). I don't think that's the overwhelmingly common case though, and if it's, say, about 50/50, then it's much more sensible to have a non-throwing primitive than a throwing one. And it looks like defining two primitives just to save a call to enforce is not a good design. After all, if you argue people forget and misspell things and all, I could argue they call the wrong function out of two with very similar charters. Honest, I just read a couple of posts proposing two primitives and for the life of me I already can't remember which was throwing and which wasn't. So the advice would be to always check to make sure the key you remove got removed to be on the safe side. I'm not seeing how that comes about. The advice is to check if you care, which is common sense. I'm wondering how such an obvious design came into question. Andrei
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: Pelle Månsson wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Your Hallå Värd! should be Hallå Värld!, to be Swedish. D: Thanks! Ouch, two mistakes in one word. Also, should I put a comma in between the words? Actually, I see now that you had it as Hallå, värd!, and it should be Hallå, värld!, no need to capitalize the second word. Unless what you want to say is Hello, host!, in which case your värd is correct. Also, I am wondering, why is the undefined behavior of opCatAssign kept? Couldn't every T[] know if it is the owner of the memory in question? Sorry if I bring outdated discussions up unnecessarily. We don't know how to do that cheaply. Andrei How about doing it expensively? Maybe storing a boolean in each T[]? I think undefined behavior is bad.
Re: The Thermopylae excerpt of TDPL available online
Ellery Newcomer wrote: Andrei Alexandrescu wrote: Ellery Newcomer wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Maybe I haven't been paying attention lately, but shouldn't assert(x == 0) be assert(x[] == 0) ? Where does the former occur? Thanks, Andrei top of page 102 Thanks. Notice that x is an integer because it was fetched as array[5]. Andrei
Re: The Thermopylae excerpt of TDPL available online
On Thu, 29 Oct 2009 00:38:33 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Still reading, but here's a quick comment. I found it odd that the syntax for element-wise copying (4.1.7) comes sections after the section on copying (4.1.4). Perhaps a sentence mentioning where element-wise copying can be found would be appropriate. (Props though on including a memory layout figure. It may not seem like much, but I've seen Java students have no idea what an array is in memory.)
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu, el 29 de octubre a las 12:23 me escribiste: Leandro Lucarella wrote: Leandro Lucarella, el 29 de octubre a las 13:21 me escribiste: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: BTW, it looks like array literals will be dynamic arrays, from the code in your book. Can you or Walter explain why this is better to make array literals statically stored immutable memory like strings (which adds an inconsistency to the language)? Is this just to avoid [1,2,3].dup; when you want to get a dynamic array from an array literal or is there other reasons? I don't have a better explanation than the excerpt: Beware, however: if you replace @int[3]@ above with @auto@, @a@'s type will be deduced as @int[]@, not @int...@. Although it seems logical that the type of \cc{[1, 2, 3]} should be @int[3]@ which in a way is more ``precise'' than @int[]@, it turns out that dynamically-sized arrays are used much more often than fixed-size arrays, so insisting on fixed-size array literals would have been a usability impediment and a source of unpleasant surprises. Effectively, the use of literals would have prevented the gainful use of @a...@. As it is, array literals are @T[]@ by default, and @T[n]@ if you \emph{ask} for that specific type and if @n@ matches the number of values in the literal (as the code above shows). I saw that, but I think introducing an inconsistency (and depart on how literals usually work) is worse than having to explicitly state the type or adding a .dup to the literal. But I guess it's just me. Another question about the book: you explain dynamic arrays are being represented by a start and end pointer, much like the STL, but that's not the real implementation. I know you say in the book that the implementation doesn't necessarily work like that, but I wonder if you decided to explain things like that because it's planned to change the dynamic arrays implementation or just because you found it more didactic. Thanks. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Algún día los libros desterrarán a la radio y el hombre descubrirá el oculto poder del Amargo Serrano. -- Ricardo Vaporeso. El Bolsón, 1909.
Re: associative arrays: iteration is finally here
Andrei Alexandrescu, el 29 de octubre a las 12:33 me escribiste: Bill Baxter wrote: I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. I don't find this reasonable. If you know removal must have succeeded, just type enforce(aa.remove(theKey)). I don't think I don't agree, this is like saying you should bound-check every array access. I think it's nice to have safety by default. If you are expecting to have an error, you will be extra careful to spell the key correctly. This should cover the cases where you are distracted and not expecting any errors. I think the check could be done in non-release mode only though, just like bound checking. that's the overwhelmingly common case though, and if it's, say, about 50/50, then it's much more sensible to have a non-throwing primitive than a throwing one. And it looks like defining two primitives just to save a call to enforce is not a good design. This is one case where I think practicality beats purity, because the whole point of throwing an exception is for the cases you don't expect it to fail. Again, think of array bounds, you can force the programmer to add lots of enforce() in the code and remove bound checking from the compiler. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- EXPOSICION INTERNACIONAL DE INODOROS -- Crónica TV
Re: The Thermopylae excerpt of TDPL available online
Robert Jacques wrote: On Thu, 29 Oct 2009 00:38:33 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Still reading, but here's a quick comment. I found it odd that the syntax for element-wise copying (4.1.7) comes sections after the section on copying (4.1.4). Perhaps a sentence mentioning where element-wise copying can be found would be appropriate. (Props though on including a memory layout figure. It may not seem like much, but I've seen Java students have no idea what an array is in memory.) Good point, thanks. Andrei
Re: associative arrays: iteration is finally here
On Thu, Oct 29, 2009 at 10:33 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Bill Baxter wrote: On Thu, Oct 29, 2009 at 8:39 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Leandro Lucarella wrote: Andrei Alexandrescu, el 28 de octubre a las 20:29 me escribiste: Your test looks something up and then removes it. Andrei Well, my extended test case looks something up, manipulates the found value, and then possibly removes it. Ok, I understand your points, thanks for explaining. What about and overload of remove() like this: bool remove(in T key, out U value); If the element was present, it's returned in value, so you can manipulate it. I thought about just returning a pointer: U* remove(in T key); But I guess that pointer would point to the element stored in the the AA private data, but that element was just removed, so bad things would happen, that's why the only option is to copy the data, right? I think this all is overdoing it. First, I disagree that remove should ever throw an exception. It's not a code that the user is supposed to check (with dire consequences if she doesn't), it's just additional information just in case you need it. I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. I don't find this reasonable. If you know removal must have succeeded, just type enforce(aa.remove(theKey)). I don't think that's the overwhelmingly common case though, and if it's, say, about 50/50, then it's much more sensible to have a non-throwing primitive than a throwing one. And it looks like defining two primitives just to save a call to enforce is not a good design. After all, if you argue people forget and misspell things and all, I could argue they call the wrong function out of two with very similar charters. Honest, I just read a couple of posts proposing two primitives and for the life of me I already can't remember which was throwing and which wasn't. So the advice would be to always check to make sure the key you remove got removed to be on the safe side. I'm not seeing how that comes about. The advice is to check if you care, which is common sense. I'm wondering how such an obvious design came into question. Ok. You convinced me that your way doesn't suck. And you can ask the Python designers how the so-called obvious design came into question. Apparently it's not as obvious as you think. And I would suggest from experience with Python that having two functions is also not as bad as you think. But I'm convinced that having two functions is not significantly better than having one function that doesn't throw. --bb
Re: associative arrays: iteration is finally here
Leandro Lucarella wrote: Andrei Alexandrescu, el 29 de octubre a las 12:33 me escribiste: Bill Baxter wrote: I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. I don't find this reasonable. If you know removal must have succeeded, just type enforce(aa.remove(theKey)). I don't think I don't agree, this is like saying you should bound-check every array access. I think it's nice to have safety by default. remove from an associative array is not unsafe. If you are expecting to have an error, you will be extra careful to spell the key correctly. This should cover the cases where you are distracted and not expecting any errors. I think the check could be done in non-release mode only though, just like bound checking. Bounds checking is eliminated in release mode solely for efficiency reasons. There is no other good reason to eliminate checks. But in the case of remove, the amount of work done is consistent enough to make a check negligible. that's the overwhelmingly common case though, and if it's, say, about 50/50, then it's much more sensible to have a non-throwing primitive than a throwing one. And it looks like defining two primitives just to save a call to enforce is not a good design. This is one case where I think practicality beats purity, because the whole point of throwing an exception is for the cases you don't expect it to fail. Again, think of array bounds, you can force the programmer to add lots of enforce() in the code and remove bound checking from the compiler. I can't think of array bounds. The situations are completely unrelated. Andrei
Re: associative arrays: iteration is finally here
On Thu, Oct 29, 2009 at 11:16 AM, Leandro Lucarella llu...@gmail.com wrote: Andrei Alexandrescu, el 29 de octubre a las 12:33 me escribiste: Bill Baxter wrote: I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. I don't find this reasonable. If you know removal must have succeeded, just type enforce(aa.remove(theKey)). I don't think I don't agree, this is like saying you should bound-check every array access. I think it's nice to have safety by default. If you are expecting to have an error, you will be extra careful to spell the key correctly. This should cover the cases where you are distracted and not expecting any errors. I think the check could be done in non-release mode only though, just like bound checking. that's the overwhelmingly common case though, and if it's, say, about 50/50, then it's much more sensible to have a non-throwing primitive than a throwing one. And it looks like defining two primitives just to save a call to enforce is not a good design. This is one case where I think practicality beats purity, because the whole point of throwing an exception is for the cases you don't expect it to fail. Again, think of array bounds, you can force the programmer to add lots of enforce() in the code and remove bound checking from the compiler. The problem with this argument (which I was also about to make) is that accessing an array out of bounds is almost never normal behavior. But for deleting things, it often is. Think also about delete itself. In C++ and D delete on a null pointer is fine, and is defined to be a no-op. This was done explicitly to avoid always having to do if(p) delete p; all the time. And really it works out just fine in practice. If we're going to keep arguing that remove() should throw, then really delete should too. --bb
Re: The Thermopylae excerpt of TDPL available online
Leandro Lucarella wrote: Andrei Alexandrescu, el 29 de octubre a las 12:23 me escribiste: Leandro Lucarella wrote: Leandro Lucarella, el 29 de octubre a las 13:21 me escribiste: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: BTW, it looks like array literals will be dynamic arrays, from the code in your book. Can you or Walter explain why this is better to make array literals statically stored immutable memory like strings (which adds an inconsistency to the language)? Is this just to avoid [1,2,3].dup; when you want to get a dynamic array from an array literal or is there other reasons? I don't have a better explanation than the excerpt: Beware, however: if you replace @int[3]@ above with @auto@, @a@'s type will be deduced as @int[]@, not @int...@. Although it seems logical that the type of \cc{[1, 2, 3]} should be @int[3]@ which in a way is more ``precise'' than @int[]@, it turns out that dynamically-sized arrays are used much more often than fixed-size arrays, so insisting on fixed-size array literals would have been a usability impediment and a source of unpleasant surprises. Effectively, the use of literals would have prevented the gainful use of @a...@. As it is, array literals are @T[]@ by default, and @T[n]@ if you \emph{ask} for that specific type and if @n@ matches the number of values in the literal (as the code above shows). I saw that, but I think introducing an inconsistency (and depart on how literals usually work) is worse than having to explicitly state the type or adding a .dup to the literal. But I guess it's just me. It's me as well. The decision didn't go without a fight (I had your viewpoint and Walter didn't). He convinced me with two arguments. One is that 90% of the time you actually want T[], not T[n]. The second is that string literals already have dynamic (not static) type, although the most informative type would be fixed-size. Another question about the book: you explain dynamic arrays are being represented by a start and end pointer, much like the STL, but that's not the real implementation. I know you say in the book that the implementation doesn't necessarily work like that, but I wonder if you decided to explain things like that because it's planned to change the dynamic arrays implementation or just because you found it more didactic. We will change the implementation at some point, but right now I hope I made it clear enough it's about the notion of a bounded chunk of typed memory, than the representation of it. Andrei
Re: Shared Hell
Kagamin wrote: Walter Bright Wrote: A function that accesses shared data has to put in fences. There's no way to have the same code deal with shared and unshared code. Shared code perfectly deals with unshared data (it's not guaranteed that shared data is accessed by more than one thread). In other words unshared data is implicitly castable to shared. Unfortunately, there is a subtle problem with that that makes such implicit casts unsafe. Shared data can be handed off to other threads. So if thread local data is implicitly cast to shared, then it can be handed off to other threads. Meaning it is no longer guaranteed to be thread local.
another stack frame optimization issue
So I have this optimization in which I jump from function to function to avoid the overhead of setting up and tearing down identical stack frames. Now I want to be able to jump from a member function of one object to a member function of another object. I accomplished this with g++ by replacing the this pointer that is passed in as a hidden parameter. After some difficulty with dmd I realized that the this pointer is actually stored in EAX. But simply updating EAX to hold the new this pointer doesn't seem to be working. I've verified that EAX contains the address of the destination object, but it is still behaving as if the this pointer had not changed... class Test() { static byte* jumpTo; void* nextObject; int count; void Run() { if (count++ 5) return; asm { mov ECX, EAX; mov EAX, nextObject[ECX]; jmp dword ptr jumpTo; } } } int main(char[][] args) { //14 is offset for parameterless member function with no stack variables Test.jumpTo = cast(byte*)(Test.Run) + 14; auto t1 = new Test(); auto t2 = new Test(); t1.nextObject = cast(void*)t2; t2.nextObject = cast(void*)t1; t1.Run(); Stdout(t1.count, t2.count); return 0; } ...This gives me the result 7, 0. I don't have the actual disassembled code in front of me but IIRC member variables are referenced via offset from the location stored in EAX. I'm not sure what else to try.
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Thanks for the excerpt! I've only had the time to give it a brief skim so far, but it's looking good. This is what I found: p16: int quadrupeds[100], int legs[4 * quadrupeds.length] - is the C-style array declaration syntax intended? p20: No mention of the new T[][](rows, cols) syntax? p26 (User-Defined Types as Keys): No need for opEquals? -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu Wrote: Any feedback is welcome. Thanks! Thanks Andrei, that was an excellent read. Some comments: Page 102, line 23. I'm not a native English speaker, but it seems like you're missing a such in the sentence there is a thing as a Page 116, line 13: shouldn't array be defined as = void, for efficiency? Section 4.3: As someone who is new to D, I would like to see an example involving a multidimensional array in which all dimensions are fixed. Something like int a[3][2] = [ ??? ];
Re: associative arrays: iteration is finally here
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Denis Koroskin wrote: On Wed, 28 Oct 2009 17:22:00 +0300, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Walter has magically converted his work on T[new] into work on making associative arrays true templates defined in druntime and not considered very special by the compiler. Wow, this is outstanding! (I hope it didn't have any negative impact on compile-time AA capabilities). This is very exciting because it opens up or simplifies a number of possibilities. One is that of implementing true iteration. I actually managed to implement last night something that allows you to do: int[int] aa = [ 1:1 ]; auto iter = aa.each; writeln(iter.front.key); writeln(iter.front.value); Two other iterations are possible: by key and by value (in those cases iter.front just returns a key or a value). One question is, what names should these bear? I am thinking of makign opSlice() a universal method of getting the all iterator, a default that every container must implement. For AAs, there would be a iterate keys and iterate values properties or functions. How should they be called? Thanks, Andrei If AA is providing a way to iterate over both keys and values (and it's a default iteration scheme), why should AA provide 2 other iteration schemes? Can't they be implemented externally (using adaptor ranges) with the same efficiency? foreach (e; keys(aa)) { writefln(key: %s, e); } foreach (e; values(aa)) { writefln(value: %s, e); } Of course. In fact, given the iterator with .key and .value, you can always apply map!a.key or map!a.value to select the desired member. I'd also like you to add a few things in an AA interface. First, opIn should not return a pointer to Value, but a pointer to a pair of Key and Value, if possible (i.e. if this change won't sacrifice performance). I'm coy about adding that because it forces the implementation to hold keys and values next to each other. I think that was a minor mistake of STL - there's too much exposure of layout details. Second, AA.remove method should accept result of opIn operation to avoid an additional lookup for removal: if (auto value = key in aa) { aa.remove(key); // an unnecessary lookup } I'll make aa.remove(key) always work and return a bool that tells you whether there was a mapping or not. Something like this would be perfect: struct Element(K,V) { const K key; V value; } struct AA(K,V) { //... ref Element opIn(K key) { /* throws an exception if element is not found */ } void remove(ref Element elem) { /* removes an element from an AA */ } void remove(K key) { remove(key in this); } AARange!(K,V) opSlice() { /* iterates over both keys and values */ } } Last, I believe foreach loop should automatically call opSlice() on iteratee. foreach in D2 should already call opSlice() whenever it's defined. If it doesn't, that's a bug in the compiler. Andrei Wouldn't opIn be more useful if it returned a range starting with the element that was found?
Re: associative arrays: iteration is finally here
On Oct 30, 09 01:14, bearophile wrote: KennyTM~: Um what? aa[theKey] = 1 doesn't fail, why should aa.remove(theKey) be special? That's a different situation. You probably meant to say: If aa[theKey]++; doesn't fail, why should aa.remove(theKey) be special? void discard(K,V)(ref V[K] aa, in K key) { if (!aa.remove(key)) assert(false); } This is stupid. Part of the point of built-in AAs is to avoid to import things. If I need to import (or worse define) that discard template in all programs where I use an AA, then I will create my own AAs and I'll just import and use them in the first place. Bye, bearophile This does not contradicts with .remove() not throwing an exception when a key is not found. If you like you can put it in object.d. (Moreover, having .remove() to throw means you can't delete any dictionary items in nothrow functions. Sure you can silent it with try/catch but that's expensive.)
Re: The Thermopylae excerpt of TDPL available online
Tom S wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Thanks for the excerpt! I've only had the time to give it a brief skim so far, but it's looking good. This is what I found: p16: int quadrupeds[100], int legs[4 * quadrupeds.length] - is the C-style array declaration syntax intended? Thanks, fixed. p20: No mention of the new T[][](rows, cols) syntax? Oops, completely forgot about that one. p26 (User-Defined Types as Keys): No need for opEquals? There currently is, but there shouldn't and it won't. Andrei
Re: The Thermopylae excerpt of TDPL available online
On Thu, 29 Oct 2009 13:30:35 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: It's me as well. The decision didn't go without a fight (I had your viewpoint and Walter didn't). He convinced me with two arguments. One is that 90% of the time you actually want T[], not T[n]. The argument may be flawed because, out of those 90% of arrays, only small part may be initialized from array literals. Many (most?) are created with new or appended. I suspect dynamic arrays created from literals are as rare as static arrays in real world code. Probably, I'll investigate how exactly rare.
Re: associative arrays: iteration is finally here
rmcguire wrote: Wouldn't opIn be more useful if it returned a range starting with the element that was found? Thought about that, but it's hard to justify. Items aren't sorted in any particular order, so you'd get pretty much a random bunch of stuff. Andrei
Re: More PC Precision Stuff
On 2009-10-29 09:42:58 -0400, dsimcha dsim...@yahoo.com said: I've gotten underway hacking the GC to add precise heap scanning, but I thought of one really annoying corner case that really would make things an order of magnitude more complicated if it were handled properly: Structs and classes that have large static arrays embedded. For example: class Foo { Foo next; void*[4 * 1024 * 1024] hugeArray; } The problem here is that scanning this precisely would require me to either generate a megabyte bitmask that explicitly says scan every element of hugeArray or to change my bitmask data structure from a flat array to something nested and an order of magnitude more complex to generate at compile time. You don't need something with nesting, but something a little more complex yes. For instance you could replace the bitmask with an array of integers, each telling you in turn how many words to skip and how many words have pointers. For instance: struct Foo { int a; void* b1; void* b2; void* b3; int[4] c; void*[3000] d; } ushort[4] fooMemoryMap = [1, 3, 4, 3000]; 1word without pointer 3words with pointers 4words without pointer 3000 words with pointers Now one of the remaining problems is how to handle weak pointers. The other problem is that this doesn't scale well if your static array contains a struct with pointers and non-pointers. For this you'd need to have a way to repeat a pattern (something like a rewind command in the above stream). Both can be solved by giving a special meaning to the most significant bit: enum { // For even values (non pointers) SKIP_FLAG = 0 ushort.sizeof*8-1; REPEAT_FLAG = 1 ushort.sizeof*8-1; // for odd values (pointers) STRONG_PTR_FLAG = 0 ushort.sizeof*8-1; WEAK_PTR_FLAG = 1 ushort.sizeof*8-1; } Giving you this memory map for Foo: ushort[4] fooMemoryMap = [ 1| SKIP_FLAG, // one word of non-pointers 3| STRONG_PTR_FLAG, // three words of pointers 4| SKIP_FLAG, // four words of non-pointers 3000 | STRONG_PTR_FLAG, // 3000 words of pointers ]; Now you can encode even a big static array of Foos in the middle of a struct with a reasonably-sized memory map (14 bytes): struct Bar { Foo[500] a; int[500] b; } ushort[7] barMemoryMap = [ 1| SKIP_FLAG, // one word of non-pointers 3| STRONG_PTR_FLAG, // three words of pointers 4| SKIP_FLAG, // four words of non-pointers 3000 | STRONG_PTR_FLAG, // 3000 words of pointers 4| REPEAT_FLAG, // rewind 4 instructions 500 // and repeat 500 times 500 | SKIP_FLAG, // 500 words of non-pointers ]; Here, Foo's memory map just gets inserted at the right place in Bar's memory map. No nesting or pointers or anything, just a repeat instruction. An it takes only 14 bytes. -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: The Thermopylae excerpt of TDPL available online
On Thu, 29 Oct 2009 21:59:13 +0300, Max Samukha spam...@d-coding.com wrote: On Thu, 29 Oct 2009 13:30:35 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: It's me as well. The decision didn't go without a fight (I had your viewpoint and Walter didn't). He convinced me with two arguments. One is that 90% of the time you actually want T[], not T[n]. The argument may be flawed because, out of those 90% of arrays, only small part may be initialized from array literals. Many (most?) are created with new or appended. I suspect dynamic arrays created from literals are as rare as static arrays in real world code. Probably, I'll investigate how exactly rare. I agree. It also involves a hidden allocation and there is no way around it: int[] t = [0, 1, 2] ~ [3, 4, 5]; // how many allocations here take place? 1? No, 3!
Re: associative arrays: iteration is finally here
KennyTM~, el 30 de octubre a las 02:55 me escribiste: On Oct 30, 09 01:14, bearophile wrote: KennyTM~: Um what? aa[theKey] = 1 doesn't fail, why should aa.remove(theKey) be special? That's a different situation. You probably meant to say: If aa[theKey]++; doesn't fail, why should aa.remove(theKey) be special? void discard(K,V)(ref V[K] aa, in K key) { if (!aa.remove(key)) assert(false); } This is stupid. Part of the point of built-in AAs is to avoid to import things. If I need to import (or worse define) that discard template in all programs where I use an AA, then I will create my own AAs and I'll just import and use them in the first place. Bye, bearophile This does not contradicts with .remove() not throwing an exception when a key is not found. If you like you can put it in object.d. (Moreover, having .remove() to throw means you can't delete any dictionary items in nothrow functions. Sure you can silent it with try/catch but that's expensive.) Not if it's an Error instead of an exception. I think that should be the case, .remove() check should be like bound check, something done at non-release mode, not something to use in the regular flow of a program to avoid using opIn(). -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Esta desenchufada la internet de ese televisor? -- Osvaldo Lucarella
Re: associative arrays: iteration is finally here
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: rmcguire wrote: Wouldn't opIn be more useful if it returned a range starting with the element that was found? Thought about that, but it's hard to justify. Items aren't sorted in any particular order, so you'd get pretty much a random bunch of stuff. Andrei Oh, I thought that ranges were going to be applied to network/file IO. I which case there is plenty of places one might want to jump forward in a range... ah but then we're talking AAs. Well I suppose the Socket class could have opIn return a range. hehe Thanks for replying
Re: More PC Precision Stuff
dsimcha wrote: I've gotten underway hacking the GC to add precise heap scanning, but I thought of one really annoying corner case that really would make things an order of magnitude more complicated if it were handled properly: Structs and classes that have large static arrays embedded. For example: class Foo { Foo next; void*[4 * 1024 * 1024] hugeArray; } The problem here is that scanning this precisely would require me to either generate a megabyte bitmask that explicitly says scan every element of hugeArray or to change my bitmask data structure from a flat array to something nested and an order of magnitude more complex to generate at compile time. Since this is such a rare case in practice, I'm tempted to just say that any object with size above some arbitrary limit, say 1 kb, just gets scanned conservatively and be done with it. For arrays, this would be a limit on the size of the element, i.e. for a T[], it would be a limit on T.sizeof, *not* T.sizeof * length. I'd like to get the community's input on this: Is this enough of a corner case that I have permission to cop out of solving it properly for the sake of simplicity? Could you or anyone else solve this problem at a later stage? If that would not be made more difficult then I would say cop out, at least for now.
Re: More PC Precision Stuff
On Thu, 29 Oct 2009 22:32:54 +0300, Lutger lutger.blijdest...@gmail.com wrote: dsimcha wrote: I've gotten underway hacking the GC to add precise heap scanning, but I thought of one really annoying corner case that really would make things an order of magnitude more complicated if it were handled properly: Structs and classes that have large static arrays embedded. For example: class Foo { Foo next; void*[4 * 1024 * 1024] hugeArray; } The problem here is that scanning this precisely would require me to either generate a megabyte bitmask that explicitly says scan every element of hugeArray or to change my bitmask data structure from a flat array to something nested and an order of magnitude more complex to generate at compile time. Since this is such a rare case in practice, I'm tempted to just say that any object with size above some arbitrary limit, say 1 kb, just gets scanned conservatively and be done with it. For arrays, this would be a limit on the size of the element, i.e. for a T[], it would be a limit on T.sizeof, *not* T.sizeof * length. I'd like to get the community's input on this: Is this enough of a corner case that I have permission to cop out of solving it properly for the sake of simplicity? Could you or anyone else solve this problem at a later stage? If that would not be made more difficult then I would say cop out, at least for now. Don't worry, it won't have any impact on the existing code.
Re: associative arrays: iteration is finally here
Andrei Alexandrescu, el 29 de octubre a las 13:26 me escribiste: Leandro Lucarella wrote: Andrei Alexandrescu, el 29 de octubre a las 12:33 me escribiste: Bill Baxter wrote: I think bool remove(key) is better than all other designs suggested so far. I agree with the folks who say it's error-prone. I can just see myself now removing a key I know is in the dictionary and being baffled when my program fails somewhere later on because I typed aa.remove(theKey) when it should have been aa.remove(thekey). I knew it was there so I didn't want to clutter up my code with a check for it. I don't find this reasonable. If you know removal must have succeeded, just type enforce(aa.remove(theKey)). I don't think I don't agree, this is like saying you should bound-check every array access. I think it's nice to have safety by default. remove from an associative array is not unsafe. In the sense of memory corruption that's true. But your program will be at least leaking memory if you thought the key was present in the AA (the majority of the use cases for remove(), because come on, if you are removing something is because you think there are very good chances that the key is in the AA :). If your program then iterate the AA and there is a key that it doesn't supposed to be there, it will blow in very original, hard to track ways. What's the point of that? If you want to remove something you're not sure that it really is in the AA, you should use a safer method. Maybe try_remove(), or an extra parameter to remove() or maybe just ask first if key in aa (but this have an extra lookup, and I think that's the whole point that triggered this discussion). If you are expecting to have an error, you will be extra careful to spell the key correctly. This should cover the cases where you are distracted and not expecting any errors. I think the check could be done in non-release mode only though, just like bound checking. Bounds checking is eliminated in release mode solely for efficiency reasons. There is no other good reason to eliminate checks. But in Well, same for removing an inexistent key from an AA then :) the case of remove, the amount of work done is consistent enough to make a check negligible. Ok, but make it an Error, not an exception, so it can be used in nothrow functions. Removing an nonexistent key from an AA should be a programming error, except if you state in some way that you know that maybe the key is not there (which should be rare). that's the overwhelmingly common case though, and if it's, say, about 50/50, then it's much more sensible to have a non-throwing primitive than a throwing one. And it looks like defining two primitives just to save a call to enforce is not a good design. This is one case where I think practicality beats purity, because the whole point of throwing an exception is for the cases you don't expect it to fail. Again, think of array bounds, you can force the programmer to add lots of enforce() in the code and remove bound checking from the compiler. I can't think of array bounds. The situations are completely unrelated. I don't think they are *completely* unrelated. I agree is not exactly the same because array bound error automatically imply memory corruption and nonexistent key removal don't, but they are a bug in the vast majority of the cases. At least this is my experience. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Fitter, happier, more productive, comfortable, not drinking too much, regular exercise at the gym (3 days a week), getting on better with your associate employee contemporaries,
Re: More PC Precision Stuff
== Quote from Lutger (lutger.blijdest...@gmail.com)'s article dsimcha wrote: I've gotten underway hacking the GC to add precise heap scanning, but I thought of one really annoying corner case that really would make things an order of magnitude more complicated if it were handled properly: Structs and classes that have large static arrays embedded. For example: class Foo { Foo next; void*[4 * 1024 * 1024] hugeArray; } The problem here is that scanning this precisely would require me to either generate a megabyte bitmask that explicitly says scan every element of hugeArray or to change my bitmask data structure from a flat array to something nested and an order of magnitude more complex to generate at compile time. Since this is such a rare case in practice, I'm tempted to just say that any object with size above some arbitrary limit, say 1 kb, just gets scanned conservatively and be done with it. For arrays, this would be a limit on the size of the element, i.e. for a T[], it would be a limit on T.sizeof, *not* T.sizeof * length. I'd like to get the community's input on this: Is this enough of a corner case that I have permission to cop out of solving it properly for the sake of simplicity? Could you or anyone else solve this problem at a later stage? If that would not be made more difficult then I would say cop out, at least for now. I would be much more inclined to cop out on this, except that I would be making a design decision that might not be easy to change in the future w.r.t. how bitmasks are structured. If we eventually fixed this, it would likely be a breaking change to the GC interface, after D2 had gone gold. Then again, GC.malloc is a pretty low-level interface, and most access would be through whatever replaces new, which would likely be in the standard lib and could be modified in lockstep. Therefore, if/when we were to get a more principled scheme, it might be transparent to most user code, at least at the source level. One thing I definitely need to know from the insiders (Walter, Sean, etc.) is, how much do we care about having a stable, well thought out, formally specified interface to the GC routines, both at the source and binary level, at this stage in the game? If I did something hackish to get precise heap scanning mostly working, would the patch likely be rejected because it would create cruft that would have to be kept for backwards compatibility?
Re: associative arrays: iteration is finally here
KennyTM~: (Moreover, having .remove() to throw means you can't delete any dictionary items in nothrow functions. Sure you can silent it with try/catch but that's expensive.) In nothrow functions you can use a different method, like discard (or a similar name less intuitive than remove), that's like remove, but it doesn't throw and just returns false when the key was absent. The idea is to use the safer method by default and the less safe one as a performance optimization (or where you are sure you want that semantics) in the other places. Bye, bearophile
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu, el 29 de octubre a las 13:30 me escribiste: Leandro Lucarella wrote: Andrei Alexandrescu, el 29 de octubre a las 12:23 me escribiste: Leandro Lucarella wrote: Leandro Lucarella, el 29 de octubre a las 13:21 me escribiste: Andrei Alexandrescu, el 28 de octubre a las 23:38 me escribiste: BTW, it looks like array literals will be dynamic arrays, from the code in your book. Can you or Walter explain why this is better to make array literals statically stored immutable memory like strings (which adds an inconsistency to the language)? Is this just to avoid [1,2,3].dup; when you want to get a dynamic array from an array literal or is there other reasons? I don't have a better explanation than the excerpt: Beware, however: if you replace @int[3]@ above with @auto@, @a@'s type will be deduced as @int[]@, not @int...@. Although it seems logical that the type of \cc{[1, 2, 3]} should be @int[3]@ which in a way is more ``precise'' than @int[]@, it turns out that dynamically-sized arrays are used much more often than fixed-size arrays, so insisting on fixed-size array literals would have been a usability impediment and a source of unpleasant surprises. Effectively, the use of literals would have prevented the gainful use of @a...@. As it is, array literals are @T[]@ by default, and @T[n]@ if you \emph{ask} for that specific type and if @n@ matches the number of values in the literal (as the code above shows). I saw that, but I think introducing an inconsistency (and depart on how literals usually work) is worse than having to explicitly state the type or adding a .dup to the literal. But I guess it's just me. It's me as well. The decision didn't go without a fight (I had your viewpoint and Walter didn't). Oh, ok. Thanks for the fight ;) He convinced me with two arguments. One is that 90% of the time you actually want T[], not T[n]. I don't know how did he come up with that number. At least, talking about arrays that comes from a literal, I don't think that is the case. In a program I'm sure more than 90% of the array usage are dynamic arrays, but when talking about array literals I'm not very convinced, I think you usually just want an iterable from them. The second is that string literals already have dynamic (not static) type, although the most informative type would be fixed-size. Damn! Are you saying that this: auto s = hello; Really does something like this in C: char* s = gc_malloc(5, NO_SCAN); memcpy(s, hello, 5); ? I though it was just like C, a pointer to an statcally allocated memory block. What's the point to heap-allocate an immutable chunk of memory? Another question about the book: you explain dynamic arrays are being represented by a start and end pointer, much like the STL, but that's not the real implementation. I know you say in the book that the implementation doesn't necessarily work like that, but I wonder if you decided to explain things like that because it's planned to change the dynamic arrays implementation or just because you found it more didactic. We will change the implementation at some point, but right now I hope I made it clear enough it's about the notion of a bounded chunk of typed memory, than the representation of it. I think the point is taken, I was just curious about what's the plan. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Salvajes, de traje, me quieren enseñar Salvajes, de traje, me quieren educar
Re: The Thermopylae excerpt of TDPL available online
Andrei Alexandrescu wrote: Ellery Newcomer wrote: Andrei Alexandrescu wrote: Ellery Newcomer wrote: Andrei Alexandrescu wrote: It's a rough rough draft, but one for the full chapter on arrays, associative arrays, and strings. http://erdani.com/d/thermopylae.pdf Any feedback is welcome. Thanks! Andrei Maybe I haven't been paying attention lately, but shouldn't assert(x == 0) be assert(x[] == 0) ? Where does the former occur? Thanks, Andrei top of page 102 Thanks. Notice that x is an integer because it was fetched as array[5]. Andrei Oh wow. I'm dyslexic.