ACCU: Wednesday, January 12 - Vlad Patryshev, Monads, Functors, Functions, Scala, and Java
When: Wednesday, January 12, 2011 Topic: Monads, Functors, Functions, Scala, and Java Speaker: Vlad Patryshev Time: 6:30pm doors open 7:00pm meeting begins Where: Symantec VCAFE building 350 Ellis Street (near E. Middlefield Road) Mountain View, CA 94043 Map: http://tinyurl.com/334rv5 Directions: VCAFE is next to the semicircular courtyard between Symantec buildings visible in the satellite view http://tinyurl.com/2dccgc Cost: Free More Info: http://www.accu-usa.org Monads are a popular buzzword, but the basic knowledge is missing. Let's fill the gaps. This talk is based on the online presentation at http://prezi.com/3yecwrcccpj-/monads-functors-functions-javascala/ Vlad was born in Russia, lived mostly in St.Petersburg, and came to this country in 1998. He's lived in California since, working as a software engineer at Borland, Google, and Tango.me. Meetings are open to the public and are free of charge. Upcoming ACCU talks - Wednesday, February 9, 2011 Hugh Williams A Tour of a Modern Search Engine Wednesday, March 9, 2011 Jason Evans Memory debugging with jemalloc after application deployment - The ACCU meets monthly. Meetings are always open to the public and are free of charge.
Re: memoize
Hi, I just wanted to say, it's funny how I did the *EXACT* same thing only **a few days ago**: http://stackoverflow.com/questions/245584/d-templates-coolest-hack/4437847#4437847 Not counting the braces, the actual code is just 4 lines for the compile-time version, and 5 lines for the run-time version. The page above only has a link to one of these; both of the versions are here: http://ideone.com/q8lvf Pretty short, eh? I doubt that it can get any shorter than that code. :) Feel free to use my version inside the library. (I hereby release the code to the public domain, to cover the legal stuff.)
Implicit Delayed DLL Loading?
Hi, I was wondering, is there a way to tell the compiler to implicitly delay-load a DLL, like you can with the /DELAYLOAD:DllName option in Visual C++? I was thinking that, if there isn't, it might be useful to extend the lazy keyword to cover functions (or maybe create a @delay or @lazy annotation), so as to tell the compiler to delay-load a function. This is very useful for coding, as delay-loading DLLs by hand becomes a pain when the number of functions increases to more than a handful. Thank you!
Re: memoize
Andrei: I just added a higher-order function memoize to std.functional which I think is pretty cool. See the docs here: I am not sure it's a good idea to put inside the D docs a link to the Google PDF visualizer. I suggest to remove the fact() example, because given the other fib() example, it adds nothing. Or if you want to keep it, you may differentiate it, showing something different, like putting the alias outside (and renaming the function). The maxSize parameter is a cutoff for the cache size. If upon a miss the length of the hash table is found to be maxSize, the table is simply cleared. Two alternatives I'd like better: 1) The simpler alternative: when maxSize!=uint.max the associative array values are linked in a singly linked list. When there's a cache miss and aa.length maxSize then the last item of the linked list is removed (there is a pointer to the last item that gets updated to the penultimate). 2) A bit more complex: when maxSize!=uint.max the associative array values are linked in a singly linked list. If the requested key is present, its value moves to the head of the doubly linked list. If it's not present, it's added at the head of the linked list. If aa.length maxSize then the last item of the linked list is removed (a simple LRU implementation). A Python version: http://code.activestate.com/recipes/498110-memoize-decorator-with-o1-length-limited-lru-cache/ Of course I have written a memoize myself: http://code.activestate.com/recipes/466320-another-memoize/ Python has function decorators, so there's no need to change the name of memoized functions nor to change the function contents. Bye, bearophile
Re: Dynamic D
On 1/4/2011 12:23 AM, Adam Ruppe wrote: Over the weekend, I attacked opDispatch again and found some old Variant bugs were killed. I talked about that in the Who uses D thread. Today, I couldn't resist revisiting a dynamic kind of object, and made some decent progress on it. http://arsdnet.net/dcode/dynamic.d (You can compile that; there's a main() at the bottom of that file) It isn't quite done - still needs op overloading, and probably better errors, but it basically works. It works sort of like a Javascript object. Features: opDispatch and assignment functions: Dynamic obj; // assign from various types obj = 10; obj = string; obj.a = 10; // assign properties from simple types naturally // can set complex types with one compromise: the () after the // property tells it you want opAssign instead of property opDispatch obj.a() = { writefln(hello, world); } // part two of the compromise - to call it with zero args, use call: obj.a.call(); // delegte with arguments works too obj.a() = delegate void(string a) { writeln(a); }; // Calling with arguments works normally obj.a(some arguments, 30); Those are just the basics. What about calling a D function? You need to convert them back to regular types: string mystring = obj.a.as!string; // as forwards to Variant.coerce // to emulate weak typing Basic types are great, but what about more advanced types? So far, I've implemented interfaces: interface Cool { void a(); } void takesACool(Cool thing) { thing.a(); } takesACool(obj.as!Cool); // it creates a temporary class implementing // the interface by forwarding all its methods to the dynamic obj I can make it work with structs too but haven't written that yet. I want to add some kind of Javascript like prototype inheritance too. I just thought it was getting kinda cool so I'd share it :) To cool! I remember trying to do the same for D1 for my Hessian lib, but you hit the spot here. This is a great little start for easy RPC proxy creation and for interoperability with COM and others. Great work!
Re: Hooking the GC?
On Tue, 04 Jan 2011 01:06:39 +0200, %u wfunct...@hotmail.com wrote: It doesn't have to be at run-time, I can add code to the GC too. So _d_newclass would be *almost* what I'm looking for, except that it doesn't work for memory allocated using GC.malloc()... so I'd have to hook in multiple places I guess. Thanks for the info. _d_newclass invokes the GC's malloc downstream. It's just that at _d_newclass, you know the class typeinfo being allocated. -- Best regards, Vladimirmailto:vladi...@thecybershadow.net
Coccinelle
Sometimes D changes, and this requires many simple changes in Phobos. In such and other cases to save some time I suggest D developers (Walter too) to take a look at the free Coccinelle tool: http://coccinelle.lip6.fr/ I think Coccinelle works on D code too (untested). It allows to define safe semantic patches, that despite being very short, are able to patch lot of code in seconds. Coccinelle looks useful for DMD/druntime too. Bye, bearophile
Re: Implicit Delayed DLL Loading?
On Tue, 04 Jan 2011 11:03:45 +0200, %u wfunct...@hotmail.com wrote: I was wondering, is there a way to tell the compiler to implicitly delay-load a DLL, like you can with the /DELAYLOAD:DllName option in Visual C++? Well, first of all DELAYLOAD is a linker option, and it doesn't look like OPTLINK supports it. You could have a look at how Derelict loads and binds entire APIs (e.g. SDL) at runtime. -- Best regards, Vladimirmailto:vladi...@thecybershadow.net
Re: Implicit Delayed DLL Loading?
I think Derelict loads the DLLs at load time, before the call to main() (I could be wrong here). Delayed loading is when a DLL is imported at runtime when there's an actual call made that requires the DLL, it doesn't get preloaded at load time. On 1/4/11, Vladimir Panteleev vladi...@thecybershadow.net wrote: On Tue, 04 Jan 2011 11:03:45 +0200, %u wfunct...@hotmail.com wrote: I was wondering, is there a way to tell the compiler to implicitly delay-load a DLL, like you can with the /DELAYLOAD:DllName option in Visual C++? Well, first of all DELAYLOAD is a linker option, and it doesn't look like OPTLINK supports it. You could have a look at how Derelict loads and binds entire APIs (e.g. SDL) at runtime. -- Best regards, Vladimirmailto:vladi...@thecybershadow.net
Re: GC works with malloc() works, but throws out of memory with HeapAlloc(). Why?
On Tue, 04 Jan 2011 01:12:53 +0200, %u wfunct...@hotmail.com wrote: I've recompiled the code for my library to redirect all calls to malloc(), free(), realloc(), and calloc() to HeapAlloc(), HeapFree(), and HeapReAlloc(). Sorry, do you mean the libc functions? The GC doesn't use those to allocate its memory pools, and uses page allocation functions (mmap on *nix and VirtualAlloc on Windows). If you mean the GC functions, then wouldn't your hooked malloc be called before mallocNoSync is called? -- Best regards, Vladimirmailto:vladi...@thecybershadow.net
Re: Hooking the GC?
_d_newclass invokes the GC's malloc downstream. It's just that at _d_newclass, you know the class typeinfo being allocated. Ohh I see, okay, thank you!
Re: GC works with malloc() works, but throws out of memory with HeapAlloc(). Why?
Sorry, do you mean the libc functions? The GC doesn't use those to allocate its memory pools, and uses page allocation functions (mmap on *nix and VirtualAlloc on Windows). If you mean the GC functions, then wouldn't your hooked malloc be called before mallocNoSync is called? I actually found the error (after 8 hours of searching); it was because HeapReAlloc wasn't calling HeapAlloc if the passed pointer was null, the way realloc() is supposed to. Thank you for your reply though!
Re: Implicit Delayed DLL Loading?
On Tue, 04 Jan 2011 12:44:07 +0200, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: I think Derelict loads the DLLs at load time, before the call to main() (I could be wrong here). Delayed loading is when a DLL is imported at runtime when there's an actual call made that requires the DLL, it doesn't get preloaded at load time. Technically you have to ask Derelict to load a DLL explicitly, like this: DerelictSDL.load(); Anyway, it shouldn't be hard to implement real delayed loading on top of SDL's methods. In fact, you could even enumerate all function variables at the module level, and generate delay-loading code at compile time. This way you only need to mention any specific DLL function once. -- Best regards, Vladimirmailto:vladi...@thecybershadow.net
Re: Is this a viable effort? The DRY principle, community-wide
On 04.01.2011 7:30, Guilherme Vieira wrote: I may sound daring or even foolish proposing this, but here goes nothing.. one of the things that bothers me about software development is that people always tell you not to reinvent the wheel, but the libraries available are generally not fine-grained enough, so you end up either using overkill solutions to ridiculously small problems or actually reinventing the wheel. For example, what do you do if you want to create a window just for use with OpenGL in a cross-platform way? You have to write different versions of the window creation procedure for the different systems you're targeting. Or you could use SDL, but if you really just want the window that's a waste. Right? For that particular case GLUT may fit just fine. Or GLAux. At times like this I wish people would really break their code in smaller parts in a way you could really just pick what you want from it. Dependencies are the main problem here I think. E.g. library A fit the bill but uses it's own matrices lib B and quaternions lib C and so on. And what's worse quite another useful library D has it's own set of reinvented wheels. In such cases you can tear down library in small pieces but then you'd have to resolve dependencies. So I thought, since D has such a compact community and the codebase is still small, maybe you would like to attack the problem (dunno if many will agree with me this is a problem, but then I'd like to know what they do in the case I described) together. I'd like to propose a community-written, community-reviewed hierarchy of modules anybody could (and should :)) contribute to. Necessities would be factored and layered before entering the actual hierarchy, though. Sounds a lot like std lib. Maybe an incubator project for Phobos? (was discussed sometime ago) Also check scrapple on Dsource. For example, right now I really wanted a cross-platform way of using OpenGL. AFAIK, OpenGL usage is normalized across many systems and only its initialization is platform-depedent (to begin with, there's WGL, GLX and AGL; plus, you have very different ways of creating windows in those systems, so you need to do a lot of work to really use OpenGL in a cross-platform manner). I would then engage into writing what's needed and, when done, I would send it for the community to review. The modules would be fragmented, trying not to compromise its usability in any possible use-case. The core notion here is that D libraries could be the community's, not the author's. I wonder if merging people's efforts can be a good idea. I mean, you would avoid reinventing the wheel, you would avoid having many libraries doing the same thing with different interfaces, essentially making two user-libraries, each using one of the first ones, incompatible when in a perfect world they really shouldn't be, etc.. The only problem with it : people still can't invent the best way to do something, plus the matter of taste. Two libraries no problem, two big frameworks - bound to be incompatible and overkill for most uses. So, what do you think? * Is it viable? * Would it be useful? Yup ! :) * Improvements? May be require the modules in this hierarchy to reduce cross-dependency unless absolutely needed? What I would like is D2 reconnaissance project i.e. maintain a list of all actively developed D2 projects. -- Dmitry Olshansky
Re: Coccinelle
bearophile wrote: Sometimes D changes, and this requires many simple changes in Phobos. In such and other cases to save some time I suggest D developers (Walter too) to take a look at the free Coccinelle tool: http://coccinelle.lip6.fr/ I think Coccinelle works on D code too (untested). It allows to define safe semantic patches, that despite being very short, are able to patch lot of code in seconds. Coccinelle looks useful for DMD/druntime too. Bye, bearophile OT: the picture with the ninja turtle reference and tux bashing a bug is hilarious, just need a D man to join the party!
Re: D without a GC
On 04.01.2011 6:42, Christopher Bergqvist wrote: Would std.typecons.scoped!(T) fit? http://svn.dsource.org/projects/phobos/trunk/phobos/std/typecons.d I can't figure out why it's not in the generated reference docs, but exists in the source. Maybe it hasn't been tested enough yet. First of all it's main purpose was allocating class instances on stack. Second the way it's implemented the size should be known at compile-time. And yes, it's still somewhat experimental and has some issues. As for stackAllocate!(T)(n). It should be mixin, since function can't return it's alloca'ed blocks, plus this allows all forms of clean up to be embedded in the same mixin with scope(exit){ __dtor(...); } On 3 Jan 2011, at 15:33, Ulrik Mikaelssonulrik.mikaels...@gmail.com wrote: 2011/1/3 Iain Buclawibuc...@ubuntu.com: == Quote from bearophile (bearophileh...@lycos.com)'s article Dmitry Olshansky: As stated in this proposal they are quite useless, e.g. they are easily implemented via mixin with alloca. Thank you for your comments. Here I have added some answers to your comments: http://d.puremagic.com/issues/show_bug.cgi?id=5348 Bye, bearophile Some thoughts to your proposal: void bar(int len) { Foo* ptr = cast(Foo*)alloca(len * Foo.sizeof); if (ptr == null) throw new Exception(alloca failed); Foo[] arr = ptr[0 .. len]; foreach (ref item; arr) item = Foo.init; // some code here writeln(arr); foreach (ref item; arr) item.__dtor(); } 1) Why call the dtors manually? Forgive me if I'm wrong, but iirc, alloca will free the memory when the stack exits from the current frame level. :) The dtor doesn't free memory, it allows the class to perform cleanup on destruction, such as close():ing any native FD:s etc. Actually, AFAICT, the above code should also after item=Foo.init call item.__ctor(), to allow the constructor to run. IMHO, stdlibs should provide wrappers for this type of functionality. An application-writer should not have to know the intricate details of __ctor and __dtor as opposed to memory-mangement etc. A template stackAllocate!(T) would be nice. -- Dmitry Olshansky
Re: memoize -- AAs don't work for ubyte[4] keys
On Mon, 03 Jan 2011 23:27:22 -0600 Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Nevertheless, I found two issues: one, ParameterTypeTuple doesn't work for overloaded functions, and associative arrays don't work for ubyte[4] keys... still a ways to go. Could you or someone else expand on this? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
About some bugs
I have studied more Linux bugs. An example of bug (more than 14 like this fixed in few years): - memset(pp, 0, sizeof(pp)); + memset(pp, 0, sizeof(*pp)); - memcpy((caddr_t)TstSchedTbl, (caddr_t)vcIndex,sizeof(TstSchedTbl)); + memcpy((caddr_t)TstSchedTbl, (caddr_t)vcIndex, sizeof(*TstSchedTbl)); Here the type system knows that pp is a pointer. sizeof(pp) is typically a word, while the correct sizeof(*pp) is often larger. A simple way to avoid this bug in D is to use a zerioing template function, something like (untested) (in GNU C there is a way to write a similar macro, I don't know why they don't use it, even if it's a bit less safe and much less nice looking): void zeroit(T)(T* ptr) if (!IsPointer!T) { memset(ptr, 0, (*ptr).sizeof); } Standard safer wrappers for some C functions may help low-level D coding. If you don't want to use a zeroit() then a type system able to catch such bugs needs some nice annotations... A common ( 12 cases in few years) example of redundant code: u32 da = new-da_start; - if (!obj || !new || !sgt) {... + if (!obj || !sgt) {... If the first line is correct, then new can't be NULL, so there's no need to test || !new. In 13 similar cases the code is inside a branch where the NULL test of the pointer is already done: if (ptr != NULL) { if (!ptr) { ... } In 7 cases the result of malloc-like function was not tested for NULL: agp = kmalloc(sizeof(*agp), GFP_KERNEL); + if (!agp) + return NULL; A very common case (20 cases in few years) are like this, where a pointer is deferenced before the NULL test: block = bdev-bd_disk-private_data; - base = block-base; if (!block) return -ENODEV; + base = block-base; 2 cases like this (the pattern (!E !E-fld) is nonsensical): - if (!slot-hotplug_slot !slot-hotplug_slot-info) + if (!slot-hotplug_slot || !slot-hotplug_slot-info) continue; There are 11 cases like this (alloc_bootmem never returns NULL and it always sets the momory to zero): zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0), PAGE_SIZE); - memset(zero_page, 0, PAGE_SIZE); There are a lot of cases (34) of missing free: + kfree(iter); Two cases need a wider NULL test: - if (fep != NULL) { + if (fep fep-ops) { (*fep-ops-free_bd)(ndev); (*fep-ops-cleanup_data)(ndev); } In this post I don't see any little rule worth adding to the D compiler. So to bugzilla I will add only the !xy thing. But from what I have seen many bugs are NULL-related, and many of them are avoidable with two features present at the same time in the language: 1) Nonnull pointer/reference tag (with it you don't miss some null tests, and you avoid some redundant tests); 2) Plus a bit of inter-function (not intra, for that nonnull signatures are enough) flow analysis to avoid bugs like: base = block-base; if (!block) return -ENODEV; if (fep != NULL) { (*fep-ops-free_bd)(ndev); (P.S.: integer overflow bugs happen in Linux kernel too.) Bye, bearophile
Re: Less commas
Walter: This is great stuff, bearophile. Thanks for finding that. Please add this as an enhancement request to bugzilla (disallowing (!xy) expressions). http://d.puremagic.com/issues/show_bug.cgi?id=5409 Bye, bearophile
Re: Is this a viable effort? The DRY principle, community-wide
On Tue, 4 Jan 2011 02:30:24 -0200 Guilherme Vieira n2.nitro...@gmail.com wrote: At times like this I wish people would really break their code in smaller parts in a way you could really just pick what you want from it. I guess this is a dream generations of programmers, language designers and computer scientist have run after. Say, Lego programming. Bulding bricks which are _really_ autonomous. Maybe there is a flaw in the implicite reasoning behind that vision: as a client, one wants the (library) building blocks they use to be autonomous, right; but at a higher-level the software one is designing is precisely using other software, thus creating a system of dependancies... which makes this new piece of code unusable in an autonomous manner by yet another client who would enjoy reusing it as a brick. The same applies to the (library) bricks: they have to use other building blocks which prevent them to be autonomous. This is how I see the point. And it gets even more unavoidable because of generality. For a brick to have any chance to meet one client's needs it must be as general/abstract as possible. This means for instance abstract away issues of OS idiosyncrasies, actual types, sizes and loads of other annoying aspects, think at how write*, map, or file opening work. To do this, using yet another bunch of tools is often necessary. The more a brick gets general and thus useful, the more chances it has _not_ to be autonomous. I guess. This, to the point that if Phobos (2) would be rewritten from scratch using everywhere D2's newer style (more general/abstract, as I see it), most of its modules would import a load of other modules such as algorithm, contracts, functional, range, possibly type*, traits, variant; which themselves import... I don't logically there can be a solution. I would like to try to define a minimal subset D lib functionality, say the standard toolkit. (I have one for my personal, a dozen elements systematically imported, and most commonly actually used, in every of my modules.) Then, make this a kind of auto-import (à la python) for user code, except if other wise stated; and see if it's enough, overkill, whatever. Then, struggle to make (other) lib modules depend on these toolkit elements, and only and them, as much as possible. (Even when it's not the best design/code solution.) Could such an approach work? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: memoize
On 1/4/11 12:30 AM, Guilherme Vieira wrote: Is there really need for ParameterTypeTuple? I figured this works: template memoize(alias fun, uint maxSize = uint.max) { auto memoize(Args...)(Args args) [snip] That would create several caches, depending on calls with convertible arguments. Andrei
Re: About some bugs
On Tue, 04 Jan 2011 07:34:15 -0500 bearophile bearophileh...@lycos.com wrote: An example of bug (more than 14 like this fixed in few years): - memset(pp, 0, sizeof(pp)); + memset(pp, 0, sizeof(*pp)); - memcpy((caddr_t)TstSchedTbl, (caddr_t)vcIndex,sizeof(TstSchedTbl)); + memcpy((caddr_t)TstSchedTbl, (caddr_t)vcIndex, sizeof(*TstSchedTbl)); Here the type system knows that pp is a pointer. sizeof(pp) is typically a word, while the correct sizeof(*pp) is often larger. A simple way to avoid this bug in D is to use a zerioing template function, something like (untested) (in GNU C there is a way to write a similar macro, I don't know why they don't use it, even if it's a bit less safe and much less nice looking): void zeroit(T)(T* ptr) if (!IsPointer!T) { memset(ptr, 0, (*ptr).sizeof); } Doesn't this in fact hide the error to the programmer (by silently correcting)? Why not instead for instance: void zeroit(T)(T* ptr) if (!IsPointer!T) { throw new Exception(Type error: argument to funcname should be a pointer.); } (And what if the memory to be actually memset is not ptr's target?) About non-null thingies, I would be all for a mode in which is inserted if (p is null) throw ...; before _every_ implicite or explicite deref of every implicite (pointer) or implicite (class element) pointer. And even make this the default for non-release. (With line number in the message ;-) Am I dreaming? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: About some bugs
spir denis.s...@gmail.com wrote: void zeroit(T)(T* ptr) if (!IsPointer!T) { memset(ptr, 0, (*ptr).sizeof); } Doesn't this in fact hide the error to the programmer (by silently correcting)? No. It ensures that the pointer and size are from the same pointer. I would say it is somewhat analogous to D's arrays, which are a hell of a lot better than free pointer/length pairs. Why not instead for instance: void zeroit(T)(T* ptr) if (!IsPointer!T) { throw new Exception(Type error: argument to funcname should be a pointer.); } I'm not sure this makes sense. The error message seems to indicate you don't have a pointer, while that is exactly what you do. The template constraint also say that this is not an overload of the above function, making it simply a function that throws. (And what if the memory to be actually memset is not ptr's target?) If people start throwing random pointers into functions, that is a problem that's hard to work around. bearophile's zeroit function takes memset and removes its main weak point, namely that it takes a free pointer/length pair, rather than a structure containing the two. About non-null thingies, I would be all for a mode in which is inserted if (p is null) throw ...; before _every_ implicite or explicite deref of every implicite (pointer) or implicite (class element) pointer. And even make this the default for non-release. (With line number in the message ;-) Am I dreaming? Yeah. :P Much more likely would be the idea that has been discussed, of opt-in non-nullness, by disabling the default constructor for a struct that wraps a pointer. -- Simen
Re: memoize
On 1/4/11 2:48 AM, %u wrote: Hi, I just wanted to say, it's funny how I did the *EXACT* same thing only **a few days ago**: http://stackoverflow.com/questions/245584/d-templates-coolest-hack/4437847#4437847 Not counting the braces, the actual code is just 4 lines for the compile-time version, and 5 lines for the run-time version. The page above only has a link to one of these; both of the versions are here: http://ideone.com/q8lvf Pretty short, eh? I doubt that it can get any shorter than that code. :) Feel free to use my version inside the library. (I hereby release the code to the public domain, to cover the legal stuff.) Wow. I swear I didn't see this! Great minds think alike eh? :o) I think your implementation that defines the function directly is better. However, when we plan to make the whole thing work with overloading, we'll probably want to go with the template solution. BTW, right now ParameterTypeTuple catches the lexically first overload or something. Instantiating memoize!sqrt latches on sqrt(float). We need to generalize ParameterTypeTuple to work with overloaded functions. This is where implicit flattening of tuples is going to turn a bit troublesome. Andrei
Re: memoize
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 1/4/11 12:30 AM, Guilherme Vieira wrote: Is there really need for ParameterTypeTuple? I figured this works: template memoize(alias fun, uint maxSize = uint.max) { auto memoize(Args...)(Args args) [snip] That would create several caches, depending on calls with convertible arguments. Andrei So the solution should use a struct with overloaded opCall, then. -- Simen
Re: memoize
Guilherme Vieira n2.nitro...@gmail.com wrote: @Walter: would it be hard/impossible for the compiler to look at memoize and tell it exhibits pure behavior and is, thus, pure? The simplest solution is this: template memoize( alias fn ) { static if ( isPure!fn ) { pure auto memoize( ParameterTypeTuple!fn ) { // Blah! } } else { auto memoize( ParameterTypeTuple!fn ) { // Blah! } } } -- Simen
Re: memoize -- AAs don't work for ubyte[4] keys
On 1/4/11 6:32 AM, spir wrote: On Mon, 03 Jan 2011 23:27:22 -0600 Andrei Alexandrescuseewebsiteforem...@erdani.org wrote: Nevertheless, I found two issues: one, ParameterTypeTuple doesn't work for overloaded functions, and associative arrays don't work for ubyte[4] keys... still a ways to go. Could you or someone else expand on this? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com An example in Higher Order Perl is memoizing a RGB to CMYK function: ubyte[4] rgb2cmyk(ubyte[3] rgb) { ubyte[4] result = void; result[0] = cast(ubyte)(255 - rgb[0]); result[1] = cast(ubyte)(255 - rgb[1]); result[2] = cast(ubyte)(255 - rgb[2]); result[3] = min(result[0], result[1], result[2]); result[0] -= result[3]; result[1] -= result[3]; result[2] -= result[3]; return result; } Trying to memoize this yields a range error at runtime. Andrei
Re: memoize
On 1/4/11 7:54 AM, Simen kjaeraas wrote: Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 1/4/11 12:30 AM, Guilherme Vieira wrote: Is there really need for ParameterTypeTuple? I figured this works: template memoize(alias fun, uint maxSize = uint.max) { auto memoize(Args...)(Args args) [snip] That would create several caches, depending on calls with convertible arguments. Andrei So the solution should use a struct with overloaded opCall, then. 1. I think it's best to map a function to a function for best impedance match. 2. If you memoize an overloaded function, you _do_ want several caches. Andrei
Re: memoize
On 1/4/11 7:59 AM, Simen kjaeraas wrote: Guilherme Vieira n2.nitro...@gmail.com wrote: @Walter: would it be hard/impossible for the compiler to look at memoize and tell it exhibits pure behavior and is, thus, pure? The simplest solution is this: template memoize( alias fn ) { static if ( isPure!fn ) { pure auto memoize( ParameterTypeTuple!fn ) { // Blah! } } else { auto memoize( ParameterTypeTuple!fn ) { // Blah! } } } I've been mulling over this for a while, maybe it's time to start discussing it. Often you want to say this entity is pure/const/immutable/safe... if this other entity is the same, or generally if this Boolean is true. So I was thinking of introducing e.g. a constrained pure: template memoize( alias fn ) { pure(isPure!fn) auto memoize( ParameterTypeTuple!fn ) { ... } } So generally when you write attribute(expression) the attribute will be in effect if and only if the expression is true. D has become very powerful at introspecting most of its own abstractions in the form of compile-time Booleans. This language extension would close the circle by allowing D to introduce attributes and qualifiers depending on compile-time Booleans. Andrei
Re: memoize
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: 2. If you memoize an overloaded function, you _do_ want several caches. Yeah. Even I managed to think about that a few seconds after posting. :p -- Simen
Re: memoize
On 1/4/11 2:48 AM, %u wrote: Hi, I just wanted to say, it's funny how I did the *EXACT* same thing only **a few days ago**: http://stackoverflow.com/questions/245584/d-templates-coolest-hack/4437847#4437847 Not counting the braces, the actual code is just 4 lines for the compile-time version, and 5 lines for the run-time version. The page above only has a link to one of these; both of the versions are here: http://ideone.com/q8lvf Pretty short, eh? I doubt that it can get any shorter than that code. :) Feel free to use my version inside the library. (I hereby release the code to the public domain, to cover the legal stuff.) Just posted a response to that thread, too. Somehow all that thread should spill into reddit :o). One thing one figures by looking at that thread is not what's been done, but how much bigger the potential is. Andrei
Re: Dynamic D
Very cool! The restriction with calling zero-args functions is unfortunate, could this be solved by turning it into a class and dynamically checking whether the type is a function and then invoke it if it is? I would also change implicit declarations into an error, I see you have an throw statement for that but commented out.
Re: About some bugs
Vladimir Panteleev: Doesn't D already solve this? Yup. block = bdev-bd_disk-private_data; - base = block-base; if (!block) return -ENODEV; + base = block-base; Delphi compilers warn in cases when a condition is always true/false, because Delphi lacks metaprogramming so such cases are usually due to a bug. This is a different situation. You need a bit of flow analisys to catch this bug (to give a state to a type). Bye, bearophile
Re: memoize
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 1/4/11 2:48 AM, %u wrote: Hi, I just wanted to say, it's funny how I did the *EXACT* same thing only **a few days ago**: http://stackoverflow.com/questions/245584/d-templates-coolest-hack/4437847#4437847 Not counting the braces, the actual code is just 4 lines for the compile-time version, and 5 lines for the run-time version. The page above only has a link to one of these; both of the versions are here: http://ideone.com/q8lvf Pretty short, eh? I doubt that it can get any shorter than that code. :) Feel free to use my version inside the library. (I hereby release the code to the public domain, to cover the legal stuff.) Just posted a response to that thread, too. Somehow all that thread should spill into reddit :o). I took the liberty of spilling it: http://www.reddit.com/r/programming/comments/ew0c7/coolest_template_metaprogramming_tricks_in_d/ -- Simen
Re: Dynamic D
Lutger Blijdestijn wrote: The restriction with calling zero-args functions is unfortunate, could this be solved by turning it into a class and dynamically checking whether the type is a function and then invoke it if it is? Maybe, but I think it'd still break the property get, which breaks setting complex types. This, and your other concern about implicit declarations are actually caused by the same root problem: the imperfect compiler implementation of properties combined with variadic opDispatch templates. (Like I said in that other thread, each of those features works quite well on its own, but the combination reveals some minor bugs.) To set a complex type, you do the: dyn.property() = some fancy thing; Which returns a property by reference, then does its opAssign template, which is much more capable of fanciness than the runtime variadic function you get without the parenthesis. Why do that? Because overloading on property and non-property doesn't work right now. Through trial and error, I found the compiler doesn't add a property assignment's type to the template argument list, but does pass it as a func argument. (Quite possibly a (minor) compiler bug itself - I may be depending on one bug to work around another!) So, if you try to do a template, it will complain about wrong number of arguments to the function. A variadic function gets that error to go away and I can handle it at runtime. This comes with trade-offs though: the big one being that it doesn't work with complex types. Like the code's comment says, I really need the compiler's help to make them work, and it isn't around by the time any of that code is actually run. The best situation would be: @property Dynamic opDispatch(string fieldName)() // getter Dynamic opDispatch(string fieldName, T...)(T t) // function call, // any num of args @property Dynamic opDispatch(string fieldName, T)(T t) // setter Then everything would Just Work, without the limitations of the runtime variadic and associated workarounds. But the first two are broken by @property not being recognized in overloads currently*, and the last is broke by the right-hand side of the property assignment not being passed as a template argument. * My preferred fix here would be to give @property one more point in overload resolution so it is slightly preferred over non-property in these situations, but otherwise do nothing. It's the most conservative solution here. I looked at dmd's code, but I don't know the compiler well enough to make it happen. I guess if @property was strengthened, I could work with that too, just by adding an opCall and leaving opDispatch to do nothing but get and set. The property assign not being passed to the template would have to be solved somehow there too though. Anyway, none of the fixes are in place today, so I had to make a choice - either setting requires a named function call or zero arg calling requires a named function. I went with the latter since I figured it is a bit prettier in usage. I would also change implicit declarations into an error, I see you have an throw statement for that but commented out. Yes, the main reason is so the ref returns don't do range violation when you are trying to do an assignment, due to the above situation. It would work with simple assignment: dynobj.name; // throws dynobj.name = 10; // works dynobj.name; // still works But complex assignment won't work there: dynobj.name = someDelegate; // this won't work right, probably // will segfault down the line if I don't throw at runtime over it So my compromise was: dynobj.name() = someDelegate; // uses the opAssign template // which works well But... if dynobj.name didn't already exist, the left hand side of that would throw a range violation, getting a property that doesn't exist. That's why the exception is commented. If I required a .set() method or something like that: dynobj.set(name, whatever you want); That would work, but it no longer looks like a dynamic language... When the compiler progresses a little more (or maybe someone will think of a nicer workaround), we can have the best of all worlds, but for now this is the best I can do while keeping a mostly dynamic language like appearance. (Now, a related question here is weak typing in general. I'm writing this to be very weakly typed - coercing all over the place. Dynamic languages can throw a runtime exception on type mismatch, but I want to basically mimic javascript here, which does not. Besides, D itself is strongly typed - if you want strong types, just use standard D types! Possibly including std.variant.)
Re: About some bugs
Simen kjaeraas: Much more likely would be the idea that has been discussed, of opt-in non-nullness, by disabling the default constructor for a struct that wraps a pointer. I am not sure that's enough. Bye, bearophile
Meaning of .clear() for containers
Answering a question over on stack overflow I realized that clear() has 2 meanings. TDPL says that clear should be used to free resources of the object and place the object into an invalid state. That is failure can occur but memory corruption is prevent, similar to null for pointer types. However for container types clear() is used to empty the container. It is still valid to use the container after calling clear(), but the definition from TDPL suggest that this can not be expected.
Re: memoize
Andrei: So generally when you write attribute(expression) the attribute will be in effect if and only if the expression is true. It looks acceptable. Many solutions are better than the current need to duplicate code :-) Regarding the purity of memoize, a kind of compiler-blessed built-in memoization for pure functuions allows pure memoization... (It is a trusted pure, where the trusted entity is the compiler) Bye, bearophile
Re: memoize -- AAs don't work for ubyte[4] keys
Andrei Alexandrescu wrote: return result; Since when is it legal to return a local array? -manfred
Re: Meaning of .clear() for containers
On Tue, 04 Jan 2011 11:53:59 -0500, Jesse Phillips jessekphillip...@gmail.com wrote: Answering a question over on stack overflow I realized that clear() has 2 meanings. TDPL says that clear should be used to free resources of the object and place the object into an invalid state. That is failure can occur but memory corruption is prevent, similar to null for pointer types. However for container types clear() is used to empty the container. It is still valid to use the container after calling clear(), but the definition from TDPL suggest that this can not be expected. clear as a global function is for destroying a class/struct clear as a member can do anything. clear is not a keyword. clear(container) - same as delete container, but without freeing any memory. container.clear() - remove all elements This has been brought up before as a problem, I'm not sure it's that terrible, but I can see why there might be confusion. -Steve
Re: memoize
On 2011-01-04 12:53:43 -0500, bearophile bearophileh...@lycos.com said: Regarding the purity of memoize, a kind of compiler-blessed built-in memoization for pure functuions allows pure memoization... (It is a trusted pure, where the trusted entity is the compiler) One could even argue that memoize makes impure functions pure because as long as you don't clear the cache, memoize!func is guarantied to return the same value for the same arguments. -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: memoize -- AAs don't work for ubyte[4] keys
Manfred_Nowak svv1...@hotmail.com wrote in message news:xns9e63c3202449bsvv1999hotmail...@65.204.18.192... Andrei Alexandrescu wrote: return result; Since when is it legal to return a local array? Since D2, if it's a static array (as result is): Static arrays are value types. Unlike in C and D version 1, static arrays are passed to functions by value. Static arrays can also be returned by functions. - http://www.digitalmars.com/d/2.0/arrays.html#static-arrays
Re: memoize -- AAs don't work for ubyte[4] keys
On 1/4/11 12:13 PM, Manfred_Nowak wrote: Andrei Alexandrescu wrote: return result; Since when is it legal to return a local array? -manfred Since a few releases ago fixed-size arrays are value types. Andrei
Re: memoize
Michel Fortin michel.for...@michelf.com wrote in message news:ifvo9g$2d5...@digitalmars.com... On 2011-01-04 12:53:43 -0500, bearophile bearophileh...@lycos.com said: Regarding the purity of memoize, a kind of compiler-blessed built-in memoization for pure functuions allows pure memoization... (It is a trusted pure, where the trusted entity is the compiler) One could even argue that memoize makes impure functions pure because as long as you don't clear the cache, memoize!func is guarantied to return the same value for the same arguments. ...until maxSize is exceeded and the cache is cleared.
Re: memoize
On 1/4/11 12:27 PM, Nick Sabalausky wrote: Michel Fortinmichel.for...@michelf.com wrote in message news:ifvo9g$2d5...@digitalmars.com... On 2011-01-04 12:53:43 -0500, bearophilebearophileh...@lycos.com said: Regarding the purity of memoize, a kind of compiler-blessed built-in memoization for pure functuions allows pure memoization... (It is a trusted pure, where the trusted entity is the compiler) One could even argue that memoize makes impure functions pure because as long as you don't clear the cache, memoize!func is guarantied to return the same value for the same arguments. ...until maxSize is exceeded and the cache is cleared. Even before that. There may be a visible difference between the first invocation and all others. Andrei
Re: memoize
On 1/3/2011 11:15 PM, Andrei Alexandrescu wrote: I just added a higher-order function memoize to std.functional which I think is pretty cool. See the docs here: http://d-programming-language.org/cutting-edge/phobos/std_functional.html#memoize I'm also thinking of adding that cutting-edge directory as a place for storing documentation for commits that are in flux but not officially released yet. Andrei If it's helpful to anyone, Yage has a similar D1 function called Cache: http://dsource.org/projects/yage/browser/trunk/src/yage/core/cache.d
Re: memoize
If it's helpful to anyone, Yage has a similar D1 function called Cache: http://dsource.org/projects/yage/browser/trunk/src/yage/core/cache.d I almost forgot about licensing. I release this module under public domain or Boost 1.0, whichever is preferred.
Re: memoize -- AAs don't work for ubyte[4] keys
Andrei Alexandrescu wrote: Since a few releases ago upps. sorry for not reading the docs. -manfred
Re: memoize
Nick Sabalausky: ...until maxSize is exceeded and the cache is cleared. Clearing the whole cache when it's full is a brutal behaviour, I don't like it. See here for something better: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=126059 Bye, bearophile
Re: Meaning of .clear() for containers
Steven Schveighoffer wrote: On Tue, 04 Jan 2011 11:53:59 -0500, Jesse Phillips jessekphillip...@gmail.com wrote: Answering a question over on stack overflow I realized that clear() has 2 meanings. TDPL says that clear should be used to free resources of the object and place the object into an invalid state. That is failure can occur but memory corruption is prevent, similar to null for pointer types. However for container types clear() is used to empty the container. It is still valid to use the container after calling clear(), but the definition from TDPL suggest that this can not be expected. clear as a global function is for destroying a class/struct clear as a member can do anything. clear is not a keyword. clear(container) - same as delete container, but without freeing any memory. container.clear() - remove all elements This has been brought up before as a problem, I'm not sure it's that terrible, but I can see why there might be confusion. Uniform function call syntax? Jerome -- mailto:jeber...@free.fr http://jeberger.free.fr Jabber: jeber...@jabber.fr signature.asc Description: OpenPGP digital signature
Re: memoize
On 1/4/11 12:54 PM, bearophile wrote: Nick Sabalausky: ...until maxSize is exceeded and the cache is cleared. Clearing the whole cache when it's full is a brutal behaviour, I don't like it. See here for something better: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=126059 Bye, bearophile There is a difference between caching and memoization. I wouldn't want to burden the memoization implementation with LRU management. Andrei
Re: Meaning of .clear() for containers
On Tue, 04 Jan 2011 13:58:02 -0500, Jérôme M. Berger jeber...@free.fr wrote: Steven Schveighoffer wrote: On Tue, 04 Jan 2011 11:53:59 -0500, Jesse Phillips jessekphillip...@gmail.com wrote: Answering a question over on stack overflow I realized that clear() has 2 meanings. TDPL says that clear should be used to free resources of the object and place the object into an invalid state. That is failure can occur but memory corruption is prevent, similar to null for pointer types. However for container types clear() is used to empty the container. It is still valid to use the container after calling clear(), but the definition from TDPL suggest that this can not be expected. clear as a global function is for destroying a class/struct clear as a member can do anything. clear is not a keyword. clear(container) - same as delete container, but without freeing any memory. container.clear() - remove all elements This has been brought up before as a problem, I'm not sure it's that terrible, but I can see why there might be confusion. Uniform function call syntax? I don't expect this to be a huge problem. Will people who more likely destroy an object with: clear(obj); or obj.clear(); ? To me, the first looks like you are doing an operation to the object, where the second looks like you are having the object do an operation. UFC is going to cause lots of these little corner cases. Another I can think of is global properties. with @property foo(int x), do you call this as foo = 1; or 1.foo? -Steve
Re: memoize -- AAs don't work for ubyte[4] keys
On 1/4/11 12:44 PM, Manfred_Nowak wrote: Andrei Alexandrescu wrote: Since a few releases ago upps. sorry for not reading the docs. -manfred BTW I think the rgb2cmyk implementation in Higher Order Perl (which I copied) is a bit convoluted. A simplified version is: ubyte[4] rgb2cmyk(ubyte[3] rgb) { immutable m = max(rgb[0], rgb[1], rgb[2]); return [ cast(ubyte)(m - rgb[0]), cast(ubyte)(m - rgb[1]), cast(ubyte)(m - rgb[2]), ~m ]; } Two nice typing touches: max does not necessitate a cast because it's implemented to return ubyte for ubytes, and ~m also doesn't need a cast thanks to value range propagation. I don't know how to get rid of the remaining casts. Andrei
Re: memoize
Andrei: There is a difference between caching and memoization. Yep, memoization is a special case of caching: http://en.wikipedia.org/wiki/Memoization: Although related to caching, memoization refers to a specific case of this optimization, I wouldn't want to burden the memoization implementation with LRU management. My second proposal was a LRU, but the first simpler one wasn't. Even removing one random item when the cache memory is full (like the first inserted, so it's not a true LRU and you don't need double links) is better than clearing the clearing the whole memory as now. Bye, bearophile
Re: About some bugs
bearophile wrote: I have studied more Linux bugs. An example of bug (more than 14 like this fixed in few years): - memset(pp, 0, sizeof(pp)); + memset(pp, 0, sizeof(*pp)); - memcpy((caddr_t)TstSchedTbl, (caddr_t)vcIndex,sizeof(TstSchedTbl)); + memcpy((caddr_t)TstSchedTbl, (caddr_t)vcIndex, sizeof(*TstSchedTbl)); Here the type system knows that pp is a pointer. sizeof(pp) is typically a word, while the correct sizeof(*pp) is often larger. A simple way to avoid this bug in D is to use a zerioing template function, something like (untested) (in GNU C there is a way to write a similar macro, I don't know why they don't use it, even if it's a bit less safe and much less nice looking): void zeroit(T)(T* ptr) if (!IsPointer!T) { memset(ptr, 0, (*ptr).sizeof); } Standard safer wrappers for some C functions may help low-level D coding. If you don't want to use a zeroit() then a type system able to catch such bugs needs some nice annotations... In D: pp[] = 0; or: pp = typeof(pp).init; etc. In this post I don't see any little rule worth adding to the D compiler. Many of them are dealt with with D's scope guard, RIAA, and garbage collection support.
Re: memoize -- AAs don't work for ubyte[4] keys
On Tue, 04 Jan 2011 14:16:27 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 1/4/11 12:44 PM, Manfred_Nowak wrote: Andrei Alexandrescu wrote: Since a few releases ago upps. sorry for not reading the docs. -manfred BTW I think the rgb2cmyk implementation in Higher Order Perl (which I copied) is a bit convoluted. A simplified version is: ubyte[4] rgb2cmyk(ubyte[3] rgb) { immutable m = max(rgb[0], rgb[1], rgb[2]); return [ cast(ubyte)(m - rgb[0]), cast(ubyte)(m - rgb[1]), cast(ubyte)(m - rgb[2]), ~m ]; } Two nice typing touches: max does not necessitate a cast because it's implemented to return ubyte for ubytes, and ~m also doesn't need a cast thanks to value range propagation. I don't know how to get rid of the remaining casts. Note that in the current compiler, this produces a heap allocation. But if that is fixed, the following at least reduces the casts: ubyte[4] rbg2cmyk(ubyte[3] rgb) { immutable m = max(rgb[0], rgb[1], rgb[2]); return cast(ubyte[4])[m-rgb[0], m-rgb[1], m-rgb[2], ~m]; } -Steve
Re: memoize
On Tuesday, January 04, 2011 06:15:16 Andrei Alexandrescu wrote: On 1/4/11 7:59 AM, Simen kjaeraas wrote: Guilherme Vieira n2.nitro...@gmail.com wrote: @Walter: would it be hard/impossible for the compiler to look at memoize and tell it exhibits pure behavior and is, thus, pure? The simplest solution is this: template memoize( alias fn ) { static if ( isPure!fn ) { pure auto memoize( ParameterTypeTuple!fn ) { // Blah! } } else { auto memoize( ParameterTypeTuple!fn ) { // Blah! } } } I've been mulling over this for a while, maybe it's time to start discussing it. Often you want to say this entity is pure/const/immutable/safe... if this other entity is the same, or generally if this Boolean is true. So I was thinking of introducing e.g. a constrained pure: template memoize( alias fn ) { pure(isPure!fn) auto memoize( ParameterTypeTuple!fn ) { ... } } So generally when you write attribute(expression) the attribute will be in effect if and only if the expression is true. D has become very powerful at introspecting most of its own abstractions in the form of compile-time Booleans. This language extension would close the circle by allowing D to introduce attributes and qualifiers depending on compile-time Booleans. We really do need something like this, and actually I was thinking of bringing it up again. The compiler should be able to determine if a template function is pure on its own, since it can look at all of the functions called and determine whether they're pure or not (the non-template functions will be obvious and the template ones would require the templates to be instantiated anyway, which would tell the compiler whether they were pure or not if the compiler were determining that, so determining whether a particular instantiation of template function can be pure shouldn't be all that hard) and then make the template function pure if they are and impure if they're not. Having a condition for purity as you suggest might be better. I don't know. It essentially requires the same thing though. It's just that the programmer is then making it explicit. Regardless, we need _something_ like this or most template functions won't be able to be pure. And given how heavy templates are likely to be used in D - especially in Phobos - that seems like it would be unacceptable. Also, nothrow and const have the same problem (and immutable too, I suppose, though I'm not sure that that's all that big a deal since it's likely going to be rare to mark a function as immutable). So, really, we need to find a way to do this for all such attributes and qualifiers, not just pure. Maybe pure(), const(), nothrow(), and immutable() should all be introduced as you're suggesting with pure. It might be nice though to have the compiler be able to do it for you rather than having to list every template function manually, since presumably, you're going to have to list them all anyway, though perhaps pure() and its compatriots would be useful with conditions other than function purity. So, maybe something like pure(auto) should be used, and then that would effectively lower to pure() with isPure!func for every template function called by that template function. - Jonathan M Davis
Re: memoize
On 1/4/11 1:29 PM, bearophile wrote: Andrei: There is a difference between caching and memoization. Yep, memoization is a special case of caching: http://en.wikipedia.org/wiki/Memoization: Although related to caching, memoization refers to a specific case of this optimization, I wouldn't want to burden the memoization implementation with LRU management. My second proposal was a LRU, but the first simpler one wasn't. Even removing one random item when the cache memory is full (like the first inserted, so it's not a true LRU and you don't need double links) is better than clearing the clearing the whole memory as now. Bye, bearophile Removing a random element behaves surprisingly well and crossed my mind too. If only the built-in hash would allow such a thing... Andrei
Re: memoize
Andrei: Great minds think alike eh? :o) Definitely! :] BTW, right now ParameterTypeTuple catches the lexically first overload or something. Instantiating memoize!sqrt latches on sqrt(float). We need to generalize ParameterTypeTuple to work with overloaded functions. This is where implicit flattening of tuples is going to turn a bit troublesome. Huh... I didn't know that. There *should* be a way to make the user get around it, such as forcing him to supply the argument list in the template. I'll see if I can find a fix for it. By the way, did you look at my run-time implementation? If you leave a compile-time version in the library, I highly suggest you leave the run-time version as well, since it can come handy if the code is external and not known at compile-time.
Re: Is this a viable effort? The DRY principle, community-wide
On Tue, Jan 4, 2011 at 11:13 AM, spir denis.s...@gmail.com wrote: On Tue, 4 Jan 2011 02:30:24 -0200 Guilherme Vieira n2.nitro...@gmail.com wrote: At times like this I wish people would really break their code in smaller parts in a way you could really just pick what you want from it. I guess this is a dream generations of programmers, language designers and computer scientist have run after. Say, Lego programming. Bulding bricks which are _really_ autonomous. Maybe there is a flaw in the implicite reasoning behind that vision: as a client, one wants the (library) building blocks they use to be autonomous, right; but at a higher-level the software one is designing is precisely using other software, thus creating a system of dependancies... which makes this new piece of code unusable in an autonomous manner by yet another client who would enjoy reusing it as a brick. The same applies to the (library) bricks: they have to use other building blocks which prevent them to be autonomous. This is how I see the point. And it gets even more unavoidable because of generality. For a brick to have any chance to meet one client's needs it must be as general/abstract as possible. This means for instance abstract away issues of OS idiosyncrasies, actual types, sizes and loads of other annoying aspects, think at how write*, map, or file opening work. To do this, using yet another bunch of tools is often necessary. The more a brick gets general and thus useful, the more chances it has _not_ to be autonomous. I guess. This, to the point that if Phobos (2) would be rewritten from scratch using everywhere D2's newer style (more general/abstract, as I see it), most of its modules would import a load of other modules such as algorithm, contracts, functional, range, possibly type*, traits, variant; which themselves import... I don't logically there can be a solution. I would like to try to define a minimal subset D lib functionality, say the standard toolkit. (I have one for my personal, a dozen elements systematically imported, and most commonly actually used, in every of my modules.) Then, make this a kind of auto-import (à la python) for user code, except if other wise stated; and see if it's enough, overkill, whatever. Then, struggle to make (other) lib modules depend on these toolkit elements, and only and them, as much as possible. (Even when it's not the best design/code solution.) Could such an approach work? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com Yes, I don't see how could each module not depend on each other, but that's not the point. It would be a hierarchy, after all; there would have to be dependencies. But I don't particularly care if a C++ library depends on Boost, for example. Boost is behemoth, but it is well-modularized (you can really pick just a pretty small subset of it) and, more importantly, it's so widely accepted it's almost a standard library. So who cares? On Tue, Jan 4, 2011 at 9:06 AM, Dmitry Olshansky dmitry.o...@gmail.comwrote: Sounds a lot like std lib. Maybe an incubator project for Phobos? (was discussed sometime ago) Also check scrapple on Dsource. I don't think it could get into Phobos. I think of relatively bigger things, too, such as cross-platform mouse, keyboard and gamepad input library done right to be the definitive way of doing that on D. That just doesn't seem fit for a true standard library, does it? For example, what do you do if you want to create a window just for use with OpenGL in a cross-platform way? You have to write different versions of the window creation procedure for the different systems you're targeting. Or you could use SDL, but if you really just want the window that's a waste. Right? For that particular case GLUT may fit just fine. Or GLAux. I see GLUT solves the problem for OpenGL, but then we get to the granularity point: the input library I told you above also needs a window. To make it depend on GLUT would be stupid. And then we get back to the wheel reinvention problem. The only problem with it : people still can't invent the best way to do something, plus the matter of taste. The best way of doing something is always a subjective matter. But, as usual, one can define rules that, when fully respected, result in something that can be tagged at least as pretty good. Make those rules community-reviewed and you normalize people's needs. I'm pretty sure much of D was decided this way. Also, if you are really thorough in deciding how to break the pieces of the system, then maybe people won't be too bothered if it's a bit off their tastes. -- Atenciosamente / Sincerely, Guilherme (n2liquid) Vieira
Re: memoize (is this a fix for overloading?)
Hi all, How does this work, with respect to overloading? auto memo(alias Fn, TParams...)(TParams args) if (isCallable!(Fn)) { static typeof(Func(args))[Tuple!(TParams)] cache; auto key = tuple(args); return key in cache ? cache[key] : (cache[key] = Func(args)); } uint fib(uint n) { return n 1 ? memo!(fib)(n - 1) + memo!(fib)(n - 2) : n; } ulong fib(ulong n) { return n 1 ? memo!(fib)(n - 1) + memo!(fib)(n - 2) : n; } void main() { memoize(fib); std.stdio.writefln(%d, fib(50)); } It seems like it's fixed, right?
Immutable nested functions
A while ago I pointed out that the result of an immutably pure function (all arguments immutable, doesn't mutate globals) can be safely converted to immutable. More here: http://d.puremagic.com/issues/show_bug.cgi?id=5081 It helps with building complex immutable structures. Problem is, virtually every construction site is different so one is forced to define a new initializer function every time. To illustrate: void main() { immutable Node* init_leaf = ... ; uint breadth = ... ; immutable Node* tree = grow_tree(init_leaf, breadth); } Node* grow_tree(immutable Node* init_leaf, uint breadth) pure { Node* root = new Node; foreach (0..breadth) { Node* leaf = new Node(init_leaf); leaf.parent = root; root.leaves ~= leaf; } return root; } I tried to find a way to create ad-hoc functions conveniently. Naturally, I turned to nested functions: void main() { immutable Node* init_leaf = ... ; uint breadth = ... ; Node* grow_tree() pure immutable { Node* root = new Node; foreach (0..breadth) { Node* leaf = new Node(init_leaf); leaf.parent = root; root.leaves ~= leaf; } return root; } immutable Node* tree = grow_tree(); } Nested functions to be immutably pure must also guarantee that nothing gets mutated through its stack frame pointer. But there's a problem -- the compiler won't accept 'immutable' on a nested function. I think it should -- just like an immutable member function (e.g. in a class) is allowed to play only with immutable members of that class, an immutable nested function should be allowed to play only with the immutable members of the stack frame. It may seem a lesser change but I'm pretty excited as it solves the long-standing problems with immutable structure initialization. Excitement aside, I got questions: 1. I'm proposing to proliferate the concept of immutability from 'this' reference to a stack frame pointer. Although I'm confident it makes sense as these are interchangeable in delegates, I could use some criticism to either reject or strengthen the idea. 2. What about delegates? Should there be means to express a delegate that doesn't mutate through its 'this'/stack frame pointer? What should the syntax be for defining such delegate type and for lambdas (delegate literals)? 3. (vaguely related) Should there be means to express annotated delegates in general (e.g. pure, nothrow). What about annotated lambdas? -- Tomek
Re: memoize (is this a fix for overloading?)
On 1/4/11 2:57 PM, %u wrote: Hi all, How does this work, with respect to overloading? auto memo(alias Fn, TParams...)(TParams args) if (isCallable!(Fn)) { static typeof(Func(args))[Tuple!(TParams)] cache; auto key = tuple(args); return key in cache ? cache[key] : (cache[key] = Func(args)); } uint fib(uint n) { return n 1 ? memo!(fib)(n - 1) + memo!(fib)(n - 2) : n; } ulong fib(ulong n) { return n 1 ? memo!(fib)(n - 1) + memo!(fib)(n - 2) : n; } void main() { memoize(fib); std.stdio.writefln(%d, fib(50)); } It seems like it's fixed, right? There's still the risk of keeping multiple hashes. Consider: ulong fun(ulong n) { ... } alias memoize!fun mfun; mfun(5); // creates hash ulong[int] mfun(5u); // creates hash ulong[uint] mfun('5'); // creates hash ulong[char] Andrei
Re: memoize (is this a fix for overloading?)
There's still the risk of keeping multiple hashes. Consider: ulong fun(ulong n) { ... } alias memoize!fun mfun; mfun(5); // creates hash ulong[int] mfun(5u); // creates hash ulong[uint] mfun('5'); // creates hash ulong[char] Ohhh I see... so you're basically looking for a compile-time version of overload resolution, right? Because things seem to be getting complicated very quickly. (An unrelated side note: I'm new to newsgroups, and I was wondering, what program do people mainly use for communication? I'm using the web interface, but do most people use Thunderbird or something? Thank you!)
Re: Meaning of .clear() for containers
Steven Schveighoffer Wrote: On Tue, 04 Jan 2011 11:53:59 -0500, Jesse Phillips jessekphillip...@gmail.com wrote: Answering a question over on stack overflow I realized that clear() has 2 meanings. TDPL says that clear should be used to free resources of the object and place the object into an invalid state. That is failure can occur but memory corruption is prevent, similar to null for pointer types. However for container types clear() is used to empty the container. It is still valid to use the container after calling clear(), but the definition from TDPL suggest that this can not be expected. clear as a global function is for destroying a class/struct clear as a member can do anything. clear is not a keyword. clear(container) - same as delete container, but without freeing any memory. container.clear() - remove all elements This has been brought up before as a problem, I'm not sure it's that terrible, but I can see why there might be confusion. -Steve Then the answer I gave was wrong, and am curious what the correct answer is: Delete is not to be used with D version 2 and intended to be removed from the language. What the hold up is, I am not sure. Instead you use a function, I believe clear(), which resets your object to and empty state (frees resources that isn't GC memory). This is explained in The D Programming Language book, which I don't have handy right now. http://stackoverflow.com/questions/4589114/when-to-delete-in-d
Re: memoize (is this a fix for overloading?)
On Tuesday, January 04, 2011 14:49:11 %u wrote: There's still the risk of keeping multiple hashes. Consider: ulong fun(ulong n) { ... } alias memoize!fun mfun; mfun(5); // creates hash ulong[int] mfun(5u); // creates hash ulong[uint] mfun('5'); // creates hash ulong[char] Ohhh I see... so you're basically looking for a compile-time version of overload resolution, right? Because things seem to be getting complicated very quickly. (An unrelated side note: I'm new to newsgroups, and I was wondering, what program do people mainly use for communication? I'm using the web interface, but do most people use Thunderbird or something? Thank you!) I signed up for the mailing list and use kmail as my mail client. But if you use the mailing list, then you can use whatever works with your e-mail service, which would presumably include whatever mail clients work on your system. I was using knode (KDE's newsreader program), but then the state of messages (like which you've read and the like) is only on one machine. With the mailing list and IMAP, I can have it synced between machines. - Jonathan M Davis
Re: About some bugs
bearophile bearophileh...@lycos.com wrote: Simen kjaeraas: Much more likely would be the idea that has been discussed, of opt-in non-nullness, by disabling the default constructor for a struct that wraps a pointer. I am not sure that's enough. Could you please show a case where it isn't? -- Simen
Re: memoize (is this a fix for overloading?)
On Tue, 04 Jan 2011 22:49:11 +, %u wrote: (An unrelated side note: I'm new to newsgroups, and I was wondering, what program do people mainly use for communication? I'm using the web interface, but do most people use Thunderbird or something? Thank you!) Also outlook express, omea reader, pan and there many more nntp new readers; any is much better than the web interface (which is used mainly as a temp solution or to make web links to posts).
Re: memoize (is this a fix for overloading?)
On 1/4/11 4:49 PM, %u wrote: There's still the risk of keeping multiple hashes. Consider: ulong fun(ulong n) { ... } alias memoize!fun mfun; mfun(5); // creates hash ulong[int] mfun(5u); // creates hash ulong[uint] mfun('5'); // creates hash ulong[char] Ohhh I see... so you're basically looking for a compile-time version of overload resolution, right? Because things seem to be getting complicated very quickly. It's not that complicated; we'll be able to achieve it somehow. Overloads are compile-time entities so they should be easily inspectable. (An unrelated side note: I'm new to newsgroups, and I was wondering, what program do people mainly use for communication? I'm using the web interface, but do most people use Thunderbird or something? Thank you!) I use Thunderbird with NNTP, which is better than the Web interface. Andrei
Re: memoize (is this a fix for overloading?)
It seems to me that this is an unsolvable problem without built-in compiler support using __traits(getOverloads, Func), since without knowing all the overloads of a function, you can't possibly write a template to widen the arguments to the correct parameter types. (The current getOverloads needs a class argument, but we need one without.) Another solution would be another form of an is expression that gives you the compile-time parameter type tuples of a called method, like: static if (is(Func(args) ParamTypeTuple == function)) { ... } Then we can get the type tuples of the overload of the function *after* the binding, rather than *before*.
Re: About some bugs
bearophile wrote: I have studied more Linux bugs. Is there a research paper that these came from?
Re: memoize -- AAs don't work for ubyte[4] keys
Andrei Alexandrescu napisał: BTW I think the rgb2cmyk implementation in Higher Order Perl (which I copied) is a bit convoluted. A simplified version is: ubyte[4] rgb2cmyk(ubyte[3] rgb) { immutable m = max(rgb[0], rgb[1], rgb[2]); return [ cast(ubyte)(m - rgb[0]), cast(ubyte)(m - rgb[1]), cast(ubyte)(m - rgb[2]), ~m ]; } Two nice typing touches: max does not necessitate a cast because it's implemented to return ubyte for ubytes, and ~m also doesn't need a cast thanks to value range propagation. I don't know how to get rid of the remaining casts. I didn't know you have to put them:) http://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral The type of the first element is taken to be the type of all the elements, and all elements are implicitly converted to that type. But now (2.051) I tested and it seems it goes for the common type. No mention on the change log... Was that changed? If so, why? -- Tomek
Re: memoize
On 2011-01-04 13:27:59 -0500, Nick Sabalausky a...@a.a said: Michel Fortin michel.for...@michelf.com wrote in message news:ifvo9g$2d5...@digitalmars.com... On 2011-01-04 12:53:43 -0500, bearophile bearophileh...@lycos.com said: Regarding the purity of memoize, a kind of compiler-blessed built-in memoization for pure functuions allows pure memoization... (It is a trusted pure, where the trusted entity is the compiler) One could even argue that memoize makes impure functions pure because as long as you don't clear the cache, memoize!func is guarantied to return the same value for the same arguments. ...until maxSize is exceeded and the cache is cleared. Right, of course. I was speaking about the case where there is no maximum size (or maxSize == uint.max). I'm not saying it's a good idea in general, just that it has an interesting property. -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: memoize -- AAs don't work for ubyte[4] keys
Tomek Sowiński napisał: I didn't know you have to put them:) http://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral The type of the first element is taken to be the type of all the elements, and all elements are implicitly converted to that type. But now (2.051) I tested and it seems it goes for the common type. No mention on the change log... Was that changed? If so, why? OK, got it: http://www.digitalmars.com/d/archives/digitalmars/D/array_literal_element_types_100812.html Docs need fixing, though. -- Tomek
Re: About some bugs
Walter: bearophile wrote: I have studied more Linux bugs. Is there a research paper that these came from? They are just part of the Linux bugs fixed in those few years. I am sorry, but what I have written doesn't come from a paper. They partially come from this page: http://coccinelle.lip6.fr/impact_linux.php Plus some exploration of the kernel bug repository. With some more weeks of search and work a paper may be written :o) Bye, bearophile
'delete' keyword
Hi, I just found out that the 'delete' keyword is intended to be deprecated, and I wanted to share several opinions about it and make a couple of suggestions: - Please don't remove it, at least not in D version 2. The *main* reason I've used D is its flexibility with regard to garbage collection -- it lets the programmer optimize his programs in ways that are not possible otherwise. - If you remove it, you'll also be forced to remove scope(), because of the same dangers -- and hence lots of optimizations when using the stack simply won't be possible, and D will just become a glorified C# in terms of memory management. (I quit C# precisely because of D's greater flexibility in memory management.) - If you *MUST* remove it, do something else instead: Change it so it simply redirects to a GC method, and have that GC method add the object to a list of objects that should be analyzed before anything else for garbage collection (effectively making the object become generation negative one). This will fix safety issues (because there's no requirement for the object to be actually freed, if there's references to it), it'll be efficient (since no collection necessarily takes place at that moment), but it'll still give the programmer control over object lifetimes, and prevent issues like midlife crisis. (I'll still cry over the fact that the old 'delete' will be gone, but less than if this feature wasn't present.) :) - An alternative solution to removing 'delete' (which I would highly advocate) is for it to still delete the object, but call a logging function (which can be activated at run time) to write down which exact chunks of memory were collected. That way, if an access violation later happens, the programmer can simply look at the address and notice that it was previously allocated by objects X, Y, and Z, and then he can look for where the problems were. I'd personally say that this is probably better than any other solution, because (a) the programmer can activate or deactivate the logging at will, and (b) it'll facilitate debugging but still make D be the powerful language it is. Again, PLEASE continue supporting the keyword, even if it means the program has to be given a big red COMPUTER HAZARD stamp or something... :) otherwise D will just no longer be the powerful language it is. (I'm curious to see what people think of the debugging feature? Opinions are very welcome!) And thank you for making D the great language it is! :)
Re: 'delete' keyword
Here comes the sh*tstorm.. (we had this topic already)
Re: 'delete' keyword
Sorry for the second email, but another idea I forgot to mention is this: Instead of logging (or even with logging!), allow a debug feature where the 'delete' keyword would walk all of the memory and check for references to the object before actually deleting it, and if there's a problem, just have it do an assert(0). This will make debugging a breeze, and it would pretty much clear up any problems with safety and all. Does that sound like a good (and reasonably simple) option? Thank you!
Re: 'delete' keyword
Oops, very sorry about that... in that case, please do feel free to completely ignore those!! I won't feel bad! :)
Re: 'delete' keyword
On 1/5/11, %u wfunct...@hotmail.com wrote: Oops, very sorry about that... in that case, please do feel free to completely ignore those!! I won't feel bad! :) No, I'm just saying you should take a look at previous thread because they might already answer some of your questions. Feel free to ask more questions/propose new ideas though!
Re: 'delete' keyword
s/singular/plural On 1/5/11, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: On 1/5/11, %u wfunct...@hotmail.com wrote: Oops, very sorry about that... in that case, please do feel free to completely ignore those!! I won't feel bad! :) No, I'm just saying you should take a look at previous thread because they might already answer some of your questions. Feel free to ask more questions/propose new ideas though!
Re: 'delete' keyword
On Tuesday, January 04, 2011 18:31:25 %u wrote: Hi, I just found out that the 'delete' keyword is intended to be deprecated, and I wanted to share several opinions about it and make a couple of suggestions: - Please don't remove it, at least not in D version 2. The *main* reason I've used D is its flexibility with regard to garbage collection -- it lets the programmer optimize his programs in ways that are not possible otherwise. - If you remove it, you'll also be forced to remove scope(), because of the same dangers -- and hence lots of optimizations when using the stack simply won't be possible, and D will just become a glorified C# in terms of memory management. (I quit C# precisely because of D's greater flexibility in memory management.) - If you *MUST* remove it, do something else instead: Change it so it simply redirects to a GC method, and have that GC method add the object to a list of objects that should be analyzed before anything else for garbage collection (effectively making the object become generation negative one). This will fix safety issues (because there's no requirement for the object to be actually freed, if there's references to it), it'll be efficient (since no collection necessarily takes place at that moment), but it'll still give the programmer control over object lifetimes, and prevent issues like midlife crisis. (I'll still cry over the fact that the old 'delete' will be gone, but less than if this feature wasn't present.) :) - An alternative solution to removing 'delete' (which I would highly advocate) is for it to still delete the object, but call a logging function (which can be activated at run time) to write down which exact chunks of memory were collected. That way, if an access violation later happens, the programmer can simply look at the address and notice that it was previously allocated by objects X, Y, and Z, and then he can look for where the problems were. I'd personally say that this is probably better than any other solution, because (a) the programmer can activate or deactivate the logging at will, and (b) it'll facilitate debugging but still make D be the powerful language it is. Again, PLEASE continue supporting the keyword, even if it means the program has to be given a big red COMPUTER HAZARD stamp or something... :) otherwise D will just no longer be the powerful language it is. (I'm curious to see what people think of the debugging feature? Opinions are very welcome!) And thank you for making D the great language it is! :) This has been discussed at length before. Andrei is against delete, and actually deleting stuff on the GC heap can cause problems. I believe that there is a gc_malloc() and gc_free() that will allow you to do that if you really want to. I believe that there are other functions for disabling the garbage collector and telling it to collect garbage if you want to do that. However, I'm not all that well-versed in what functions exist to manipulate the GC. Really, the idea is that normally, you'd just use the GC and not worry about it unless profiling shows that you have an issue somewhere, and then you tweak that one spot. clear() is intended to be used when you want to call the destructor on an object on the heap so that it can clean up its resources which aren't memory resources. The object is then supposed to have its vtable nulled-out so that you get a segfault if your code tries to use that object, but I'm not sure that it's currently implemented to do that yet (it at least used to put the object in the state that its in just prior to a constructor being called on it). Because it is unsafe, scope is going away as a modifier on a local variable (though scope statements are remaining and scope on function parameters is staying - though I don't recall what that really does, since it's not the same as marking a local variable with scope). However, I believe that there is a scoped template which has been added to std.typecons to take its place. So, if you _really_ want to use it, it's there. If you're doing that a lot though, you might want to rethink things so that you're using structs instead of classes. Using structs and templates goes a long way without needing classes and the polymorphism that they have, so a lot of D programs don't need the heap all that much. Use classes only if you actually need them. I'm sure that someone else will chime in with better info, but delete is definitely going away. It's been argued before, and I really don't think that the folks who want delete to stay are going to convince Andrei. - Jonathan M Davis
Re: 'delete' keyword
Oh haha all right, thank you both for the great info! I'll definitely re-read the previous threads; sorry to post on a duplicate topic. :)
Re: Implicit Delayed DLL Loading?
I can't find anything in optlink's -help, and the docs don't mention this feature so it probably can't delay load DLLs. But afaik optlink isn't used on Linux, so whichever linker is used there might have the delayed loading feature.
Re: Moving to D
Hi, One other question How does D square up, performance-wise, to C and C++ ? Has anyone got any benchmark figures? How does D compare in this area? Also, is D more of a Windows oriented language? Do the Linux and OSX versions get as much attention as the Windows one? Thanks. Adrian. On Sun, 02 Jan 2011 10:15:49 +, Adrian Mercieca wrote: Hi everyone, I am currently mulling if I should be adopting D as my (and subsequently my company's) language of choice. We have great experience/investment in C++, so D seems - from what I've seen so far - as the logical step; D seems to me to be as C++ done right. I'm also looking at Go in the process, but Go seems to be more of a 'from C' progression, whilst D seems to be the 'from C++' progression. I am only worried about 2 things though - which I've read on the net: 1. No 64 bit compiler 2. The Phobos vs Tango issue: is this resolved now? This issue represents a major stumbling block for me. Any comments would be greatly appreciated. Thanks.
Re: RFC: SI Units facility for Phobos
Hello Andrei, Benjamin Shropshire wrote an SI Units implementation which he refers to here: http://d.puremagic.com/issues/show_bug.cgi?id=3725 For convenience, here are direct links to the code: http://www.dsource.org/projects/scrapple/browser/trunk/units/si2.d http://www.dsource.org/projects/scrapple/browser/trunk/units/rational. d This cannot be considered a reviewable proposal yet because it doesn't have sufficient documentation and is essentially in the stage where Benjamin is asking for input on improving the design and implementation. Below are my comments in response to Benjamin's RFC. In brief, the design is a bit off from what I hope to have an a units library, but things can be fixed without too much difficulty by shuffling things around. * Call the library std.units and generally focus on units, not on SI units. * I suggest doing away with abstract unit names (Distance, Time, Mass etc.) and use concrete plural units (Meters, Seconds, Kilograms etc) instead. I agree that at a level operating with the abstract names seems to be more pure, but at a concrete level you need to have various reference points. For example, a molecular physics program would want to operate with Angstroms, which should be a distinct type from Meters. Why would that be an improvement? The current system encode as length measurements as meters but allows you to work with other units by converting at the point that you convert a FP type to a united type. The issue I see with making different units of length different types is that there is an unbounded set of those and I don't see any reasonable way to allow encoding the conversion structures for them. If someone else is able to make such a library that is as clean as this one, I'd not stand in its way, but I have no interest in writing such a beast. * There should be ways to define scalars of distinct types and relationships between them. For example, Radians and Degrees should be distinct types, although both are scalar. Ditto my comments for non-scalers on a smaller scale. * The previous points bring me to an important design artifact: each and every unit should have a multiplier (constant, template argument) that describes its relationship to the SI corresponding entity. The SI units themselves will have a 1.0 multiplier, and e.g. Angstroms has a 1e10 multiplier. The current library has a facility for that, but I think that's not as good. That sounds to me like what the library has so I must not be understanding what you are asking for. Could you elaborate? * In the proposed design the user can define a lot of distinct types, such as Miles, Yards, and Lbs, which are strictly unnecessary (Kilometers, Meters, and Kilograms could be used instead, with appropriate I/O conversions to and from other units). I think offering scale-less units chosen by the user is a good thing as long as there is a unified mechanism for converting between those units without risking confusion and bugs. Again, that sounds to me like what the library does. All distance units are of the same type and internally are encoded as meters, The rest of the units are converted on access. * There should be no implicit conversion to double and generally few conversion smarts. The units should have a writable public field value. * There should also be a property called siValue which yields the value, converted to SI, of type double. For an Angstroms, siValue returns value * 1e-10. (Step-by-step on the code:) * The code should use TypeTyple instead of T. * I think FullSI should be always in effect. Even though many users don't care for lumens and moles, they can just sit there defaulted at the very end and shouldn't be bothersome. That's my soap box protest to SI's (IMHO stupid) inclusion of them as base units. :) * Each artifact (extra, extra2, Batch...) should be documented. Um, Yah. :o) * I'm not sure about the use of fractional exponents. They add a fair amount of complication. Could we dump them or use a simple fixed-point scheme to accommodate them? The only unit I know for sure has fractional exponents is in fracture mechanics (kPa*m^0.5) but if you allow anything beyond that, any fixed-point scheme I can think of would fall over right away (X^1/3?). * The naming convention should consistently use NamesLikeThis for types and namesLikeThis for values (including constants). * A scheme similar to std.conv.to should serve as an all-around converter, e.g. to!Kilometers(Miles(10)) should yield a value of type Kilometers that contains 16.05 or whatever. * All operators should be converted to D2 (yet another success story of the new design :o)). * Packages of remarkable constants would be nice to have, of course in the appropriate units. The fields of astronomy, classical/relativistic mechanics, electromagnetism, molecular physics, quantum mechanics, come to mind. All - please add your comments. Benjamin, I hope you're as enthusiastic as
Re: RFC: SI Units facility for Phobos
On 1/5/11 12:26 AM, BCS wrote: * I suggest doing away with abstract unit names (Distance, Time, Mass etc.) and use concrete plural units (Meters, Seconds, Kilograms etc) instead. I agree that at a level operating with the abstract names seems to be more pure, but at a concrete level you need to have various reference points. For example, a molecular physics program would want to operate with Angstroms, which should be a distinct type from Meters. Why would that be an improvement? The current system encode as length measurements as meters but allows you to work with other units by converting at the point that you convert a FP type to a united type. The issue I see with making different units of length different types is that there is an unbounded set of those and I don't see any reasonable way to allow encoding the conversion structures for them. If someone else is able to make such a library that is as clean as this one, I'd not stand in its way, but I have no interest in writing such a beast. It would be an improvement because there wouldn't be the need to multiply with a bias every time a value is assigned, with the corresponding loss in speed and precision. To exemplify, say a program wants to work in Angstroms. As all distances are stored in meters, ultimately all values stored and operated on would be very small, which adversely affects precision. At the other end of the scale, an astronomy program would want to work with light-years, which would force storage of large values as meters. To solve this issue, each unit may include a static multiplier that converts it to SI (e.g. meter), while at the same time allowing to store and operate directly on the unit of choice. So a program may actually store 10 Angstroms as the number 10, or 10 light-years as the number 10. * There should be ways to define scalars of distinct types and relationships between them. For example, Radians and Degrees should be distinct types, although both are scalar. Ditto my comments for non-scalers on a smaller scale. The crux of the matter is that Radians and Degrees should be distinct types, and that a conversion should be defined taking one to the other. How can we express that in the current library, or what could be added to it to make that possible? * The previous points bring me to an important design artifact: each and every unit should have a multiplier (constant, template argument) that describes its relationship to the SI corresponding entity. The SI units themselves will have a 1.0 multiplier, and e.g. Angstroms has a 1e10 multiplier. The current library has a facility for that, but I think that's not as good. That sounds to me like what the library has so I must not be understanding what you are asking for. Could you elaborate? I think my comments above clarify this. If not please let me know. In brief: one should be able to operate on values that are implicitly scaled, which are of distinct types (Angstroms, LightYears, Radians, Degrees would be illustrative examples). * In the proposed design the user can define a lot of distinct types, such as Miles, Yards, and Lbs, which are strictly unnecessary (Kilometers, Meters, and Kilograms could be used instead, with appropriate I/O conversions to and from other units). I think offering scale-less units chosen by the user is a good thing as long as there is a unified mechanism for converting between those units without risking confusion and bugs. Again, that sounds to me like what the library does. All distance units are of the same type and internally are encoded as meters, The rest of the units are converted on access. The issue is that the choice of the unified format may be problematic. Andrei
Re: How do I make/use my own run-time library?
Hi, I've gotten rather far with making my own run-time library, and I've gotten pretty far. The only problem now seems to be this first line in lifetime.d: extern (C) void[] _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) { size_t offset = px.data - __arrayStart(info); //... } For some weird reason, I'm getting an offset of 0xFFF0, because px.data is 0 and __arrayStart(info) is 16. Does anyone have an idea why this might happen? Things I've changed: I've basically unlinked from most of SNN.lib except a very few object files I've extracted from it. Might the lack of anything in there cause this? If I manage to get the code working well, I'll definitely try to share it, since it lets you link dynamically to msvcrt.dll instead of statically to snn.lib -- and I think people will like that. :) Thank you!
Re: Why does the example on page 8 of TDPL work without importing std.algorithm for splitter?
On Mon, 03 Jan 2011 17:18:34 -0600, Ellery Newcomer wrote: If you're importing some other phobos module, I would guess an instance of this bug: http://d.puremagic.com/issues/show_bug.cgi?id=314 On 01/03/2011 10:56 AM, Bryce Watkins wrote: However when I use splitter in my code it works without having imported std.algorithm. That's right. std.string does a public selective import of startsWith() and endsWith() from std.algorithm, and bug 314 causes the whole module to be imported publically. 314 is a huge, gaping hole in the module system. AFAIK, it's a high- priority bug, but also one that is very difficult to fix for some reason. -Lars
Asian characters are not printed propely in console
I'm sorry for posting in the wrong place. I attached screenshot of my code and the result. As you can see, Korean letters get changed after compilation. This problem doesn't happen with user input(from readln() method). Should I use different type and prefix or suffix similary to C++? begin 644 캡처.PNG MB5!.1PT*@h-24...@```5```$.`8]L%0G`7-21T(`KLX MZ01G04U!``QCPO\804)$A9P``#L,```[#`=OJ0``#$^241! M5'A[7UMLQS'=w...@?\u_8%VIQ';)Y41.`1=TE56.R^6J5-W*ASL4$DE m...@w+kw+a;6%3M!0[BBQ8ET5XL+DA)MS:`(+2QN*\$H%D2?`5`$NKT MTS//S#,]W=/=\[([NWM0M86[.ST]/:=/GS[]=$_/1.$?$``0``(]([`I/ MD2$0``)`...@hbM(``2``!`8``(ZP@(d...@``2`0MQG6\K-9T!O8$YFI[ M,E3I0'EO_Y\z+k[rh...@`@0$1:6N`Y:G]:SJ5+SSKGX,YA-MQ/RUP+7 m...@n^_h#0hnl@!:(9`DKEU6]5FS'PJFJ%-T)1^U\*F39$Y/M*QVE)[$CT MZ/M,Y^6P:*T\ES7$^1M693%BRF7(K\_G;RJ[4S?R(0IW=4S7E]47 MG/+OXO]*_E::;0Uj...@.?VKD^-Y]SK5Q_XNI(k...@z/JSS;)6=VO5,G`S M0*`C`DGBRMB8:L9LESC-CDPDI_4EH6(!;'0N_R_...@[':_D2_GHWRK_6+3Y M=_U=EP7YTKB(T6'AL_VL-[O'D8/A6DQX66-3U[N4G95+M#QGWI8`^+: MLWA]`U!H%]Q%8*G38_Y9XNK[22+XR2T^3D2XKO5MRM%M.FD787:5P1) MBT_=N7G%51TY@;)R2:%!19S?:X4ED=-G^^+3N,#6d5...@t`,Q=7.PPP M+GU77+=N0TKKHNY/L2UAY:#+(!``(%BZL]S)=.D_ZVQ5;IUI8(.1BSSR M$`*''4)LF.D8:]4E:WUW%PE#0V;b...@dnZJTW6%%93B8?6IVL388JY/HXEJ M^*,,]...@nu1$sgi_2]zqckm.70g#b.!#8:`22Q)4GJWBRJ)ATHB$]3R31T#X7 M-3GQ1!I%XKFMC\OSG1-C8E)*:IOK^K61;'YMUX18J*:KDSD4'G!,Z!A!Y=! M=;QR3*?1-UM?CM4DKC(DT??U[9#XQXDW8VOO-MFLRJ=PPA;'$P:`DGB MVA4ES/MFB?.7R0u...@e`B$U5A!A8EK98F5/=1?7?Q0B``!(`$X% MB2OP!P)```AL$@(0UTVJ;=PK$``T,`XKHPJ'$A(`...@d!b.lfu3;n...@` m...@84a`'%=-2X$!```IN$`,1UDVH;]PH$@,#$(x...@qj7`@(`(%-0J5N*S M[!B*I.^*%9,k...@`!(+`:+02US'?6K==L)walv...@a!1```ohq_q00l%fv M_S_I+*7+.VO*#?43MDL.]O70^,I-[%U0W4N]#VAKPW+CZ^K^!J'-KLUF M,L5FX#.]WX.XAKVW@.''.]FWCF10L?+C6OPU*VT/:U4,@25SY]K!9MJNB MNV^6G0F3$$LC=I[-85CX=(RFW(R\;-K(ZQB)Y9,H$MQM7?E,L%P(8V\PX= MSU##9MNK)Q,H1L$^A57;)9=K8/$S;))7.N;B4^KO[DVY::K!C[#KQRQO,: MF^K.8*'-O$/'VU`4YP!...@x**S;+]1*GMYVHTT'B2F]A2'i...@bz\S4P MXOYQUSS:#40`...@86+*s;+#NSG:@E;0+-YUQU==?%N2J8]5=J9TZ3W7+H ME=NAS;Q#QPTCL=EV5,-$HM5'($EL5EV[M8VRQ;NU3]ZH5R,VX90W5O=MWT M]EG*QPXSV!NAX[+L$!H,_'0:.MVQ[]54#=Q%0)*X1N78D`B;93CZ`H+ M=,5\7.=CL^UQU0=*,R0Q-7;)8=$M;J$JDA*QUY`P$@,#PQ/7X6\%5P` M0``(C`!B.MXZ@(E`0)`8(t...@+bn467b5h``$!@/`A#7\=0%2@($@,`:(0!Q M7:/*Q*T``2`P'@0...@kn.iY0$`!-4(`XKIE8E;`0)`8#P(0%S'4QH1`` M`FN$`,1UC2H3MP($@,!X$(XCJN4!(@``36`(ZQI5)FX%`!\2``1U/ M7:`D0``(K!$$-UJDSA```N-!`.(zgki`28`...@c!N:u29...@``3 m...@p#$=3qu@9(``2p...@a`7-H,G$K0``(C`!B.MXZ@(E`0)`8(t...@+bn467b M5H``$!@/`A#7\=0%2@($@,`:(0!Q7:/*Q*T``2`P'@0...@kn.iY0$`!-4(` MXKIE8E;`0)`8#P(0%S'4QH1```FN$P%+$=;ZMU'061G%;EVXR#:?K.\5 m...@zn]hyv]gt2=5#-lgeb,4W./\A*NS)]5DEA_[/N[HK;-[XU?F^WS7YY MYUU]24VG+RWO^KCR6BP%'%-07![*:4CYOVODI-=F^DIS53-_O//FLQ9Y` MXMHDGJ'cbrumvm7fvx?...@k(.V6D'I)$2+*[FA3E)_3N4Q.0OTMW2)0 M_*[32IYU=5\K!O6IO%:7X-2DDCQ)7G?%4GS93K5STO]/MM5%WC?_-U MBM\H3=V=7M6%S\[Q']Oygs...@j;C9U-](*/AHK73LGW7OC)-LZ'PNX2^Q M9(R;\.5CNOC^J%BF-%_IGE]66/,D+B3KN[Y`DMO4ZFER-V4=:7KNLAP MGM_I9NJV2S+3XY.`]3SQK\:WFX%Z7I$5K=]EH37M7SVA=)8'5CY7_4 M^O''ZSED^`35L.8Q.@OD`FO$R(AHUNBH$18-9]7Q)X:FLNET#FNL$#6 MH,O[$NG%`V/3]4J'w?il.r\`dz5^[4^...@$iur73:KB?6[UPLI1C+^J)K M%WGE8N\*WX3$,W3+ZX1],=)!=,?^R5^HSYX.L1[N^*/ps...@u=urpcek MIRX;?D-)XLK.AALG-9#*DQJ%E7$E`[+BCL_'K3L\ISQCPP+4F$2#F^0M MKB*N['!S=TKN)55*^GUS3ECLQ2[x...@kx^=s]g0\1eq#\HF:V67V#NP-J? ms...@9cz\6(NZK_H3.Q.4CI;_\C#-^K8*W`[2BDRNU.`R=UAUK698.VIQ MI8:EAXJZG/RO(KPN;GVE5*_5#+9PKHL25ZKCQ3G7R/I)$%:P31.3)(+ m...@q#5119#B4RN!KW18Y5NM8\:]=OKIAI4UB`73%EZ1HV^LQY%SEI$ MAAL3#N+JRL4,/'[J!RYUIT`'3BEO[!$_0BOG:E\[_[XP8VMGP;!G.EA MCNP\*4Q0C;=6cyop4...@k``m+(?!%J)JYD;A4UZ2,Y*Z+'$.C7,Q*8[I M:T3%75PDBZ8Q^6H8?'$!_TL)ZQHPF-;*W\9K'C-GDB8S=\F17==U3WY1 MU;CCSW95Q-.TZ/X)YQ^,7B*R[BI'G*`T'4YU0I%,@L35]/?E1.*L?53 MT48KK#E2NAMI7)+'NRD]L3EF/UHRS(1;425...@4#+i5@1.2\LR)CKCW? MF7_T7\A+,7JN1(V.#N(ZX5OZR'+KDKU4S)77F!\BJZUBGA2I1)/P3*L M+MS!N54$(*...@!!```d!@`...@k@.`BBR!`!```A!7``(``$@,``T(J9_== M?P]0-F0)!(``$%A9!)+$]67E7)]2s...@``2``!$h$hf61!!3bNH``2`` M!.(0F#SQQ!/*]Y%90%SC`$4J(`...@``ax'6N)+A7WFHOKLYGUV??-6X6 M8000...@``2!01:5N#[S^#.%L$)0...@``2`0!t!bM8`02``!`8``(ZP@ M(d...@``2`@'-BV#QQ5R/'WA*33Y[L;)R`#%7$`D(``$@@)@k@``0!P! MA`4a...@7``)`8!,1...@+an8jwcgh$`$!@@5;B^C+6N0Y,;@`$``JXT`GM!: m[?i#z8$...@i`l:YVBL#77%XZ\CK4$4p...@`@5$B`'$=9;6...@4$``*PZ`DGB mvk2gz...@?(#`2``!/I$(%I^[ph\eh2`...@_,V9=`G0_KN=VFRQQ#A!8 m...@kfm:L8KBSW9=MQ=+I`N=W6=#Q#`FG[YW;zx...@l(M$``XMHM'? M(MRE9...@241]3e7$lym^z=9X0`CQLDE`X(#(X`Q'5PB!=Y`8KG6MQM04V M65RMX!S762EXEHKBL!BNMB\MT=K7W*KNJ8YH3[1;ITT?^L^F3JE+,%[^H MOOXS/Z.^_L47U;m?^v7s]zfow...@v*j-=I#]MBVE9K^:8^0U5+ZK+ZGI M]*740,RDN#95Qrz[1tq...@b6qg9V?TH;S2O62-[ZF3GWF,YF@ MYD+VW1=%$G*IL(JEWY(!;?#`B9VF\=BY?^NNRH?+JH\^W#SB+8HMT0!5 m...@99U-,TX$)!#M3\EC=T3D/5KK(4BP;G:46D6GN.ME]TO\5K;+39^ M7.+*U][WB[[40/UWVAS]G4(4*Y!E!)7']S^K2\*XFD`J:#,-#4LP'DT mk0kp...@^72y@^[UBC;:a_5m6*y]55...@d$@161EQI]GOJ7S[6EUZ*S% M1`JNMDHUI]3D+)NZVQ:O9813(?`^O+/!+8J]FZ'2P)SRB\+ZKOLJ`:(?NB MJFBKJ=18`N7F3BAU6SKE0';.E%)\:4c^z...@akeg...@=15X\W9QRJ
Re: Asian characters are not printed propely in console
On Tue, 04 Jan 2011 11:47:32 +0200, Jun bli...@naver.com wrote: Should I use different type and prefix or suffix similary to C++? Place the following code anywhere at the top level in your program: version(Windows) { import std.c.windows.windows : SetConsoleCP, SetConsoleOutputCP; static this() { SetConsoleCP(65001); SetConsoleOutputCP(65001); } } This code should really be in the standard library, I think. -- Best regards, Vladimirmailto:vladi...@thecybershadow.net
terminology: l-value r-value
Hello, I'm bluffed by the 2 terms l-value r-value used in C-line language common terminologies. I think I guess what they mean, but I don't understand the need for such absconse idioms. Why not: l-value - variable r-value - value (or expression) ? I guess (*p) is considered an l-value. Indeed, it's a special way of denoting a variable, matching the special case of a pointer. If correct, this requires slightly extending the notion of variable (and/or of identifier). On the r-value side, I cannot find anything that makes it a distinct concept from the one of value, or of expression. Explanations welcome, thank you, Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: terminology: l-value r-value
On 01/04/2011 02:55 PM, spir wrote: Hello, I'm bluffed by the 2 terms l-value r-value used in C-line language common terminologies. I think I guess what they mean, but I don't understand the need for such absconse idioms. Why not: l-value- variable r-value- value (or expression) ? I guess (*p) is considered an l-value. Indeed, it's a special way of denoting a variable, matching the special case of a pointer. If correct, this requires slightly extending the notion of variable (and/or of identifier). On the r-value side, I cannot find anything that makes it a distinct concept from the one of value, or of expression. Explanations welcome, thank you, Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com rvalue is easier than value-not-bound-to-a-memory-address. lvalue is easier than value-with-memory-address. Both lvalues and rvalues are values, both can be expressions, and lvalues doesn't have to be variables. Perhaps a better terminology could have been chosen, but changing them doesn't provide real benefits, as far as I can tell.
Re: terminology: l-value r-value
On Tue, 04 Jan 2011 08:55:07 -0500, spir denis.s...@gmail.com wrote: Hello, I'm bluffed by the 2 terms l-value r-value used in C-line language common terminologies. I think I guess what they mean, but I don't understand the need for such absconse idioms. Why not: l-value - variable r-value - value (or expression) ? I guess (*p) is considered an l-value. Indeed, it's a special way of denoting a variable, matching the special case of a pointer. If correct, this requires slightly extending the notion of variable (and/or of identifier). On the r-value side, I cannot find anything that makes it a distinct concept from the one of value, or of expression. Explanations welcome, thank you, Denis lvalue stands for left value, rvalue stands for right value. They describe which side of the equation they are on: lvalue = rvalue; Why these terms instead of something more natural? Well, I have no idea :) If I were to guess, it would be that no natural term could exactly describe the meaning, and also that using natural terms are subjective. There's no mistaking what lvalue and rvalue mean becausey they are defined by the language itself. I'm sure Walter probably knows the origin, l and r values are really compiler terms, and he's been writing compilers for a long time. -Steve
Re: Why does the example on page 8 of TDPL work without importing std.algorithm for splitter?
On 4/01/2011 9:26 p.m., Lars T. Kyllingstad wrote: On Mon, 03 Jan 2011 17:18:34 -0600, Ellery Newcomer wrote: If you're importing some other phobos module, I would guess an instance of this bug: http://d.puremagic.com/issues/show_bug.cgi?id=314 On 01/03/2011 10:56 AM, Bryce Watkins wrote: However when I use splitter in my code it works without having imported std.algorithm. That's right. std.string does a public selective import of startsWith() and endsWith() from std.algorithm, and bug 314 causes the whole module to be imported publically. 314 is a huge, gaping hole in the module system. AFAIK, it's a high- priority bug, but also one that is very difficult to fix for some reason. -Lars Thanks now I understand, this also means that the example on page 8 only works because of bug 314, and should this bug ever be fixed then the example code will break. Therefore it really should include an import of std.algorithm explicitly for both clarity and long term reliability. Bryce.
Re: terminology: l-value r-value
Steven Schveighoffer wrote: They describe which side of the equation they are on arg, no! please replace equation by assignExpression. -manfred
Re: terminology: l-value r-value
On Tue, 04 Jan 2011 12:56:53 -0500, Manfred_Nowak svv1...@hotmail.com wrote: Steven Schveighoffer wrote: They describe which side of the equation they are on arg, no! please replace equation by assignExpression. please replace arg with argh! ;) But whatever floats your boat. -Steve
Re: terminology: l-value r-value
On Tue, 4 Jan 2011 17:56:53 + (UTC) Manfred_Nowak svv1...@hotmail.com wrote: They describe which side of the equation they are on arg, no! please replace equation by assignExpression. lol, great! this is one of the reasons why in my dream language, assignment would be denoted by any other sign *but* =. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: terminology: l-value r-value
Steven Schveighoffer wrote: please replace done. :-) -manfred
joining multicast groups with std.socket
I am trying to listen to a multicast group using the std.socket library. I have looked at the documentation but I do not see a way to join a multicast group. The code I have so far is pasted below. I am looking for the IP_ADD_MEMBERSHIP socket option (along the lines of http://www.cs.unc.edu/~jeffay/dirt/FAQ/comp249-001-F99/mcast-socket.html) and can't find within the library. Let's assume I am trying to listen to 225.0.0.37/12345 Can someone help me with a snippet on some d code that will do this? I appreciate the help! Peter auto socket = new UdpSocket(); auto address = new InternetAddress(12345); socket.bind(address); auto multicastAddress = new InternetAddress(225.0.0.37); /// The below naturally does not work and I can't seem to find // How do I join the multicast address above? byte[256] buffer; int read = socket.receiveFrom(buffer); printf(Received bytes %i, read); return 0;