Re: Sociomantic
On Tuesday, 18 March 2014 at 16:06:41 UTC, Sociomantic wrote: http://translate.google.com/translate?sl=detl=enjs=nprev=_thl=enie=UTF-8u=http%3A%2F%2Fwww.welt.de%2Fwirtschaft%2Fwebwelt%2Farticle125913260%2FBriten-kaufen-Berliner-Start-up-fuer-200-Millionen.html damn. was gonna apply for a job in 3 years. :)
Re: Emacs users: flycheck-dmd-dub
Am 19.03.2014 00:16, schrieb Atila Neves: V0.0.4 now supports both package.json and dub.json Atila There is one change that I would highly recommend - using the output of dub describe instead of directly reading dub.json: - It's planned to add an SDL based format, which otherwise then would also have to be supported - Properly determining the right dependency versions/paths, configurations and platform specific values is not easy, but vital to get the correct results - Parts of the format may get extended in the future, requiring constant maintenance of the elisp package dub describe always outputs a JSON document* and has everything resolved down to bare compiler settings, so it's trivial to handle. Regards, Sönke * There is currently a bug where sometimes a non-JSON preamble is output before the actual contents, so it's necessary to skip until the first '{' before interpreting the output. This will be resolved in the next version.
Re: 1st draft of complete class-based std.random successor
On Wednesday, 19 March 2014 at 23:49:41 UTC, Joseph Rushton Wakeling wrote: * std.random2.distribution, random distributions such as uniform, normal, etc.; Related: please consider using parts of SimpleRNG the excellent work of John D. Cook which provides many random distributions in a compact and documented way. https://github.com/p0nce/gfm/blob/master/math/gfm/math/simplerng.d (here a port)
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 01:32:41 UTC, Chris Williams wrote: On Wednesday, 19 March 2014 at 23:49:41 UTC, Joseph Rushton Wakeling wrote: Hello all, As some of you may already know, monarch_dodra and I have spent quite a lot of time over the last year discussing the state of std.random. To cut a long story short, there are significant problems that arise because the current RNGs are value types rather than reference types. Any chance that you could describe them? I was about to resume porting the dcrypt library into Phobos, and had intended to flip the classes into structs, to match what the rest of the library was doing. The issue isn't class vs struct, but rather value semantic vs reference semantic (classes are always ref, but structs can be either). Basically, if you make a copy, and modify the copy, will the original range be modified? The problem with value semantics is that it always un-expected duplication of the range, which is a critical blocker problem as far as random goes. The tell-tale usecase is: // auto g = rndGen(); g.take(10).writeln(); g.take(10).writeln(); // This will write the same sequence... TWICE!
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 00:09:51 UTC, bearophile wrote: Joseph Rushton Wakeling: * std.random2.adaptor, random adaptors such as randomShuffle, randomSample, etc. Please don't use stuttering names like std.random2.randomShuffle. std.random2.shuffle is enough. Agreed. `randomShuffle` can be made a deprecated alias: This way, random2 should still be mostly drop in replacement, but we won't drag along the bad names. My own feeling is that ultimately it is a responsibility of the language to offer nice ways to allocate classes without necessarily relying on new or the GC. I don't think the language is yet there. So I think currently this is not a good idea. I think there is 0 doubt that reference semantics is the way to go. An advantage of using class is that it is still *possible* to place them on the stack with Scoped, or with some future language mechanic. On the other hand, if we implement as reference structs, then that's that. Furthermore, even in terms of performance, I think a heap allocated PRNG will still flat-out beat the value based one, if only because of the size of the damn thing. That said, being able to allocate them on the malloc heap, and not the GC heap, would be (IMO) also a valid design. A simple and dumb design might be to still implement them with value semantic but: 1. Disable postblit. 2. Make .save() return a Random* This would mean 1. No dangers of accidental copy. 2. Range* is a ForwardRange. 3. Trivially allows GC/malloc/stack allocation. With good aliases (alias Random = RadomImpl*;), and a make! template we could make the default useage transparent to this mechanism yet make it easy to get our hands under the hood. But at this point, we are really beating around the bush on this issue. There are two things for sure: 1. Reference semantics by default. 2. There comes a point where we have to move forward. I didn't check the code yet, but a middle ground could be to make all constructors private, and disable T.init. Then, we force construction through a make! template. This might not be what's most convenient, but it would allow us to potentially change the design at a later stage, without breaking user code. Do you have a simple but very fast function that generates uniforms in [0.0, 1.0]? :-) AFAIK, the allocation issue is only for ranges? uniform is just a function, I don't think it affected by the issue. Even if you are operating on a passed range, either ranges are reference semantics, and you take by value, or they are value semantic, and you take by ref. Either way, you have to pay for the indirection.
Re: Emacs users: flycheck-dmd-dub
On Thursday, 20 March 2014 at 07:17:04 UTC, Sönke Ludwig wrote: Am 19.03.2014 00:16, schrieb Atila Neves: V0.0.4 now supports both package.json and dub.json Atila There is one change that I would highly recommend - using the output of dub describe instead of directly reading dub.json: - It's planned to add an SDL based format, which otherwise then would also have to be supported I currently have a tool that read and writes the dub.json files. What would you suggest for this tool since describe would only solve the reading part and not the writing. Furthermore adding SDL format as well doubles the effort for this. Is dub usable as a library so that this wouldn't be a problem? /Jonas
Re: Emacs users: flycheck-dmd-dub
Ah, ok. I'll wait for the bug to be fixed. In the meanwhile, the package is now on MELPA and can be installed as any other emacs package. Atila On Thursday, 20 March 2014 at 07:17:04 UTC, Sönke Ludwig wrote: Am 19.03.2014 00:16, schrieb Atila Neves: V0.0.4 now supports both package.json and dub.json Atila There is one change that I would highly recommend - using the output of dub describe instead of directly reading dub.json: - It's planned to add an SDL based format, which otherwise then would also have to be supported - Properly determining the right dependency versions/paths, configurations and platform specific values is not easy, but vital to get the correct results - Parts of the format may get extended in the future, requiring constant maintenance of the elisp package dub describe always outputs a JSON document* and has everything resolved down to bare compiler settings, so it's trivial to handle. Regards, Sönke * There is currently a bug where sometimes a non-JSON preamble is output before the actual contents, so it's necessary to skip until the first '{' before interpreting the output. This will be resolved in the next version.
Re: D-Scanner 0.1.0-beta3 and DCD 0.3.0-beta4
The latest Zeus IDE beta adds support for DCD document comment completion. Zeus already has support for DCD goto definition, brace and dot completion. For more details refer to this link: http://www.zeusedit.com/zforum/viewtopic.php?p=10795 NOTE: Zeus is shareware, runs natively on the Windows and can run on Linux using Wine. Jussi Jumppanen Author: Zeus Editor
Re: 1st draft of complete class-based std.random successor
monarch_dodra: I think there is 0 doubt that reference semantics is the way to go. I agree. Furthermore, even in terms of performance, I think a heap allocated PRNG will still flat-out beat the value based one, if only because of the size of the damn thing. OK. Do you have a simple but very fast function that generates uniforms in [0.0, 1.0]? :-) AFAIK, the allocation issue is only for ranges? Here I was not talking about allocations: https://d.puremagic.com/issues/show_bug.cgi?id=5240 Bye, bearophile
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 08:22:37 UTC, monarch_dodra wrote: The issue isn't class vs struct, but rather value semantic vs reference semantic (classes are always ref, but structs can be either). That's only completely true if structs are referred to by pointer. ref parameters/returns aren't quite sufficient to keep a struct acting as a reference for all purposes. But good example. I'll have to consider that when I port the cryptographic prngs.
Re: 1st draft of complete class-based std.random successor
On Wednesday, 19 March 2014 at 23:49:41 UTC, Joseph Rushton Wakeling wrote: Hello all, As some of you may already know, monarch_dodra and I have spent quite a lot of time over the last year discussing the state of std.random. To cut a long story short, there are significant problems that arise because the current RNGs are value types rather than reference types. We had quite a lot of back and forth on different design ideas, with a lot of helpful input from others in the community, but at the end of the day there are really only two broad approaches: create structs that implement reference semantics internally, or use classes. So, as an exercise, I decided to create a class-based std.random. The preliminary (but comprehensive) results of this are now available here: https://github.com/WebDrake/std.random2 Besides re-implementing random number generators as classes rather than structs, the new code splits std.random2 into a package of several different modules: * std.random2.generator, pseudo-random number generators; * std.random2.device, non-deterministic random sources; * std.random2.distribution, random distributions such as uniform, normal, etc.; * std.random2.adaptor, random adaptors such as randomShuffle, randomSample, etc. * std.random2.traits, RNG-specific traits such as isUniformRNG and isSeedable. A package.d file groups them together so one can still import all together via import std.random2. I've also taken the liberty of following the new guideline to place import statements as locally as possible; it was striking how easy and clean this made things, and it should be easy to port that particular change back to std.random. The new package implements all of the functions, templates and range objects from std.random except for the old std.random.uniformDistribution, whose name I have cannibalized for better purposes. Some have been updated: the MersenneTwisterEngine has been tweaked to match the corresponding code from Boost.Random, and this in turn has allowed the definition of a 64-bit Mersenne Twister (Mt19937_64) and an alternative 32-bit one (Mt11213b). There are also a number of entirely new entries. std.random2.distribution contains not just existing functions such as dice and uniform, but also range-based random distribution classes UniformDistribution, NormalDistribution and DiscreteDistribution; the last of these is effectively a range-based version of dice, and is based on Chris Cain's excellent work here: https://github.com/D-Programming-Language/phobos/pull/1702 The principal weak point in terms of functionality is std.random2.device, where the implemented random devices (based on Posix' /std/random and /std/urandom) are really very primitive and just there to illustrate the principle. However, since their API is pretty simple (they're just input ranges with min and max defined) there should be plenty of opportunity to improve and extend the internals in future. Advice and patches are welcome for everything, but particularly here :-) What's become quite apparent in the course of writing this package is how much more natural it is for ranges implementing randomness to be class objects. The basic fact that another range can store a copy of an RNG internally without creating a copy-by-value is merely the start: for example, in the case of the class implementation of RandomSample, we no longer need to have complications like, @property auto ref front() { assert(!empty); // The first sample point must be determined here to avoid // having it always correspond to the first element of the // input. The rest of the sample points are determined each // time we call popFront(). if (_skip == Skip.None) { initializeFront(); } return _input.front; } that were necessary to avoid bugs like https://d.puremagic.com/issues/show_bug.cgi?id=7936; because the class-based implementation copies by reference, we can just initialize everything in the constructor. Similarly, issues like https://d.puremagic.com/issues/show_bug.cgi?id=7067 and https://d.puremagic.com/issues/show_bug.cgi?id=8247 just vanish. Obvious caveats about the approach include the fact that classes need to be new'd, and questions over whether allocation on the heap might create speed issues. The benchmarks I've run (code available in the repo) seem to suggest that at least the latter is not a worry, but these are obviously things that need to be considered. My own feeling is that ultimately it is a responsibility of the language to offer nice ways to allocate classes without necessarily relying on new or the GC. A few remarks on design and other factors: * The new range objects have been implemented as final classes for speed purposes. However, I tried another approach where the RNG class
Re: Soon Nick will be $75 richer...
On Wednesday, 19 March 2014 at 05:40:22 UTC, Nick Sabalausky wrote: On 3/18/2014 4:28 PM, Andrei Alexandrescu wrote: ... pending Martin's approval. https://d.puremagic.com/issues/show_bug.cgi?id=3490 https://www.bountysource.com/issues/1327154-dmd-never-inlines-functions-that-could-throw Heh, cool, thanks all :) Speaking of, I learned a lot about DMD's inliner while doing that, so I've posted an explanation of it on the Wiki: http://wiki.dlang.org/DMD_Source_Guide#Inliner Since it's based mainly on what I sussed out from looking at the source, it could probably use a look-over by a DMD guru in case I've misunderstood anything. Awesome write-up. Very informative.
Re: Soon Nick will be $75 richer...
On Thursday, 20 March 2014 at 19:12:29 UTC, Brad Anderson wrote: On Wednesday, 19 March 2014 at 05:40:22 UTC, Nick Sabalausky wrote: On 3/18/2014 4:28 PM, Andrei Alexandrescu wrote: ... pending Martin's approval. https://d.puremagic.com/issues/show_bug.cgi?id=3490 https://www.bountysource.com/issues/1327154-dmd-never-inlines-functions-that-could-throw Heh, cool, thanks all :) Speaking of, I learned a lot about DMD's inliner while doing that, so I've posted an explanation of it on the Wiki: http://wiki.dlang.org/DMD_Source_Guide#Inliner Since it's based mainly on what I sussed out from looking at the source, it could probably use a look-over by a DMD guru in case I've misunderstood anything. Awesome write-up. Very informative. +1 Imagine if the whole of the compiler/runtime was documented this well...
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 19:04:01 UTC, Andrea Fontana wrote: Still no cmwc rng... IMO cmwc should replace mt as default RNG. Faster. Longer period. More passed tests (if i'm right MT didn't pass testu01). And it is parametric to get faster result or longer period. http://en.wikipedia.org/wiki/Multiply-with-carry#Complementary-multiply-with-carry_generators Would a Lagged Fibonacci generator instead fit your needs? I wrote one, but it was held of until `random` was updated. It's goal, first, is to replace the old module. It'll add new stuff once it has achieved that goal.
Re: Soon Nick will be $75 richer...
On 3/19/14, Nick Sabalausky seewebsitetocontac...@semitwist.com wrote: Speaking of, I learned a lot about DMD's inliner while doing that, so I've posted an explanation of it on the Wiki: http://wiki.dlang.org/DMD_Source_Guide#Inliner I was really impressed by the write-up. I never touched the inliner before so these docs come in very handy. Thanks a bunch for this!
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 01:07:54 UTC, bearophile wrote: In Bugzilla probably there are many bug reports/enhancement requests about std.random, so I suggest you to read them. Some of them can be useful, while other are probably already addressed in the current (or planned) std.random2. Yes, indeed. Quite a few of them _are_ addressed, I think, but now that I've got the essentials of the design laid out, I should be systematic and go through them. Another random one that was just commented by Infiltrator: https://d.puremagic.com/issues/show_bug.cgi?id=5901 Well, you already have the NormalDistribution in std.random2.distribution ;-) I clearly can also implement function-only Box-Muller variant that spends 2 random variates to generate a single normally-distributed value, as this doesn't have the problem of needing to store state or allocate memory, so I will add that at some stage. I'm reluctant to add a specific fastRandom because I think here the better option is a really nice range-based algorithm that can generate high quality variates at speed (e.g. the Ziggurat algorithm is a good candidate here). There's a quite good review of different algorithms here: http://www.cse.cuhk.edu.hk/~phwl/mt/public/archives/papers/grng_acmcs07.pdf But of course I'm open to arguments here :-)
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 01:32:41 UTC, Chris Williams wrote: Any chance that you could describe them? I was about to resume porting the dcrypt library into Phobos, and had intended to flip the classes into structs, to match what the rest of the library was doing. I think there's a good case for a std.random2.crypto module that contains RNGs that are specifically suitable for cryptography. That said I think the bar here has to be set VERY high, which is why I didn't even begin working on it yet. It has been argued by some that where crypto in Phobos is concerned, we shouldn't take community contributions but we should hire security experts to write the functionality for us. Anyway, let's keep in touch about this and discuss how we could support one another's efforts. About the issues with value-type RNGs (as monarch_dodra says, it's not structs vs. classes per se, as you can implement reference types via structs; it's just more finnicky to do so), probably the best starting point is to read through the various bugs that have been reported as a result of this: https://d.puremagic.com/issues/show_bug.cgi?id=7067 https://d.puremagic.com/issues/show_bug.cgi?id=7936 https://d.puremagic.com/issues/show_bug.cgi?id=8247 https://d.puremagic.com/issues/show_bug.cgi?id=10322 Although some of these are marked as fixed, the fixes are pretty unpleasant and are workarounds rather than solutions of the underlying problem. It may look like only a few issues, but the implications are nasty. We had extensive discussions about this over the last year: http://forum.dlang.org/thread/mailman.259.1357667544.22503.digitalmar...@puremagic.com http://forum.dlang.org/thread/mailman.1017.1370879340.13711.digitalmar...@puremagic.com http://forum.dlang.org/thread/mailman.1157.1371497540.13711.digitalmar...@puremagic.com http://forum.dlang.org/thread/mailman.1209.1371565034.13711.digitalmar...@puremagic.com http://forum.dlang.org/thread/mailman.443.1377369357.1719.digitalmar...@puremagic.com http://forum.dlang.org/thread/5218fd04.8040...@webdrake.net The bottom line is that implementing your RNGs as classes automatically gets you out of the worst of these traps by giving you reference semantics from the get-go. Whether there are other problems that arise from this that make you prefer another design is a question you'll have to answer for yourself -- someone may yet come up with an objection that shows my current design is a Very Bad Idea ;-) Anyway, the example with rndGen.take(10).writeln that monarch_dodra gave is probably the best argument one can make. Imagine a cryptographic application where you're generating (supposedly) two different sets of random data, and because of an unintended value-type copy like this they turn out to be identical. Insecure much? :-)
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 08:30:09 UTC, ponce wrote: Related: please consider using parts of SimpleRNG the excellent work of John D. Cook which provides many random distributions in a compact and documented way. https://github.com/p0nce/gfm/blob/master/math/gfm/math/simplerng.d (here a port) Good call, I'll take a close look at that. Can you provide me with a link to the original project too? (Yes, I can just Google it, I'm being lazy:-)
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 21:16:27 UTC, Joseph Rushton Wakeling wrote: I think there's a good case for a std.random2.crypto module that contains RNGs that are specifically suitable for cryptography. That said I think the bar here has to be set VERY high, which is why I didn't even begin working on it yet. It has been argued by some that where crypto in Phobos is concerned, we shouldn't take community contributions but we should hire security experts to write the functionality for us. To be certain that the implementation doesn't have any security holes?
Re: Emacs users: flycheck-dmd-dub
Am 20.03.2014 10:10, schrieb Jonas Drewsen: On Thursday, 20 March 2014 at 07:17:04 UTC, Sönke Ludwig wrote: Am 19.03.2014 00:16, schrieb Atila Neves: V0.0.4 now supports both package.json and dub.json Atila There is one change that I would highly recommend - using the output of dub describe instead of directly reading dub.json: - It's planned to add an SDL based format, which otherwise then would also have to be supported I currently have a tool that read and writes the dub.json files. What would you suggest for this tool since describe would only solve the reading part and not the writing. Furthermore adding SDL format as well doubles the effort for this. Is dub usable as a library so that this wouldn't be a problem? /Jonas Yes, it has been built to be usable as a library, although there are certain parts of the API that are not yet considered full quality. But package file reading and writing using the Package class works fine and is already used by some other projects, such as the package registry. Having said that, there are of course cases where processing the JSON file directly isn't really problematic. It just may not be the best idea to rebuild the dependency and platform logic as long as the package format isn't fully stable.
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 08:51:08 UTC, monarch_dodra wrote: Agreed. There is consensus it seems. I will make the fix ;-) I think there is 0 doubt that reference semantics is the way to go. An advantage of using class is that it is still *possible* to place them on the stack with Scoped, or with some future language mechanic. On the other hand, if we implement as reference structs, then that's that. I suppose the one concern I have is whether these reference-type RNGs might generate unpleasant unintended effects with other range objects in Phobos. One thing that I really must do now that the basic design is in place is to systematically go through all the different ways in which these ranges could interact with deterministic ranges, and whether there are any issues to address. Furthermore, even in terms of performance, I think a heap allocated PRNG will still flat-out beat the value based one, if only because of the size of the damn thing. I don't know if you or anyone else has run the simple benchmark programs I created, but my impression was that for the RNGs and other functions here there is no significant speed difference between the std.random2 class implementations and their std.random struct predecessors. Where there _is_ a difference it seems more likely to be down to algorithm rather than class/struct or heap/stack. For example, my new Mersenne Twister is slightly slower, but probably because it's carrying extra parameters compared to that of std.random. On the other hand, generating random numbers by foreach'ing over uniform() calls does not seem to have any speed difference with popFrontN()'ing over a Uniform Distribution. That said, being able to allocate them on the malloc heap, and not the GC heap, would be (IMO) also a valid design. A simple and dumb design might be to still implement them with value semantic but: 1. Disable postblit. 2. Make .save() return a Random* This would mean 1. No dangers of accidental copy. 2. Range* is a ForwardRange. 3. Trivially allows GC/malloc/stack allocation. With good aliases (alias Random = RadomImpl*;), and a make! template we could make the default useage transparent to this mechanism yet make it easy to get our hands under the hood. One strict objection here: .save returning a Random* would mean that this kind of unittest will fail, no? auto rng1 = someRandomGenType; auto rng2 = rng1.save; rng1.popFrontN(10); rng2.popFrontN(10); assert(rng1.front == rng2.front); More generally, I think that, while I don't object to doing complicated stuff behind the scenes to get things simple and easy for the user, the problem I have with the above is that it really seems to require so much effort to create something which comes naturally with the current std.random2 design. I didn't check the code yet, but a middle ground could be to make all constructors private, and disable T.init. Then, we force construction through a make! template. This might not be what's most convenient, but it would allow us to potentially change the design at a later stage, without breaking user code. The idea of making constructors private and forcing the user to use the convenience functions is a very interesting one. As long as they provide an adequate interface to completely control all implementation parameters, it could provide a way to have significant leeway in controlling exactly how RNG instances are initialized. On the other hand it really feels obnoxious to cut users off from being able to use objects directly :-( Do you have a simple but very fast function that generates uniforms in [0.0, 1.0]? :-) AFAIK, the allocation issue is only for ranges? uniform is just a function, I don't think it affected by the issue. Even if you are operating on a passed range, either ranges are reference semantics, and you take by value, or they are value semantic, and you take by ref. Either way, you have to pay for the indirection. I think the issue here is just that it's possible to implement a really fast high-quality algorithm for uniformly-distributed floating point numbers in [0, 1). That has all sorts of uses not just for Phobos users but also internally in e.g. random distributions (for example, it'll give a significant speed boost to NormalDistribution).
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 21:42:13 UTC, Chris Williams wrote: To be certain that the implementation doesn't have any security holes? Yes. Of course, in the current climate one might fear that they'd be the ones introducing them ... :-)
Re: 1st draft of complete class-based std.random successor
On Thursday, 20 March 2014 at 18:43:49 UTC, Chris Williams wrote: That's only completely true if structs are referred to by pointer. ref parameters/returns aren't quite sufficient to keep a struct acting as a reference for all purposes. As far as I can tell, you're thinking of _passing_ struct parameters, and here, indeed, passing by ref is sufficient. The problem comes when you want to _store_ them. It's not safe to just store a pointer, because the (value type) struct that's being pointed to might go out of scope and be deleted. However, you can make structs behave like reference types behave like reference types, simply by making them contain (safe) references to the actual data they contain. E.g. (stupidly simple example): struct Foo { private: int *_a; public: this(int val) { _a = new int; *_a = val; } ref int a() @property { return *_a; } } unittest { auto foo1 = Foo(23); auto foo2 = foo1; foo2.a = 4; writeln(foo1.a); } Most of the discussion over RNGs in the last year is about whether we need to take a (more sophisticated) variant of this kind of approach to implement reference-type semantics for RNGs, or whether we should do something different. std.random2 is ... something different ;-)
Re: Soon Nick will be $75 richer...
On 3/20/2014 3:27 PM, John Colvin wrote: On Thursday, 20 March 2014 at 19:12:29 UTC, Brad Anderson wrote: On Wednesday, 19 March 2014 at 05:40:22 UTC, Nick Sabalausky wrote: Speaking of, I learned a lot about DMD's inliner while doing that, so I've posted an explanation of it on the Wiki: http://wiki.dlang.org/DMD_Source_Guide#Inliner Since it's based mainly on what I sussed out from looking at the source, it could probably use a look-over by a DMD guru in case I've misunderstood anything. Awesome write-up. Very informative. +1 Imagine if the whole of the compiler/runtime was documented this well... Glad to hear it's well-received! I highly encourage anyone who's first diving into an unfamiliar section of DMD or druntime to post what they've learned to the Wiki: I think that's a prime time to do so, when the new knowledge is still fresh in your mind. It really helps you digest all of it and identify any unexpected gaps in your own knowledge. Plus, others can help correct any misunderstandings, and any aspects of the code that turn out to be difficult for newcomers to grasp can be better identified.
Re: Ruby-style each in D?
On Wednesday, 19 March 2014 at 23:00:08 UTC, Walter Bright wrote: I don't have a solid enough experience with this style of programming, but one opportunity of 'each' could be that it could be specialized and achieve greater speed for some arguments. Speaking of which, it would be nice to have a compiler default iteration scheme that is optimal for any range. The current status is: for ( ; !r.empty ; r.popFront ) is sub-optimal for string types, and sometimes arrays. alias E = ElementEncodingType!Range; foreach(E e; range); will create copies of elements foreach(ref E e; range); will always work, but is arguably wrong for RValue ranges foreach(auto ref E e; range); is not legal, but there is an ER requesting it, and I think it would make perfect sense to have this. Finally: The hand written library code while ( decode(s, i) s.length ) { ... } Is faster for strings, than the compiler's/druntime's foreach(E e; range);. It would be awesome if: foreach(auto ref E e; range); Worked, *and* was always optimal. The current scheme makes those who care jump through hoops, such as in `find`'s implementation.
Re: inlining...
I just want to add these reasons for having inlining despite having compiler heuristics: 1. If you compile for embedded or PNACL on the web, you want a small executable. That means the heuristics should not inline if it increase the code size unless the programmer specified it in the code. (Or that you specify a target size, and do compiler re-runs until it fits.) 2. If you use profile guided opimization you should inline based on call frequency, but the input set might have missed some scenarios and you should be able to overrule the profile by explicit inlining in code where you know that it matters. (e.g. tight loop in an exception handler)
Re: Good name for f.byLine.map!(x = x.idup)?
On Thursday, 20 March 2014 at 01:38:38 UTC, Andrei Alexandrescu wrote: On 3/19/14, 4:53 PM, Meta wrote: On Wednesday, 19 March 2014 at 22:30:55 UTC, Peter Alexander wrote: On Sunday, 16 March 2014 at 16:58:36 UTC, Andrei Alexandrescu wrote: A classic idiom for reading lines and keeping them is f.byLine.map!(x = x.idup) to get strings instead of the buffer etc. f.readLines What about a simpler f.iter() or f.lineIter()? Ideally it would be a variation of byLine. -- Andrei What about simply templatizing (*) it? byLine() = implicit char[] byLine!string() = dupes This has the double advantage that: * Does not introduce a new symbol * Can be customized for wchar/dchar In particular, the wchar thing could be of interest to those that are reading a file they now is UTF16/UCS2. (*) Technically, it's already a template, but the parameters are inferred. We could make it so that we can use explicitly defined parameters. In particular, so that the output type is specified before the terminator type. AFAIK, the transition can be made seemlessly with no breakage.
Re: inlining...
On Thursday, 20 March 2014 at 02:08:16 UTC, Manu wrote: The problem is upside down. If you want to inline multiple levels, you start from the leaves and move downwards, not from the root moving upwards Yes, that is true in cases where leaves are frequently visited. Good point. I am most interested in full inlining, but the heuristics should probably start with the leaves for people not interested in that. Agree. Anyway, in the case of ray tracing (or any search structure) I could see the value of having the opposite in combination with CTFE/partial evaluation. Example: Define a static scene (of objects) and let the compiler turn it into a state machine of code. Another example: Define an array of data, use partial evaluation to turn it into a binary tree, then turn the binary tree into code. Inlining should be strictly deliberate, there's nothing to say that every function called in a tree should be inlined. There's a high probability there's one/some that shouldn't be among a few that should. In the case of a long running loop it does not really matter. What it does get you is a chance to use generic code (or libraries) and then do a first-resort optimization. I basically see it as a time-saving feature (programmers time). A tool for cutting development costs. Remember too, that call-site inlining isn't the only method, there would also be always-inline... Yes, that is the first. I have in another thread some time ago suggested a solution that use weighted inlining to aid compiler heuristics: http://forum.dlang.org/thread/szjkyfpnachnnyknn...@forum.dlang.org#post-szjkyfpnachnnyknnfwp:40forum.dlang.org As you can see I also suggested call-site inlining, so I am fully behind you in this. :-) Lack of inlining and GC are my main objections to D. I think always-inline is what you want for some decidedly trivial functions (although these will probably be heuristically inlined anyway), not call-site inlining. I agree. Compiler heuristics can change. It is desirable to be able to express intent no matter what the current heuristics are. I just don't see how recursive call-site inlining is appropriate, considering that call trees are often complex, subject to change, and may even call functions that you don't have source for. You should not use it blindly. You can cascade the mixin keyword if you want to, that's very simple. Not if you build the innerloop using generic components. I want this inline_everything while(conditon){ statement; statement; } I'd be highly surprised if you ever encountered a call tree where you wanted to inline everything (and the optimiser didn't do it for you). Not if you move to high-level programming using prewritten code and only go low level after profiling. As soon as you encounter a single function in the tree that shouldn't be inlined, then you'll be forced to do it one level at a time anyway. But then you have to change the libraries you are using!? Nothing prevents you to introduce exceptions as an extension though. I want inline(0.5) as default, but also be able to write inline(1) for inline always and inline(0) for inline never. func1(){} // implies inline(0.5) weighting inline func2(){} // same as inline(1) weighting, inline always inline(0.75) fun31(){} // increase the heuristics weighting inline(0) func4(){} // never-ever inline Ola.
[Proposal] Add module for C-strings support in Phobos
It's filed as enhancement 12418 [2]: C-strings processing is a special and common case so: 1. C-strings should be supported with both performance and usability. 2. There should be a dedicated module for C-strings (instead of adding such functions here and there in other modules). Current state: there is no good support for C-strings in Phobos, there is slow and broken `toStringz` (Issue 12417 [3]), and no standard way to make many common operations, like converting returned C-string to string and releasing its memory or creating a C-string from string using an allocation function. So I propose to add `unstd.c.string` [1] module to Phobos which include all use-cases I have seen implementing (correct and fast in contrast to existing ones like GtkD (yes, it's both incorrect and slow because of tons of GC allocations)) C library wrappers. [1] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html [2] https://d.puremagic.com/issues/show_bug.cgi?id=12418 [3] https://d.puremagic.com/issues/show_bug.cgi?id=12417 -- Денис В. Шеломовский Denis V. Shelomovskij
Re: [Proposal] Add module for C-strings support in Phobos
On Thursday, 20 March 2014 at 08:24:30 UTC, Denis Shelomovskij wrote: It's filed as enhancement 12418 [2]: C-strings processing is a special and common case so: 1. C-strings should be supported with both performance and usability. 2. There should be a dedicated module for C-strings (instead of adding such functions here and there in other modules). Current state: there is no good support for C-strings in Phobos, there is slow and broken `toStringz` (Issue 12417 [3]), and no standard way to make many common operations, like converting returned C-string to string and releasing its memory or creating a C-string from string using an allocation function. So I propose to add `unstd.c.string` [1] module to Phobos which include all use-cases I have seen implementing (correct and fast in contrast to existing ones like GtkD (yes, it's both incorrect and slow because of tons of GC allocations)) C library wrappers. [1] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html [2] https://d.puremagic.com/issues/show_bug.cgi?id=12418 [3] https://d.puremagic.com/issues/show_bug.cgi?id=12417 Looks like it wouldn't be really useful with Windows API. Given that wstrings are more common there. Another thing that would be nice to have is a wrapper struct for the pointer that allows accessing via e.g. opIndex and opSlice. Ext. Use case: Store the struct on D side to make sure GC doesn't clean it up and still be able to access and modify it like a normal string easily.
Re: [Proposal] Add module for C-strings support in Phobos
20.03.2014 13:20, Rikki Cattermole пишет: On Thursday, 20 March 2014 at 08:24:30 UTC, Denis Shelomovskij wrote: It's filed as enhancement 12418 [2]: C-strings processing is a special and common case so: 1. C-strings should be supported with both performance and usability. 2. There should be a dedicated module for C-strings (instead of adding such functions here and there in other modules). Current state: there is no good support for C-strings in Phobos, there is slow and broken `toStringz` (Issue 12417 [3]), and no standard way to make many common operations, like converting returned C-string to string and releasing its memory or creating a C-string from string using an allocation function. So I propose to add `unstd.c.string` [1] module to Phobos which include all use-cases I have seen implementing (correct and fast in contrast to existing ones like GtkD (yes, it's both incorrect and slow because of tons of GC allocations)) C library wrappers. [1] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html [2] https://d.puremagic.com/issues/show_bug.cgi?id=12418 [3] https://d.puremagic.com/issues/show_bug.cgi?id=12417 Looks like it wouldn't be really useful with Windows API. Given that wstrings are more common there. You misunderstand the terminology. C string is a zero-terminated string. Also looks like you didn't even go to docs page as the second example is WinAPI one. Another thing that would be nice to have is a wrapper struct for the pointer that allows accessing via e.g. opIndex and opSlice. Ext. Use case: Store the struct on D side to make sure GC doesn't clean it up and still be able to access and modify it like a normal string easily. I don't understand the use-case. If you did implemented some C library wrappers and have a personal experience, I'd like to hear your opinion on C functions calling problem and your proposal to solve it, if you dislike mine. Also with examples, please, where my solution fails and your one rocks. ) -- Денис В. Шеломовский Denis V. Shelomovskij
Re: Finally full multidimensional arrays support in D
18.03.2014 1:35, Christof Schardt пишет: I looked to the doku-page and expected to see, how some basic matrix-operations could be performed. Like e.g. (basic syntax) this: Dim a(10,12) a(3,4) = 7 a(i,j) = a(j,i) * 12 Instead I found exotic assignments and calculations. Did I expect the wrong thing? Sorry for that. Do you mead there is a lack of simple indexing examples or lack of some matrix functionality? The latter case is if you meant transpose and multiply by 12 with `a(i,j) = a(j,i) * 12`. -- Денис В. Шеломовский Denis V. Shelomovskij
Re: Appropriateness of posts
On Wednesday, 19 March 2014 at 23:18:55 UTC, H. S. Teoh wrote: Sometimes, the only way to win is to not play. T +1. You should add this to your list of quotes.
Re: [Proposal] Add module for C-strings support in Phobos
On Thursday, 20 March 2014 at 09:32:33 UTC, Denis Shelomovskij wrote: 20.03.2014 13:20, Rikki Cattermole пишет: On Thursday, 20 March 2014 at 08:24:30 UTC, Denis Shelomovskij wrote: It's filed as enhancement 12418 [2]: C-strings processing is a special and common case so: 1. C-strings should be supported with both performance and usability. 2. There should be a dedicated module for C-strings (instead of adding such functions here and there in other modules). Current state: there is no good support for C-strings in Phobos, there is slow and broken `toStringz` (Issue 12417 [3]), and no standard way to make many common operations, like converting returned C-string to string and releasing its memory or creating a C-string from string using an allocation function. So I propose to add `unstd.c.string` [1] module to Phobos which include all use-cases I have seen implementing (correct and fast in contrast to existing ones like GtkD (yes, it's both incorrect and slow because of tons of GC allocations)) C library wrappers. [1] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html [2] https://d.puremagic.com/issues/show_bug.cgi?id=12418 [3] https://d.puremagic.com/issues/show_bug.cgi?id=12417 Looks like it wouldn't be really useful with Windows API. Given that wstrings are more common there. You misunderstand the terminology. C string is a zero-terminated string. Also looks like you didn't even go to docs page as the second example is WinAPI one. I understand how c strings work. It would be nice to have more unittests for dstring/wstring, because it looks more geared towards char/string. Which is why it looks on the offset that it is less going to work. Another thing that would be nice to have is a wrapper struct for the pointer that allows accessing via e.g. opIndex and opSlice. Ext. Use case: Store the struct on D side to make sure GC doesn't clean it up and still be able to access and modify it like a normal string easily. I don't understand the use-case. If you did implemented some C library wrappers and have a personal experience, I'd like to hear your opinion on C functions calling problem and your proposal to solve it, if you dislike mine. Also with examples, please, where my solution fails and your one rocks. ) I don't dislike your approach at all. I just feel that it needs to allow for a little more use cases. Given the proposal is for phobos. What you have done looks fine for most cases to c libraries. I'm just worried that it has less use cases then it could have. I'm just nitpicking so don't mind me too much :)
Re: Appropriateness of posts
On Wednesday, 19 March 2014 at 07:51:06 UTC, Nick Sabalausky wrote: I find that interesting. This is the first I've ever heard of caucasian being even potentially offensive. Well, I am not offended by the term, I dislike it. I am offended by having to provide racial information. I am not sure what other norwegians feel about that, though. After 2WW where we lost over 1/3 of our jewish population (which was small already, jews were barred from entry until 1851) laws were established that banned registration of race, sexuality etc (unless where it has a very clear function of necessity). So my main objection is to having race and sexuality registered. But there is a bias in terms like nordic to race, even though it formally isn't a racial expression. And when we talk about north Europe, east Europe, southern Europe we refer to culture, but there is also a bias towards genetic traits if the context is about what people look like. Like, americans is more likely to evoke stereotypical images of middle class white americans than multi cultural america or the native americans. I think talking about white norwegians, or white swedes is somewhat weird and makes me a bit uneasy, either because it is too close or because the labels norwegian and swede already have a white bias, so making it explicit makes it overly racial? But talking about white americans, the whites in Africa etc is no problem at all and is politically correct. Perhaps because the usual context for those expressions is to talk about unfair treatment of minorities and lack of distribution of wealth. So that uncertainty leads americans to use caucasion (apparently derived from the extremely academic term caucasoid, or so I've been told) just out of paranoia, since it's seen as far too pedantic and technical to possibly be offensive. And this technical focus is what I object to since the nazis did take a rather scientific approach to this by measuring skulls etc to identify pure genes. Besides, how many third generation non-white american in the US have an actual ethnicity that makes sense? Like 1/4 african, 1/8 german, etc… But that said, I still find both examples as completely insufficient justification for bans on nudity. Fact of the matter is, I like to use both as shining examples of Just because you don't want to see something doesn't mean it should be banned. :-) Well, we are all coloured by the taboos that we were taught as kids. Getting over those is a challenge. I would personally not be offended by any cussing in a foreign language, I think. Though there probably are some vulgar cussing in norwegian that I'd rather not be affiliated with. part of the country.) I've heard of a court case (IANAL, of course) in San Fransisco where non-disruptive, non-sexualized public nudity was ruled legal. And it's either there or maybe Portland that has an annual non-clothed bicycling event. And I've heard that some court case in New York City ruled non-disruptive toplessness legal. Something similar in Canada too, IIRC. It's still nothing like certain other parts of the world, but still, baby steps. In the 80s the feminist movement made a big point of top less sun bathing, so you would find it everywhere (also in parks sometimes). But then it became less common outside beaches. Not sure why, probably partially because of breast cancer news reports and a lack of interest after the point had been made? I think it is difficult to uphold in cold region where you have to wear lots of cloths most of the year. I think it sends signals of being self-indulgent if you do it in your face in a park these days, but if you find your own spot then it is no problem. Of course, the population density of my country is low and the water front is accessible to the public even on private land (by law), so if you want to be nude you can always find your own spot somewhere.
Re: [Proposal] Add module for C-strings support in Phobos
20.03.2014 13:52, Rikki Cattermole пишет: On Thursday, 20 March 2014 at 09:32:33 UTC, Denis Shelomovskij wrote: 20.03.2014 13:20, Rikki Cattermole пишет: On Thursday, 20 March 2014 at 08:24:30 UTC, Denis Shelomovskij wrote: It's filed as enhancement 12418 [2]: C-strings processing is a special and common case so: 1. C-strings should be supported with both performance and usability. 2. There should be a dedicated module for C-strings (instead of adding such functions here and there in other modules). Current state: there is no good support for C-strings in Phobos, there is slow and broken `toStringz` (Issue 12417 [3]), and no standard way to make many common operations, like converting returned C-string to string and releasing its memory or creating a C-string from string using an allocation function. So I propose to add `unstd.c.string` [1] module to Phobos which include all use-cases I have seen implementing (correct and fast in contrast to existing ones like GtkD (yes, it's both incorrect and slow because of tons of GC allocations)) C library wrappers. [1] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html [2] https://d.puremagic.com/issues/show_bug.cgi?id=12418 [3] https://d.puremagic.com/issues/show_bug.cgi?id=12417 Looks like it wouldn't be really useful with Windows API. Given that wstrings are more common there. You misunderstand the terminology. C string is a zero-terminated string. Also looks like you didn't even go to docs page as the second example is WinAPI one. I understand how c strings work. It would be nice to have more unittests for dstring/wstring, because it looks more geared towards char/string. Which is why it looks on the offset that it is less going to work. I'd say must unittests do test UTF-16 UTF-32 versions. As for documentation, function signatures contain template parameter for character but probably there is a lack of ddoc unittests and/or documentation. Another thing that would be nice to have is a wrapper struct for the pointer that allows accessing via e.g. opIndex and opSlice. Ext. Use case: Store the struct on D side to make sure GC doesn't clean it up and still be able to access and modify it like a normal string easily. I don't understand the use-case. If you did implemented some C library wrappers and have a personal experience, I'd like to hear your opinion on C functions calling problem and your proposal to solve it, if you dislike mine. Also with examples, please, where my solution fails and your one rocks. ) I don't dislike your approach at all. I just feel that it needs to allow for a little more use cases. Given the proposal is for phobos. What you have done looks fine for most cases to c libraries. I'm just worried that it has less use cases then it could have. I'm just nitpicking so don't mind me too much :) Thanks. So the algorithm is like this: find C library which needs more love and file me an issue [1]. As I just added all common use-cases I have seen. [1] https://bitbucket.org/denis-sh/unstandard/issues -- Денис В. Шеломовский Denis V. Shelomovskij
DDT in Eclipse
I am finding that I have to remove DDT from Eclipse in order to get the latest CDT. Is this to be expected? Thanks. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Re: Most basic nothrow, pure, @safe functions?
On 2014-03-19 08:59, Joseph Rushton Wakeling wrote: On 19/03/14 00:20, Steven Schveighoffer wrote: I think we all agree that there are some things that the compiler simply cannot prove are nothrow, but to be able to write useful nothrow code, we have to paste nothrow on there anyway. Just to clarify my understanding here: exactly how much compiler checking _is_ done of nothrow? Is it simply to confirm that whatever is called by the function contains no throw statements (hopefully all the way down ...), or is there more ... ? It checks that any exceptions thrown in the function body are caught in a try/catch, and that any functions not marked nothrow are similarly handled in a try/catch. I believe that is all. For templated functions, the compiler does the same to figure out if the instantiation is nothrow. Thus a function can call a templated function that's not marked nothrow if its body can be compiled as such. -- Simen
Re: inlining...
On 20 March 2014 18:35, 7d89a89974b0ff40.invalid@internationalized.invalidwrote: On Thursday, 20 March 2014 at 02:08:16 UTC, Manu wrote: The problem is upside down. If you want to inline multiple levels, you start from the leaves and move downwards, not from the root moving upwards Yes, that is true in cases where leaves are frequently visited. Good point. I am most interested in full inlining, but the heuristics should probably start with the leaves for people not interested in that. Agree. Anyway, in the case of ray tracing (or any search structure) I could see the value of having the opposite in combination with CTFE/partial evaluation. Example: Define a static scene (of objects) and let the compiler turn it into a state machine of code. Another example: Define an array of data, use partial evaluation to turn it into a binary tree, then turn the binary tree into code. Inlining should be strictly deliberate, there's nothing to say that every function called in a tree should be inlined. There's a high probability there's one/some that shouldn't be among a few that should. In the case of a long running loop it does not really matter. What it does get you is a chance to use generic code (or libraries) and then do a first-resort optimization. I basically see it as a time-saving feature (programmers time). A tool for cutting development costs. Remember too, that call-site inlining isn't the only method, there would also be always-inline... Yes, that is the first. I have in another thread some time ago suggested a solution that use weighted inlining to aid compiler heuristics: http://forum.dlang.org/thread/szjkyfpnachnnyknn...@forum.dlang.org#post- szjkyfpnachnnyknnfwp:40forum.dlang.org As you can see I also suggested call-site inlining, so I am fully behind you in this. :-) Lack of inlining and GC are my main objections to D. I think always-inline is what you want for some decidedly trivial functions (although these will probably be heuristically inlined anyway), not call-site inlining. I agree. Compiler heuristics can change. It is desirable to be able to express intent no matter what the current heuristics are. I just don't see how recursive call-site inlining is appropriate, considering that call trees are often complex, subject to change, and may even call functions that you don't have source for. You should not use it blindly. You can cascade the mixin keyword if you want to, that's very simple. Not if you build the innerloop using generic components. I want this inline_everything while(conditon){ statement; statement; } I'd be highly surprised if you ever encountered a call tree where you wanted to inline everything (and the optimiser didn't do it for you). Not if you move to high-level programming using prewritten code and only go low level after profiling. As soon as you encounter a single function in the tree that shouldn't be inlined, then you'll be forced to do it one level at a time anyway. But then you have to change the libraries you are using!? Nothing prevents you to introduce exceptions as an extension though. I want inline(0.5) as default, but also be able to write inline(1) for inline always and inline(0) for inline never. func1(){} // implies inline(0.5) weighting inline func2(){} // same as inline(1) weighting, inline always inline(0.75) fun31(){} // increase the heuristics weighting inline(0) func4(){} // never-ever inline Ola. I'm sorry. I really can't support any of these wildly complex ideas. I just don't feel they're useful, and they're not very well founded. A numeric weight? What scale is it in? I'm not sure of any 'standard-inline-weight-measure' that any programmer would be able to intuitively gauge the magic number against. That will simply never be agreed by the devs. It also doesn't make much sense... different platforms will assign very different weights and different heuristics at the inliner. It's not a numeric quantity; it's a complex determination whether a function is a good candidate or not. The value you specify is likely highly context sensitive and probably not portable. Heuristic based Inlining should be left to the optimiser to decide. And I totally object to recursive inlining. It has a kind of absolute nature that removes control all the way down the call tree, and I don't feel it's likely that you would often (ever?) want to explicitly inline an entire call tree. If you want to inline a second level, then write mixin in the second level. Recurse. You are talking about generic code as if this isn't appropriate, but I specifically intend to use this in generic code very similar to what you suggest; so I don't see the incompatibility. I think you're saying like manually specifying it all the way down the call tree is inconvenient, but I would argue that manually specifying *exclusions* throughout the call tree after specifying a recursive inline is even
Re: Ruby-style each in D?
'each' sounds like a good idea for supporting component programming a little more. As bearophile as already stated, you can do something like this... someRange.filter!foo.frobulate.each!doSomethingWithIt; For Walter's question about parallel execution, I imagine something like this. // std.parallelism parallel function here. someRange.whatever.parallel(numberOfUnits).each!doSomething Basically it just removes a little foreach boilerplate. I don't think the implementation needs to be much more complicated than what Andrei wrote already, I would just pull that pretty much as-is. I also don't think an argument like you can already do this with foreach is valid. You don't *have* to use it, and some people might like it. I know I would appreciate having it in std.algorithm. (I'm kind of a range fanboy.)
Re: Most basic nothrow, pure, @safe functions?
I'd just like to toss one in there. .dup and .idup for slices and associative arrays. I've seen a few cases where these functions are not nothrow when they could be. (Because OutOfMemoryError is an Error, not an Exception.)
Re: A simple sieve in Phobos?
On Wednesday, 19 March 2014 at 17:40:50 UTC, Andrei Alexandrescu wrote: On 3/19/14, 10:01 AM, Dicebot wrote: I avoid it too but it is my personal problem to deal with. dub is de-facto standard in D tool chain and I am pretty sure eventually will be distributed with dmd. It may be time to look into this. Who wants to champion this effort? -- Andrei I think it is _tiny_ bit to early - there are some relatively big intrusive changes planned for dub (like switching to SDL as default description grammar) and it is better to start distributing it once this stuff stabilizes. I'll keep it in my notes though and start poking people once it looks feasible :) Do you have any personal requirements in mind that need to be met before legitimization of dub?
Re: inlining...
On Thursday, 20 March 2014 at 12:31:33 UTC, Manu wrote: I'm sorry. I really can't support any of these wildly complex ideas. They aren't actually complex, except tail-call optimization (but that is well understood). If you want to inline a second level, then write mixin in the second level. You might as well do copy-paste then. You cannot add inlining to an imported library without modifying it. at all, which is annoying, because I REALLY need this (I've been trying to motivate inline support for over 3 years), and I get the feeling you're just throwing hypotheticals around. You need inlining, agree, but not 1 level mixin. Because you can do that with regular inlining.
Re: Most basic nothrow, pure, @safe functions?
On Thursday, 20 March 2014 at 12:51:35 UTC, w0rp wrote: I'd just like to toss one in there. .dup and .idup for slices and associative arrays. I've seen a few cases where these functions are not nothrow when they could be. (Because OutOfMemoryError is an Error, not an Exception.) The reasons it's not nothrow is because because dup causes postblit, and postblit could throw. Of course, by that same token, postblit could be unsafe and impure. It's terribly inconsistent. Which is another big problem of druntime: Mostly everything in it is done at run-time using typeid, so there is no static inference.
Re: inlining...
Please note that 1 level mixin is not sufficient in the case of libraries. In too many cases you will not inline the function that does the work, only the interface wrapper.
Re: Ruby-style each in D?
On Thursday, 20 March 2014 at 12:32:49 UTC, w0rp wrote: // std.parallelism parallel function here. someRange.whatever.parallel(numberOfUnits).each!doSomething +1 This works: foreach(i; [0,1,2,3,4,5].parallel) i.writeln; This works: [0,1,2,3,4,5].each!writeln; This won't compile: [0,1,2,3,4,5].parallel.each!writeln; Error: template tmp.each cannot deduce function from argument types !(writeln)(ParallelForeach!(int[])), candidates are: /tmp/tmp.d(9):tmp.each(alias fun, Range)(Range range) if (isInputRange!Range)
Re: Appropriateness of posts
On Thu, 20 Mar 2014 05:35:53 -0400, Chris wend...@tcd.ie wrote: On Wednesday, 19 March 2014 at 23:18:55 UTC, H. S. Teoh wrote: Sometimes, the only way to win is to not play. T +1. You should add this to your list of quotes. -WOPR, War Games
Re: inlining...
On 21 March 2014 00:10, 7d89a89974b0ff40.invalid@internationalized.invalidwrote: Please note that 1 level mixin is not sufficient in the case of libraries. In too many cases you will not inline the function that does the work, only the interface wrapper. I don't think I would ever want to inline the whole call tree of a library. I've certainly never wanted to do anything like that in 20 years or so, and I've worked on some really performance critical systems, like amiga, dreamcast, ps2. It still sounds really sketchy. If the function that does the work is a few levels deep, then there is probably a good reason for that. What if there's an error check that writes log output or something? Or some branch that leads to other uncommon paths? I think you're making this problem up. Can you demonstrate where this has been a problem for you in the past? The call tree would have to be so very particular for this to be appropriate, and then you say this is a library, which you have no control over... so the call tree is just perfect by chance? What if the library changes?
Re: Ruby-style each in D?
On 2014-03-20 14:16, Andrea Fontana wrote: On Thursday, 20 March 2014 at 12:32:49 UTC, w0rp wrote: // std.parallelism parallel function here. someRange.whatever.parallel(numberOfUnits).each!doSomething +1 This works: foreach(i; [0,1,2,3,4,5].parallel) i.writeln; This works: [0,1,2,3,4,5].each!writeln; This won't compile: [0,1,2,3,4,5].parallel.each!writeln; Error: template tmp.each cannot deduce function from argument types !(writeln)(ParallelForeach!(int[])), candidates are: /tmp/tmp.d(9):tmp.each(alias fun, Range)(Range range) if (isInputRange!Range) It could be made to work, though: template isIterable(T) { enum isIterable = is(typeof((T t){foreach (e; t){}})); } template isRefIterable(T) { enum isRefIterable = is(typeof((T t){foreach (ref e; t){}})); } void each(alias fun, Range)(Range range) if (isInputRange!Range) { while (!range.empty) { unaryFun!fun(range.front); range.popFront(); } } void each(alias fun, Range)(Range range) if (!isInputRange!Range isRefIterable!Range) { foreach (ref e; range) { unaryFun!fun(e); } } void each(alias fun, Range)(Range range) if (!isInputRange!Range isIterable!Range !isRefIterable!Range) { foreach (e; range) { unaryFun!fun(e); } } void main() { [0,1,2,3,4,5].parallel.each!writeln; } -- Simen
Re: inlining...
On Thursday, 20 March 2014 at 08:35:22 UTC, Ola Fosheim Grøstad wrote: Nothing prevents you to introduce exceptions as an extension though. I want inline(0.5) as default, but also be able to write inline(1) for inline always and inline(0) for inline never. func1(){} // implies inline(0.5) weighting inline func2(){} // same as inline(1) weighting, inline always inline(0.75) fun31(){} // increase the heuristics weighting inline(0) func4(){} // never-ever inline It looks promising when seen like that, but introducing explicit inlining/deinlining to me correspond to a precise process: 1. Bottleneck is identified. 2. we could {inline|deinline} this call at this particular place and see what happens 3. Apply inline directive for this call. Only always or never is ever wanted for me, and for 1 level only. 4. Measure and validate like all optimizations. Now after this, even if the inlining become harmful for other reasons, I want this inlining to be maintained, whatever the cost, not subject to random rules I don't know of. When you tweak inlining, you are supposed to know what you are doing, and it's not just an optimization, it's an essential tool that enables other optimizations, help disambiguate aliasing, help the auto-vectorizer, help constant propagation... In the large majority of cases it can be left to the compiler, and in the 1% cases that matters I want to do it explicitely full stop.
Re: Ruby-style each in D?
On Thursday, 20 March 2014 at 15:02:46 UTC, Simen Kjærås wrote: On 2014-03-20 14:16, Andrea Fontana wrote: On Thursday, 20 March 2014 at 12:32:49 UTC, w0rp wrote: // std.parallelism parallel function here. someRange.whatever.parallel(numberOfUnits).each!doSomething +1 This works: foreach(i; [0,1,2,3,4,5].parallel) i.writeln; This works: [0,1,2,3,4,5].each!writeln; This won't compile: [0,1,2,3,4,5].parallel.each!writeln; Error: template tmp.each cannot deduce function from argument types !(writeln)(ParallelForeach!(int[])), candidates are: /tmp/tmp.d(9):tmp.each(alias fun, Range)(Range range) if (isInputRange!Range) It could be made to work, though: template isIterable(T) { enum isIterable = is(typeof((T t){foreach (e; t){}})); } template isRefIterable(T) { enum isRefIterable = is(typeof((T t){foreach (ref e; t){}})); } void each(alias fun, Range)(Range range) if (isInputRange!Range) { while (!range.empty) { unaryFun!fun(range.front); range.popFront(); } } void each(alias fun, Range)(Range range) if (!isInputRange!Range isRefIterable!Range) { foreach (ref e; range) { unaryFun!fun(e); } } void each(alias fun, Range)(Range range) if (!isInputRange!Range isIterable!Range !isRefIterable!Range) { foreach (e; range) { unaryFun!fun(e); } } void main() { [0,1,2,3,4,5].parallel.each!writeln; } -- Simen I think that pull request should be updated. Why isn't ParallelForEach implemented as Range, instead?
Re: Most basic nothrow, pure, @safe functions?
On Tuesday, 18 March 2014 at 23:56:15 UTC, Steven Schveighoffer wrote: On Tue, 18 Mar 2014 19:48:45 -0400, Walter Bright newshou...@digitalmars.com wrote: On 3/18/2014 4:20 PM, Steven Schveighoffer wrote: In a recent (well, recently pulled anyway) pull request that Monarch Dodra brought up, we debated what should be considered nothrow in the depths of druntime. There's a lot of low hanging nothrow fruit in druntime that doesn't need analysis, it just needs to get done: https://d.puremagic.com/issues/show_bug.cgi?id=12389 Can we mark _d_monitorenter and _d_monitorexit nothrow and have the compiler see that when using synchronized? This was the hurdle we couldn't overcome in the referenced pull request. Should those be marked nothrow? What about pure and @safe? I'd be inclined to say yes. Although monitors use lazy initialization, I think the failure to initialize a monitor should probably be considered an Error.
Re: A simple sieve in Phobos?
On 3/20/14, 6:07 AM, Dicebot wrote: On Wednesday, 19 March 2014 at 17:40:50 UTC, Andrei Alexandrescu wrote: On 3/19/14, 10:01 AM, Dicebot wrote: I avoid it too but it is my personal problem to deal with. dub is de-facto standard in D tool chain and I am pretty sure eventually will be distributed with dmd. It may be time to look into this. Who wants to champion this effort? -- Andrei I think it is _tiny_ bit to early - there are some relatively big intrusive changes planned for dub (like switching to SDL as default description grammar) and it is better to start distributing it once this stuff stabilizes. I'll keep it in my notes though and start poking people once it looks feasible :) Do you have any personal requirements in mind that need to be met before legitimization of dub? I think it should be pig easy to use, battle tested, and have some security mechanism in place. Andrei
Re: inlining...
On 2014-03-19 09:35, Manu wrote: I don't already have it, otherwise I'd be making use of it. D has no control over the inliner. GDC/LDC offer attributes, but then it's really annoying that D has no mechanism to make use of compiler-specific attributes in a portable way (ie, attribute aliasing), so I can't make use of those without significantly interfering with my code. Can't you create a tuple with different attributes depending on which compiler is currently compiling? Something like this: version (LDC) alias attributes = TypeTuple!(@attribute(forceinline); else version (GDC) alias attributes = TypeTuple!(@attribute(forceinline)); else version (DigitalMars) alias attributes = TypeTuple!(); else static assert(false); @(attributes) void foo () { } // This assume that attributes will be expanded -- /Jacob Carlborg
Re: Cannot cast X to Y at compile time...?
On Wednesday, 19 March 2014 at 20:43:59 UTC, Frustrated wrote: On Wednesday, 19 March 2014 at 16:57:38 UTC, dnspies wrote: I have a function called at CTFE which includes the lines: 97 if(conjunction exp = cast(conjunction)this_exp) { 98 inner_substitutions!(first,conjunction)(exp, map); 99 } else if(disjunction exp = cast(disjunction)this_exp) { 100 inner_substitutions!(first,disjunction)(exp, map); 101 } Here, this_exp is a reference of type expression to an object whose CTFE-runtime-type is of type disjunction. conjunction and disjunction are both descendent classes of expression. This code produces the following compilation error: source/cfgparse.d(97): Error: cannot cast [...] to cfgparse.conjunction at compile time. ([...] stands in for a very long string which I think is some sort of representation of this_exp) Just for the hell of it, I tried moving the assignment out of the conditional, and something very strange happens. 97 if(cast(conjunction)this_exp) { 98 conjunction exp = cast(conjunction)this_exp; 99 inner_substitutions!(first,conjunction)(exp, map); 100 } else if(cast(disjunction)this_exp) { 101 disjunction exp = cast(disjunction)this_exp; 102 inner_substitutions!(first,disjunction)(exp, map); 103 } source/cfgparse.d(101): Error: cannot cast [...] to cfgparse.disjunction at compile time Both the conditions compile properly, and now only the assignment fails. Why is this happening and how can I avoid it? I ran up to a similar situation when the thing trying to be cast was not what I thought it was. I.e., the error is exactly what it means. Try to create a this_exp that is a conjunction explicitly to see if that is the problem. Sorry, I don't understand. When I cast something to the wrong type, I should just get a null reference, shouldn't I? It shouldn't throw an error.
Re: Most basic nothrow, pure, @safe functions?
On 3/18/2014 5:49 PM, Walter Bright wrote: On 3/18/2014 4:56 PM, Steven Schveighoffer wrote: Can we mark _d_monitorenter and _d_monitorexit nothrow and have the compiler see that when using synchronized? This was the hurdle we couldn't overcome in the referenced pull request. Should those be marked nothrow? What about pure and @safe? Good question. I don't have an answer at the moment. I'm pretty sure they can't be pure. After all, monitors affect global state, can result in deadlocks, etc.
Re: A simple sieve in Phobos?
On Wednesday, 19 March 2014 at 17:40:50 UTC, Andrei Alexandrescu wrote: On 3/19/14, 10:01 AM, Dicebot wrote: I avoid it too but it is my personal problem to deal with. dub is de-facto standard in D tool chain and I am pretty sure eventually will be distributed with dmd. It may be time to look into this. Who wants to champion this effort? -- Andrei I'd support inclusion into the official Dlang package but it has to be ready for distribution. I'm a big fan of it but it doesn't seem 100% stable yet. For experimental libs i'd rather they were kept out of phobos and placed within the dub registry. We can load and use them at leisure from there without expecting any sort of support from the language maintainers. If included in phobos i can almost guarantee that even though they will be marked experimental devs will moan when they change because they will have an official stamp. Dub should be more embraced by the official language maintainers especially moving the Deimos repo's into there. I myself have had to duplicate and package a deimos repo and add it just to move on with a project.
Re: A simple sieve in Phobos?
On Thursday, 20 March 2014 at 21:31:13 UTC, Gary Willoughby wrote: For experimental libs i'd rather they were kept out of phobos and placed within the dub registry. We can load and use them at leisure from there without expecting any sort of support from the language maintainers. If included in phobos i can almost guarantee that even though they will be marked experimental devs will moan when they change because they will have an official stamp. +1
Re: Ruby-style each in D?
On Wednesday, 19 March 2014 at 15:06:40 UTC, Andrei Alexandrescu wrote: Pros and cons are already being discussed. Destroy! https://github.com/D-Programming-Language/phobos/pull/2024 Andrei User Ali Çehreli has posted in learn what I think is an interesting problem: http://forum.dlang.org/thread/lgfmbf$v7c$1...@digitalmars.com // This is a somewhat common little exercise: Write a function that takes the size of a diamond and produces a diamond of that size. When printed, here is the output for size 11: * *** * *** * *** * *** * *** * What interesting, boring, efficient, slow, etc. ways are there? Ali // The reason I bring it up is that this usually leads to a competition of whoever thinks up the most creative/concise UFCS chain. So here's what I'm thinking: Let's do this, but also using each/tee/tap/consume/walk (and others?)! I think this real world scenario is a good bench for seeing the effects of mixing imperative-style statements into a functional-style wrapper. Maybe the result will reveal that something is awesome, or that it is useless? That maybe something that looks like it works, is actually subtly buggy? That maybe each turns out to be useful past our wildest dreams? Who knows?
Handling invalid UTF sequences
Currently we do it by throwing a UTFException. This has problems: 1. about anything that deals with UTF cannot be made nothrow 2. turns innocuous errors into major problems, such as DOS attack vectors http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences One option to fix this is to treat invalid sequences as: 1. the .init value (0xFF for UTF8, 0x for UTF16 and UTF32) 2. U+FFFD I kinda like option 1. What do you think?
Re: Handling invalid UTF sequences
On Thursday, 20 March 2014 at 22:39:47 UTC, Walter Bright wrote: Currently we do it by throwing a UTFException. This has problems: 1. about anything that deals with UTF cannot be made nothrow 2. turns innocuous errors into major problems, such as DOS attack vectors http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences One option to fix this is to treat invalid sequences as: 1. the .init value (0xFF for UTF8, 0x for UTF16 and UTF32) 2. U+FFFD I kinda like option 1. What do you think? I had thought of this before, and had an idea along the lines of: 1. strings inside the program are always valid. 2. encountering invalid strings inside the program is an Error. 3. strings from the outside world must be validated before use. The advantage is *more* than just a nothrow guarantee, but also a performance guarantee in release. And it *is* a pretty sane approach to the problem: - User data: validate before use. - Internal data: if its bad, your program is in a failure state. As for your proposal, I can't really say. Silently accepting invalid sequences sounds nice at first, but its kind of just squelching the problem, isn't it? In any case, both proposals would be major breaking changes...
Re: Handling invalid UTF sequences
On Thursday, 20 March 2014 at 22:39:47 UTC, Walter Bright wrote: Currently we do it by throwing a UTFException. This has problems: 1. about anything that deals with UTF cannot be made nothrow 2. turns innocuous errors into major problems, such as DOS attack vectors http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences One option to fix this is to treat invalid sequences as: 1. the .init value (0xFF for UTF8, 0x for UTF16 and UTF32) 2. U+FFFD I kinda like option 1. What do you think? Hiding errors under the carpet is not a good strategy. These sequences are invalid, and doomed to explode at some point. I'm not sure what the solution is, but the .init one do not seems like the right one to me.
Re: Handling invalid UTF sequences
On 3/20/2014 6:39 PM, Walter Bright wrote: Currently we do it by throwing a UTFException. This has problems: 1. about anything that deals with UTF cannot be made nothrow 2. turns innocuous errors into major problems, such as DOS attack vectors http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences One option to fix this is to treat invalid sequences as: 1. the .init value (0xFF for UTF8, 0x for UTF16 and UTF32) 2. U+FFFD I kinda like option 1. What do you think? I'd have to give some thought to have an opinion on the right solution, however I do want to say the current UTFException throwing is something I've always been unhappy with. So it definitely should get addressed in some way.
Re: Handling invalid UTF sequences
To the extent possible, it should try to retain the data. But if ever the character is actually needed for something (like parsing JSON or displaying a glyph), the bad region should be replaced with a series of replacement characters: http://en.wikipedia.org/wiki/Replacement_character#Replacement_character
Re: Handling invalid UTF sequences
On 3/20/2014 3:51 PM, monarch_dodra wrote: In any case, both proposals would be major breaking changes... Or we could do this as alternate names, leaving the originals as throwing. Silently accepting invalid sequences sounds nice at first, but its kind of just squelching the problem, isn't it? Not exactly. The decoded/encoded string will still have invalid code units in it. It'd be like floating point nan, the invalid bits will still be propagated onwards to the output. I'm also of the belief that UTF sequences should be validated on input, not necessarily on every operation on them.
Re: Handling invalid UTF sequences
On Thursday, 20 March 2014 at 22:51:27 UTC, monarch_dodra wrote: On Thursday, 20 March 2014 at 22:39:47 UTC, Walter Bright wrote: Currently we do it by throwing a UTFException. This has problems: 1. about anything that deals with UTF cannot be made nothrow 2. turns innocuous errors into major problems, such as DOS attack vectors http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences One option to fix this is to treat invalid sequences as: 1. the .init value (0xFF for UTF8, 0x for UTF16 and UTF32) 2. U+FFFD I kinda like option 1. What do you think? I had thought of this before, and had an idea along the lines of: 1. strings inside the program are always valid. 2. encountering invalid strings inside the program is an Error. 3. strings from the outside world must be validated before use. The advantage is *more* than just a nothrow guarantee, but also a performance guarantee in release. And it *is* a pretty sane approach to the problem: - User data: validate before use. - Internal data: if its bad, your program is in a failure state. I'm a fan of this approach but Timon pointed out when I wrote about it once that it's rather trivial to get an invalid string through slicing mid-code point so now I'm not so sure. I think I'm still in favor of it because you've obviously got a logic error if that happens so your program isn't correct anyway (it's not a matter of bad user input).
Re: Ruby-style each in D?
monarch_dodra: I have just given some solutions in D.learn. So here's what I'm thinking: Let's do this, but also using each/tee/tap/consume/walk (and others?)! I think this real world scenario is a good bench for seeing the effects of mixing imperative-style statements into a functional-style wrapper. As I explained in a precedent post in this thread it's hard to design something if you don't try to use it, even something simple as a each(). So I approve such exercises. Bye, bearophile
Re: Ruby-style each in D?
On 3/20/2014 5:33 PM, bearophile wrote: As I explained in a precedent post in this thread it's hard to design something if you don't try to use it, even something simple as a each(). Right on.
Re: inlining...
On Thursday, 20 March 2014 at 15:26:35 UTC, ponce wrote: Now after this, even if the inlining become harmful for other reasons, I want this inlining to be maintained, whatever the cost, not subject to random rules I don't know of. When you The rules aren't random. The inliner conceptually use weighting anyway, you just increase the threshold for a specific call-tree. E.g. if a function is on the borderline of being inlined the probability is 50% if you add some noise to the selection with a magnitude that equals the typical approximation error of the heuristics. inline(0.75) should increase the probability to 75%. Today all functions have an implied inline(0.5). I think you should have this kind of control for all compiler heuristics thresholds that are arbitrary, not only inlining. Call site inlining is primarily useful for inlining external code. The alternative is usually to replace libraries with your own version.
Re: Handling invalid UTF sequences
On Thu, 20 Mar 2014 18:39:50 -0400, Walter Bright newshou...@digitalmars.com wrote: Currently we do it by throwing a UTFException. This has problems: 1. about anything that deals with UTF cannot be made nothrow 2. turns innocuous errors into major problems, such as DOS attack vectors http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences One option to fix this is to treat invalid sequences as: 1. the .init value (0xFF for UTF8, 0x for UTF16 and UTF32) 2. U+FFFD I kinda like option 1. What do you think? Can't say I like it. Especially since current code expects a throw. I understand the need. What about creating a different type which decodes into a known invalid code, and doesn't throw? This leaves the selection of throwing or not up to the type, which is generally decided on declaration, instead of having to change all your calls. -Steve
Re: Most basic nothrow, pure, @safe functions?
On Thu, 20 Mar 2014 17:32:01 -0400, Walter Bright newshou...@digitalmars.com wrote: On 3/18/2014 5:49 PM, Walter Bright wrote: On 3/18/2014 4:56 PM, Steven Schveighoffer wrote: Can we mark _d_monitorenter and _d_monitorexit nothrow and have the compiler see that when using synchronized? This was the hurdle we couldn't overcome in the referenced pull request. Should those be marked nothrow? What about pure and @safe? Good question. I don't have an answer at the moment. I'm pretty sure they can't be pure. After all, monitors affect global state, can result in deadlocks, etc. How do they affect global state? Resulting in deadlocks does not make them impure. This is also a pure function: pure int foo() { while(1) {} return 0; } Pure doesn't mean bug free. -Steve
Re: Most basic nothrow, pure, @safe functions?
Steven Schveighoffer: This is also a pure function: pure int foo() { while(1) {} return 0; } Pure doesn't mean bug free. Thankfully the D compiler catches the bug :-) test.d(3,4): Warning: statement is not reachable Bye, bearophile
Re: Most basic nothrow, pure, @safe functions?
On Thu, 20 Mar 2014 21:44:38 -0400, bearophile bearophileh...@lycos.com wrote: Steven Schveighoffer: This is also a pure function: pure int foo() { while(1) {} return 0; } Pure doesn't mean bug free. Thankfully the D compiler catches the bug :-) test.d(3,4): Warning: statement is not reachable I can make it not catch that error, but that is not the bug. The bug is that it never returns, effectively deadlocking. The sample is intentionally short to demonstrate my point, I (obviously) didn't try to compile it. -Steve
Re: Most basic nothrow, pure, @safe functions?
On Friday, 21 March 2014 at 02:00:11 UTC, Walter Bright wrote: On 3/20/2014 6:40 PM, Steven Schveighoffer wrote: How do they affect global state? Mutexes implicitly share state. It's the reason they exist. They can't be pure, because pure functions don't share state. If you got that road, you can't allow memory allocators to be used in pure code. That isn't a good argument.
Re: Most basic nothrow, pure, @safe functions?
On 3/20/2014 6:40 PM, Steven Schveighoffer wrote: How do they affect global state? Mutexes implicitly share state. It's the reason they exist. They can't be pure, because pure functions don't share state.
Re: Most basic nothrow, pure, @safe functions?
On Thu, 20 Mar 2014 22:00:15 -0400, Walter Bright newshou...@digitalmars.com wrote: On 3/20/2014 6:40 PM, Steven Schveighoffer wrote: How do they affect global state? Mutexes implicitly share state. It's the reason they exist. They can't be pure, because pure functions don't share state. I view it differently. I feel like locking and unlocking a mutex is pure. After calling lock, the same thing *always* happens. After unlocking, the same thing *always* happens. It's a weird thing -- when you lock a mutex, you own it after it's locked. It's no longer shared. It can be thought of as pulling memory out of the heap to temporarily own, and then putting it back, just like memory allocation (which is considered pure). This is quite different from actual global state, which is accessed via globals. trylock I don't think should be pure. I'm not sure about read/write locks. -Steve
Re: Most basic nothrow, pure, @safe functions?
On 3/20/14, 6:52 PM, Steven Schveighoffer wrote: On Thu, 20 Mar 2014 21:44:38 -0400, bearophile bearophileh...@lycos.com wrote: Steven Schveighoffer: This is also a pure function: pure int foo() { while(1) {} return 0; } Pure doesn't mean bug free. Thankfully the D compiler catches the bug :-) test.d(3,4): Warning: statement is not reachable I can make it not catch that error, but that is not the bug. The bug is that it never returns, effectively deadlocking. The sample is intentionally short to demonstrate my point, I (obviously) didn't try to compile it. -Steve My dream: pure @safe functions never cause deadlock. Andrei
Re: Most basic nothrow, pure, @safe functions?
On Thu, 20 Mar 2014 22:14:59 -0400, Steven Schveighoffer schvei...@yahoo.com wrote: On Thu, 20 Mar 2014 22:00:15 -0400, Walter Bright newshou...@digitalmars.com wrote: On 3/20/2014 6:40 PM, Steven Schveighoffer wrote: How do they affect global state? Mutexes implicitly share state. It's the reason they exist. They can't be pure, because pure functions don't share state. I view it differently. I feel like locking and unlocking a mutex is pure. After calling lock, the same thing *always* happens. After unlocking, the same thing *always* happens. It's a weird thing -- when you lock a mutex, you own it after it's locked. It's no longer shared. It can be thought of as pulling memory out of the heap to temporarily own, and then putting it back, just like memory allocation (which is considered pure). Thinking about it some more, I see what you mean -- an unshared mutex is useless. But at the same time, some logically pure functions cannot be so without mutexes. E.g. memory allocation. -Steve
Re: Cannot cast X to Y at compile time...?
On Thursday, 20 March 2014 at 21:32:08 UTC, dnspies wrote: Sorry, I don't understand. When I cast something to the wrong type, I should just get a null reference, shouldn't I? It shouldn't throw an error. If the compiler can statically determine that the cast is invalid you get an error instead. You can use something like 'static if(is(T : Foo))' to test at compile-time if T is implicitly convertible to Foo (I'm not certain the exact semantics) or 'static if(is(typeof(cast(Foo)T.init)))'. There's probably better ways to do it, and I recommend asking on D.learn to figure out how to do what you're looking for.
Re: D as A Better C?
On Wednesday, 19 February 2014 at 15:46:38 UTC, Tim Krimm wrote: On Tuesday, 18 February 2014 at 12:20:52 UTC, Rel wrote: On Tuesday, 11 February 2014 at 19:43:00 UTC, Walter Bright wrote: The subset would disallow use of any features that rely on: 1. moduleinfo 2. exception handling 3. gc 4. Object I've used such a subset before when bringing D up on a new platform, as the new platform didn't have a working phobos. What do you think? So may I ask, what is official decision on the subject? Quite a lot of people were begging for it for a long time. Obviously I'd like to have this feature in D because it would finally allow game, embedded, system (and operating system) developers to use good, modern and beautiful language for their needs. As for me I've been waiting for this for a long time. Hacking on compiler and phobos in order to make it generate stdlib-indepentent code may be interesting from time to time, but keeping such kind of project up-to-date with each new version of the compiler can be quite hard. Supporting a subset of D language features suitable for system/embedded programming and porting seems to be the best decision in this case. I have also been waiting for something like this for a long time. Well in my opinion the language should be started with a fixed number of features, that are not dependent on runtime, then improve the language by adding features supported by runtime library. Too bad that D doesn't officially support a subset without runtime depemdencies, so we have to either use C/C++ or keep on trying to hack on of D compilers. On the other hand Rust can be used without runtime libraries.
Re: dmd v2.065 compatibility
Am 14.03.2014 11:43, schrieb Chris: [1] Yesterday I tried to build a project with dub. dub had downloaded and installed dmd v2.065. The project and accompanying library had been built with dmd v2.064. dub said that the project was up to date and didn't need compiling. However, I got a long long error message informing me that there were undefined references (see below). I recompiled the library with dmd v2.065 and everything worked fine. Yet I wonder, is this behavior normal, i.e. dub says its alright but not really? DUB currently doesn't take the compiler version into account when generating the hash value used to cache the intermediate build results (in .dub/build/*), which is the reason it thought everything was up to date. This will get fixed for the next version.
Template with template?
How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works }
Re: Template with template?
On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type.
Re: Template with template?
On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } templates can be passed to templates as alias parameters, or as part of a TemplateArgumentTuple. See http://dlang.org/template.html#aliasparameters
Re: Template with template?
On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir Panteleev wrote: On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type. Yep, I've already tried this (sorry I should've mentioned it!). But I don't want this restriction.
bool Associative Array Synchronized
I'd like to cowboy it on an AA that looks like this: __gshared bool[string] m_mutex; I think it'll be much faster for my code because this AA could need to be checked and switched possibly millions of times per second and I wouldn't want to slow it down with a mutex protecting it. I'm thinking the bool would be synchronized at the hardware level anyway, since it's just a bit being flipped or returned. Am I right to assume this and (maybe an assembly guru can answer) it safe to use? Thanks
Re: Template with template?
On Thursday, 20 March 2014 at 16:40:50 UTC, Chris wrote: On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir Panteleev wrote: On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type. Yep, I've already tried this (sorry I should've mentioned it!). But I don't want this restriction. Arrays are homogeneous. All the elements must be of the same type. Different instantiations of templates are different types. You could use an array of std.variant.Variant
Re: bool Associative Array Synchronized
On Thu, 20 Mar 2014 13:43:58 -0400, Etienne etci...@gmail.com wrote: I'd like to cowboy it on an AA that looks like this: __gshared bool[string] m_mutex; I think it'll be much faster for my code because this AA could need to be checked and switched possibly millions of times per second and I wouldn't want to slow it down with a mutex protecting it. I'm thinking the bool would be synchronized at the hardware level anyway, since it's just a bit being flipped or returned. Am I right to assume this and (maybe an assembly guru can answer) it safe to use? No, it's not safe. With memory reordering, there is no safe unless you use mutexes or low-level atomics. Long story short, the compiler, the processor, or the memory cache can effectively reorder operations, making one thread see things happen in a different order than they are written/executed on another thread. There are no guarantees. -Steve
Re: bool Associative Array Synchronized
On Thursday, 20 March 2014 at 17:43:58 UTC, Etienne wrote: I'd like to cowboy it on an AA that looks like this: __gshared bool[string] m_mutex; I think it'll be much faster for my code because this AA could need to be checked and switched possibly millions of times per second and I wouldn't want to slow it down with a mutex protecting it. I'm thinking the bool would be synchronized at the hardware level anyway, since it's just a bit being flipped or returned. Am I right to assume this and (maybe an assembly guru can answer) it safe to use? Thanks On x86 only? If all you do is read/write from/to each location then you are guaranteed atomicity. Adding/removing members? Forget it Also, atomicity is not a strong enough guarantee for implementing a mutex, which is what I assume you are trying to do. You need ordering guarantees as well. Watch both of these: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2 and then look at core.atomic and then give up and use a lock :p
Re: Template with template?
Or make trait a class, storing the interface and passing the trait to the new Person in the constructor.
Re: bool Associative Array Synchronized
On 2014-03-20 1:52 PM, Steven Schveighoffer wrote: On Thu, 20 Mar 2014 13:43:58 -0400, Etienne etci...@gmail.com wrote: I'd like to cowboy it on an AA that looks like this: __gshared bool[string] m_mutex; I think it'll be much faster for my code because this AA could need to be checked and switched possibly millions of times per second and I wouldn't want to slow it down with a mutex protecting it. I'm thinking the bool would be synchronized at the hardware level anyway, since it's just a bit being flipped or returned. Am I right to assume this and (maybe an assembly guru can answer) it safe to use? No, it's not safe. With memory reordering, there is no safe unless you use mutexes or low-level atomics. Long story short, the compiler, the processor, or the memory cache can effectively reorder operations, making one thread see things happen in a different order than they are written/executed on another thread. There are no guarantees. -Steve Right, I was assuming it was always ordered, but modern processor pipelines are different I guess.
Re: bool Associative Array Synchronized
On 2014-03-20 1:58 PM, John Colvin wrote: Also, atomicity is not a strong enough guarantee for implementing a mutex, which is what I assume you are trying to do. You need ordering guarantees as well. Heh. Will do!
Re: bool Associative Array Synchronized
On Thursday, 20 March 2014 at 18:06:18 UTC, Etienne wrote: Right, I was assuming it was always ordered, but modern processor pipelines are different I guess. Even without rearranging the order of your code, your bit exists in RAM but all the logic takes place in a CPU register, meaning that any time you operate with the bit, there's at least two copies. When the CPU switches threads (which could be at any point), it empties the CPU into RAM. If the thread it's switching to then tries to interact with the bit, it's going to create a third copy. Now whichever of the two threads is slower to write back to the original location is going to smash the other's.
Re: Template with template?
On Thursday, 20 March 2014 at 17:49:52 UTC, John Colvin wrote: On Thursday, 20 March 2014 at 16:40:50 UTC, Chris wrote: On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir Panteleev wrote: On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type. Yep, I've already tried this (sorry I should've mentioned it!). But I don't want this restriction. Arrays are homogeneous. All the elements must be of the same type. Different instantiations of templates are different types. You could use an array of std.variant.Variant The elements are all of type Trait. However, Type itself might be of different types. That's why it is not possible? I've come across this restriction before when using templates, which is a big disappointment because it restricts the templatization / generalization of data structures somewhat.
Re: bool Associative Array Synchronized
On Thu, Mar 20, 2014 at 06:39:10PM +, Chris Williams wrote: On Thursday, 20 March 2014 at 18:06:18 UTC, Etienne wrote: Right, I was assuming it was always ordered, but modern processor pipelines are different I guess. Even without rearranging the order of your code, your bit exists in RAM but all the logic takes place in a CPU register, meaning that any time you operate with the bit, there's at least two copies. When the CPU switches threads (which could be at any point), it empties the CPU into RAM. If the thread it's switching to then tries to interact with the bit, it's going to create a third copy. Now whichever of the two threads is slower to write back to the original location is going to smash the other's. Furthermore, the CPU does not access bits directly; it processes them as (at least) bytes. To set/clear a bit in memory location X, the CPU has to first read X into a register (at least 8 bits long), update the bit, and write it back into memory. If two threads are simultaneously operating on different bits that resides in the same byte, whichever CPU runs last will smash whatever the first CPU wrote. Let's say you start with b in location X, and CPU1 wants to set the first bit and CPU2 wants to set the second bit. Both CPU's initially reads b into their registers, then the first CPU sets the first bit, so it becomes 0001b (in register) and the second CPU sets the second bit so it becomes 0010b (in register). Now CPU1 writes 0001b back to memory, followed by CPU2 writing 0010b back to memory. Now what CPU1 did has been smashed by CPU2's write. Now, the current AA implementation doesn't actually pack bits like this, so this particular problem doesn't actually happen, but other similar problems will occur if you add/remove keys from the AA -- two CPU's will try to update internal AA pointers simultaneously, and end up trashing it. T -- What doesn't kill me makes me stranger.
Re: Template with template?
On Thursday, 20 March 2014 at 18:39:32 UTC, Chris wrote: On Thursday, 20 March 2014 at 17:49:52 UTC, John Colvin wrote: On Thursday, 20 March 2014 at 16:40:50 UTC, Chris wrote: On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir Panteleev wrote: On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type. Yep, I've already tried this (sorry I should've mentioned it!). But I don't want this restriction. Arrays are homogeneous. All the elements must be of the same type. Different instantiations of templates are different types. You could use an array of std.variant.Variant The elements are all of type Trait. However, Type itself might be of different types. That's why it is not possible? I've come across this restriction before when using templates, which is a big disappointment because it restricts the templatization / generalization of data structures somewhat. Trait is not a type. Trait is a template. An instantiation of the Trait template is a type. Arrays are contiguous, homogeneous data. This is fundamental to their design and their performance characteristics. Workarounds use at least one of the following: indirection, tagging* and padding. Variant uses tagging and padding. Interface/base-class arrays use indirection (and tagging, ultimately). *inline or external, or even compile-time. This is true in *every* programming language, just with different names.
Re: Template with template?
On Thursday, 20 March 2014 at 18:54:30 UTC, John Colvin wrote: On Thursday, 20 March 2014 at 18:39:32 UTC, Chris wrote: On Thursday, 20 March 2014 at 17:49:52 UTC, John Colvin wrote: On Thursday, 20 March 2014 at 16:40:50 UTC, Chris wrote: On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir Panteleev wrote: On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type. Yep, I've already tried this (sorry I should've mentioned it!). But I don't want this restriction. Arrays are homogeneous. All the elements must be of the same type. Different instantiations of templates are different types. You could use an array of std.variant.Variant The elements are all of type Trait. However, Type itself might be of different types. That's why it is not possible? I've come across this restriction before when using templates, which is a big disappointment because it restricts the templatization / generalization of data structures somewhat. Trait is not a type. Trait is a template. An instantiation of the Trait template is a type. Arrays are contiguous, homogeneous data. This is fundamental to their design and their performance characteristics. Workarounds use at least one of the following: indirection, tagging* and padding. Variant uses tagging and padding. Interface/base-class arrays use indirection (and tagging, ultimately). *inline or external, or even compile-time. This is true in *every* programming language, just with different names. I thought the array T[] traits could hold any _type_ the template Trait is instantiated into. That's where I got it wrong. I understand the practical aspects of this restriction (homogeneous data, performance and the work around involved etc.). However, this makes templates less universal and rather cumbersome to work with in certain circumstances. Take for example the Person class. If I want to do numerical operations with the age of the person, I will have to convert the age to an int (or whatever) later on instead of just doing it once at the beginning (when loading data). So everytime I access Trait.map[age] I will have to convert it to a number before I can calculate anything. This, or I store it in a field of its own when instantiating Trait. Whatever workaround I choose it will make it less elegant and less simple. Maybe I expect(ed) to much of templates. Mea culpa.
Re: Template with template?
I thought the array T[] traits could hold any _type_ the template Trait is instantiated into. Different instantiations of a template could become totally unrelated types (heck, even things that are *not* types: function definitions, values, code blocks, ...). So there is now way for an array could hold them all, in general. At their core, templates are just parameterized code blocks, that become whatever strikes your fancy.
Re: Template with template?
On Thursday, 20 March 2014 at 19:38:25 UTC, Chris wrote: I thought the array T[] traits could hold any _type_ the template Trait is instantiated into. That's where I got it wrong. This is the best explanation for this restriction that I can think of: struct Person(T) { static if (is(T == int)) { int age; @property int age() { return age; } @property int age(int val) { return age = val; } @property bool isMiddleAge() { return age = 30 age = 50); } } else static if (is(T == string)) { string name; //Etc... } } Depending on what type T is, Person could have an age and associated methods, or a name and associated methods, but never both. If T is neither int nor string, it will completely empty. Therefore, Person!int MUST be a completely different type from Person!string or Person!float. It just doesn't make any sense otherwise.
Re: Template with template?
On Thursday, 20 March 2014 at 19:38:25 UTC, Chris wrote: On Thursday, 20 March 2014 at 18:54:30 UTC, John Colvin wrote: On Thursday, 20 March 2014 at 18:39:32 UTC, Chris wrote: On Thursday, 20 March 2014 at 17:49:52 UTC, John Colvin wrote: On Thursday, 20 March 2014 at 16:40:50 UTC, Chris wrote: On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir Panteleev wrote: On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote: How can I instantiate Person with Trait, i.e. a template with a template? struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person(T) { T traits[]; void addTrait(T trait) { traits ~= trait; } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); // above code compiles and works } Person!(Trait!(string, string)) person; -- or -- alias MyTrait = Trait!(string, string); Person!MyTrait person; Note that this approach won't let you have traits with different parameters within the same Person type. Yep, I've already tried this (sorry I should've mentioned it!). But I don't want this restriction. Arrays are homogeneous. All the elements must be of the same type. Different instantiations of templates are different types. You could use an array of std.variant.Variant The elements are all of type Trait. However, Type itself might be of different types. That's why it is not possible? I've come across this restriction before when using templates, which is a big disappointment because it restricts the templatization / generalization of data structures somewhat. Trait is not a type. Trait is a template. An instantiation of the Trait template is a type. Arrays are contiguous, homogeneous data. This is fundamental to their design and their performance characteristics. Workarounds use at least one of the following: indirection, tagging* and padding. Variant uses tagging and padding. Interface/base-class arrays use indirection (and tagging, ultimately). *inline or external, or even compile-time. This is true in *every* programming language, just with different names. I thought the array T[] traits could hold any _type_ the template Trait is instantiated into. That's where I got it wrong. I understand the practical aspects of this restriction (homogeneous data, performance and the work around involved etc.). However, this makes templates less universal and rather cumbersome to work with in certain circumstances. Take for example the Person class. If I want to do numerical operations with the age of the person, I will have to convert the age to an int (or whatever) later on instead of just doing it once at the beginning (when loading data). So everytime I access Trait.map[age] I will have to convert it to a number before I can calculate anything. This, or I store it in a field of its own when instantiating Trait. Whatever workaround I choose it will make it less elegant and less simple. Maybe I expect(ed) to much of templates. Mea culpa. Try this: import std.stdio; import std.variant; enum maxTraitSize = 64; struct Trait(T0, T1) { T0 name; T1 value; T1[T0] map; static assert(T0.sizeof + T1.sizeof + (T1[T0]).sizeof = maxTraitSize); this(T0 name, T1 value) { this.name = name; this.value = value; map[name] = value; } } class Person { alias ElT = VariantN!maxTraitSize; ElT[] traits; void addTrait(T)(T trait) if(is(T == Trait!Q, Q...)) { traits ~= ElT(trait); } } void main() { auto trait1 = Trait!(string, string)(Name, John); auto trait2 = Trait!(string, int)(Age, 42); writefln(%s, trait1.map); writefln(%s, trait2.map); auto p = new Person; p.addTrait(trait1); p.addTrait(trait2); writeln(p.traits); }