digitalmars.D - How does pragma(lib) work?
- dsimcha (7/7) Aug 27 2011 When I add the directive:
- Robert Clipsham (7/14) Aug 27 2011 pragma(lib) only works with one step compilation - it's useless if you
- Benjamin Thaut (9/9) Aug 27 2011 After having used the D 2.0 programming language for a year now and
- dsimcha (26/32) Aug 27 2011 Excellent article. I like the constructive criticism without the "D
- bearophile (4/5) Aug 28 2011 Otherwise, are you able and willing to add those to Bugzilla yourself?
- Benjamin Thaut (6/6) Aug 29 2011 I hoped for a little bit more feedback about the article itself.
- Jonathan M Davis (26/29) Aug 29 2011 Honestly, I find the fact that you're writing code which relies on the a...
- Walter Bright (5/12) Aug 29 2011 Andrei and I have talked about adding move constructors, but I agree wit...
- Andrei Alexandrescu (10/26) Aug 29 2011 The language semantics make move construction unnecessary. Values are
- Benjamin Thaut (16/43) Aug 29 2011 I don't see implementing a GC as that of a abnormal use case. Especially...
- Andrei Alexandrescu (13/60) Aug 29 2011 I don't believe D should be in the business of adding features that make...
- Benjamin Thaut (18/80) Aug 31 2011 My problem currenlty mostly is, that the current GC takes way more time
- Walter Bright (7/14) Aug 31 2011 The trouble with precise GC is that all the type info consumes a large a...
- Josh Simmons (9/11) Aug 31 2011 They're generally avoided in game code anyway because they're slow.
- Mehrdad (2/10) Sep 01 2011 Hm... how much per what unit? Is that an actual issue nowadays?
- Andrei Alexandrescu (6/14) Sep 01 2011 I think our community will be rid of a major hurdle once we get past the...
- dsimcha (9/14) Sep 01 2011 while(1) {
- Sean Kelly (9/25) Sep 01 2011 Yup. I want to revisit CDGC to see if it's up to snuff as the default GC...
- Robert Jacques (2/4) Sep 01 2011 Default on *nix you mean, as CDGC sadly doesn't support windows.
- Sean Kelly (8/12) Sep 02 2011 GC. It already supports precise scanning, so perhaps the rest can be =
- Robert Jacques (3/9) Sep 02 2011 Well, it would be a concurrent GC on Linux and (after patching) parallel...
- Robert Jacques (5/19) Sep 01 2011 Make that
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (5/20) Sep 01 2011 And honestly, the memory footprint for the type info is negligible with
- Sean Kelly (5/20) Sep 01 2011 There are soft realtime GCs like you describe, but I believe they're all...
- Mehrdad (26/33) Aug 27 2011 I feel like you hit the nail on the head. I feel the same way about cons...
- Daniel Murphy (5/10) Aug 27 2011 Since a few days ago, mutable strings returned from strongly pure functi...
- dsimcha (2/12) Aug 27 2011 Does the same apply to all arrays of primitives?
- Daniel Murphy (3/10) Aug 28 2011 To all types. Arrays, AAs, classes etc.
- bearophile (6/13) Aug 27 2011 The C++ compiler doesn't offer means to enforce pure functions.
- =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= (3/16) Aug 28 2011 const_cast is the root of all evil. I really don't want to see it in D.
- David Nadlinger (13/15) Aug 28 2011 It is already in D, and in an, in my personal opinion, much worse way:
- Walter Bright (7/18) Aug 28 2011 That's why D does allow this, in a user visible manner, rather than forc...
- David Nadlinger (12/26) Aug 28 2011 I know about the »it's not a bug, it's a feature« cast() syntax
- Andrei Alexandrescu (4/20) Aug 28 2011 It is quite easy to define C++-like cast operators as D functions. If
- dsimcha (18/22) Aug 28 2011 I think we should define at least the following and probably put them in...
- Mafi (2/25) Aug 28 2011 I think, to!someClass(x) works like you want dynamic cast to work.
- dsimcha (2/7) Aug 28 2011 (Slaps self in forehead.) You're right, I forgot about that. Never min...
- Andrei Alexandrescu (10/18) Aug 28 2011 I think such an addition would be worthwhile. We'd only need
- Mehrdad (4/24) Aug 31 2011 I don't know about others, but there's no way in hell that I will ever
- Andrei Alexandrescu (4/30) Sep 01 2011 Verboseness would be the last problem of a program needing many
- bearophile (6/8) Aug 28 2011 I'd like this one in Phobos:
- David Nadlinger (9/12) Aug 28 2011 I hope this finally goes through, there still seem to be some –
- Walter Bright (5/7) Aug 28 2011 The only stability issue was the massive power outage. Jan got it back u...
- David Nadlinger (5/12) Aug 28 2011 Yes – I didn't mean to discredit anyone, but I were definitely having
- Walter Bright (5/18) Aug 28 2011 It was down for 4 hours. Jan told me that he didn't care to try to get t...
- Kagamin (2/20) Aug 30 2011 In C I had to cast away const because constness is built into the struct...
- Andrei Alexandrescu (4/10) Aug 28 2011 Reddit discussion has turned to tuples:
- bearophile (6/8) Aug 28 2011 There are two more places where it's handy to expand tuples: function si...
- bearophile (4/5) Aug 29 2011 If you write D code in functional-style then lines of code often become ...
- Andrei Alexandrescu (4/9) Aug 27 2011 On reddit:
- kennytm (5/19) Aug 28 2011 On the pattern matching syntax for templates in the comments -- Sigh, th...
- Marco Leise (3/7) Aug 28 2011 Is 'more' an euphemism? ;) Good to know this syntax is possible, thx for...
- Andrej Mitrovic (12/16) Aug 29 2011 Wow I didn't know about this. So now I can do this:
- =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= (4/22) Aug 29 2011 Can it be used for overloading? I assume the way it works in that code
- Timon Gehr (4/30) Aug 29 2011 Yes:
- Andrej Mitrovic (6/6) Aug 29 2011 Oh man wouldn't it be cool if we could use this syntax like this:
- Martin Nowak (8/14) Aug 29 2011 Well, can you come up with a useful syntax for
- Timon Gehr (2/20) Aug 29 2011 void put(E: ElementType!R, R)(R r, E e) {}
- Andrei Alexandrescu (6/29) Aug 29 2011 The if-restriction on a template may build arbitrary expressions, so
- Timon Gehr (11/43) Aug 29 2011 I am not sure that we are talking about the same thing. This does not
- Andrej Mitrovic (2/2) Aug 29 2011 Yeah it's not important. But I'll definitely use the colon syntax more
- Walter Bright (3/4) Aug 29 2011 This guy wants to contact you:
- Benjamin Thaut (5/9) Aug 30 2011 Thanks for the heads up
- Sean Kelly (12/13) Aug 30 2011 having completed 3 projects with it, I wrote a small article about the =
- Sean Kelly (20/21) Aug 30 2011 having completed 3 projects with it, I wrote a small article about the =
- dsimcha (37/51) Aug 30 2011 Yea, shared really was a blunder at least in anything like its current f...
- Sean Kelly (74/130) Aug 30 2011 labeling
- dsimcha (2/3) Aug 30 2011 What's wrong with core.atomic?
- Sean Kelly (6/11) Aug 31 2011 I meant atomic types, though I could probably be convinced otherwise.
- dsimcha (4/5) Aug 30 2011 So the idea would just be that shared is a programmer-verified seal of
- Sean Kelly (7/12) Aug 31 2011 That would be the easiest thing, yeah. I had some more complex ideas in ...
- Michel Fortin (7/12) Aug 30 2011 I think D needs some kind of knowledge about memory regions into its
- Sean Kelly (6/22) Aug 31 2011 The effect on storage for statics is fantastic. I wasn't suggesting chan...
- Walter Bright (2/6) Sep 01 2011 I'm tending to agree that shared should no longer imply memory barriers.
- Kagamin (2/3) Aug 31 2011 What's the difference? Both access shared data and synchronize. If the d...
- Sean Kelly (12/17) Aug 31 2011 The unshared methods are only ever meant to be called by the queue owner...
- Kagamin (2/3) Aug 31 2011 If member data of a shared object is non-shared, it can be probably sepa...
- Sean Kelly (9/14) Aug 31 2011 owner. They access some member data without synchronization to make the ...
- Walter Bright (3/10) Aug 28 2011 On Windows, it embeds a reference to the library in the .obj file. The ....
When I add the directive: pragma(lib, "foo"); to a file called "bar.d" and then do: dmd -c bar.d does the object file bar.o or bar.obj contain a directive that reflects the pragma, or does pragma(lib) only work when compiling and linking in one step, e.g. dmd bar.d?
Aug 27 2011
On 27/08/2011 16:59, dsimcha wrote:When I add the directive: pragma(lib, "foo"); to a file called "bar.d" and then do: dmd -c bar.d does the object file bar.o or bar.obj contain a directive that reflects the pragma, or does pragma(lib) only work when compiling and linking in one step, e.g. dmd bar.d?pragma(lib) only works with one step compilation - it's useless if you want one-at-a-time compilation, hence why rebuild and other tools had pragma(link). -- Robert http://octarineparrot.com/
Aug 27 2011
After having used the D 2.0 programming language for a year now and having completed 3 projects with it, I wrote a small article about the problems I had with the D 2.0 programming language and what suggestions I have to improve it. http://3d.benjamin-thaut.de/?p=18 Comments and criticism welcome -- Kind Regards Benjamin Thaut
Aug 27 2011
On 8/27/2011 1:14 PM, Benjamin Thaut wrote:After having used the D 2.0 programming language for a year now and having completed 3 projects with it, I wrote a small article about the problems I had with the D 2.0 programming language and what suggestions I have to improve it. http://3d.benjamin-thaut.de/?p=18 Comments and criticism welcomeExcellent article. I like the constructive criticism without the "D will never be better than C++, Walter Bright is an idiot, I will never use a GC language, D is slow on one benchmark therefore it is poorly designed and will be slow forever" attitude. Some of the things you mention are definitely bugs. (I'd call emplace requiring exact c'tor arguments, TID not supporting shared, the thread-local storage/GC issue, and maybe no function overloading with template parameters bugs. The TLS issue is already known.) These have a lot higher a probability of getting fixed if you file them as bug reports (see http://d.puremagic.com/issues/ ). Better yet, if yo know how to fix it, you can submit a pull request to the DProgrammingLanguage Github page. Other things you mention are design decisions that are the result of carefully considered tradeoffs. These include structs not having an identity, lack of implicit c'tors, and shared. These are tradeoffs that may not be the best for your situation, but are not unforced errors. As far as assert, maybe there should be a compiler switch that makes all asserts behave the way assert(0) does in release mode: Simply issue the HLT instruction and use a debugger to figure out what went wrong. However, I think the current behavior of assert is the right default behavior because it gives clear hints as to what went wrong (and a stack trace on newer releases) even if you're not running in a debugger. Associative array invariance may be fixable now using reference counting. This issue has been in the back of my mind for a long time. Thanks for bringing it back to the front, and maybe it's worth fixing.
Aug 27 2011
dsimcha:Some of the things you mention are definitely bugs. (I'd call emplace requiring exact c'tor arguments, TID not supporting shared, the thread-local storage/GC issue, and maybe no function overloading with template parameters bugs. The TLS issue is already known.) These have a lot higher a probability of getting fixed if you file them as bug reports<Otherwise, are you able and willing to add those to Bugzilla yourself? Bye, bearophile
Aug 28 2011
I hoped for a little bit more feedback about the article itself. Especially about the move constructor I suggested. Does anyone see a need for this, or is it just me? -- Kind Regards Benjamin Thaut
Aug 29 2011
On Monday, August 29, 2011 13:35 Benjamin Thaut wrote:I hoped for a little bit more feedback about the article itself. Especially about the move constructor I suggested. Does anyone see a need for this, or is it just me?Honestly, I find the fact that you're writing code which relies on the address of a variable on the stack a bit scary. Normally, that is a _bad_ idea. Now, you're obviously doing something quite abnormal, so it may be a good idea in your case, but you're definitely not doing something which your average programmer is going to need to do. And the fact that structs can be moved by having their bits copied around is a definite boon for efficiency. Adding move constructors would definitely complicate things. If there were enough use cases for them, then they may be worth adding, but at this point, the compiler definitely relies on the fact that it can move a struct without affecting it, so any code which relies on a struct _not_ moving is likely to be broken. The ramifications of adding move constructors are likely far from trivial. Personally, I'd argue that it doesn't make any more sense to expect that a struct's location have _anything_ to do with its value, and that if you want to rely on its location, then you need to put it in a location that you can rely on. If anything, I'd argue that your structs should just have a variable identifying them if you want to have them be uniquely identifiable, but I don't really understand what you're doing. Certainly, for the common case, adding move constructors is a needless complication, and I'd _very_ leery of the ramifications of the compiler not being able to rely on a move having the bits stay absolutely identical (and a move constructor would make it possible for the struct's state to change completely instead of really being a move). It's not necessarily completely unreasonable, but you appear to have found what I would expect to be a _very_ abnormal use-case. - Jonathan M Davis
Aug 29 2011
On 8/29/2011 2:22 PM, Jonathan M Davis wrote:Certainly, for the common case, adding move constructors is a needless complication, and I'd _very_ leery of the ramifications of the compiler not being able to rely on a move having the bits stay absolutely identical (and a move constructor would make it possible for the struct's state to change completely instead of really being a move). It's not necessarily completely unreasonable, but you appear to have found what I would expect to be a _very_ abnormal use-case.Andrei and I have talked about adding move constructors, but I agree with you that it really seems to be a tar pit we'd really like to avoid. C++ has a lot of subtle problems caused by supporting this, not the least of which is efficiency problems.
Aug 29 2011
On 8/29/11 4:36 PM, Walter Bright wrote:On 8/29/2011 2:22 PM, Jonathan M Davis wrote:The language semantics make move construction unnecessary. Values are moveable as bits through memory. I think the article is a bit confused on this particular matter. Only objects with value semantics are freely moveable, so they have no direct interaction with the garbage collector. What they might want to do is to hold a pointer/reference _inside_ of them and deregister that pointer with the garbage collector with the destructor. Due to the indirection, it doesn't matter where the object is in memory. AndreiCertainly, for the common case, adding move constructors is a needless complication, and I'd _very_ leery of the ramifications of the compiler not being able to rely on a move having the bits stay absolutely identical (and a move constructor would make it possible for the struct's state to change completely instead of really being a move). It's not necessarily completely unreasonable, but you appear to have found what I would expect to be a _very_ abnormal use-case.Andrei and I have talked about adding move constructors, but I agree with you that it really seems to be a tar pit we'd really like to avoid. C++ has a lot of subtle problems caused by supporting this, not the least of which is efficiency problems.
Aug 29 2011
Am 30.08.2011 02:56, schrieb Andrei Alexandrescu:On 8/29/11 4:36 PM, Walter Bright wrote:I don't see implementing a GC as that of a abnormal use case. Especially given the fact that D is a garbage collected language and could benefit a lot from features that make implementing a GC easier. In thise special case the discussed struct would be a wrapper for every reference on the stack, so the references can be tracked by the GC and changed if neccessary. Adding a level of indirection to every reference would greatly impact performance because it would most likely add yet another cache miss when accessing a reference. I'm very well aware of D's concept of structs. But sometimes this concept is very bad for performance, that is what I wanted to point out. Adding a move constructor which most of the structs won't even use, should be less of a performance impact, then adding another level of indirection. -- Kind Regards Benjamin ThautOn 8/29/2011 2:22 PM, Jonathan M Davis wrote:The language semantics make move construction unnecessary. Values are moveable as bits through memory. I think the article is a bit confused on this particular matter. Only objects with value semantics are freely moveable, so they have no direct interaction with the garbage collector. What they might want to do is to hold a pointer/reference _inside_ of them and deregister that pointer with the garbage collector with the destructor. Due to the indirection, it doesn't matter where the object is in memory. AndreiCertainly, for the common case, adding move constructors is a needless complication, and I'd _very_ leery of the ramifications of the compiler not being able to rely on a move having the bits stay absolutely identical (and a move constructor would make it possible for the struct's state to change completely instead of really being a move). It's not necessarily completely unreasonable, but you appear to have found what I would expect to be a _very_ abnormal use-case.Andrei and I have talked about adding move constructors, but I agree with you that it really seems to be a tar pit we'd really like to avoid. C++ has a lot of subtle problems caused by supporting this, not the least of which is efficiency problems.
Aug 29 2011
On 8/30/11 12:45 AM, Benjamin Thaut wrote:Am 30.08.2011 02:56, schrieb Andrei Alexandrescu:Implementing a GC is an exceedingly rare privilege.On 8/29/11 4:36 PM, Walter Bright wrote:I don't see implementing a GC as that of a abnormal use case.On 8/29/2011 2:22 PM, Jonathan M Davis wrote:The language semantics make move construction unnecessary. Values are moveable as bits through memory. I think the article is a bit confused on this particular matter. Only objects with value semantics are freely moveable, so they have no direct interaction with the garbage collector. What they might want to do is to hold a pointer/reference _inside_ of them and deregister that pointer with the garbage collector with the destructor. Due to the indirection, it doesn't matter where the object is in memory. AndreiCertainly, for the common case, adding move constructors is a needless complication, and I'd _very_ leery of the ramifications of the compiler not being able to rely on a move having the bits stay absolutely identical (and a move constructor would make it possible for the struct's state to change completely instead of really being a move). It's not necessarily completely unreasonable, but you appear to have found what I would expect to be a _very_ abnormal use-case.Andrei and I have talked about adding move constructors, but I agree with you that it really seems to be a tar pit we'd really like to avoid. C++ has a lot of subtle problems caused by supporting this, not the least of which is efficiency problems.Especially given the fact that D is a garbage collected language and could benefit a lot from features that make implementing a GC easier.I don't believe D should be in the business of adding features that make implementing a GC easier. Such a task is extremely specialized; if the language allows it, that's about enough.In thise special case the discussed struct would be a wrapper for every reference on the stack, so the references can be tracked by the GC and changed if neccessary. Adding a level of indirection to every reference would greatly impact performance because it would most likely add yet another cache miss when accessing a reference. I'm very well aware of D's concept of structs. But sometimes this concept is very bad for performance, that is what I wanted to point out. Adding a move constructor which most of the structs won't even use, should be less of a performance impact, then adding another level of indirection.Clearly adding an extra level of indirection would be harmful, no two ways about it. But essentially the object model is what it is: there are value types that move, and there are reference types that don't. Deal with it. If you need to implement a garbage collector, you can't do it with move hooks because they're not provided. In a subtle way it's a given, although I totally understand how this or that hook would make your work easier. I don't find the complaint valid at all. Andrei
Aug 29 2011
Am 30.08.2011 08:00, schrieb Andrei Alexandrescu:On 8/30/11 12:45 AM, Benjamin Thaut wrote:My problem currenlty mostly is, that the current GC takes way more time then the usual 5% slowdown that gets mentioned with most GCs. Thats why I would prefer adding features that would make implementing GCs a) easier b) would actually allow do implement a GC that is not a Mark & Sweep c) faster because they won't have to scan all memory searching for a pointer Currently there is no way to track the references or pointers on the stack because the language does not include such a feature, nor can it be build with any of the language provided mechanisms. But maybe its just my point of view on this. In the field I'm mostly active in (3d games) performance is everything. Especially on the consoles. Most programmers even sacrifice most c++ features on the consoles (exceptions, RTTI, virtual functions to some extend) just to get more performance out of their game. -- Kind Regards Benjamin ThautAm 30.08.2011 02:56, schrieb Andrei Alexandrescu:Implementing a GC is an exceedingly rare privilege.On 8/29/11 4:36 PM, Walter Bright wrote:I don't see implementing a GC as that of a abnormal use case.On 8/29/2011 2:22 PM, Jonathan M Davis wrote:The language semantics make move construction unnecessary. Values are moveable as bits through memory. I think the article is a bit confused on this particular matter. Only objects with value semantics are freely moveable, so they have no direct interaction with the garbage collector. What they might want to do is to hold a pointer/reference _inside_ of them and deregister that pointer with the garbage collector with the destructor. Due to the indirection, it doesn't matter where the object is in memory. AndreiCertainly, for the common case, adding move constructors is a needless complication, and I'd _very_ leery of the ramifications of the compiler not being able to rely on a move having the bits stay absolutely identical (and a move constructor would make it possible for the struct's state to change completely instead of really being a move). It's not necessarily completely unreasonable, but you appear to have found what I would expect to be a _very_ abnormal use-case.Andrei and I have talked about adding move constructors, but I agree with you that it really seems to be a tar pit we'd really like to avoid. C++ has a lot of subtle problems caused by supporting this, not the least of which is efficiency problems.Especially given the fact that D is a garbage collected language and could benefit a lot from features that make implementing a GC easier.I don't believe D should be in the business of adding features that make implementing a GC easier. Such a task is extremely specialized; if the language allows it, that's about enough.In thise special case the discussed struct would be a wrapper for every reference on the stack, so the references can be tracked by the GC and changed if neccessary. Adding a level of indirection to every reference would greatly impact performance because it would most likely add yet another cache miss when accessing a reference. I'm very well aware of D's concept of structs. But sometimes this concept is very bad for performance, that is what I wanted to point out. Adding a move constructor which most of the structs won't even use, should be less of a performance impact, then adding another level of indirection.Clearly adding an extra level of indirection would be harmful, no two ways about it. But essentially the object model is what it is: there are value types that move, and there are reference types that don't. Deal with it. If you need to implement a garbage collector, you can't do it with move hooks because they're not provided. In a subtle way it's a given, although I totally understand how this or that hook would make your work easier. I don't find the complaint valid at all. Andrei
Aug 31 2011
On 8/31/2011 9:58 AM, Benjamin Thaut wrote:Currently there is no way to track the references or pointers on the stack because the language does not include such a feature, nor can it be build with any of the language provided mechanisms.The trouble with precise GC is that all the type info consumes a large amount of memory.But maybe its just my point of view on this. In the field I'm mostly active in (3d games) performance is everything. Especially on the consoles. Most programmers even sacrifice most c++ features on the consoles (exceptions, RTTI, virtual functions to some extend) just to get more performance out of their game.It's fairly straightforward to do the GC collection cycles during slack time, and avoid it during time critical sections. And note that if you've got hard real time constraints, you cannot even use malloc/free, as they do not run in bounded time.
Aug 31 2011
On Thu, Sep 1, 2011 at 3:23 PM, Walter Bright <newshound2 digitalmars.com> wrote:And note that if you've got hard real time constraints, you cannot even use malloc/free, as they do not run in bounded time.They're generally avoided in game code anyway because they're slow. Games don't have hard real time constraints though in the strictest sense, but you have a fixed budget with which to work all game logic and rendering having the GC kick in at the wrong time or run a bit longer than expected can lead to very nasty frame drops. You really need to be able to say when you want the GC to run, and how long you're willing to give it to execute.
Aug 31 2011
On 8/31/2011 10:23 PM, Walter Bright wrote:On 8/31/2011 9:58 AM, Benjamin Thaut wrote:Hm... how much per what unit? Is that an actual issue nowadays?Currently there is no way to track the references or pointers on the stack because the language does not include such a feature, nor can it be build with any of the language provided mechanisms.The trouble with precise GC is that all the type info consumes a large amount of memory.
Sep 01 2011
On 09/01/2011 12:23 AM, Walter Bright wrote:On 8/31/2011 9:58 AM, Benjamin Thaut wrote:I think our community will be rid of a major hurdle once we get past the debate on whether precise GC is necessary. Precise GC is necessary, there's no two ways about it. We should worry about implementing, not debating, it. AndreiCurrently there is no way to track the references or pointers on the stack because the language does not include such a feature, nor can it be build with any of the language provided mechanisms.The trouble with precise GC is that all the type info consumes a large amount of memory.
Sep 01 2011
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'sI think our community will be rid of a major hurdle once we get past the debate on whether precise GC is necessary. Precise GC is necessary, there's no two ways about it. We should worry about implementing, not debating, it. Andreiwhile(1) { vote++; } Needless to say, I'm quite frustrated that I implemented precise heap scanning almost two **years** ago and it's gone basically nowhere. Admittedly there were some unresolved plumbing issues with regard to getting the relevant type info to the GC from the new operator, etc. but it actually worked for memory allocated via GC.malloc and there were tests to back it up.
Sep 01 2011
Yup. I want to revisit CDGC to see if it's up to snuff as the default GC. It= already supports precise scanning, so perhaps the rest can be sorted via li= brary code: create!T(...) Sent from my iPhone On Sep 1, 2011, at 7:56 AM, dsimcha <dsimcha yahoo.com> wrote:=3D=3D Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'sningI think our community will be rid of a major hurdle once we get past the debate on whether precise GC is necessary. Precise GC is necessary, there's no two ways about it. We should worry about implementing, not debating, it. Andrei=20 while(1) { vote++; } =20 Needless to say, I'm quite frustrated that I implemented precise heap scan=almost two **years** ago and it's gone basically nowhere. Admittedly ther=e weresome unresolved plumbing issues with regard to getting the relevant type i=nfo tothe GC from the new operator, etc. but it actually worked for memory alloc=ated viaGC.malloc and there were tests to back it up.
Sep 01 2011
On Thu, 01 Sep 2011 11:46:32 -0400, Sean Kelly <sean invisibleduck.org> wrote:Yup. I want to revisit CDGC to see if it's up to snuff as the default GC. It already supports precise scanning, so perhaps the rest can be sorted via library code: create!T(...) Sent from my iPhoneDefault on *nix you mean, as CDGC sadly doesn't support windows.
Sep 01 2011
On Sep 1, 2011, at 7:57 PM, Robert Jacques wrote:On Thu, 01 Sep 2011 11:46:32 -0400, Sean Kelly =<sean invisibleduck.org> wrote:GC. It already supports precise scanning, so perhaps the rest can be = sorted via library code: create!T(...)Yup. I want to revisit CDGC to see if it's up to snuff as the default ==20 Default on *nix you mean, as CDGC sadly doesn't support windows.It should. It just won't be able to use its fork-based speedup. That = should still have it run on par with the GC we use today. If there are = any actual problems running on Windows, they shouldn't be too hard to = fix.=
Sep 02 2011
On Fri, 02 Sep 2011 13:34:12 -0400, Sean Kelly <sean invisibleduck.org> wrote:On Sep 1, 2011, at 7:57 PM, Robert Jacques wrote:Well, it would be a concurrent GC on Linux and (after patching) parallel(?) GC on Windows. So, I take your point that a lot of code could be re-used/shared between the two OSes.On Thu, 01 Sep 2011 11:46:32 -0400, Sean Kelly <sean invisibleduck.org> wrote:It should. It just won't be able to use its fork-based speedup. That should still have it run on par with the GC we use today. If there are any actual problems running on Windows, they shouldn't be too hard to fix.Yup. I want to revisit CDGC to see if it's up to snuff as the default GC. It already supports precise scanning, so perhaps the rest can be sorted via library code: create!T(...)Default on *nix you mean, as CDGC sadly doesn't support windows.
Sep 02 2011
On Thu, 01 Sep 2011 10:56:27 -0400, dsimcha <dsimcha yahoo.com> wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'sMake that while(1) { vote +=2 ; }I think our community will be rid of a major hurdle once we get past the debate on whether precise GC is necessary. Precise GC is necessary, there's no two ways about it. We should worry about implementing, not debating, it. Andreiwhile(1) { vote++; } Needless to say, I'm quite frustrated that I implemented precise heap scanning almost two **years** ago and it's gone basically nowhere. Admittedly there were some unresolved plumbing issues with regard to getting the relevant type info to the GC from the new operator, etc. but it actually worked for memory allocated via GC.malloc and there were tests to back it up.
Sep 01 2011
On 01-09-2011 16:42, Andrei Alexandrescu wrote:On 09/01/2011 12:23 AM, Walter Bright wrote:And honestly, the memory footprint for the type info is negligible with the amount of memory available today, especially as D is going towards x86-64 support. - AlexOn 8/31/2011 9:58 AM, Benjamin Thaut wrote:I think our community will be rid of a major hurdle once we get past the debate on whether precise GC is necessary. Precise GC is necessary, there's no two ways about it. We should worry about implementing, not debating, it. AndreiCurrently there is no way to track the references or pointers on the stack because the language does not include such a feature, nor can it be build with any of the language provided mechanisms.The trouble with precise GC is that all the type info consumes a large amount of memory.
Sep 01 2011
There are soft realtime GCs like you describe, but I believe they're all inc= remental. I don't know that approach is compatible with D.=20 Sent from my iPhone On Aug 31, 2011, at 10:35 PM, Josh Simmons <simmons.44 gmail.com> wrote:On Thu, Sep 1, 2011 at 3:23 PM, Walter Bright <newshound2 digitalmars.com> wrote:se=20 And note that if you've got hard real time constraints, you cannot even u=malloc/free, as they do not run in bounded time. =20=20 They're generally avoided in game code anyway because they're slow. =20 Games don't have hard real time constraints though in the strictest sense, but you have a fixed budget with which to work all game logic and rendering having the GC kick in at the wrong time or run a bit longer than expected can lead to very nasty frame drops. You really need to be able to say when you want the GC to run, and how long you're willing to give it to execute.
Sep 01 2011
On 8/27/2011 10:14 AM, Benjamin Thaut wrote:After having used the D 2.0 programming language for a year now and having completed 3 projects with it, I wrote a small article about the problems I had with the D 2.0 programming language and what suggestions I have to improve it. http://3d.benjamin-thaut.de/?p=18 Comments and criticism welcome "This transitiv[it]y basically kills you everywhere."I feel like you hit the nail on the head. I feel the same way about const. Transitivity is beautiful on the outside, but I can never actually get it working, so I just make everything non-const. I have to sometimes do this even in Phobos itself, because the compiler complains about something random caused by transitivity. I also fail to see what /problem/ it's trying to solve. The DigitalMars website simply states: "With transitivity, there is no way to have a const pointer to mutable int." But... so what? Maybe it should actually explain the benefit, since I can't figure it out on my own. (The related discussion on "head-const" and "tail-const" seems completely irrelevant to the topic." C++'s non-transitivity seems to be quite type-safe, even if unintuitive to the beginner (which I don't think it is). I *never* ran into issues with it. *On the bright side*, I LOVE immutable. It's one of the best features of D, IMO. (Or at least it would be, if only it /wasn't/ transitive.) I don't like the way C++ mixes the idea of "this never mutates" versus "YOU can't mutate this object", and I feel like D was really smart in making the distinction between the two. Related suggestion: All methods that return /new/ strings should return *mutable* arrays. There's really no reason (that I can think of) to not do this: if you see something returning a mutable array, you _know_ it's a new array (unless otherwise documented), so you _know_ it's safe to cast it to immutable if needed. It doesn't work the other way around, though.
Aug 27 2011
"Mehrdad" <wfunction hotmail.com> wrote in message news:j3beu2$25a8$1 digitalmars.com...Related suggestion: All methods that return /new/ strings should return *mutable* arrays. There's really no reason (that I can think of) to not do this: if you see something returning a mutable array, you _know_ it's a new array (unless otherwise documented), so you _know_ it's safe to cast it to immutable if needed. It doesn't work the other way around, though.Since a few days ago, mutable strings returned from strongly pure functions can be implicitly converted to immutable ones, so a cast won't be needed any more.
Aug 27 2011
On 8/27/2011 3:47 PM, Daniel Murphy wrote:"Mehrdad"<wfunction hotmail.com> wrote in message news:j3beu2$25a8$1 digitalmars.com...Does the same apply to all arrays of primitives?Related suggestion: All methods that return /new/ strings should return *mutable* arrays. There's really no reason (that I can think of) to not do this: if you see something returning a mutable array, you _know_ it's a new array (unless otherwise documented), so you _know_ it's safe to cast it to immutable if needed. It doesn't work the other way around, though.Since a few days ago, mutable strings returned from strongly pure functions can be implicitly converted to immutable ones, so a cast won't be needed any more.
Aug 27 2011
"dsimcha" <dsimcha yahoo.com> wrote in message news:j3bk94$2e72$1 digitalmars.com...To all types. Arrays, AAs, classes etc.Since a few days ago, mutable strings returned from strongly pure functions can be implicitly converted to immutable ones, so a cast won't be needed any more.Does the same apply to all arrays of primitives?
Aug 28 2011
Mehrdad:"With transitivity, there is no way to have a const pointer to mutable int." But... so what? Maybe it should actually explain the benefit, since I can't figure it out on my own.D wants both mutable data and (strongly) pure functions. How do you bridge such two worlds? If you have mutable data and you want to pass it to a pure function, you need a way to say this data structure will not change, nor any data it refers to. I think the D transitive const is the simpler way to do this.C++'s non-transitivity seems to be quite type-safe, even if unintuitive to the beginner (which I don't think it is). I *never* ran into issues with it.The C++ compiler doesn't offer means to enforce pure functions. In my opinion it's possible to add a C++-style const to D too, but this further increases the complexity of D, it cannot be used for purity, and it can't be used for compiler optimizations, you are allowed to safely cast it away when you want, it's just a convention, as in C++. But maybe it's useful anyway because most times you try to mutate the first level of a data structure, and such shallow const is enough to catch such unintentional mutation bug. Bye, bearophile
Aug 27 2011
On 28-08-2011 01:05, bearophile wrote:Mehrdad:const_cast is the root of all evil. I really don't want to see it in D. - Alex"With transitivity, there is no way to have a const pointer to mutable int." But... so what? Maybe it should actually explain the benefit, since I can't figure it out on my own.D wants both mutable data and (strongly) pure functions. How do you bridge such two worlds? If you have mutable data and you want to pass it to a pure function, you need a way to say this data structure will not change, nor any data it refers to. I think the D transitive const is the simpler way to do this.C++'s non-transitivity seems to be quite type-safe, even if unintuitive to the beginner (which I don't think it is). I *never* ran into issues with it.The C++ compiler doesn't offer means to enforce pure functions. In my opinion it's possible to add a C++-style const to D too, but this further increases the complexity of D, it cannot be used for purity, and it can't be used for compiler optimizations, you are allowed to safely cast it away when you want, it's just a convention, as in C++. But maybe it's useful anyway because most times you try to mutate the first level of a data structure, and such shallow const is enough to catch such unintentional mutation bug. Bye, bearophile
Aug 28 2011
On 8/28/11 8:54 PM, Alex Rønne Petersen wrote:const_cast is the root of all evil. I really don't want to see it in D. - AlexIt is already in D, and in an, in my personal opinion, much worse way: You can just cast away const/immutable with cast(). What do you propose for the situations where you need to cast away const? (Yes you'll find yourself in one of them from time to time in the real world, e.g. when dealing with legacy/C code…) I know that this is not the general consensus, but I very much like the C++ casting operators, because you can quickly get a rough idea what is going on when you see a cast in the code, whereas for D, cast() be anything between a perfectly harmless downcast (if checking for null, obviously), changing the storage class (const/immutable/shared), or causing the bytes stored to be interpreted in a completely different way! David
Aug 28 2011
On 8/28/2011 12:44 PM, David Nadlinger wrote:It is already in D, and in an, in my personal opinion, much worse way: You can just cast away const/immutable with cast().True, but such is explicitly undefined behavior, and is not allowed in safe mode.What do you propose for the situations where you need to cast away const? (Yes you'll find yourself in one of them from time to time in the real world, e.g. when dealing with legacy/C code…)That's why D does allow this, in a user visible manner, rather than forcing one to do it in a backdoor manner (like using inline asm).I know that this is not the general consensus, but I very much like the C++ casting operators, because you can quickly get a rough idea what is going on when you see a cast in the code, whereas for D, cast() be anything between a perfectly harmless downcast (if checking for null, obviously), changing the storage class (const/immutable/shared), or causing the bytes stored to be interpreted in a completely different way!To cast away const, use: cast()expr i.e. there is a special syntax for it.
Aug 28 2011
On 8/28/11 10:17 PM, Walter Bright wrote:On 8/28/2011 12:44 PM, David Nadlinger wrote:I know about the »it's not a bug, it's a feature« cast() syntax officially added some three (?) months ago, but it should be noted that it also removes shared from the type (incidentally, const_cast removes volatile as well). Personally, I think that being explicit about the type of operation one intends to perform is a good thing, especially if you are about to subvert the type system. Still, I feel using my own custom set of casting templates would be too confusing for other people reading my code – would anybody else be interested in adding »restricted« casting templates to Phobos? DavidI know that this is not the general consensus, but I very much like the C++ casting operators, because you can quickly get a rough idea what is going on when you see a cast in the code, whereas for D, cast() be anything between a perfectly harmless downcast (if checking for null, obviously), changing the storage class (const/immutable/shared), or causing the bytes stored to be interpreted in a completely different way!To cast away const, use: cast()expr i.e. there is a special syntax for it.
Aug 28 2011
On 08/28/2011 02:44 PM, David Nadlinger wrote:On 8/28/11 8:54 PM, Alex Rønne Petersen wrote:It is quite easy to define C++-like cast operators as D functions. If there's enough demand for that, we may include such in the standard library. Andreiconst_cast is the root of all evil. I really don't want to see it in D. - AlexIt is already in D, and in an, in my personal opinion, much worse way: You can just cast away const/immutable with cast(). What do you propose for the situations where you need to cast away const? (Yes you'll find yourself in one of them from time to time in the real world, e.g. when dealing with legacy/C code…) I know that this is not the general consensus, but I very much like the C++ casting operators, because you can quickly get a rough idea what is going on when you see a cast in the code, whereas for D, cast() be anything between a perfectly harmless downcast (if checking for null, obviously), changing the storage class (const/immutable/shared), or causing the bytes stored to be interpreted in a completely different way! David
Aug 28 2011
On 8/28/2011 4:52 PM, Andrei Alexandrescu wrote:It is quite easy to define C++-like cast operators as D functions. If there's enough demand for that, we may include such in the standard library. AndreiI think we should define at least the following and probably put them in std.conv, since these would add real value over the cast operator, the first in terms of straightforwardness and readability and the second in terms of error checking: reinterpretCast: Reinterprets the bit pattern at a given address as some other type. This should be broadened from C++ to allow reinterpretCasting from any type to any type. For example: // Fancy way of making a floating point number negative. float f = 5; auto i = reinterpretCast!int(f); // Flip the sign bit. i &= ~(1 << 31); f = reinterpretCast!float(i); dynamicCast: Cast a class to another. This should throw something derived from Error (not Exception) on failure instead of just returning null. If you want null, just use the cast operator. Maybe we should change its name, though. How about checkedCast or downCast?
Aug 28 2011
Am 28.08.2011 23:13, schrieb dsimcha:On 8/28/2011 4:52 PM, Andrei Alexandrescu wrote:I think, to!someClass(x) works like you want dynamic cast to work.It is quite easy to define C++-like cast operators as D functions. If there's enough demand for that, we may include such in the standard library. AndreiI think we should define at least the following and probably put them in std.conv, since these would add real value over the cast operator, the first in terms of straightforwardness and readability and the second in terms of error checking: reinterpretCast: Reinterprets the bit pattern at a given address as some other type. This should be broadened from C++ to allow reinterpretCasting from any type to any type. For example: // Fancy way of making a floating point number negative. float f = 5; auto i = reinterpretCast!int(f); // Flip the sign bit. i &= ~(1 << 31); f = reinterpretCast!float(i); dynamicCast: Cast a class to another. This should throw something derived from Error (not Exception) on failure instead of just returning null. If you want null, just use the cast operator. Maybe we should change its name, though. How about checkedCast or downCast?
Aug 28 2011
On 8/28/2011 5:18 PM, Mafi wrote:(Slaps self in forehead.) You're right, I forgot about that. Never mind.dynamicCast: Cast a class to another. This should throw something derived from Error (not Exception) on failure instead of just returning null. If you want null, just use the cast operator. Maybe we should change its name, though. How about checkedCast or downCast?I think, to!someClass(x) works like you want dynamic cast to work.
Aug 28 2011
On 08/28/2011 04:31 PM, dsimcha wrote:On 8/28/2011 5:18 PM, Mafi wrote:I think such an addition would be worthwhile. We'd only need std.conv.reinterpretCast as that's a distinct way to convert types than to!T. The function would only work if the source and target types have the same size. Some overloads of it would be safe (e.g. integral or floating point target) whereas others won't (e.g. those that forge pointers or references). Note that reinterpretCast would support conversions not covered by cast, e.g. converting a chunk of memory to a class object or one struct to another struct. Andrei(Slaps self in forehead.) You're right, I forgot about that. Never mind.dynamicCast: Cast a class to another. This should throw something derived from Error (not Exception) on failure instead of just returning null. If you want null, just use the cast operator. Maybe we should change its name, though. How about checkedCast or downCast?I think, to!someClass(x) works like you want dynamic cast to work.
Aug 28 2011
On 8/28/2011 2:49 PM, Andrei Alexandrescu wrote:On 08/28/2011 04:31 PM, dsimcha wrote:I don't know about others, but there's no way in hell that I will ever type "reinterpretCast" in my source code (let alone /import/ std.conv, just for a cast) unless the IDE was the one doing the typing.On 8/28/2011 5:18 PM, Mafi wrote:I think such an addition would be worthwhile. We'd only need std.conv.reinterpretCast as that's a distinct way to convert types than to!T. The function would only work if the source and target types have the same size. Some overloads of it would be safe (e.g. integral or floating point target) whereas others won't (e.g. those that forge pointers or references). Note that reinterpretCast would support conversions not covered by cast, e.g. converting a chunk of memory to a class object or one struct to another struct. Andrei(Slaps self in forehead.) You're right, I forgot about that. Never mind.dynamicCast: Cast a class to another. This should throw something derived from Error (not Exception) on failure instead of just returning null. If you want null, just use the cast operator. Maybe we should change its name, though. How about checkedCast or downCast?I think, to!someClass(x) works like you want dynamic cast to work.
Aug 31 2011
On 09/01/2011 12:06 AM, Mehrdad wrote:On 8/28/2011 2:49 PM, Andrei Alexandrescu wrote:Verboseness would be the last problem of a program needing many instances of reinterpretCast. AndreiOn 08/28/2011 04:31 PM, dsimcha wrote:I don't know about others, but there's no way in hell that I will ever type "reinterpretCast" in my source code (let alone /import/ std.conv, just for a cast) unless the IDE was the one doing the typing.On 8/28/2011 5:18 PM, Mafi wrote:I think such an addition would be worthwhile. We'd only need std.conv.reinterpretCast as that's a distinct way to convert types than to!T. The function would only work if the source and target types have the same size. Some overloads of it would be safe (e.g. integral or floating point target) whereas others won't (e.g. those that forge pointers or references). Note that reinterpretCast would support conversions not covered by cast, e.g. converting a chunk of memory to a class object or one struct to another struct. Andrei(Slaps self in forehead.) You're right, I forgot about that. Never mind.dynamicCast: Cast a class to another. This should throw something derived from Error (not Exception) on failure instead of just returning null. If you want null, just use the cast operator. Maybe we should change its name, though. How about checkedCast or downCast?I think, to!someClass(x) works like you want dynamic cast to work.
Sep 01 2011
Andrei Alexandrescu:It is quite easy to define C++-like cast operators as D functions. If there's enough demand for that, we may include such in the standard library.I'd like this one in Phobos: http://d.puremagic.com/issues/show_bug.cgi?id=5559 Having it in Phobos is hopefully better than creating your own one from scratch when the need arises. Bye, bearophile
Aug 28 2011
On 8/28/11 10:52 PM, Andrei Alexandrescu wrote:It is quite easy to define C++-like cast operators as D functions. If there's enough demand for that, we may include such in the standard library.I hope this finally goes through, there still seem to be some – hurricane-related, probably – stability issues with the server. Anyway, a library solution is definitely what I am thinking about, especially since it's just a matter of a template with a fitting constraint. But as said in my other post (that also took quite a few attempts to post), I think such casting templates would make most sense if standardized, i.e. included with Phobos. David
Aug 28 2011
On 8/28/2011 3:56 PM, David Nadlinger wrote:I hope this finally goes through, there still seem to be some – hurricane-related, probably – stability issues with the server.The only stability issue was the massive power outage. Jan got it back up running using a generator. Jan has always done an excellent job taking care of the server, and I am very satisfied.
Aug 28 2011
On 8/29/11 1:27 AM, Walter Bright wrote:On 8/28/2011 3:56 PM, David Nadlinger wrote:Yes – I didn't mean to discredit anyone, but I were definitely having problems reaching the server during the last few hours. I didn't look at a traceroute though, it could well be that some carrier was at fault. DavidI hope this finally goes through, there still seem to be some – hurricane-related, probably – stability issues with the server.The only stability issue was the massive power outage. Jan got it back up running using a generator. Jan has always done an excellent job taking care of the server, and I am very satisfied.
Aug 28 2011
On 8/28/2011 4:34 PM, David Nadlinger wrote:On 8/29/11 1:27 AM, Walter Bright wrote:It was down for 4 hours. Jan told me that he didn't care to try to get the generator engaged in total darkness in the middle of a hurricane. I don't blame him, I wouldn't either. Messing with generators can be dangerous, and getting hit with flying debris even worse.On 8/28/2011 3:56 PM, David Nadlinger wrote:Yes – I didn't mean to discredit anyone, but I were definitely having problems reaching the server during the last few hours. I didn't look at a traceroute though, it could well be that some carrier was at fault.I hope this finally goes through, there still seem to be some – hurricane-related, probably – stability issues with the server.The only stability issue was the massive power outage. Jan got it back up running using a generator. Jan has always done an excellent job taking care of the server, and I am very satisfied.
Aug 28 2011
Mehrdad Wrote:I feel like you hit the nail on the head. I feel the same way about const. Transitivity is beautiful on the outside, but I can never actually get it working, so I just make everything non-const. I have to sometimes do this even in Phobos itself, because the compiler complains about something random caused by transitivity. I also fail to see what /problem/ it's trying to solve. The DigitalMars website simply states: "With transitivity, there is no way to have a const pointer to mutable int." But... so what? Maybe it should actually explain the benefit, since I can't figure it out on my own. (The related discussion on "head-const" and "tail-const" seems completely irrelevant to the topic." C++'s non-transitivity seems to be quite type-safe, even if unintuitive to the beginner (which I don't think it is). I *never* ran into issues with it.In C I had to cast away const because constness is built into the struct itself - if you want the struct to be accessed as readonly. In D transitive const is transparent - you can have the save structure both readonly and mutable.
Aug 30 2011
On 08/27/2011 12:14 PM, Benjamin Thaut wrote:After having used the D 2.0 programming language for a year now and having completed 3 projects with it, I wrote a small article about the problems I had with the D 2.0 programming language and what suggestions I have to improve it. http://3d.benjamin-thaut.de/?p=18 Comments and criticism welcomeReddit discussion has turned to tuples: http://www.reddit.com/r/programming/comments/jwkvx/suggestions_for_the_d_20_programming_language/ Andrei
Aug 28 2011
Andrei Alexandrescu:Reddit discussion has turned to tuples:boost::tuples::tie is ugly compared to the syntax proposed in that pull request.They work well except when expanding to multiple variables,There are two more places where it's handy to expand tuples: function signatures and foreach :-) But I don't know what good syntax to use yet, suggestions welcome. Is Kenji Hara interested? Bye, bearophile
Aug 28 2011
One of the comments written by Walter:Few programmers stuff so much on one line that it becomes difficult picking out the error.<If you write D code in functional-style then lines of code often become quite long. Bye, bearophile
Aug 29 2011
On 8/27/11 12:14 PM, Benjamin Thaut wrote:After having used the D 2.0 programming language for a year now and having completed 3 projects with it, I wrote a small article about the problems I had with the D 2.0 programming language and what suggestions I have to improve it. http://3d.benjamin-thaut.de/?p=18On reddit: http://www.reddit.com/r/programming/comments/jwkvx/suggestions_for_the_d_20_programming_language/ Andrei
Aug 27 2011
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 8/27/11 12:14 PM, Benjamin Thaut wrote:On the pattern matching syntax for templates in the comments -- Sigh, the spec gotta advertise this valid syntax in the operator overloading page more: Foo opBinary(string op:"+")(...) { ... }After having used the D 2.0 programming language for a year now and having completed 3 projects with it, I wrote a small article about the problems I had with the D 2.0 programming language and what suggestions I have to improve it. http://3d.benjamin-thaut.de/?p=18On reddit: http://www.reddit.com/r/programming/comments/jwkvx/suggestions_for_the_d_20_programming_language/ Andrei
Aug 28 2011
Am 29.08.2011, 05:44 Uhr, schrieb kennytm <kennytm gmail.com>:On the pattern matching syntax for templates in the comments -- Sigh, the spec gotta advertise this valid syntax in the operator overloading page more: Foo opBinary(string op:"+")(...) { ... }Is 'more' an euphemism? ;) Good to know this syntax is possible, thx for clarifying.
Aug 28 2011
On 8/29/11, kennytm <kennytm gmail.com> wrote:On the pattern matching syntax for templates in the comments -- Sigh, the spec gotta advertise this valid syntax in the operator overloading page more: Foo opBinary(string op:"+")(...) { ... }Wow I didn't know about this. So now I can do this: enum Foo { A, B } void test(Foo foo:Foo.A)() {} instead of the more verbose: void test(Foo foo)() if (foo == Foo.A) {}
Aug 29 2011
On 29-08-2011 18:15, Andrej Mitrovic wrote:On 8/29/11, kennytm<kennytm gmail.com> wrote:Can it be used for overloading? I assume the way it works in that code is that it only runs the function if foo equals Foo.A. - AlexOn the pattern matching syntax for templates in the comments -- Sigh, the spec gotta advertise this valid syntax in the operator overloading page more: Foo opBinary(string op:"+")(...) { ... }Wow I didn't know about this. So now I can do this: enum Foo { A, B } void test(Foo foo:Foo.A)() {} instead of the more verbose: void test(Foo foo)() if (foo == Foo.A) {}
Aug 29 2011
On 08/29/2011 06:30 PM, Alex Rønne Petersen wrote:On 29-08-2011 18:15, Andrej Mitrovic wrote:Yes: void test(Foo foo)() {} // handles Foo.A void test(Foo foo:Foo.B)() {} // handles Foo.BOn 8/29/11, kennytm<kennytm gmail.com> wrote:Can it be used for overloading? I assume the way it works in that code is that it only runs the function if foo equals Foo.A. - AlexOn the pattern matching syntax for templates in the comments -- Sigh, the spec gotta advertise this valid syntax in the operator overloading page more: Foo opBinary(string op:"+")(...) { ... }Wow I didn't know about this. So now I can do this: enum Foo { A, B } void test(Foo foo:Foo.A)() {} instead of the more verbose: void test(Foo foo)() if (foo == Foo.A) {}
Aug 29 2011
Oh man wouldn't it be cool if we could use this syntax like this: void test(R1:isInputRange, R2:isForwardRange)(R1 r1, R2 r2) {} I'm not sure how that would work with multiple constraints or constraints that need comparisons, e.g. ElementType: void test(R1:isInputRange && ElementType == int, R2:isForwardRange)() {} Just throwing ideas for D5 there.. lol.
Aug 29 2011
On Mon, 29 Aug 2011 18:55:56 +0200, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Oh man wouldn't it be cool if we could use this syntax like this: void test(R1:isInputRange, R2:isForwardRange)(R1 r1, R2 r2) {} I'm not sure how that would work with multiple constraints or constraints that need comparisons, e.g. ElementType: void test(R1:isInputRange && ElementType == int, R2:isForwardRange)() {} Just throwing ideas for D5 there.. lol.Well, can you come up with a useful syntax for void put(E, R)(R r, E e) if(is(E : ElementType!R)) {} et.al. Otherwise having another syntax which put the sometimes heavy template constraints on the exact opposite side of the function signature is not too tempting.
Aug 29 2011
On 08/29/2011 07:44 PM, Martin Nowak wrote:On Mon, 29 Aug 2011 18:55:56 +0200, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:void put(E: ElementType!R, R)(R r, E e) {}Oh man wouldn't it be cool if we could use this syntax like this: void test(R1:isInputRange, R2:isForwardRange)(R1 r1, R2 r2) {} I'm not sure how that would work with multiple constraints or constraints that need comparisons, e.g. ElementType: void test(R1:isInputRange && ElementType == int, R2:isForwardRange)() {} Just throwing ideas for D5 there.. lol.Well, can you come up with a useful syntax for void put(E, R)(R r, E e) if(is(E : ElementType!R)) {} et.al. Otherwise having another syntax which put the sometimes heavy template constraints on the exact opposite side of the function signature is not too tempting.
Aug 29 2011
On 8/29/11 1:39 PM, Timon Gehr wrote:On 08/29/2011 07:44 PM, Martin Nowak wrote:The if-restriction on a template may build arbitrary expressions, so this case is addressed by pattern matching through "luck". So we definitely need if-restricted templates. Though I agree pattern matching syntax is nice, it is but an inferior alternative. AndreiOn Mon, 29 Aug 2011 18:55:56 +0200, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:void put(E: ElementType!R, R)(R r, E e) {}Oh man wouldn't it be cool if we could use this syntax like this: void test(R1:isInputRange, R2:isForwardRange)(R1 r1, R2 r2) {} I'm not sure how that would work with multiple constraints or constraints that need comparisons, e.g. ElementType: void test(R1:isInputRange && ElementType == int, R2:isForwardRange)() {} Just throwing ideas for D5 there.. lol.Well, can you come up with a useful syntax for void put(E, R)(R r, E e) if(is(E : ElementType!R)) {} et.al. Otherwise having another syntax which put the sometimes heavy template constraints on the exact opposite side of the function signature is not too tempting.
Aug 29 2011
On 08/29/2011 08:59 PM, Andrei Alexandrescu wrote:On 8/29/11 1:39 PM, Timon Gehr wrote:I am not sure that we are talking about the same thing. This does not actually compile now, because the compiler does never instantiate the template when performing pattern matching, so pattern matching only works with template structs/classes. Andrej's suggestion was to actually allow arbitrary expressions: Andrej Mitrovic wrote:On 08/29/2011 07:44 PM, Martin Nowak wrote:The if-restriction on a template may build arbitrary expressions, so this case is addressed by pattern matching through "luck". So we definitely need if-restricted templates. Though I agree pattern matching syntax is nice, it is but an inferior alternative.On Mon, 29 Aug 2011 18:55:56 +0200, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:void put(E: ElementType!R, R)(R r, E e) {}Oh man wouldn't it be cool if we could use this syntax like this: void test(R1:isInputRange, R2:isForwardRange)(R1 r1, R2 r2) {} I'm not sure how that would work with multiple constraints or constraints that need comparisons, e.g. ElementType: void test(R1:isInputRange && ElementType == int, R2:isForwardRange)() {} Just throwing ideas for D5 there.. lol.Well, can you come up with a useful syntax for void put(E, R)(R r, E e) if(is(E : ElementType!R)) {} et.al. Otherwise having another syntax which put the sometimes heavy template constraints on the exact opposite side of the function signature is not too tempting.void test(R1:isInputRange && ElementType == int, R2:isForwardRange)() {}Basically, in an ideal world, it could be written more like this: void test(R1: InputRange!int, R2: ForwardRange!_)() {} But I don't consider that important. For me, guards are good enough to specify static duck typing interfaces.
Aug 29 2011
Yeah it's not important. But I'll definitely use the colon syntax more often now.
Aug 29 2011
On 8/27/2011 10:14 AM, Benjamin Thaut wrote:Comments and criticism welcomeThis guy wants to contact you: http://www.reddit.com/r/programming/comments/jwkvx/suggestions_for_the_d_20_programming_language/c2g2wos
Aug 29 2011
Am 29.08.2011 23:12, schrieb Walter Bright:On 8/27/2011 10:14 AM, Benjamin Thaut wrote:Thanks for the heads up -- Kind Regards Benjamin ThautComments and criticism welcomeThis guy wants to contact you: http://www.reddit.com/r/programming/comments/jwkvx/suggestions_for_the_d_20_programming_language/c2g2wos
Aug 30 2011
On Aug 27, 2011, at 10:14 AM, Benjamin Thaut wrote:After having used the D 2.0 programming language for a year now and =having completed 3 projects with it, I wrote a small article about the = problems I had with the D 2.0 programming language and what suggestions = I have to improve it. "Either the builtin assert should be configureable so that it triggers a = breakpoint before throwing the exception, or there sould be a way to = built a custom assert" You can use core.exception.setAssetHandler to override the default = assert behavior. This is deprecated, however, because to my knowledge = no one has ever used it and because you can't actually return from this = handler--you must throw. This is because DMD doesn't generate a valid = call stack around the assert call for efficiency reasons.=
Aug 30 2011
On Aug 27, 2011, at 10:14 AM, Benjamin Thaut wrote:After having used the D 2.0 programming language for a year now and =having completed 3 projects with it, I wrote a small article about the = problems I had with the D 2.0 programming language and what suggestions = I have to improve it. Here's another one: "8. std.concurreny TID does not support shared" I really need to fix this. It's a pain though, for the reasons related = to the ones you mention in "5. Shared". A tid, for example, fronts a = message queue object that has some shared interface elements and some = unshared interface elements. The shared portion, rather than labeling = functions as synchronized, uses synchronized internally to make the = mutex use as fine-grained as possible. And the logically unshared = portion only synchronizes when accessing the shared data in the object. = So to make Tid work with shared I would basically have to label the = shared methods as shared and re-evaluate the ASM output once the = compiler inserts memory barriers, and cast away shared when accessing = the message queue from within its owner thread. What gets me about all = this is that rather than helping me, the type system is working against = me. I love shared as far as its use for globals is concerned, and for = concrete variables, but not so much for classes.=
Aug 30 2011
== Quote from Sean Kelly (sean invisibleduck.org)'s articleI really need to fix this. It's a pain though, for the reasons related to the ones you mention in "5. Shared". A tid, for example, fronts a message queue object that has some shared interface elements and some unshared interface elements. The shared portion, rather than labeling functions as synchronized, uses synchronized internally to make the mutex use as fine-grained as possible. And the logically unshared portion only synchronizes when accessing the shared data in the object. So to make Tid work with shared I would basically have to label the shared methods as shared and re-evaluate the ASM output once the compiler inserts memory barriers, and cast away shared when accessing the message queue from within its owner thread. What gets me about all this is that rather than helping me, the type system is working against me. I love shared as far as its use for globals is concerned, and for concrete variables, but not so much for classes.Yea, shared really was a blunder at least in anything like its current form. I think it's time we just admit it and do our best to mitigate it or find a way to massively overhaul it (though I'm skeptical that it can be overhauled successfully, especially with the constraints on backwards compatibility). The default thread-local/explicit global was a great idea, as was providing a share-nothing-except-immutable message passing-based concurrency module in Phobos for people who want safe, simple, coarse-grained concurrency. Message passing is safe and good for a lot of stuff, but not everything. Once you're trying to use a threading paradigm where you need shared mutable state, though, it can't be safe and it's a waste of time for the language to try. Even if you get rid of low-level data races, you still need to worry about high-level invariants, so you've only won half the battle. Furthermore, the shared type constructor cripples shared-state multithreading so much that it's almost useless unless you do some casting, defeating its purpose. The way I see this evolving is that almost all multithreaded code in D will either: 1. Avoid sharing and just use some combination of straight message passing and immutable data. 2. Bypass shared with casts, use of core.thread, std.parallelism, etc. and just do threading the old-fashioned way. (Though shared-state multithreading can be made less dangerous by encapsulating high-level paradigms. In this respect std.parallelism represents a middle ground between the completely safe std.concurrency and the completely flexible core.thread.) Ironically, I don't see this as such a bad outcome, except for the wasted "shared" keyword and dead trees describing it. D is a systems language and there needs to be ways to do dangerous, unchecked multithreading. It's great to provide a safe but limited way to write concurrent programs (such as share-nothing message passing), it's a no-brainer to prohibit the dangerous ways in SafeD, and it's fine to require some explicitness when using the dangerous ways (such as importing a different module). However, fighting the type system every inch of the way while paying lip service to playing nice with shared is not an acceptable solution. If you need shared state then you're almost guaranteed to need to cast away shared all over the place, and if you need to do so then you may as well bypass it entirely because it's just getting in the way and not providing any safety. This is why I've been so adamant about keeping core.thread and std.parallelism the way they are unless shared massively improves in ways that I'm very skeptical are even possible.
Aug 30 2011
On Aug 30, 2011, at 1:41 PM, dsimcha wrote:=3D=3D Quote from Sean Kelly (sean invisibleduck.org)'s articlerelatedI really need to fix this. It's a pain though, for the reasons =labelingto the ones you mention in "5. Shared". A tid, for example, fronts a message queue object that has some shared interface elements and some unshared interface elements. The shared portion, rather than =object.functions as synchronized, uses synchronized internally to make the mutex use as fine-grained as possible. And the logically unshared portion only synchronizes when accessing the shared data in the =allSo to make Tid work with shared I would basically have to label the shared methods as shared and re-evaluate the ASM output once the compiler inserts memory barriers, and cast away shared when accessing the message queue from within its owner thread. What gets me about =againstthis is that rather than helping me, the type system is working =forme. I love shared as far as its use for globals is concerned, and =form. Iconcrete variables, but not so much for classes.=20 Yea, shared really was a blunder at least in anything like its current =think it's time we just admit it and do our best to mitigate it or =find a way tomassively overhaul it (though I'm skeptical that it can be overhauled successfully, especially with the constraints on backwards =compatibility).=20 The default thread-local/explicit global was a great idea, as was =providing ashare-nothing-except-immutable message passing-based concurrency =module in Phobosfor people who want safe, simple, coarse-grained concurrency. Message =passing issafe and good for a lot of stuff, but not everything. =20 Once you're trying to use a threading paradigm where you need shared =mutablestate, though, it can't be safe and it's a waste of time for the =language to try. I think the idea behind shared as it applies to classes is that the = desired application won't have many shared objects, and those that are = shared should typically be fairly simple things like containers of = objects that don't have external references. The typical "web of shared = objects" as per Java is an invitation to disaster, and so the model = rightly discourages that. Regarding classes, I think one fundamental problem is that shared is = transitive. Simply putting memory barriers between accesses to shared = data doesn't mean that the algorithm itself will be correct if executed = concurrently. Transitively applying shared to member data and allowing = lock-free operations on this data and having the compiler even insert = memory barriers suggests to the neophyte user (IMO) that this is a safe = and acceptable means for making a class multithreaded when nothing could = be further from the truth. Another issue with transitivity is how this = affects C API calls, as the recent flurry of Windows patches to Phobos = can attest.Even if you get rid of low-level data races, you still need to worry =abouthigh-level invariants, so you've only won half the battle. =Furthermore, theshared type constructor cripples shared-state multithreading so much =that it'salmost useless unless you do some casting, defeating its purpose. The =way I seethis evolving is that almost all multithreaded code in D will either: =20 1. Avoid sharing and just use some combination of straight message =passing andimmutable data. =20 2. Bypass shared with casts, use of core.thread, std.parallelism, =etc. and justdo threading the old-fashioned way. (Though shared-state =multithreading can bemade less dangerous by encapsulating high-level paradigms. In this =respectstd.parallelism represents a middle ground between the completely safe std.concurrency and the completely flexible core.thread.)shared data, but that data can't be terribly complex. I do very much = dislike having to cast away shared though, because it makes for a very = awkward API design. For example, say I want to use synchronized in a = fine-grained manner. I have to do something like this: class MyClass { shared void doSomething() { cast(Unshared!(MyClass)).doSomething_(); } private void doSomething_() { =85 synchronized(this) { =85 } =85 }Ironically, I don't see this as such a bad outcome, except for the =wasted "shared"keyword and dead trees describing it. D is a systems language and =there needs tobe ways to do dangerous, unchecked multithreading. It's great to =provide a safebut limited way to write concurrent programs (such as share-nothing =messagepassing), it's a no-brainer to prohibit the dangerous ways in SafeD, =and it's fineto require some explicitness when using the dangerous ways (such as =importing adifferent module). However, fighting the type system every inch of =the way whilepaying lip service to playing nice with shared is not an acceptable =solution. Ifyou need shared state then you're almost guaranteed to need to cast =away sharedall over the place, and if you need to do so then you may as well =bypass itentirely because it's just getting in the way and not providing any =safety. Thisis why I've been so adamant about keeping core.thread and =std.parallelism the waythey are unless shared massively improves in ways that I'm very =skeptical are evenpossible.And this is why I haven't made much effort to change core.thread. I've = actually tried twice so far and gave up each time after seeing the = cascade of changes necessary. I'd like to say that the 'shared' attribute on member functions should = just mean "make this member visible through a shared reference" and do = away with the memory barriers idea entirely, except that D really does = need some form of atomics. I'm really not sure what the solution is = here.=
Aug 30 2011
On 8/30/2011 8:01 PM, Sean Kelly wrote:I'd like to say that the 'shared' attribute on member functions should just mean "make this member visible through a shared reference" and do away with the memory barriers idea entirely, except that D really does need some form of atomics. I'm really not sure what the solution is here.What's wrong with core.atomic?
Aug 30 2011
I meant atomic types, though I could probably be convinced otherwise. Sent from my iPhone On Aug 30, 2011, at 5:25 PM, dsimcha <dsimcha yahoo.com> wrote:On 8/30/2011 8:01 PM, Sean Kelly wrote: =20st mean "make this member visible through a shared reference" and do away wi= th the memory barriers idea entirely, except that D really does need some fo= rm of atomics. I'm really not sure what the solution is here.I'd like to say that the 'shared' attribute on member functions should ju==20 What's wrong with core.atomic?
Aug 31 2011
On 8/30/2011 8:01 PM, Sean Kelly wrote:I'd like to say that the 'shared' attribute on member functions should just mean "make this member visible through a shared reference"So the idea would just be that shared is a programmer-verified seal of approval that "yes, this is thread-safe without the user of the object taking any additional precautions"?
Aug 30 2011
That would be the easiest thing, yeah. I had some more complex ideas in the c= oncurrency list, but dunno if they're practical.=20 Sent from my iPhone On Aug 30, 2011, at 5:37 PM, dsimcha <dsimcha yahoo.com> wrote:On 8/30/2011 8:01 PM, Sean Kelly wrote:st mean "make this member visible through a shared reference"I'd like to say that the 'shared' attribute on member functions should ju==20 So the idea would just be that shared is a programmer-verified seal of app=roval that "yes, this is thread-safe without the user of the object taking a= ny additional precautions"?=20
Aug 31 2011
On 2011-08-31 00:01:09 +0000, Sean Kelly <sean invisibleduck.org> said:I'd like to say that the 'shared' attribute on member functions should just mean "make this member visible through a shared reference" and do away with the memory barriers idea entirely, except that D really does need some form of atomics. I'm really not sure what the solution is here.I think D needs some kind of knowledge about memory regions into its type system. The challenge is to not add too much complexity. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 30 2011
The effect on storage for statics is fantastic. I wasn't suggesting changing= that, if that's what you meant.=20 Sent from my iPhone On Aug 30, 2011, at 5:42 PM, Michel Fortin <michel.fortin michelf.com> wrote= :On 2011-08-31 00:01:09 +0000, Sean Kelly <sean invisibleduck.org> said: =20ystem. The challenge is to not add too much complexity.I'd like to say that the 'shared' attribute on member functions should just mean "make this member visible through a shared reference" and do away with the memory barriers idea entirely, except that D really does need some form of atomics. I'm really not sure what the solution is here.=20 I think D needs some kind of knowledge about memory regions into its type s==20 =20 --=20 Michel Fortin michel.fortin michelf.com http://michelf.com/ =20
Aug 31 2011
On 8/30/2011 5:01 PM, Sean Kelly wrote:I'd like to say that the 'shared' attribute on member functions should just mean "make this member visible through a shared reference" and do away with the memory barriers idea entirely, except that D really does need some form of atomics. I'm really not sure what the solution is here.I'm tending to agree that shared should no longer imply memory barriers.
Sep 01 2011
Sean Kelly Wrote:The shared portion, rather than labeling functions as synchronized, uses synchronized internally to make the mutex use as fine-grained as possible. And the logically unshared portion only synchronizes when accessing the shared data in the object.What's the difference? Both access shared data and synchronize. If the data accessed is unshared, there should be no problem to do it from shared method - there will be no barriers because the data is unshared, as I understand it.
Aug 31 2011
The unshared methods are only ever meant to be called by the queue owner. Th= ey access some member data without synchronization to make the queue efficie= nt for receive calls. I could make these methods shared anyway, but if they w= ere called concurrently by accident it would mean data corruption.=20 Sent from my iPhone On Aug 31, 2011, at 12:37 AM, Kagamin <spam here.lot> wrote:Sean Kelly Wrote: =20ynchronized internally to make the mutex use as fine-grained as possible. A= nd the logically unshared portion only synchronizes when accessing the share= d data in the object.The shared portion, rather than labeling functions as synchronized, uses s==20 What's the difference? Both access shared data and synchronize. If the dat=a accessed is unshared, there should be no problem to do it from shared meth= od - there will be no barriers because the data is unshared, as I understand= it.
Aug 31 2011
Sean Kelly Wrote:The unshared methods are only ever meant to be called by the queue owner. They access some member data without synchronization to make the queue efficient for receive calls. I could make these methods shared anyway, but if they were called concurrently by accident it would mean data corruption.If member data of a shared object is non-shared, it can be probably separated into another object, which will be really unshared. Unshared object can aggregate shared part through alias this if you want to see them as one object.
Aug 31 2011
On Aug 31, 2011, at 11:36 AM, Kagamin wrote:Sean Kelly Wrote: =20owner. They access some member data without synchronization to make the = queue efficient for receive calls. I could make these methods shared = anyway, but if they were called concurrently by accident it would mean = data corruption.The unshared methods are only ever meant to be called by the queue ==20 If member data of a shared object is non-shared, it can be probably =separated into another object, which will be really unshared. Unshared = object can aggregate shared part through alias this if you want to see = them as one object. Fair enough.=
Aug 31 2011
On 8/27/2011 8:59 AM, dsimcha wrote:When I add the directive: pragma(lib, "foo"); to a file called "bar.d" and then do: dmd -c bar.d does the object file bar.o or bar.obj contain a directive that reflects the pragma, or does pragma(lib) only work when compiling and linking in one step, e.g. dmd bar.d?On Windows, it embeds a reference to the library in the .obj file. The .o format does not support this, so on those platforms it adds "foo.a" to the link command.
Aug 28 2011