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.