Re: is there a cleaner way to new a static sized array?
BCS wrote: I need a function that works like the following: T* New(T)() { return new T; } But that also works with static arrays: auto i = New!(int)(); auto a = New!(int[27])(); The cleanest solution I can think of is: T* New(T)() { return (new T[1]).ptr; } but that seems ugly. Any ideas? Does something like this work as expected? T* New(T)() { static struct X { T x; } return &(new X).x } (untested)
Re: exceptions
Ellery Newcomer wrote: On 02/24/2010 12:37 PM, Robert Clipsham wrote: On 24/02/10 17:51, Ellery Newcomer wrote: import tango.core.tools.TraceExceptions; If you want to use gdb then type 'b _d_throw_exception' (or 'b _d_throw' for dmd) before you run your app. This will break on every exception thrown, so you may have to hit 'c' a few times to continue at each thrown exception until you find the one you need. Thanks! b _d_throw gives me Function "_d_throw" not defined. same for _d_throw_exception. I can get a breakpoint on _d_arraycopy, but there seem to be way too many calls for it to be useful. Hmm, that's odd... if you type b _d_t or b _d_ then you should get a list of runtime functions, do you see anything listed there that could be related? It seems odd to me that that function isn't there, it always is for me. I'm pretty sure I use a debug version of the runtime though, so that could be it. Your best option is probably to use Tango's built in stack tracing for now if you can't get gdb working properly. I've never had issues with it, but I use a custom version of gdb with the D patches applied, as well as a compiler built with debug symbols, and the runtime/other libraries built with them too in most cases. Oooh! nice trick! Ah, it's '_d_th...@4' and quotes help. Yahoo! By the way, that's because someone defined _d_throw to have Windows calling convention, even on Linux. I wonder what that's useful for. Do I need to do anything special to get stack tracing to work? when I try to compile a simple program it barfs on me and gives undefined reference to `dladdr' from import tango.core.tools.TraceExceptions; You must link to libdl (-ldl). void main(){ int[] i = [1,2]; int[] j = new int[3]; j[] = i[]; } oh well. Thanks a ton, I'm back in business now!
Re: immutable string literal?
Steven Schveighoffer wrote: On Mon, 22 Feb 2010 09:27:57 -0500, strtr wrote: Thanks, I understand. But, how about a runtime error? Isn't a literal placed in easy to identify should-only-read memory? A segfault is a runtime error. The problem with Windows is it doesn't throw an error on writes to its data segment (unlike Linux). In reality, the result of your program is undefined, so don't expect any help from the compiler/runtime. There's nothing D1 can do about that. In order for D to intercept that, it would have to instrument every write to memory, and that would cause performance problems like you wouldn't believe. Windows can protect memory as read-only too. Why dmd doesn't do that is a mystery. Even if .exe doesn't support read-only data segments, the runtime could have done so in early start-up code. The short answer: Just don't do that. -Steve
Re: Why isn't == used to compare structs
Don wrote: Trass3r wrote: Why isn't == used to compare the struct members in the code above? I mean, if I compare the structs with == it could also use == to compare the members. If I use "is" to compare the structs it could use "is" to compare them members. Structs are compared *bitwise*! Not in D2, any more. If a member has an opEquals, it's compared using ==. Seems arrays inside structs still are not compared with ==.
Re: converting a byte array to a struct array?
Trass3r wrote: grauzone schrieb: Second, the bug: casting arrays at compiletime seems to behave differently from casting at runtime. Casting at compiletime doesn't reinterpret cast, it does conversion! Demonstration here: http://codepad.org/OGjXADdu Feel free to file some bug reports. Just found out this is stated as a feature in the docs. http://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral Interesting. then this is an anti-feature too. At least it sounds like a very bad idea. The compiler/language tries to be "smart" here, but only introduces inconsistencies. http://codepad.org/bvk63OPw
Re: What wrong did i do? (key in hashtable is always null)
The Anh Tran wrote: This is just a small D exercise. I port c++ knucleotide from shootout.alioth.debian.org Issue 1: If i manually listing hashtable contents, the key does exist in that ht. But (key in hash_table) always yield null. Worse, if i use: "auto val = ht[key]", an exception is thrown. Problem code is from line 163 to 177. Issue 2: If I pass an AA (uint[ulong]) to a template function. DMD complains that uint[ulong] is void. How can i get the type of AA? DMD 2.037. Linux Ubuntu. Source code: ftp://ftp.4utours.com/dualamd/Dlang/knu5.d Is your opCmp/toHash really called? Maybe the function signature is off, and dmd doesn't "find" the function. Just a guess, I don't really know how this D2 stuff works. Sample data: ftp://ftp.4utours.com/dualamd/Dlang/fa50k.txt Thanks.
Re: Memory RAM usage
bearophile wrote: (I have recently seen a 13X speedup in a not synthetic program just modifying how memory is used and reducing memory usage, keeping the same algorithm. I can show you an URL if you want). Yes, please do! Do you know how can Free Pascal use so little RAM? Here in this nbody benchmark (a simple N body gravitational simulation) it seems to use less than half of the memory used by C, yet the C code is tight and clean enough, and both use 64 bit floating point numbers: http://shootout.alioth.debian.org/u32q/benchmark.php?test=nbody&lang=all&sort=kb In other benchmarks memory usage of Free Pascal is not dramatically lower, but it's usually near the top of lower memory usage in all Shootout benchmarks. No idea. I just know that FPC doesn't use GCC. I think it doesn't even link to libc! (I can't really confirm, ldd crashes on the executable produced by fpc.) Maybe it just avoids some constant overhead due to this. Bye, bearophile
Re: define new types within templates
teo wrote: There was a way to define new types within templates and I think that I have seen that demonstrated here in the newsgroups, but cannot find it now. Can someone help me please? I would like to do something like this: template MyTemplate(T) { struct T ~ "Struct" // define FooStruct structure { int x; } class T ~ "Class" // define FooClass class { void bar(T ~ "Struct" t) { // ... } } } void main() { mixin MyTemplate!("Foo"); FooStruct t; FooClass f = new FooClass(); f.bar(t); } Hopefully I am not mistaken. I don't know for what you're asking, but there's absolutely no need to use string mixins (see Trass3r's reply). Instead you can just define a type inside the template, and then access it by instantiating it: template MyTemplate(T) { struct Struct { T x; } } void main() { MyTemplate!(int).Struct t; t.x = 123; } You can use mixin MyTemplate!(int); to bring "Struct" into the module namespace, and you can use e.g. "alias MyTemplate!(int) IntStruct;" to save typing.
Re: converting a byte array to a struct array?
Trass3r wrote: I got some RGB palette in a byte array which I'd like to convert or "map" to an RGB struct array, isn't this easily possible without using dozens of struct constructors? RGB[256] PALETTE = cast(RGB[256]) [ 0x00, 0x00, 0x00, 0xE3, 0x53, 0x00, 0xCF, 0x4B, 0x07, 0xBF, 0x43, 0x0F, ... doesn't work cause of "non-constant expression" RGB[256] PALETTE = (cast(RGB[]) [ 0x00, 0x00, 0x00, 0xE3, 0x53, 0x00, 0xCF, 0x4B, 0x07, 0xBF, 0x43, 0x0F, ... ]) (0 .. 256); compiles, but yields empty structs (and doesn't seem right anyway). You've hit both an anti-feature and a bug. First the anti-feature: [0xAB, ...] will yield an int[], not a ubyte[] (I guess ubyte[] is what you're expecting). If you cast two arrays, the compiler will reinterpret cast all data. The result won't be what you intended. Second, the bug: casting arrays at compiletime seems to behave differently from casting at runtime. Casting at compiletime doesn't reinterpret cast, it does conversion! Demonstration here: http://codepad.org/OGjXADdu Feel free to file some bug reports.
Re: floating point verification using is?
bearophile wrote: Steven Schveighoffer: If I have 2 identical floating point values, how do I ensure they are binary equivalents of eachother? Try this inside std.math of Phobos2: bool isIdentical(real x, real y); I thought 'a is b' would work, but it just morphs into a == b, which isn't helpful. Why doesn't 'is' just do a bit compare for floating points? "is" is used to compare references. No. If you use it with structs, the type's opEquals is not called. "is" is used for a lot of things. I agree that is should do a bitwise comparison for floating points. That would be a nice fix for D2. Bye, bearophile
Re: Immutable & circular imports
Tomek Sowiński wrote: Amusing things happen when immutable arguments and circular imports are put together: -- module hello; import test; struct Strukt { Staly* s; } -- module test; import hello; immutable struct Staly { int a; } void f_strukt(Strukt* stk) { f_staly(stk.s);// ups! } void f_staly(Staly* s) { } -- Error: function test.f_staly (immutable(Staly)* s) is not callable using argument types (Staly*) Error: cannot implicitly convert expression ((*stk).s) of type Staly* to immutable(Staly)* Am I writing code too weird or is this a compiler bug? The only thing about circular imports on D page is: "Cycles (circular dependencies) in the import declarations are allowed as long as not both of the modules contain static constructors or static destructors." So what I tried to pull off seems fair game. There are a _lot_ of circular dependency bugs, and there are a lot of immutable related bugs. Combine both together and you get... probably even more bugs. Tomek
Re: Tempated class instantiation
Mike L. wrote: I'm making a class template that only works with strings, so I thought it'd be good to instantiate each template with char, wchar, and dchar right in the template's module so that when it's compiled it'll be part of the .obj file and won't have to compile it for every other project that uses it. However, I get an error reproducible with this: module test; class A(T) { version(broken) { class B { T blah() { return t; } } } T t; } mixin A!(int); int main() { A!(int) a = new A!(int)(); return 0; } If what I want to do makes sense, how should I be doing it? AFAIK it works if you do alias B!(int) Something; If you want to get the above code to work, use template A(T) instead of class A(T) + mixin.
Re: Compilation constants
Phil Deets wrote: On Wed, 11 Nov 2009 13:34:32 -0500, Phil Deets wrote: On Wed, 11 Nov 2009 13:30:17 -0500, Phil Deets wrote: On Wed, 11 Nov 2009 08:50:48 -0500, bearophile wrote: In a C program I have a numeric constant SIZE (that is in [1,32]), that I can define when I compile the code, like this: gcc -DSIZE=14 ... How can I do the same thing in D? The solution I have found is to put in the D code: version(B1) const SIZE = 1; version(B2) const SIZE = 2; version(B3) const SIZE = 3; version(B4) const SIZE = 4; ... version(B14) const SIZE = 14; ... And then compile the D program with: dmd -version=B14 ... Or: ldc -d-version=B14 ... Do you know nicer ways to do this in D? (if there are no nicer ways, is this simple feature worth adding to D?) Thank you, bye, bearophile What I would probably do is generate a simple .d file right before you compile. I'm used to using forums where I can post, look at what I wrote, then edit if necessary. To continue my thought, the file could be called constants.d and it could contain just be just one line: enum SIZE=14; Or use import expressions and mixins, something like mixin("SIZE="~import("config.txt")); But actually, that's horrible. See, I need edit functionality :). s/just be just/just/ You can delete your posts to emulate editing...
Re: FMOD working with Windows
Joel Christensen wrote: grauzone wrote: Joel Christensen wrote: FMOD sound (record and play) is off D Programming web site. http://wiki.dprogramming.com/FMod/HomePage I followed instructions from the web site. But one instruction said to use 'coffimplib.exe' but I couldn't see where it is to download it, and one link wasn't found (Dr.Dobb). You can avoid the whole crap with linking to a .lib and use derelict. Derelict simply dynamically loads the DLL. I've already tried derelict. I don't know how to use it to either record or even play audio files. 1. Get the derelict fmod bindings (I think they are not in the derelict svn, but there's a link on the derelict project page on dsource) 2. import derelict.fmod.fmod; 3. DerelictFMOD.load(); 4. Use the fmod API normally I have in the past gotten FMOD working (record and play I think, record at lessed) with C++. Using the tools 'copy' and 'paste'. Also there's a library I use that has recording ability, but I don't how to use it either.
Re: FMOD working with Windows
Joel Christensen wrote: FMOD sound (record and play) is off D Programming web site. http://wiki.dprogramming.com/FMod/HomePage I followed instructions from the web site. But one instruction said to use 'coffimplib.exe' but I couldn't see where it is to download it, and one link wasn't found (Dr.Dobb). You can avoid the whole crap with linking to a .lib and use derelict. Derelict simply dynamically loads the DLL.
Re: How to run unittests?
al wrote: It seems that unittests are not run (I've tried putting while(1){} and writef() there - no effect). Even this code doesn't run assert(): import std.stdio; int main(string[] args) { assert(args.length == -1); writef("shouldn't work!"); return 0; } I'm using: dmd -debug -w -unittest -run main.d Is there a secred debug switch, or is it simply a bug? Which version of DMD is usable? (I've got v1.050) I think it's a bug. Works for me under Linux. I guess the OSX versions of dmd are simply not in a useable state yet.
Re: How to override function?
Zarathustra wrote: I would like to know, how to override function if subclass and super class are located in the same package and different modules. For instance when they are in the same module: //___ module main; class Foo{ this(){ proc(); } void proc(){ writefln("Foo"); } } class Bar : Foo{ override void proc(){ writefln("Bar"); } } void main(){ new Bar; } //___ the result is "Bar" so it's great, but: //___ module pack.foo; class Foo{ this(){ proc(); } package void proc(){ // without 'package' it works well writefln("Foo"); } } //___ module pack.bar; class Bar : Foo{ package override void proc(){ // without 'package' it works well writefln("Bar"); } } //___ module main; void main(){ new Bar; } //___ the result is "Foo" so it's unexpected to me. It's a bug. package functions are never virtual, and the "override" attribute is just ignored. Same with private. Welcome to D.
Re: Sorry, I just love templates, AAs and mixins :)
Saaa wrote: public void addToAA(char[] var_name, KT, ET)(KT key, ET element) { mixin(ET.stringof~`[]* elements = key in `~var_name~`;`); if( elements == null ) { ET[] temp; temp.length = 1; temp[0] = element; mixin(var_name~`[key] = temp;`); } else { (*elements).length = (*elements).length + 1; (*elements)[(*elements).length-1] = element; } } It's unreadable. What the hell does it do? How do you use it? It's a good example how you can write-only code in D.
Re: Sizeof class instance
Justin Johansson wrote: grauzone Wrote: Justin Johansson wrote: How does one determine the sizeof (in bytes) of an instance of a class in D? .sizeof works as advertised for structs, but for reference types, .sizeof yields the sizeof the referencing variable (effectively same as size of a pointer) and not the size of the underlying instance. As Jarrett said, x.classinfo.init.length is the simplest way in D1. I did try scanning the NG and read spec_D1.00.pdf. Perhaps I missed it in the latter. I guess that PDF is horribly outdated, although it may work for some purposes. btw. I was poking under the hood of std.xml and though, wow, instances of Element class look humongous, and so I'm interested to how exactly how humongous. Wasn't std.xml for D2? Anyway, last what I remember is that std.xml is unmaintained, slow, buggy, and shouldn't be seriously used. Yes and yes. I'm currently using D1 but with view to D2 am having a peek at it's libs. I can see why std.xml in D2 is slow, and would not be surprised if buggy as well; it is quite disgusting code that's been hacked together without any real rhyme or reason. So guess I'll be writing my own stuff and leveraging on C libs where possible. Got Expat parser running with D without too much trouble. In case you didn't know, Tango's XML parser is said to be even faster than other commonly used XML parsers in C/Java: http://dotnot.org/blog/archives/2008/03/10/xml-benchmarks-updated-graphs-with-rapidxml/ Also: http://prowiki.org/wiki4d/wiki.cgi?AllLibraries/XmlLibraries Thanks for comment grauzone. -- Justin Johansson
Re: Sizeof class instance
Justin Johansson wrote: How does one determine the sizeof (in bytes) of an instance of a class in D? .sizeof works as advertised for structs, but for reference types, .sizeof yields the sizeof the referencing variable (effectively same as size of a pointer) and not the size of the underlying instance. As Jarrett said, x.classinfo.init.length is the simplest way in D1. I did try scanning the NG and read spec_D1.00.pdf. Perhaps I missed it in the latter. I guess that PDF is horribly outdated, although it may work for some purposes. btw. I was poking under the hood of std.xml and though, wow, instances of Element class look humongous, and so I'm interested to how exactly how humongous. Wasn't std.xml for D2? Anyway, last what I remember is that std.xml is unmaintained, slow, buggy, and shouldn't be seriously used. Thanks for all help. Justin
Re: Linking in an .so on linux with rebuild?
Daniel Keep wrote: I found a solution. See http://stackoverflow.com/questions/335928/linux-gcc-linking-ld-cannot-find-a-library-that-exists For me, I needed readline and history, so I did this: $ cd /lib $ sudo ln -s libreadline.so.5 libreadline.so $ sudo ln -s libhistory.so.5 libhistory.so After that, ld didn't complain. Interesting. On my system (Debian), the libreadline.so symlink is in a separate -dev package. Who knows why.
Re: Linking in an .so on linux with rebuild?
Nick Sabalausky wrote: I can't seem to get that to work. Tried all sorts of stuff. Off the top of my head: -ll This should work. If the lib is named "libsomething", don't include the "lib": -llsomething Excluding the "lib" seems to be standard on Unix-like OSes. -ll.so "-L-l " "-L-l .so" -L-l -L -L-l -L.so None of them were able to find the file (and, yes, the name+path are right), and I'm not using any links.
Re: D1: std.md5: corrections for the given example
notna wrote: grauzone schrieb: md5_example_2.d(7): expression expected, not 'auto' md5_example_2.d(7): found 'len' when expecting ')' md5_example_2.d(7): found '=' instead of statement (this is line 7 after I removed comments and blank lines from your edit) Stewart. God I'm stupid. Sorry. I guess I wish that worked. http://d.puremagic.com/issues/enter_bug.cgi ??? What do you wanna tell us? That while (auto len = file.readBlock(buffer.ptr, buffer.sizeof)) has to work and does not because it's a bug? And that's why you think a bug report should be opened? Enhancement request to allow auto in while, to make it consistent with if. (You can write "if(auto x = foo()) {...}")
Re: D1: std.md5: corrections for the given example
downs wrote: Stewart Gordon wrote: downs wrote: while (auto len = file.readBlock(buffer.ptr, buffer.sizeof)) md5_example_2.d(7): expression expected, not 'auto' md5_example_2.d(7): found 'len' when expecting ')' md5_example_2.d(7): found '=' instead of statement (this is line 7 after I removed comments and blank lines from your edit) Stewart. God I'm stupid. Sorry. I guess I wish that worked. http://d.puremagic.com/issues/enter_bug.cgi
Re: How does D cope with aliasing
#ponce wrote: Stewart Gordon Wrote: My recollection of reading the spec is that a D compiler is allowed to optimise by assuming no pointer aliasing. But I can't remember at the moment where I read this. I don't know if this is neat or nasty for a compiler to do so. OT : Is there a DMD switch to disable bound check exceptions ? This way I wouldn't have to rely on pointers so much. If you always want DMD never to bounds check for specific code, you just can write "a.ptr[index]" instead of "a[index]" (when a is an array). That's because array.ptr returns a pointer to the first element, and using [] on a pointer works exactly like C pointer math. The good thing about this is that you still can use array slices and the .length field, so the code most likely is less messy than the C version would be.
Re: Any way to workaround Optlink crash?
div0 wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Jérôme M. Berger wrote: Max Samukha wrote: Tom S wrote: Max Samukha wrote: COFF/ELF output would not be that bad though, at least if there's some linker that supports these *and* its license allows it to be bundled with DMD. I doubt such a linker exists. And if it does, I doubt it is of quality good enough to replace OPTLINK. GNU ld supports these formats on *nix, windows and MacOS. It has very good quality and its license allows it to be bundled with anything... Jerome Yeah but have you actually linked a D program with it? (esp. on 'doze) Probably that wasn't really clear: dmd on Linux uses GNU ld for linking. Walter has an ELF backend for this. Walter also wrote a backend for Mach for the MacOSX port. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFKnZkuT9LetA9XoXwRAv5BAJ4+P/lRQsHCVN/eDrZaAgPvHsbWZACdF/Dx 7CQ28E5zAM4v2aNWM9RCMms= =kOpB -END PGP SIGNATURE-
Re: Error: constant false is not an lvalue
I wouldn't be surprised if W himself has forgotten about this rule, since other parts of the spec make no mention of it, or seem to depend on the default-initialization of variables. "If the Initializer is void, however, the variable is not initialized. If its value is used before it is set, undefined program behavior will result." http://www.digitalmars.com/d/1.0/declaration.html And below that, there's even an example with local variables. I think what you were referring to is an outdated part of the specification, especially because "= void;" was added only recently. (Which also shows how worthless the specification is: not only incomplete, but full or inconsistencies and errors?) As to whether initializing variables by default or disallowing reading uninitialized values is better: I think it's very annoying, if the compiler tries to be smart, but then comes in to your way. Additionally, the result of the uninitialized value detection might end up being compiler specific, and that wouldn't be beautiful at all anymore. Actually, that case is very likely, since Walter would never rigorously define how exactly it should be done.
Re: Error: constant false is not an lvalue
Jarrett Billingsley wrote: On Sun, Aug 30, 2009 at 12:24 AM, Ary Borenszweig wrote: Steven Schveighoffer escribió: On Sat, 29 Aug 2009 20:15:55 -0400, Ellery Newcomer wrote: void blah(out bool a = false){ // blah blah blah } compile time use of blah results in error. Am I doing anything wrong? out implies a reference. You can't have a reference to a manifest constant like that. If you want to ensure a is false at the beginning of the function do: void blah(out bool a) { a = false; // blah blah blah } -Steve Or just not write it, because "out" automatically initializes the value of the variable to it's default one, in the case of bool it's false. Although teeechnically speaking that would be illegal code. The D spec says that it's not legal to use the value of uninitialized variables. Default initialization is kind of a poor man's substitute for actual flow control which determines that. By relying on default Am I the only one, who likes the current behaviour, and finds it annoying to be forced by the compiler to initialize all variables? initialization, you're relying on what is actually nonconformant behavior, and it could be broken in the future or by a smarter compiler. How is this nonconformant? Initialization is guaranteed by D. But we're getting really technical here ;)
Re: Strange calculation problem
bearophile wrote: Lars T. Kyllingstad: I think the compiler should be smart enough to figure this out for itself, but until that happens you can work around it by suffixing at least one of the integer literals with LU, so the compiler interprets the entire expression as an ulong: To make this fix happen Walter has to know this problem exists... And this is why bug reports were invented... Bye, bearophile
Re: CRTP in D?
bearophile wrote: I don't know much C++. Can CRTP be used in D1 too, to improve the performance of some D1 code? http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern Why don't you just go and try? If you hit forward referencing errors when using structs, try classes with final methods. Bye, bearophile
Re: 'static' keyword for positional array initialization
Ali Cehreli wrote: Lars T. Kyllingstad Wrote: I've tried with DMD 2.031, and I can't reproduce this. This works fine for me: int[2] static_0 = [ 1, 1 ]: int[2] static_1 = [ 1:1 ]; Where did you put the declarations? I've tried putting them at both module level and in a class, and both times it compiled without problems. Thank you very much for both of your answers. :) I hadn't realized that the location of the definitions would make a difference. As you say, both of the lines work for me in the global scope (probably in a class too), but not in main: void main() { int[2] static_0 = [ 1, 1 ]; int[2] static_1 = [ 1:1 ]; } dmd: init.c:431: virtual Expression* ArrayInitializer::toExpression(): Assertion `j < edim' failed. The 'static' keyword on the 1:1 line fixes the problem... The error message is a compiler bug, but AFAIK the code above is not valid anyway. The special initializer syntax (apparently called static inittializers) for arrays and structs only works for data that's stored on the data segment. This applies for global variables, static variables, and class member initializers. It simply doesn't work for normal variables, which allocate their storage on the stack.
Re: Pointer to method C++ style
LOOKUP_TABLE[0] = Method("method1", &Component.method1); LOOKUP_TABLE[1] = Method("method2", &Component.method2); These two lines are weird. ``pragma(msg)`` shows that type of ``&method1`` is ``void function()`` while it must be ``void delegate()`` for a non-static member because of difference in calling convention. Actually I think that taking an address of a non-static member in a static context must be a compile time error. It's because I'm taking the address of the function on the type, not on an instance. It's not a delegate because there's no "this" pointer yet. It makes sense to me anyways. A delegate is a normal function pointer coupled with a hidden context parameter. But you can't call that function pointer. Actually, you can probably subvert type safety, because functions have a different calling conventions from delegates. This also means that SafeD should disallow taking the address of methods from a type (without instance). That's really silly. A nicer way would be to make &Type.method return a delegate with ptr set to null. Then calling this delegate would result in a (harmless) null pointer exception. But even then, there's no safe way to construct a real delegate out of the method pointer. You can't simply assign an object instance to ptr, because you can't statically know if the funcptr of the delegate really is a method of that object instance. Looks like SafeD proves to be unfeasible again.
Re: dmd crashes with "out of memory" error
Trass3r wrote: Robert Fraser schrieb: File is probably too big. Remember that for every byte in your binary, DMD is likely allocating several hundred for the literal xpression object + codegen for the expression, etc., and frees very little dynamically allocated memory. So we can't even embed a 1.7 MB file? For embedding data, use import() (http://www.digitalmars.com/d/1.0/expression.html#ImportExpression). Or did you do this? I don't know the file size restrictions of import either.
Re: Array slice length confusion
Daniel Keep wrote: Tim Matthews wrote: Kagamin wrote: Tim Matthews Wrote: I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi. Current plan is to introduce new type - array - into the language. Do you know the ng posts or where ever that was posted? Best bet would be to search for "T[new]". Superseded by Andrei's Array struct.
Re: Should be easy
Ever heard of recursion? Why don't you simply handle all types recursively? Why do you need this "array depth" stuff?
Re: Inside the switch statement
BCS wrote: Hello grauzone, http://groups.google.com/group/net.lang.c/msg/66008138e07aa94c Many people (even Brian Kernighan?) have said that the worst feature of C is that switches don't break automatically before each case label. Oh god, that's from 1984, and even today we're struggling with this bullshit in the most modern dialect of C, D. I'm sorry, you don't have my sympathy on this one. There are to many place I've used fall throught to chuck it out. What kind of fall-throughs were these? A: case value1: case value2: case valueN: code1(); break; B: case value1: code1(); case value2: code2(); break;
Re: Inside the switch statement
http://groups.google.com/group/net.lang.c/msg/66008138e07aa94c >Many people (even Brian Kernighan?) have said that the worst feature of C is that switches don't break automatically before each case label. Oh god, that's from 1984, and even today we're struggling with this bullshit in the most modern dialect of C, D.
Re: legal identifier check
Saaa wrote: Hello Saaa, static if(is(typeof({ /* code to be checked for validity goes here */ }))) ... How does that piece of code work anyways :D that checks to see if the {...} is a valid delegate literal by using is() to see if semantic checks fail. Ah, I see. Can this be done at runtime? You have to write it yourself. Here's a good starting point: http://www.digitalmars.com/d/1.0/lex.html#identifier
Re: Encoding problems...
Robert Fraser wrote: > Jarrett Billingsley wrote: >> On Wed, May 27, 2009 at 8:55 PM, Robert Fraser >> wrote: >>> Hi all, >>> >>> Quick question: I want to use some unicode identifiers, but I get >>> "unsupported char 0xe2", both with using and not using a BOM. The characters >>> in question are the superset/subset-equals operators: ⊇ and ⊆... Perhaps >>> these are just unsupported by DMD (in which case, I'll file a bug)? >>> >>> Thanks, >>> Robert >> If they're not classified as "universal alpha" I don't think you can >> use them in identifiers. How the hell did your news client switch from UTF-8 to Japanese-something? (charset=UTF-8 => charset=ISO-2022-JP) > > Lame. K; thanks. Don't worry, people working with your code will be thankful!
Re: synchronized and thread
reimi gibbons wrote: if i encapsulate a part of statements within function with synchronized keyword and then let says 1 thread is calling the function, then another thread try to access it, will d put the later thread to wait (sleep) until the 1st call finished it or it will signal failure to access? thanks The other thread will wait.
Re: Comparing D structs
Dan wrote: That sounds great, and seems like yet another reason for me to switch to D (other than the removal of header files which always seemed like a kludge). I heard that the compiler can change the padding bytes to non-null on some occasions. For example, the compiler could treat member a as 32 bit value when assigning it: struct { char a; //offset 0 int b; //offset 4 } Nothing in the C standard says that the compiler has to preserve the padding bytes between a and b. So I was told. Just for the record though, I think one can initialize/blank/calloc C structs too, but the problem is that some struct elements (of the same array) may have padding while others don't, or perhaps they have different size paddings. Not sure what you mean.
Re: Comparing D structs
Dan wrote: Structs can't easily be compared in C because of potential 'padding' inside the struct which may (or may not) exist. I was jut wondering if D somehow gets round this, and allows something like memcmp to easily compare two structs. How about using the == operator?
Re: Who wants to have some fun memory debugging?
Maybe it's time to put together an instrumented GC... Wishlist: - some way to know _when_ a collection happened (or how often) - logging of allocations (module/linenumber of allocator, size of allocation, type of allocation) - per TypeInfo allocation statistics - per module allocation statistics
Re: Who wants to have some fun memory debugging?
Wild guess: there's a false pointer, that keeps one element in the list from being collected, and because the list-prev pointers are still there, all following elements won't be collected either in consequence. If I had time, I'd try two experiments: 1. before freeing everything, reset the prev field of each element; if this makes the leak go away, my guess would probably be right 2. use the destructor (Data had to be a class) to keep track of how many elements are actually freed by the GC (just a thread safe counter, that's incremented in the ctor and decremented in the dtor); just to find out if this is an internal GC problem, or if you have too many live garbage
Re: 3 variant questions
Dear Saaa, these varargs suck badly and you shouldn't use them. It's so simple to introduce portability errors or heisenbugs, and it's incredibly hard to get it right. You're better off with alternatives. Alternative 1: Typesafe Variadic Functions Useful if the variadic arguments should have only one type. And they're very easy to use. It's documented somewhere on http://www.digitalmars.com/d/1.0/function.html Alternative 2: Tuples http://www.digitalmars.com/d/1.0/template.html#TemplateTupleParameter The variadic arguments can have any types, but such functions can't really be virtual methods or delegates. Why is this extra step necessary and why won't simple casting not work? You should never directly work with _argptr. It's not guaranteed to be a simple pointer. For example, I believe that GCC will sometimes use registers (God only knows WHY). I think it's because GCC tries to keep the usual calling convention, where some arguments are passed as registers. Which is utterly pointless and stupid (ok, maybe it was easier to implement in gdc), and turns using varargs into hell. It would be so simple if _argptr was just an array of pointers to the actual arguments. It'd be so simple it makes me mad.
Re: D input: how-to (RFC)
int read(/+File inFile = stdin,+/ A...)(out A a) /+Uncommenting results in: Error: arithmetic/string type expected for value-parameter, not File+/ That would make inFile a template parameter, which obviously doesn't make sense with objects, and I guess File is an object. This should work: int read(A...)(File inFile, out A a) OK... that works, but how would I set stdin as the default input "file"? You can't have default arguments and variadic arguments at the same time. That's just how the syntax works. At best, you could change the signature to "int read(A...)(ref A a)". Then you could check if the first argument is of the type File, and if not, use a default value for inFile, and so on. I tried: int read(A...)(out A a, File inFile = stdin) but the compiler hangs trying to compile it whenever I call read() using 50% of the CPU resource in the process. No matter if it's allowed or not, the compiler shouldn't hang. Maybe report a bug: http://d.puremagic.com/issues/ bools can't be read? If the implementation is incomplete, there should be at least an "assert(false);", maybe even a "static assert(false);". Got it. What value would you read for a bool though? to me it can be 0||1, true||false, yes||no, etc... Would I simply use 0 && 1 and forget about the rest? Because this function seems to deal with user input, maybe you should allow as many as possible. else static if(is(typeof(t) == string)) if(a.length > 1) a[i] = input[i]; else a[i] = data; Also, the array index i isn't checked for input, and random things could happen. (You'd get an exception in debug mode, but not in release mode.) ??? not sure what you mean here. i is the index of the variable as it appears in the tuple "A". Why would I need to check it for input? i is valid as long as we have not reached the end of the tuple. You loop over a, so a[i] will always be correct. But input[i] could be out of bounds, as far as I can see. Shouldn't split() already remove all white space? split removes the white space but only from the copy of the string returned. The original remains untouched. Oops... right.
Re: D input: how-to (RFC)
Tyro[a.c.edwards] wrote: I am looking for a D version of scanf() but I'm sure there is no such thing so I tried contrived one. I am sure I missed a slew of obvious There's readf() in std.stream. I think you have to use std.cstream : din to use it with stdin. int read(/+File inFile = stdin,+/ A...)(out A a) /+Uncommenting results in: Error: arithmetic/string type expected for value-parameter, not File+/ That would make inFile a template parameter, which obviously doesn't make sense with objects, and I guess File is an object. This should work: int read(A...)(File inFile, out A a) { start: auto data = stripr(readln()); auto input = split(data); string assign() { return ` try { if(a.length != input.length) return -1; a[i] = to!(typeof(t))(input[i]); } catch (ConvError e) { writeln("Invalid input!"); goto start; }`; } If the user types in too much or too less input, read() returns with an error (-1), and the caller has to deal with it. If the user typed in something unparseable, the function prompts an error and lets the user retry. This is inconsistent. Also, instead of using CTFE to return a const string, why not simply const assign = ` ` ; You're using D 2.0, you probably have to replace "const" by "enum". I don't know. You use goto to retry. I'd replace it by a loop. If someone wants to argue with me if goto is or is not evil, go ahead. foreach(i, t; a) { static if(is(typeof(t) == void)) {} else static if(is(typeof(t) == bool)) {} bools can't be read? If the implementation is incomplete, there should be at least an "assert(false);", maybe even a "static assert(false);". else static if(is(typeof(t) == byte)) mixin(assign); else static if(is(typeof(t) == ubyte)) mixin(assign); else static if(is(typeof(t) == short)) mixin(assign); else static if(is(typeof(t) == ushort)) mixin(assign); else static if(is(typeof(t) == int)) mixin(assign); else static if(is(typeof(t) == uint)) mixin(assign); else static if(is(typeof(t) == long)) mixin(assign); else static if(is(typeof(t) == ulong)) mixin(assign); /+static if(is(typeof(t) == cent)) mixin(assign); static if(is(typeof(t) == ucent)) mixin(assign);+/ else static if(is(typeof(t) == float)) mixin(assign); else static if(is(typeof(t) == double)) mixin(assign); else static if(is(typeof(t) == real)) mixin(assign); Oh god, what the fuck! String mixins are the new #define! OK, at least this reduces the code duplication, but the code duplication shouldn't be there in the first place. You could just throw all the types into a tuple, and then foreach() on it, checking for the type in each iteration. Or just make a single giant if() statement to check for all types to!() supports (like if(is(typeof(t) == int) && is(typeof(t) == uint)...). In any case, you could reduce the number of is() parts by using isNumeric() from std.traits. Or find a way to check for to!() supported data types automatically (but I don't know to!() well enough if this is possible). else static if(is(typeof(t) == ifloat)) a[i] = ifloat.max; else static if(is(typeof(t) == idouble)) a[i] = idouble.max; else static if(is(typeof(t) == ireal)) a[i] = ireal.max; else static if(is(typeof(t) == cfloat)) a[i] = cfloat.max; else static if(is(typeof(t) == cdouble)) a[i] = cdouble.max; else static if(is(typeof(t) == creal)) a[i] = creal.max; What? else static if(is(typeof(t) == char)) a[i] = input[i][0]; input could be an empty string, and random things could happen. else static if(is(typeof(t) == wchar)) mixin(assign); else static if(is(typeof(t) == dchar)) a[i] = input[i][0]; else static if(is(typeof(t) == string)) if(a.length > 1) a[i] = input[i]; else a[i] = data; I see, if the caller of the function only requests a char[], the splitting by white space is disregarded, and the whole string is returned. Isn't that a but inconsistent? At least, it could always return the remainder of the string, if this char[] parameter is the last of the function. Also, the array index i isn't checked for input, and random things could happen. (You'd get an exception in debug mode, but not in release mode.) Also, http://en.wikipedia.org/wiki/Dangling_else else static if(is(typeof(t) == dstring)) {} else static if(is(typeof(t) == char[])) a[i] = stripr(data).dup; Shouldn't split() already remove all white space? } return 0; }
Re: dmd on ubuntu installation
Michael P. wrote: Michael P. Wrote: Mike Parker Wrote: Michael P. wrote: Frits van Bommel Wrote: Michael P. wrote: But when I type dmd in the terminal, I get this: mich...@ubuntu:~$ dmd bash: /usr/local/bin/dmd: Permission denied mich...@ubuntu:~$ Do you know why? Looks like you didn't "chmod +x" it. Zip files don't store *nix permissions... Okay, but what should I do to fix that? I tried: mich...@ubuntu:~$ chmod u+x /usr/local/bin/{dmd,dumpobj,obj2asm,rdmd} chmod: changing permissions of `/usr/local/bin/dmd': Operation not permitted chmod: changing permissions of `/usr/local/bin/dumpobj': Operation not permitted chmod: changing permissions of `/usr/local/bin/obj2asm': Operation not permitted chmod: changing permissions of `/usr/local/bin/rdmd': Operation not permitted mich...@ubuntu:~$ but that happened. :( Try adding 'sudo' to the front of the chmod command line. You have to execute it as root. Okay, I still can't run dmd. I get the same thing. But it works when I do sudo dmd. mich...@ubuntu:~/d$ cd .. mich...@ubuntu:~$ sudo chmod u+x /usr/local/bin/{dmd,dumpobj,obj2asm,rdmd} [sudo] password for michael: mich...@ubuntu:~$ dmd bash: /usr/local/bin/dmd: Permission denied mich...@ubuntu:~$ sudo dmd Digital Mars D Compiler v1.043 Copyright (c) 1999-2009 by Digital Mars written by Walter Bright Documentation: http://www.digitalmars.com/d/1.0/index.html Usage: *snip* mich...@ubuntu:~$ dmd bash: /usr/local/bin/dmd: Permission denied mich...@ubuntu:~$ Any suggestions now? BTW, I did get a .d file to compile. Had to use 'sudo dmd' and not just 'dmd'. The files are probably not readable (r) or executable (x) by all other users (o). Try "chmod o+rx /usr/local/bin/dmd".
Re: Resource availability: fonts
http://digitalmars.com/d/1.0/expression.html#ImportExpression It returns a char[], which is a misdesign, because the loaded file can be binary data as well. I think.
Re: Resource availability: fonts
Use ubyte[] fontbytes = cast(ubyte[])import("yourfont.ttf");
Re: Get the name of a function and the parameters?
D". Because a D compiler that doesn't use DMD's front-end is not D compatible. Because the front end *is* the specification of the language. ...and it's full of bugs.
Re: Get the name of a function and the parameters?
Jarrett Billingsley wrote: On Tue, Apr 28, 2009 at 10:23 PM, Daniel Keep wrote: That requires f to be a type, which loses you the actual names. And you cannot (last time I checked) have aliases in a tuple. Check again - tuples can be any arbitrary mix of types, expressions, and aliases. :) Wow, it actually works. But I really don't understand why. It seems the compiler directly passes symbols as tuple arguments, and later dumbs it down to what it needs (like an alias, a type, ...). Makes me think nobody will ever be able to write a separate bug-free DMD frontend. I'm scared.
Re: Get the name of a function and the parameters?
Jarrett Billingsley wrote: On Sun, Apr 26, 2009 at 12:23 PM, Jacob Carlborg wrote: Is it possible to get the name of a function and the names of the function parameters? Name of a function? Yes. public template NameOfFunc(alias f) { version(LDC) const char[] NameOfFunc = (&f).stringof[1 .. $]; else const char[] NameOfFunc = (&f).stringof[2 .. $]; } debug { private void _foo_(){} static assert(NameOfFunc!(_foo_) == "_foo_", "Oh noes, NameOfFunc needs to be updated."); } It has to be used at compile time with an alias of course, but it works. I'd like to pass several functions at once. Is there a way to make this variadic? The obvious approach (writing "NameOfFunc(alias f...)") fails with a syntax error. Name of params? No, not that I've found. Sometimes the compiler will give parameter names of functions declared with tuple parameters in error messages; I wonder if that could be abused. Don't you love it? "Most C++ template features are discovered." So are D's.
Re: static initialization of associative arrays
What's the advantage of doing this? Having quicker startup times? Syntax. Read the first post of this thread.
Re: clone method of Object
bearophile wrote: grauzone: the clone method will only copy member b, but not a or c. A *good* implementation of this function seems fit to be added to Phobos. And serialization, and a complete reflection API. Bye, bearophile
Re: clone method of Object
There are two things on my side: 1. Compiler refuses to clone private attributes. I have tried gdc/gdmd/dmd_v1 in Linux. It was changed in dmd later, and now you can access private attributes by using tupleof. I don't know when exactly it was changed, but it should work at least with dmd 1.039 and later. GDC probably uses an ancient front-end version, and I think nobody should use it.
Re: clone method of Object
Qian Xu wrote: grauzone wrote: newobject.tupleof[i] = old.tupleof[i]; If the current value of tupleof[i] is an object, the object will be referenced, won't it? Shall I write: auto elem = old.tupleof[i]; static if (is(typeof(elem) == class)) { newobject.tupleof[i] = clone(elem); } else { newobject.tupleof[i] = elem; } Object graphs often contain circular references liker this: class A { B b; } class B { A a; } auto a = new A(); auto b = new B(); a.b = b; b.a = a; Your recursive approach wouldn't quite work with that. Before cloning an object, you'll first have to check if the object was already cloned. If this is the case, use the previously created clone instead of making a new clone. --Qian
Re: clone method of Object
grauzone wrote: Qian Xu wrote: Hi All, is there any (easy) way to clone an object or any other classes? --Qian Simple answer: No. Complicated answer: Yes, but you have to write it yourself. Here's a nice starting point. You can use tupleof to get all members of a class. Note that this doesn't deal with superclasses, and members of superclasses are not copied: T clone(T)(T old) { auto newobject = new T(); foreach (int i, _; old.tupleof) { newobject.tupleof[i] = old.tupleof[i]; } return newobject; } cloned = clone(yourobject); I should add that members of subclasses are not copied either. E.g. if you have class A {int a;} class B : A {int b;} class C : B {int c;} B someobject; clone(someobject); the clone method will only copy member b, but not a or c.
Re: clone method of Object
Qian Xu wrote: Hi All, is there any (easy) way to clone an object or any other classes? --Qian Simple answer: No. Complicated answer: Yes, but you have to write it yourself. Here's a nice starting point. You can use tupleof to get all members of a class. Note that this doesn't deal with superclasses, and members of superclasses are not copied: T clone(T)(T old) { auto newobject = new T(); foreach (int i, _; old.tupleof) { newobject.tupleof[i] = old.tupleof[i]; } return newobject; } cloned = clone(yourobject);
Re: Indexing an associative array with a list of types
What exactly are you trying to accomplish? It seems that you want to use the AA in CTFE, but it doesn't work, because using AAs with classes as keys don't work in CTFE?
Re: Indexing an associative array with a list of types
Doctor J wrote: I'd like to make a compile-time constant associative array mapping a list of types to an integer: int[??] typemap; typemap[(int,float)] = 1; typemap[(long,double)] = 2; ... int t = typemap[(int,float)]; I tried playing with std.typetuple but no luck. I can get halfway there with a function template, but then I can't iterate over the keys or values. Is there a way to do something like this in D? More generally, is there a way to store a type in a variable? Just curious, how did you do this function template thing? Thanks. Types are a compiletime only thing. To get a "runtime" handle for a type, use TypeInfo. For each type, there exists exactly one TypeInfo object instance. You can get this object with typeid(): TypeInfo ti = typeid(int); Your example above could actually be implemented like this: int[TypeInfo[]] typemap; typemap[[typeid(int), typeid(float)]] = 1; (Two [] bracket pairs because one is for indexing into the AA, and one is an array delegate for constructing the TypeInfo[] array, which is used as key.)
Re: Class templates with types determined at runtime
Not sure what you're actually trying to do, but you can do this: class Container { abstract void dostuff(); } class ContainerSDgsdg(T) : Container { override void dostuff() { //can use T here } } Container bla = new ContainerSDgsdg!(int)(); //can pass around "bla" freely, because class Container is not //templated! the actual class is, but this doesn't matter. bla.stuff();
Re: Format.convert problme
Qian Xu wrote: grauzone wrote: Check if the variable is a pointer, and if yes, dereference it: alias typeof(i) T; static if (is(T T2 : T2*)) { T2 i2 = *i; Format.convert("{}", i2); } else { Format.convert("{}", i); } Hi again, I cannot compile this code What exactly are you doing? What do you want to do? Without knowing this, we can only guess. My first reply to you was also just a guess. I thought maybe you had a templated function, and wanted to dump a templated variable, or so. Anyway, here's a complete version of my example above. It uses Stdout.formatln instead of Format.convert, but this shouldn't matter at all. import tango.io.Stdout; void main() { int v = 55; int *pv = &v; //pv (an int pointer) can be exchanged with v (an int), //and it still works auto i = pv; alias typeof(i) T; static if (is(T T2 : T2*)) { T2 i2 = *i; Stdout.formatln("{}", i2); } else { Stdout.formatln("{}", i); } }
Re: Format.convert problme
Qian Xu wrote: Hi All, tango.text.convert.Format provides a nice function to convert anything to string. It works perfect except the argument is a pointer type. It will print the address of a pointer instead of its value For instance: int* i = new int; *i = 10; Format.convert("{}", i); // <- the address of the pointer -- How to let it print the value instead of the address? Because I wanna write a dump function to dump the value of any data type (also void, null) Check if the variable is a pointer, and if yes, dereference it: alias typeof(i) T; static if (is(T T2 : T2*)) { T2 i2 = *i; Format.convert("{}", i2); } else { Format.convert("{}", i); }
Re: What's the purpose of the -v1 switch?
Jarrett Billingsley wrote: On Wed, Apr 1, 2009 at 12:01 PM, Trass3r wrote: I mean it can only be used with dmd 1.x compilers anyway. else if (strcmp(p + 1, "v1") == 0) { #if DMDV1 global.params.Dversion = 1; #else error("use DMD 1.0 series compilers for -v1 switch"); break; #endif } It turns off the features which were added to D1 after 1.000. Things like the 'ref' and 'macro' keywords, string mixins, import expressions, changes to .init etc. So, technically, we already have a D 1.1?
Re: About alias
Trass3r wrote: Sam Hu schrieb: I am confused again this time about the key word alias when I read below tutorial: http://www.dsource.org/projects/tutorials/wiki/MetaBinarySearch Let's say this one: template bSearch(alias Match, alias Fail, alias x, A...) { const bSearch = bSearchAlg!(0,Match,Fail,x,A); } what is the meaning of the 'alias ' before parm Match in the parms list,and what's the purpose? http://www.digitalmars.com/d/2.0/template.html#TemplateAliasParameter Be aware that alias parameters are only available in D2.0. Wrong: http://www.digitalmars.com/d/1.0/template.html#TemplateAliasParameter
Re: dump object
Qian Xu wrote: Hi All, previously I saw an article about how to dump an object with all properties. -code--- void log(T)(T obj) { static if (is(T == struct) || is(T == class)){ writef("{"); foreach(i,_;obj.tupleof) { writefln("%s : %s,", obj.tupleof[i].stringof[4..$], obj.tupleof[i]); } writefln("}"); } else { writefln(obj); } } -code--- But this function does not work with private attributes of an object. How to print all public properties of an object? It would be very useful for debug propose. Use a newer compiler version. dmd 1.041 should work. I'm successfully using this feature for serialization. Best regards --Qian
Re: LPT
Jarrett Billingsley wrote: On Wed, Mar 25, 2009 at 5:00 PM, Jarrett Billingsley wrote: On Wed, Mar 25, 2009 at 4:21 PM, Zarathustra wrote: Have you got any idea how to manipulate LPT port in Windows XP with D? Um, the same way you'd do it with any other language...? I mean, if you computer even _HAS_ an LPT port. I haven't seen one in years. My computer is only a year old and has one LPT and two serial ports. The only traditional thing that's missing is a floppy drive.
Re: How to reduce compile times?
Jarrett Billingsley wrote: On Sat, Mar 21, 2009 at 3:45 PM, grauzone wrote: Also, I noticed that "dsss build -full" seems to be the way to pass this flag on the command line. But the project is recompiled even when no file was modified at all. This is not good: it should only recompile if something has changed. Why would you recompile if you haven't changed anything? :P I want to build system to recompile the program automatically before I execute it. Doing this manually is not an option, because it's annoying and I could forget it.
Re: How to reduce compile times?
Brian wrote: On Sat, 21 Mar 2009 15:44:41 +0100, grauzone wrote: I'm using dsss (with dmd under Linux) to compile my project, and build/compile times are reaching unacceptable highs. out of curiosity, how much code do you actually have? im using D for something with ~12,000 lines of code right now, spread among 40 files or so, with a somewhat excessive use of CTFE and templates all over. a full rebuild takes about 5 seconds with incremental builds taking 1 or 2 seconds in most cases. i just wanted to know what "excessively high" means P.S. using dmd 1.036, rebuild 0.78, phobos, linux 65906 physical lines of code (+ some Tango .di imports + some small external libraries), maybe 200+ files, takes 1m10s to build when using normal dsss. With -full and oneatatime=no, compile time goes down to 6-7 seconds. It's not that template- and CTFE-heavy. Incremental builds can take relatively long (depending where the changed files are in the dependency tree), and it's really annoying.
Re: How to reduce compile times?
I use bud, which builds everything with a single run of dmd, but uses incremental compilation. If I get linker errors, I just run my cleanup script and try again. Or add -full to bud's command line. In my case, this practically always causes linker errors. Of course I don't know why.
Re: How to reduce compile times?
Jarrett Billingsley wrote: On Sat, Mar 21, 2009 at 2:50 PM, grauzone wrote: What I need is to make dsss completely recompile the project, even if only a single source file was modified. This way, no errors should occur, and it would still be faster than with oneatatime=yes. -full Sorry for being so helpless, but where do I add this to the rebuild configfile? Also, I noticed that "dsss build -full" seems to be the way to pass this flag on the command line. But the project is recompiled even when no file was modified at all. This is not good: it should only recompile if something has changed.
Re: How to reduce compile times?
Christopher Wright wrote: grauzone wrote: PS: another thing that possibly would bring a speed gain would be to make dsss compile the whole project in one run, instead of invoking a new dmd process for each source file. How do I need to change the rebuild configuration to achieve this? oneatatime = [yes|no] You want 'no'. This will occasionally produce issues with ModuleInfo not being defined with some dmd versions, I think. Or something like that. Yes, this causes random linker errors. What I need is to make dsss completely recompile the project, even if only a single source file was modified. This way, no errors should occur, and it would still be faster than with oneatatime=yes. (Damn that crappy support for incremental compilation.)
Re: DSSS verbose mode?
The closest thing that I know is "dsss build -v"
How to reduce compile times?
I'm using dsss (with dmd under Linux) to compile my project, and build/compile times are reaching unacceptable highs. What are some tips to speed up the build process? For example, I could imagine that heavy use of templates and CTFE slows the compiler down. Maybe string mixins with CTFE on the module level are most expensive: here, the compiler has to do heavy weight semantic analysis every time a module is imported from another module (maybe even recursively). But I don't really know; it depends too much on how the compiler works internally. Without some kind of "build profiler", I have no clue what is actually causing slow downs. It's like groping in the dark! The only thing that comes near to this seems to be to insert a "pragma(msg, blabla)" at random points in your modules. Then you recompile the project and count how many times the message is outputted. Actually, the whole issue seems to boil down to reducing module dependencies. But then again, your "main" module recursively depends from _all_ used modules in your project. What I personally found useful in practice is to reduce the number of interdependent modules by separating them into interface and implementation modules, e.g. by using delegates or inheritance. Then you can "hide" the implementation from most modules by removing the static dependencies. But this only works in some cases, and is always inconvenient. PS: another thing that possibly would bring a speed gain would be to make dsss compile the whole project in one run, instead of invoking a new dmd process for each source file. How do I need to change the rebuild configuration to achieve this?
Re: Universel toString
Daniel Keep wrote: Qian Xu wrote: Hi All, I want to write an universel toString() method for debugging propose. However I cannot write in one version. The compiler says error all the time. Could someone tell me, how to write an universel one? What I want, is to convert primtive types (int, int*, bool, bool*, etc.) to string using "tango.text.Convert.to()" and convert object to string by calling obj.toString. ... Best regards --Qian Xu to!(char[]) should call toString. to!(T) should support all atomic types, strings, structs and classes. So to!(char[])(x) almost like format("%s", x)? -- Daniel
Re: Char[] confusing
Qian Xu wrote: Lutger wrote: s[4] means the fifth element of s[] s[0..4] is a slice from the first to the fifth, but not including the fifth element. The last element in a slice is always one past the end of that slice. Thank you both. I have to do math in mind in order to keep my code correct ;-) IMO, it does not make any sense. s[start..end] end - is neither the count of characters in the array slice, nor the end index of the slice. it is just the index after the real end character. Think of it as "everything in the string before this."
Re: chaining
Brian wrote: I want to use a chaining system for easy setting of object attributes, which would work great for a single object, unfortunately derived classes cannot inherit the chained functions implicitly, whats the best way around this? class Base { int x; Base foo(int x_) { this.x = x_; return this; } } class Derived : Base { Derived bar(int y_) { return this; } } // usage: auto m = (new Derived).foo(10).bar(x); // bar can be accessed through foo Couldn't you just write the above example as: auto m = new Derived; m.foo(10); m.bar(x); This is actually much more readable: the reader doesn't need to know that the functions foo and bar return m; instead, the code uses m directly. Obviously, this is also simpler to implement than chaining. I don't get why some people like chaining. Unlike in languages like C++, you can always use "auto" to keep the typing to a minimum. What more arguments are there for chaining?
Re: Dynamic Array Garbage collection
Jarrett Billingsley wrote: On Tue, Feb 24, 2009 at 10:42 PM, Daniel Keep wrote: You missed the array literal. I saw that, but thought that it would be a short[] literal since it's usually the type of the first argument. Odd, it works. And properly too. Could it be because of integer promotion rules? I give up on trying to figure out what the compiler does to figure out the type of array literals :P
Re: "Symbol undefined" on interface with public getter and package setter
Last time I checked I could even use "override" to... erm, override methods that had package protection. The compiler didn't even complain, and I had to find out the hard way that the method wasn't virtual.
Re: Encoding of eol in multiline wysiwyg strings
Jarrett Billingsley wrote: On Tue, Feb 17, 2009 at 4:41 AM, KlausO wrote: Hello, does the D specification specify how the "end of line" is encoded when you use wysiwyg strings. Currently it seems to be '\n' on windows (And I guess it will '\n' on linux, too.). Is this the intended behaviour ? http://www.digitalmars.com/d/1.0/lex.html "Wysiwyg Strings Wysiwyg quoted strings are enclosed by r" and ". All characters between the r" and " are part of the string except for EndOfLine which is regarded as a single \n character." It's not a big issue but somtimes when you use wysiwyg strings, string concatenation and import expressions to combine some text the result is a string with mixed EOL encodings. Thanks for clarifying, It's the import() expression that's messing things up. It just loads the file verbatim and does no line-ending conversions. But many people would like to use import() to read binary data. I guess one could extend the language specification to solve this: //load, convert line endings, check for valid UTF-8 char[] import_text(char[] filename); //return unchanged file contents as byte array ubyte[] import_binary(char[] filename); On the other hand, both could be implemented as compile-time functions using the current import().
Re: get a struct member pointer
bearophile wrote: Daniel Keep: void lookup(T)(T[] s, size_t offset) { char[] text = *cast(char[]*)(cast(void*)(&s[0]) + offset); } I am learning still this topic, but can't this create an aliasing problem, as in C? http://www.cellperformance.com/mike_acton/2006/06/understanding_strict_aliasing.html My theory is, that Walter's code generator is too primitive to care about aliasing. But I guess it's possible, that aliasing rules will be added later to the language, when LDC (hopefully) gets big? By the way, wtf is Daniel's code doing at all? Bye, bearophile
Re: Internal error: ..\ztc\evalu8.c 2093
John Reimer wrote: Hello Zarathustra, When I trying build dwt-win 3.4.1 I get the following error: Internal error: ..\ztc\evalu8.c 2093 command line: dsss build I using DSSS 0.78, Tango 0.99.7 with DMD 1.033. OS: Windows XP Any ideas? Can you try a more recent compiler... like dmd 1.037? Also, I would highly recommend /not/ using DSSS version 0.78. I suggest you use 0.75. You can use 0.78 if you enjoy looong build times. :) I still use dsss 0.75, because it's the only dsss version, which can build my project without generating linker errors all the time. I also see that you recommend dmd 1.037. That's funny, because that's the latest "stable" version for me as well. Later dmd versions just go into an infinite loop or so when compiling my project. -JJR
Re: Compare two objects
Qian Xu wrote: Hi All, I want to test, if two objects are equal. The rules are as follows: 1. When both are null, it should return true. 2. When one of them is null, it should return false. 3. When both not null, then compare their values (as two strings) My test code --- class Test { private int value; this(int value) { this.value = value; } public int getValue() { return this.value; } bool opEquals(Test obj) { if (obj is null) { return this is null; } return this.getValue() == obj.getValue(); } } procedure test(Test a, Test b) { if (a is null && b is null) return true; if (a !is null && a == b) return true; return false; } void main() { Test a; Test b = new Test(100); assert(test(a, b)); // ok assert(a != b); // av error } If object at the left side of the != is null, I will get an AV error immediately. If I want to compare two objects safely, I have to write my own test(..) function. But this is not nice. Can someone explain, is this a design shortcoming of D-Compiler, or I am wrong. It's a shortcoming in the design of the == operator. Code like "a==b" will always be compiled to this: > a.opEquals(b) If a is null, the call will always cause a segfault. You simply can't call a method on a null object. There are two reasons for this: 1. it will dereference the object's vtable to look up virtual methods and 2. the runtime will try to call the object's invariant, which segfaults too. (Actually, I see an assert with a null check in _d_invariant(). But somehow, gdb usually still shows a segfault in _d_invariant(). Maybe Phobos isn't compiled in debug mode.) The D compiler even has a special rule to disallow compilation of code like "a==null" (yes, because of the null literal). It seems Walter added this, because people were using this code to check if an object is null. Conclusion: == is absolutely useless in your case. Use something else. Best regards --Qian Xu
Re: Time some code using Tango
Jarrett Billingsley wrote: On Tue, Feb 3, 2009 at 5:54 PM, Matthias Walter wrote: Hi there, I'd like to time some functions using Tango, but only including the really used CPU-time. StopWatch and the other time functions I've found don't mind on the CPU usage, which means if I time multiple processes at once which share a single CPU, their times increase... Best regards Matthias Walter That's something that the OS could do for you, like the "timex" command on unix. There's probably something magical in /proc/ that you can use. I have no idea what the corresponding functionality would be in Windows, but it probably has something. If he had to use OS specific APIs (which would be another sad thing about Tango), I'd suggest to use clock_gettime() with CLOCK_THREAD_CPUTIME_ID under Unix. What is timex?
Re: Some performance questions
I agree. Of course using an interface to call a method always requires a virtual method call. It's even slower than a virtual method call, because it needs to convert the interface reference into an object reference. But he still could call the method in question directly. Implementing an interface can be useful to enforce a contract. You can't do that with structs. Code compiled in debug mode (or was it not-release mode) also calls the code to check the invariant, even if you didn't define one. I guess this can make calling struct methods much faster than object methods.
Re: Some performance questions
Jarrett Billingsley wrote: On Mon, Feb 2, 2009 at 3:11 PM, Chris Nicholson-Sauls wrote: Or he's caching some very big/complex parameters in the code he's actually writing... maybe. That said: do we have any assurance that, were the functor class tagged as 'final', the call would cease to be virtual? If so, then the only extra cost on the call is that of the hidden "this" sitting in ESI. I still don't care for the memory allocation involved, personally, but if these are long-lived functors that may not be a major problem. (Ie, if he calls foo(?,X) a million times, the cost of allocating one object is amortized into nearly nothing.) Oh, I suppose I should also point out that if you made these functors' methods final, they wouldn't be able to implement interfaces, since interface implementations must be virtual. So, at that point, you're using a final scope class - might as well use a struct anyway. As far as I know, interface methods can still be final methods in a class. final methods are only disallowed to be overridden further. But it's perfectly fine to mark a method final, that overrides a method from a super class. final so to say only works in one direction. Then the compiler can optimize calls, if they are statically known to be final. If not, it still has to do a vtable lookup on a method call, even if the actually called method is final. So it can still make sense to use a class instead of a struct.
Re: Some performance questions
Jarrett Billingsley wrote: On Mon, Feb 2, 2009 at 8:31 AM, Lars Kyllingstad wrote: I have some functions for which I want to find the nicest possible combination of performance and usability. I have two suggestions as to how they should be defined. "Classic" style: real myFunction(real arg, int someParam, inout real aReturnValue) { declare temporary variables; do some calculations; store a return value in aReturnValue; return main return value; } The user-friendly way, where the function is encapsulated in a class: class MyFunctionWorkspace { declare private temporary variables; real anotherReturnValue; this (int someParam) { ... } real myFunction(real arg) { do some calculations; store a return value in aReturnValue; return main return value; } } I'm sure a lot of people will disagree with me on this, but let me first say why I think the last case is more user-friendly. For one thing, the same class can be used over and over again with the same parameter(s). Also, the user only has to retrieve aReturnValue if it is needed. If there are many such "additional" inout parameters which are seldom needed, it gets tedious to declare variables for them every time the function is called. I could overload the function, but this also has drawbacks if there are several inout parameters with the same type. My questions are: - If I do like in the second example above, and reuse temporary variables instead of allocating them every time the function is called, could this way also give the best performance? (Yes, I know this is bad form...) ...or, if not... - If I (again in the second example) move the temporary variables inside the function, so they are allocated on the stack instead of the heap (?), will this improve or reduce performance? I could write both types of code and test them against each other, but I am planning to use the same style for several different functions in several modules, and want to find the solution which is generally the best one. Any gains you get from skipping the initial calculations will be swiftly cut down by the cost of heap allocation and cache misses, if you allocate this object several times. A much better way to get the usability of the latter with the better performance of the former is to use a struct instead of a class. I highly doubt you'll be needing to inherit these "operation objects" anyway. The struct will be allocated on the stack, and you still get all the usability. Why not use scope to allocate the class on the stack? For everything else, I agree with Donald Knuth (if he really said that...)
Re: foreach/opApply is the visitor pattern
BCS wrote: Correct me if I'm wrong but I thing that D's opApply is a form of the Visitor pattern where the calling function's stack frame is the visitor object. This just occurred to me. Maybe I've been missing something re the visitor pattern but I think this make for a nice, cool and easy way to describe it. (Also I don't remember it being described that way) More importantly, why does it matter?
Re: foreach/opApply is the visitor pattern
BCS wrote: Hello Robert, BCS wrote: Correct me if I'm wrong but I thing that D's opApply is a form of the Visitor pattern where the calling function's stack frame is the visitor object. This just occurred to me. Maybe I've been missing something re the visitor pattern but I think this make for a nice, cool and easy way to describe it. (Also I don't remember it being described that way) Er no. There's no double-dispatch (at least automatically), there's only one foreach body delegate. The visitor pattern as far as I know it uses dynamic dispatch so the visitor object can handle different objects in the class hierarchy differently. For example, you couldn't use a foreach to enumerate through a syntax tree and handle expressions and statements differently (well, you could, but you'd have to do it manually). OK I'll grant that it doesn't follow the normal pattern to the letter but it can be viewed as a degenerate case where there is only one visitable type. Does that mean all function calls are a degenerate case of the visitor pattern?
Re: Segmentation error at the end problem (148 line program listing)
Daniel Keep wrote: grauzone wrote: The garbage collector isn't guaranteed to to free and destroy an unreachable object. That's because the GC is conservative. So if you want to be sure the object's resources are freed, you have to do it explicitly. I think you have two choices: 1. Remove close() from the destructor, and call close() manually when you're done. 2. Use scope or delete to ensure the destructor is always directly called, and never by the GC. Here's how you can use scope: { scope BlockFile f = new BlockFile(...); //... do something with f } //f goes out of scope, and the compiler inserts delete f; If you're going to do that, you really should make the it a scope class to ensure you never accidentally let the GC try to delete it. I (and a few others) petitioned what feels like years ago for a simple argument to dtors to distinguish between deterministic destruction (delete/scope) and automatic destruction (GC). Never gained any ground, sadly. I think it'd be even better to make them different functions. The finalizer could just be a virtual function called finalize(). Really, the differences between proper destructors and finalizers should be large enough to justify separate functions. Or even better, ditch finalizers and their wacky semantics (which make them quite useless anyway), and invent something like notify-able weakpointers. D already provides basic support for this (Object.notifyRegister()), but I think in Phobos 1.0 it's a bit buggy. There were some issues with race conditions and locking.
Re: Segmentation error at the end problem (148 line program listing)
The garbage collector isn't guaranteed to to free and destroy an unreachable object. That's because the GC is conservative. So if you want to be sure the object's resources are freed, you have to do it explicitly. I think you have two choices: 1. Remove close() from the destructor, and call close() manually when you're done. 2. Use scope or delete to ensure the destructor is always directly called, and never by the GC. Here's how you can use scope: { scope BlockFile f = new BlockFile(...); //... do something with f } //f goes out of scope, and the compiler inserts delete f;
Re: Segmentation error at the end problem (148 line program listing)
Charles Hixson wrote: I replaced BlockFile.close with: void close() { if (bf !is null) delete bf;//bf.close; bf = null; } But that didn't alter the segmentation fault. (Did you try it under D1 or D2?) Your destructor calls close(), and close() accesses the reference bf. But accessing references is not allowed in destructors. I think "delete bf;" still counts as accessing a reference. The reason is, that the garbage collector calls the destructor, when an object becomes unreachable. The order the destructors are called is undefined. References to other objects may no longer be valid, because these objects were already destroyed.
Accessing private class members with tupleof
Is it legal to access private members of a class using tupleof, when normal access would be illegal? It is not really clear from the D1.0 specification: > The .tupleof property returns an ExpressionTuple of all the fields in > the class, excluding the hidden fields and the fields in the base > class. Do private members count as hidden, or does the specification only consider the vtable and monitor fields as hidden fields? What exactly are "hidden fields" at all? It seems newer dmd versions allow you to access private members, while older versions raise a compile-time error. Here is an example to demonstrate the issue (for D1.0): ---file a.d module a; class Test { int a = 1; protected int b = 2; private int c = 3; package int d = 4; } ---file b.d module b; import a; int[] get(Test t) { int[] result; foreach (i, x; t.tupleof) { result ~= t.tupleof[i]; } return result; } import std.stdio; void main() { //outputs [1,2,3,4] writefln(get(new Test())); }
Re: Prevent default-initialised struct
I think it would really suck to introduce special cases to forbid default initialization of structs. And assuming T was the type of the struct, what would T.init do? Or typeid(T).init()? Use a class instead. If you really need a struct, you could use a private field, that signals if the struct was properly initialized. E.g. struct Foo { debug private bool initialized; static Foo opCall() { Foo n; debug n.initialized = true; return n; } void foo() { assert (initialized); //do something useful } }