Re: Dynamically Sized Structs
On Thu, 17 Apr 2014 14:40:25 -0400, Kagamin s...@here.lot wrote: So you assert that variable length structs can't be allocated on heap and sokoban example is a wrong example of variable length struct usage? And how heap indirection is different from stack indirection? It's still indirection. I think the biggest issue I would have with your implementation would be if I wrapped it in another struct that I wanted to store on the heap. -Steve
Re: std.file.read returns void[] why?
On Thu, 17 Apr 2014 17:04:25 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Thursday, 17 April 2014 at 12:59:20 UTC, Steven Schveighoffer wrote: It was never possible. You must explicitly cast to void[]. void[] makes actually little sense as the result of whole-file read that allocates. byte[] is at least usable and more accurate. In fact, it's a little dangerous to use void[], since you could assign pointer-containing values to the void[] and it should be marked as NOSCAN (no pointers inside file data). However, when using the more conventional read(void[]) makes a LOT of sense, since any T[] implicitly casts to void[]. -Steve void[] will only make sense once you've accepted that void.sizeof == 1. It is already accepted that when we talk about length in a void[], it's the number of bytes. But the data has no formal type. But any array implicitly casts to void[]. This is why it makes a good parameter for read or write (when reading or writing the binary data). Well, I guess void[] is C++'s char* for indiscriminate buffers. Speaking of which, does void* trigger strict aliasing in D? This subject seems like a hot potato no-one wants to touch. No, it's equivalent to void *, not char *. in D, ubyte[] would be the equivalent of C's char *. -Steve
Re: std.file.read returns void[] why?
On Fri, 18 Apr 2014 02:04:16 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Thursday, 17 April 2014 at 21:27:44 UTC, Steven Schveighoffer wrote: On Thu, 17 Apr 2014 17:04:25 -0400, monarch_dodra monarchdo...@gmail.com wrote: void[] will only make sense once you've accepted that void.sizeof == 1. It is already accepted that when we talk about length in a void[], it's the number of bytes. But the data has no formal type. Well, I always thought that void[] slice meant there are slice.length items, starting at slice.ptr. I don't know the size of the individual items. For example, in C, a lot of functions take void* first, size_t num, size_t width. In fact, most of druntime functions take void[] buffers that work that way. There's an associated typeid, so that you can now how large each individual items are. import std.stdio; void main() { int[] x = new int[5]; void[] y = x; writeln(y.length); // 20 } When a function takes a typeid, that usually is because the translation is not made. In druntine cases, the compiler is removing the type, and sticking it into the typeid instead. But the length has not been translated to bytes! It's still in terms of the original type. In those cases, it's equivalent to: void[] y = *cast(void[]*)x; which would make y.length == 5. But any array implicitly casts to void[]. This is why it makes a good parameter for read or write (when reading or writing the binary data). I guess. I just find it kind of strange that a type that has no type would have an actual sizeof. Then again, I thought void had no sizeof in C, but I just checked, and I was wrong. It's a little strange, but while void has no size, void[] *does* have a size. The size is in bytes. You can think of an array as starts at this address, and ends at that address. Because addresses are in terms of bytes, so is the length of that array. I admit, I didn't think C's void had a size ;) I'm pretty sure it doesn't in D, but then again... -Steve
Re: Dynamically Sized Structs
On Fri, 18 Apr 2014 00:05:03 -0400, Kagamin s...@here.lot wrote: Well, it's proof of concept of bound checked variable-size struct, I wrote it in a minute. It even compiles and runs. Please take no offense :) I just was pointing out a difference between a hand-managed and hand-written struct that I might have written and the one that you created. Depending on usage, yours might be sufficient. Note, you could probably, with mixin magic, make a version that could be emplaced inside a struct or class without an extra indirection. -Steve
Re: Dynamically Sized Structs
On Fri, 18 Apr 2014 12:59:35 -0400, Kagamin s...@here.lot wrote: Oh, and I don't believe, that a variable-size struct can be emplaced inside fixed-size struct or class. Only as a smart pointer from the example. It goes at the end. Then you need to allocate the whole thing with that in mind. -Steve
Re: Reducing an array
On Thu, 17 Apr 2014 09:46:25 -0400, Tim Holzschuh via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Hi there, I try to remove all equal elements of an array, thus [2,2] -- [2]. I thought this maybe would be possible with std.algorithm.reduce, but at least the way I tried it doesn't work: arr.reduce( (a,b) = a != b ); reduce doesn't do what you think it does. It applies a function to all elements, keeping track of the result of each function call, and passing it to the next one. In other words, reduce!fn(a, range) is like doing this: fn(range[5], fn(range[4], fn(range[3], fn(range[2], fn(range[1], fn(range[0], a)); What you want is probably uniq: http://dlang.org/library/std/algorithm/uniq.html Note that it works on a SORTED range, so you want to sort first. Note also that what it returns is not an array, but a lazily iterated range over the array. If you want another array, this is the code I would use: arr.sort(); arr = arr.uniq.array(); -Steve
Re: toString() through interface
On Sat, 19 Apr 2014 20:45:50 -0400, Adam D. Ruppe destructiona...@gmail.com wrote: On Sunday, 20 April 2014 at 00:35:30 UTC, David Held wrote: Since all implementations of an interface must derive from Object That's not true. They can also come from IUnknown or a C++ interface. This is also not true. Only interfaces derived from IUnknown point to a COM object. Only interfaces marked as extern(C++) can point to a C++ object. Any interface that is purely D MUST point at a D object that derives from Object, EVEN D-defined COM or C++ objects (the latter doesn't really exist). His code should compile IMO. cast(Object)(foo).toString(); (cast(Object)foo).toString() might work This might return null tho if it is a non-D object through the interface! As stated above, this is not possible. -Steve
Re: toString() through interface
On Sat, 19 Apr 2014 20:51:49 -0400, David Held d...@wyntrmute.com wrote: On 4/19/2014 5:35 PM, David Held wrote: interface Foo { } class Bar : Foo { override string toString() pure const { return Bar; } } void main() { Foo foo = new Bar; foo.toString(); } To make things more interesting, consider the call to toString() from inside a class (which is closer to my actual use case): class Baz { override string toString() pure const { return cast(Object)(foo).toString(); } Foo foo; } This really makes the compiler go bonkers: src\Bug.d(11): Error: pure nested function 'toString' cannot access mutable data 'foo' src\Bug.d(11): Error: pure nested function 'toString' cannot access mutable data 'foo' src\Bug.d(11): Error: no property 'toString' for type 'Bug.Foo' src\Bug.d(11): Error: pure nested function 'toString' cannot access mutable data 'foo' src\Bug.d(11): Error: need 'this' for 'foo' of type 'Bug.Foo' Apparently, DMD features high-availability error reporting, because the first message might not be received by the programmer, so it writes it again, then gives you a different message, and writes it one more time, just in case there was a communication error or some other fault preventing you from receiving this important message about access to 'foo'. Again, the cast appears to do absolutely nothing, as the compiler insists on looking up toString() in Foo instead of Object. What is really peculiar is that message 1, 2, and 4 are complaining that Baz.toString() is not allowed to access foo because it is mutable. And yet, the 5th error message tells us how to fix it: just add 'this.': override string toString() pure const { return cast(Object)(this.foo).toString(); } Now we just get this: src\Bug.d(11): Error: no property 'toString' for type 'const(Foo)' To explain what the compiler is having trouble with, you have to understand precedence. cast(Object) does not come before '.' So what the compiler thinks you said is: return cast(Object)(this.foo.toString()); Others have said how to fix it. I just wanted to point out why you need to fix it that way. -Steve
Re: Regarding foreach loop index ranges
On Mon, 21 Apr 2014 07:49:03 -0400, bearophile bearophileh...@lycos.com wrote: In this case I am not sure about bug reports, so I ask here. In this program the first loop doesn't compile, giving a nice error: test.d(3,5): Error: index type 'ubyte' cannot cover index range 0..300 If you comment out the first loop, the second compiles and runs, but it seems to go in an infinite loop: void main() { int[300] data; foreach (ubyte i, x; data) {} // Error foreach (ubyte i, x; data[]) {} // compiles } For the second loop one possible alternative behavour is to refuse a ubyte index and accept only a size_t index if it loops on a dynamic array. Another alternative is: the i variable can go from 0 to 255, then go up to the modulus of the remaining indexes, and then stop. A third option is allow the code to compile, but throw an assert in non-release mode when the foreach statement is encountered ubyte cannot process all indexes of data. This would be the least code-breaking option that saves a bug (you don't know that the code can handle modulo indexes). Then you could deprecate to disallowing ubyte indexes. -Steve
Re: Best way to check for an element in an array?
On Mon, 21 Apr 2014 23:25:39 -0400, Taylor Hillegeist taylorh...@gmail.com wrote: So I find myself Doing this kind of thing very frequently. I have a Array of Somethings and i want to see if something specific is inside the array. I wrote a template for it. but is this the best way to do this kind of thing. I feel like it doesn't help with readability. Is there a better way? Maybe i missed something in the std library. import std.stdio; Change this: template FNDR(T){ To this: template isIn(T) { bool isIn(T Element, T[] Array){ bool rtn=false; foreach(T ArrayElement; Array){ if(Element==ArrayElement){ rtn=true; } } return rtn; } } void main(string[] args) { int[3] stuff=[0,1,2]; if (FNDR!int.isIn(2,stuff)) now: if(isIn(2, stuff)) see implicit function template instantiation (IFTI) in docs. Also, using UFCS (Unified Function Call Syntax (I think)), we can do: if(2.isIn(stuff)) Or if you swap the parameters, and perhaps rename your template/function: if(stuff.contains(2)) { writeln(Hello World!); } } -Steve
Re: Named template constraints
On Tue, 22 Apr 2014 10:58:41 -0400, Andrej Mitrovic via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On 4/22/14, Tim Holzschuh via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: What does (inout int = 0) mean/affect here? This was asked recently, see my reponse here: http://forum.dlang.org/post/mailman.102.1396007039.25518.digitalmars-d-le...@puremagic.com I think this can be fixed a different way: template isInputRange(R) { enum bool isInputRange = is(typeof( (R r) { R r2 = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront(); // can invoke popFront() auto h = r.front; // can get the front of the range })); } Note, is the r2 = R.init needed? Not sure. -Steve
Re: Named template constraints
On Tue, 22 Apr 2014 11:15:14 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:06:34 UTC, Steven Schveighoffer wrote: Note, is the r2 = R.init needed? Not sure. Yes: It R2 has no default init, or is an immutable, then that line will fail to compile. I don't believe it's possible to have no 'init'. I think the reason it says '= R.init' is for ranges that have @disable this(). Also, an immutable can be initialized that way: immutable int[] = int[].init; Of course, it wouldn't pass the rest of isInputRange. -Steve
Re: Array of interface only with cast()?
On Tue, 22 Apr 2014 11:19:57 -0400, Andre an...@s-e-a-p.de wrote: Hi, I just stumbled about this issue with array of interface. I want to pass several objects (C and D) which shares the same interface A. It seems somehow cumbersome that it only works if there is a cast on the first element of the array. interface A{} class B: A{} class C: B{}; class D: B{}; void main() { //A[] arr = [new C(), new D()]; // Does not work A[] arr = [cast(A) new C(), new D()]; // Does work } Is the cast really needed? At this point, yes. This is because the expression [new C(), new D()] does not take into account what you are assigning to (IMO it should). The compiler will use the most derived type possible that all the elements implicitly cast to. In this case, it will be a B[]. -Steve
Re: The lifetime of reduce's internal seed
On Tue, 22 Apr 2014 14:17:57 -0400, Ali Çehreli acehr...@yahoo.com wrote: I don't think there is slicing an rvalue though. (?) reduce() is taking a copy of the seed and then returning a slice to it because the user slices it in their lambda. It effectively does the following, which unfortunately compiles: int[] foo() { int[1] sum; return sum[];// -- no warning } It's not slicing an rvalue, but the above is trivially no different than: int[] foo() { int[1] sum; return sum; } which does NOT compile. The issue is that D's escape analysis is very very simplistic. It would be nice if it were better. Ironically, because of return type inference in lambdas, you circumvented the check! -Steve
Re: Named template constraints
On Tue, 22 Apr 2014 11:36:07 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:30:36 UTC, Steven Schveighoffer wrote: Also, an immutable can be initialized that way: immutable int[] = int[].init; Isn't that exactly R.init ? Yes, you said if it's an immutable it would fail to compile. I think this is not true. -Steve
Re: The lifetime of reduce's internal seed
On Tue, 22 Apr 2014 14:47:19 -0400, monarch_dodra monarchdo...@gmail.com wrote: In this case no, but; // int[1] foo(); int[] a = foo(); // *is* slicing an rvalue, and it *does* compile. I don't think there needs to be escape analysis to catch this. Oh yeah, that's bad. -Steve
Re: Named template constraints
On Tue, 22 Apr 2014 14:50:44 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 18:35:58 UTC, Steven Schveighoffer wrote: On Tue, 22 Apr 2014 11:36:07 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:30:36 UTC, Steven Schveighoffer wrote: Also, an immutable can be initialized that way: immutable int[] = int[].init; Isn't that exactly R.init ? Yes, you said if it's an immutable it would fail to compile. I think this is not true. -Steve Ah... you said: Note, is the r2 = R.init needed? Not sure. To whitch I replied: Yes: It R2 has no default init, or is an immutable, then that line will fail to compile. I meant that if you *don't* add the R.init, then the code will *not* compile. EG = R.init is necessary. Sorry for the mixup :/ OH!!! I meant is the whole *line* necessary, not the R.init part :) Note that in my updated version, r is passed in as a parameter to the mock function. This means if R is inout(something), it will be part of the parameters, and you don't need a dummy inout parameter to shut the compiler up. So the r2 = R.init; was just to keep things the same, but I'm not sure it's necessary to have. It has a comment saying can define a range object, whereas it could just be I need a range object to compile the rest of this code :) -Steve
Re: Variable Naming Issue (Conflicts?)
On Tue, 22 Apr 2014 15:35:33 -0400, Casey sybra...@gmail.com wrote: If I prefix all of the generated variables with an underscore, it works fine. It looks like the variable delete is the issue. To me, it looks like it's expecting some sort of delete method. delete is a keyword, it cannot be a symbol. -Steve
Re: Undefined symbol ModuleInfoZ when including a SWIG generated module
On Wed, 23 Apr 2014 20:34:11 -0400, Walter Gray walter.r.g...@gmail.com wrote: Hi there, I'm currently trying to set up a small demo project using the Leap Motion API in D. I've run SWIG with -d -d2, and created the intermediate C++ DLL along with a pair of .d files, leap.d and leap_im.d. I'm new to D, but very interested and I'd like to set this up in an idiomatic way be able to share it, but I'm running into a problem: When I create a simple sample project with Visual D and import the Leap module, I get a number of linker errors: Error 42: Symbol Undefined _D4Leap10Controller6__ctorMFZC4Leap10Controller (Leap.Controller Leap.Controller.__ctor()) Error 42: Symbol Undefined _D4Leap10Controller7__ClassZ Error 42: Symbol Undefined _D4Leap12__ModuleInfoZ I've discovered that if I run dmd manually and link in the object files for leap.d and leap_im.d, these problems go away, and if I create a separate project to build a .lib and then link to that it also solves the issue. Both of these options seem hacky to me though, and I'm wondering if there's some 3rd option I'm missing - the files contain the entire definitions, so why would it be necessary to link to them AND specify them as imports? What am I missing here? Every module in D generates a moduleinfo object. The runtime links all these together and uses it to run static constructors and destructors. It also contains runtime type info for any items defined within the module. Even if a module has only templates, or even if it's empty! You still have to compile and include it in the link step if it's imported from a module you are compiling. As for Visual D, I don't know much about how it works. -Steve
Re: Is this a bug?
On Mon, 28 Apr 2014 06:04:53 -0400, John Colvin john.loughran.col...@gmail.com wrote: On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote: not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; } struct T { int[10]* f; } void main() { int[10] test; T t = T(test); T* b = t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before. You don't need them. (*b.f)[4] works. '.' has precedence over '*'. -Steve
Re: Is this a bug?
On Tue, 29 Apr 2014 03:43:54 -0400, Andrey n...@none.no wrote: btw, short a,b,c; a = b + c; //error: cannot implicitly convert expression of type 'int' to 'short' Guys!! Tell me that I have an old slutty version of the compiler... No. It's due to integer promotion. All operations are done at the int level, so the expression b + c is actually an int. C allows this transgression because it's convenient. D makes you acknowledge that you are throwing away bits the compiler generated for you. Note, += does work: a = b; a += c; -Steve
Re: why arithmetic for bytes different than for ints?
On Fri, 02 May 2014 16:32:54 -0400, Vlad Levenfeld vlevenf...@gmail.com wrote: Dunno why I didn't try it earlier, but splitting it across lines like y += 1; y %= 2; assert (y == 1); works. So, bug, then? Yes. -Steve
Re: Any chance to avoid monitor field in my class?
On Wed, 07 May 2014 10:44:55 -0400, Yuriy yuriy.gluk...@gmail.com wrote: Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling. The de-facto minimum size of a class is 16 bytes, due to the minimum block size of the heap. 8 bytes vtbl pointer on 64-bit systems would still allocate into 16-byte blocks. -Steve
Re: Any chance to avoid monitor field in my class?
On Thu, 08 May 2014 13:21:07 -0400, Yuriy yuriy.gluk...@gmail.com wrote: On Thursday, 8 May 2014 at 14:57:37 UTC, Steven Schveighoffer wrote: The de-facto minimum size of a class is 16 bytes, due to the minimum block size of the heap. 8 bytes vtbl pointer on 64-bit systems would still allocate into 16-byte blocks. -Steve Yes, but still the question remains open for non-empty classes (e.g. want to use a 64bit useful payload), and for _emplacing_ any classes anywhere (e.g. on stack). To what end? What are you trying to save? Afaiu, there's no solution except for declaring extern(C++) (yes, i know, it's a hack), and it will not work, if a class is templated on something which can not be cpp-mangled. So the question is: is there any reason why this is not possible? I mean, maybe this question was closed long before. It would not be derived from Object, which has the field. In other words, this would crash: synchronized(cast(Object)obj) { ... } Also, do shared classes actually require monitors? Perhaps you meant unshared classes? No, they don't, but a monitor is only allocated on demand, so you don't have to worry about it. However, note that it is perfectly acceptable to cast to and from shared as long as you guarantee the uniqueness of the reference. If the monitor is not present, this can cause problems. -Steve
Re: Any chance to avoid monitor field in my class?
On Thu, 08 May 2014 14:17:42 -0400, Yuriy yuriy.gluk...@gmail.com wrote: On Thursday, 8 May 2014 at 17:49:01 UTC, Steven Schveighoffer wrote: To what end? What are you trying to save? I'm trying to reimplement std.variant in a nice OOP way, that supports CTFE, zero-size and a minimal amount of void*-casts. For that i'm using my VariantPayload(T) class, which i want to be as small as possible, as this is supposed to be an utility class which you never know how will be used. Well, I don't think I know enough to judge whether what you are doing is worthwhile... But my question more was about where do you plan to put so many of these objects that you will save a significant amount of bytes, aside from the heap (which already uses 16-byte blocks). It would not be derived from Object, which has the field. In other words, this would crash: synchronized(cast(Object)obj) { ... } Wouldn't cast(Object) return null here, so that synchronized will throw or assert or smth? I see no reason for a crash. Then what is this object? All D objects derive from Object. Perhaps you meant unshared classes? No, they don't, but a monitor is only allocated on demand, so you don't have to worry about it. Errm.. I'm not sure i understand the subject correctly, but according to Alexandrescu's book, a class declared as shared does not require synchronized() over it. I mean, it manages it's synchronization inside itself, and it's user just has to trust it. And if so, why ever synchronizing() on it? The meaning of shared is not well defined. Even TDPL is outdated on this. The idea in the book is that shared types would use memory barriers to ensure correct ordering of access, and correct data access. But it does not prevent races for multiple threads, you still need synchronized. Unshared objects, on the other hand, should not ever need synchronization tools, since only one thread has access! -Steve
Re: Any chance to avoid monitor field in my class?
On Thu, 08 May 2014 15:47:46 -0400, Yuriy yuriy.gluk...@gmail.com wrote: But my question more was about where do you plan to put so many of these objects that you will save a significant amount of bytes, aside from the heap (which already uses 16-byte blocks). Hm.. Stack/emplace, How many of these? In order to justify saving 8 bytes per instance, you have have a lot. I don't see emplacing thousands or tens of thousands of objects on the stack. arrays, n-dimensional arrays? Arrays of objects are stored as arrays of object references, with each one pointing at a separate block on the heap. :) Besides, if we're talking of D as a system language to replace C++ and to scratch everything out of a silicon wafer (also think of embedded platforms here), it's crucial for me to be able to control such things. From my experience, in a 5000-class project you would have about 20 classes that need to be synchronized on. Moreover, mutex synchronization is not in fashion nowadays, as we tend to use transitional synchronization. And so my 4980 classes will contain an extra field i don't use. What?? =) In D, class is not used for such things, struct is. It would not be derived from Object, which has the field. In other words, this would crash: Those are your words. I'm assuming you want D classes, but without the monitor object. D classes derive from Object. Then what is this object? All D objects derive from Object. Those are your words also =) Any chance to avoid monitor field in my class? Those are your words. What is it that you want? The meaning of shared is not well defined. Even TDPL is outdated on this. The idea in the book is that shared types would use memory barriers to ensure correct ordering of access, and correct data access. But it does not prevent races for multiple threads, you still need synchronized. Yes, i understand that. By implementing a shared class, you're on your own with syncing, but also you tell the user, that your class doesn't need to be synchronized on. Right? A defined shared class I think is supposed to imply that all its methods are shared (meaning the 'this' pointer must be shared). It does not imply that they are thread safe. Unshared objects, on the other hand, should not ever need synchronization tools, since only one thread has access! Here's two use-cases. class A {} shared class B {} // Somewhere in code { shared A sharedA; // This would need synchronized() on access. A unsharedA; // This would not. But since, the class is defined as unshared, we still will have __monitor in it, and that is good, since we can cast between unshared A and shared A. B b; shared B sharedB; // Here in both cases we know, that we will never need to sync on b or sharedB, as both of those are thread safe (it's not our business, how they do it, but they kinda are). So do we need this __monitor, which will never be used actually? } shared != thread safe. You still need to synchronize -Steve
Re: Any chance to avoid monitor field in my class?
On Thu, 08 May 2014 17:05:56 -0400, Yuriy yuriy.gluk...@gmail.com wrote: How many of these? In order to justify saving 8 bytes per instance, you have have a lot. I don't see emplacing thousands or tens of thousands of objects on the stack. Ok, i guess i have to agree with you. But. Why are you protecting __monitors so eagerly? :) I'm not, I'm trying to help you justify the path your taking :) Because where it's currently leading is somewhere that D doesn't support. This means in order to support it, you have to maintain a parallel compiler, or somehow convince the compiler writers to add such support. Neither of these burdens is small. Arrays of objects are stored as arrays of object references, with each one pointing at a separate block on the heap. Or again you can emplace them in the heap, so that they occupy a continuous chunk. This is not a good idea. The dtors of classes in the GC is stored per block, not per chunk of a block. In D, class is not used for such things, struct is. But classes have vtbls which is an ultimate feature for me, and moreover, it works in ctfe, while reinventing vtbls for ctfe might be a challenging task. Removing the monitor could also prove quite challenging. I don't doubt your reasons, but then again, you have what you have right now in D. Asking for more, you have to provide it, or convince others to. If it's the latter, you need to make a very very strong case. I'm assuming you want D classes, but without the monitor object. D classes derive from Object. Any chance to avoid monitor field in my class? Those are your words. What is it that you want? Thats right. I was saying that extern(C++) almost suits me except for it's mangling. And you said that extern(C++) classes are not derived from Object? But still such objects would have RTTI which will forbid casting to Object, wouldn't they? extern(C++) objects are not considered D objects. A D object can implement a C++ interface, but once you get to the C++ interface, you cannot go back. This sounds to me very different from your goal. -Steve
Re: why can't I call const methods on shared objects?
On Fri, 09 May 2014 17:37:35 -0400, Vlad Levenfeld vlevenf...@gmail.com wrote: Error: non-shared const method is not callable using a shared mutable object Why not? If the method is const, it can't modify the object anyway. Non-shared methods cannot be called on shared objects. Otherwise, you could have unintended race conditions. -Steve
Re: why can't I call const methods on shared objects?
On Fri, 09 May 2014 17:45:37 -0400, Vlad Levenfeld vlevenf...@gmail.com wrote: Is there any way to declare a method as safe regardless of shared/mutability/etc (or some other way to avoid cast(Type)object.property every time I want to check a property which won't affect any state)? Not really for shared. For everything else, there's const for value properties, and inout for reference properties. Shared is quite different, because the method has to be cognizant of race conditions. It has to be implemented differently. Casting away shared is somewhat dangerous, but OK if you logically know there is no race condition. -Steve
Re: Array!T and find are slow
On Wed, 14 May 2014 19:50:33 -0400, Meta jared...@gmail.com wrote: On Wednesday, 14 May 2014 at 22:32:01 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: Yeah, much as Andrei would hate to hear it (enforce was his idea, and he quite likes the idiom), the fact that lazy is so inefficient makes it so that it's arguably bad practice to use it in high performance code. We really need to find a way to make it so that lazy is optimized properly so that we _can_ safely use enforce, but for now, it's not a good idea unless the code that you're working on can afford the performance hit. Honestly, in general, I'd avoid most anything which uses lazy (e.g. that's why I'd use explict try-catch blocks rather than use std.exception.assumeWontThrow - like enforce, it's a nice idea, but it's too expensive at this point). - Jonathan M Davis On the topic of lazy, why *is* it so slow, exactly? Last time I remember, the issue is that functions with lazy parameters will never be inlined. -Steve
Re: Why std.algorithm.sort can't be applied to char[]?
On Wed, 14 May 2014 05:13:42 -0400, Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Wed, 14 May 2014 08:27:45 + monarch_dodra via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Monday, 12 May 2014 at 18:44:22 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: Sure, you can cast char[] to ubyte[] and sort that if you know that the array only holds pure ASCII. In fact, you can use std.string.representation to do it - e.g. auto ascii = str.representation; and if str were mutable, then you could sort it. But that will only work if the string only contains ASCII characters. Regardless, he wanted to know why he couldn't sort char[], and I explained why - all strings are treated as ranges of dchar, making it so that if their element type is char or wchar, so they're not random access and thus can't be sorted. Arguably, a smart enough implementation should know how to sort a char[], while still preserving codepoint integrity. I don't think that that can be done at the same algorithmic complexity though. So, I don't know if that would be acceptable or not from the standpoint of std.algorithm.sort. But even if it's a good idea, someone would have to special case sort for char[], and no one has done that. I think it can be done at O(nlgn) complexity, but you must allocate a block of scratch space to do the sorting. You can't do it in-place because swapping isn't available. Might as well convert to dchar and back explicitly. Merge sort may allow more promising speedups, but I still think you will need to allocate extra space. As a matter of fact, the built in sort property does it. void main() { char[] s = éöeèûà.dup; s.sort; writeln(s); } //prints: eàèéöû I'm surprised. I thought that one of Bearophile's favorite complaints was that it didn't sort unicode properly (and hence one of the reasons that it should be removed). Regardless, I do think that it should be removed. I can't believe this worked. I want to say that it's a freak accident for that set of characters. Looking in druntime, I don't see where the special case is. -Steve
Re: Why std.algorithm.sort can't be applied to char[]?
On Thu, 15 May 2014 11:37:07 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Thursday, 15 May 2014 at 13:26:45 UTC, Steven Schveighoffer wrote: On Wed, 14 May 2014 05:13:42 -0400, Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Wed, 14 May 2014 08:27:45 + monarch_dodra via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: As a matter of fact, the built in sort property does it. void main() { char[] s = éöeèûà.dup; s.sort; writeln(s); } //prints: eàèéöû I'm surprised. I thought that one of Bearophile's favorite complaints was that it didn't sort unicode properly (and hence one of the reasons that it should be removed). Regardless, I do think that it should be removed. I can't believe this worked. I want to say that it's a freak accident for that set of characters. Looking in druntime, I don't see where the special case is. -Steve Must be a hell of a freak accident ;) auto s = é東öe京ûタèワà.dup; writeln(s.sort); = eàèéöûタワ京東 It's in rt/adi.d Seriously, I fucking hate the file names in druntime. I looked in qsort.d. extern (C) char[] _adSortChar(char[] a) It's basically: string=dstring=sort=dstring=string. OK, that's what I would have expected. I don't think we should support this. BTW, the built in reverse also works with char[], and so does std.algorithm.reverse (and it does it pretty cleverly too, might I say). This is a different algorithm. Sort requires random-access swapping. Reverse does not. As far as I'm concerned, if we *can* do it in n.log(n), and somebody provides the implementation, then there is no reason to not offer dchar sorting for char[]/wchar. I think there is nothing wrong with requiring the steps to be explicit. We should not hide such bloat behind sort. -Steve
Re: Objects(from classes) at Compile time? no gc
On Fri, 16 May 2014 02:31:18 -0400, Jacob Carlborg d...@me.com wrote: On 16/05/14 06:59, Taylor Hillegeist wrote: The subject says it all really. i have this example: import core.memory; class fruit{ int value=5; public int getvalue(){ return value; } } int main(string[] args) { GC.disable; static fruit myfruit; return myfruit.getvalue(); } Most of the smart people will see that i want the program to return 5 but I did something dumb and didn't put in the new statement? So my question is in longer words Can I create instances of objects at compile time? and if not why not, i could build something (roughly)equivalent out of structs and functions and have it at compile time? If you create an immutable instance it's possible to create it at compile time: int main(string[] args) { GC.disable; immutable fruit myfruit = new immutable(fruit); pragma(msg, myfruit.getvalue); // will print 5 at compile time return myfruit.getvalue(); } Although, I don't know if it will allocate it during runtime as well. It will not. -Steve
Re: Array!T and find are slow
On Fri, 16 May 2014 11:36:44 -0400, Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Thu, 15 May 2014 08:04:59 -0300 Ary Borenszweig via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Isn't there a way in D to just expand: enforce(cond, failure); (or something with a similar syntax) to this, at compile-time: if(!cond) throw new Exception(failure); I thought D could do this, so enforce should do this instead of using lazy arguments. No. enforce is a function, and the only other things that it could be with that syntax would be other callables (e.g. a lambda, delegate, or functor). I think it *could* optimize properly, and that would be an amazing improvement to the compiler, if someone wants to implement that. Essentially, you need to be able to inline enforce (not a problem since it's a template), and then deduce that the lazy calls can just be moved to where they are used, in this case, only once. This would make a logging library even better too. -Steve
Re: idup class
On Fri, 16 May 2014 16:28:41 -0400, Joshua Niehus jm.nie...@gmail.com wrote: trying to follow: http://ddili.org/ders/d.en/class.html //--- OSX 10.9 DMD 2.065 module test; class Foo { int num; this(int num) { this.num = num; } Foo dup() const { return new Foo(this.num); } immutable(Foo) idup() const { return new immutable(Foo)(this.num); } } void main() { auto foo = new Foo(1); auto mfoo = foo.dup(); auto ifoo = foo.idup(); } * test.d(15): Error: mutable method test.Foo.this is not callable using a immutable object * test.d(15): Error: no constructor for Foo * Failed: [dmd, -v, -o-, test.d, -I.] //--- What am i missing? your constructor needs the immutable tag. this(int num) immutable ... However, you can avoid much of this by tagging things as pure: (untested, but just keep the internals the same) class Foo { int num; this(int num) pure {...} Foo dup() const pure {...} immutable(Foo) idup() const pure {...} } void main() { ... // same implementation } Note that doing this, you do not need to have an idup, this should work: immutable ifoo = foo.dup(); -Steve
Re: idup class
On Fri, 16 May 2014 16:36:36 -0400, Ali Çehreli acehr...@yahoo.com wrote: Beat you by 8 seconds :) -Steve
Re: string-ish range/stream from curl ubyte[] chunks?
On Fri, 16 May 2014 16:57:41 -0400, Vlad b100d...@gmail.com wrote: Hello D programmers, I am toying with writing my own HTML parser as a pet project, and I strive to have a range API for the tokenizer and the parser output itself. However it occurs to me that in real-life browsers the advantage of this type of 'streaming' parsing would be given by also having the string that plays as input to the tokenizer treated as a 'stream'/'range'. While D's *string classes do play as ranges, what I want to write is a 'ChunkDecoder' range that would take curl 'byChunk' output and make it consumable by the tokenizer. Now, the problem: string itself has ElementType!string == dchar. Consuming a string a dchar at a time looks like a wasteful operation if e.g. your string is UTF-8 or UTF-16. So, naturally, I would like to use indexOf() - instead of countUntil() - and opSlice (without opDollar?) on my ChunkDecoder (forward) range. Q: Is anything like this already in use somewhere in the standard library or a project you know? There is an effort by myself and Dmitry Olshansky to create a stream API that looks like a range. I am way behind on getting it to work, but I have something that compiles. The effort is to replace the underlying mechanism for std.stdio (optionally), and to replace std.stream Q2: Or do you have any pointers for what the smallest API would be for a string-like range class? I think Dmitry has a pretty good API. I will hopefully be posting my prototype soon. I hate to say wait for it, because I have been very lousy at getting things finished lately. But I want to have something to show before the conference. The code I have will support all encodings, and provide a range API that works with dchar-like ranges. The idea is to be able to make code that works with both arrays and streams seamlessly. And bonus: Q3: any uses of such a string-ish range in other standard library methods that you can think of and could be contributed to? e.g. suppose this doesn't exist and I / we come up with a proposal of minimal API to consume a string from left to right. I hate for you to duplicate efforts, hold off until we get something workable. Then we can discuss the API. Dmitry's message is here: http://forum.dlang.org/post/l9q66g$2he3$1...@digitalmars.com My updates have not been posted yet to github, I don't want to post half-baked code yet. Stay tuned. -Steve
Re: string-ish range/stream from curl ubyte[] chunks?
On Fri, 16 May 2014 18:36:02 -0400, Vlad b100d...@gmail.com wrote: On Friday, 16 May 2014 at 21:35:04 UTC, Steven Schveighoffer wrote: On Fri, 16 May 2014 16:57:41 -0400, Vlad b100d...@gmail.com wrote: Q: Is anything like this already in use somewhere in the standard library or a project you know? There is an effort by myself and Dmitry Olshansky to create a stream API that looks like a range. I am way behind on getting it to work, but I have something that compiles. The effort is to replace the underlying mechanism for std.stdio (optionally), and to replace std.stream Q2: Or do you have any pointers for what the smallest API would be for a string-like range class? I think Dmitry has a pretty good API. I will hopefully be posting my prototype soon. I hate to say wait for it, because I have been very lousy at getting things finished lately. But I want to have something to show before the conference. The code I have will support all encodings, and provide a range API that works with dchar-like ranges. The idea is to be able to make code that works with both arrays and streams seamlessly. And bonus: Q3: any uses of such a string-ish range in other standard library methods that you can think of and could be contributed to? e.g. suppose this doesn't exist and I / we come up with a proposal of minimal API to consume a string from left to right. I hate for you to duplicate efforts, hold off until we get something workable. Then we can discuss the API. Dmitry's message is here: http://forum.dlang.org/post/l9q66g$2he3$1...@digitalmars.com My updates have not been posted yet to github, I don't want to post half-baked code yet. Stay tuned. -Steve Just to make one thing clear: would this future module work with e.g. the ubyte[] chunks I receive from curl? Most likely. I would expect a curl-based stream to fit right in, it's just passing in bytes. One piece that I haven't quite fleshed out is how to drive the process. In some cases, you are pulling data from the source (traditional stream-based I/O), in other cases, something else is pushing the data (CURL). We need to handle both seamlessly. I admit I have never looked at D's curl package, just used it via C/C++. p.s. Is this the talk? http://dconf.org/2014/talks/olshansky.html That is Dmitry's talk, from the same guy. But I think this is not about his I/O ideas, but his excellent std.regex package. -Steve
Re: Is it possible to assumeSafeAppend malloced memory?
On Mon, 19 May 2014 09:44:44 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Monday, 19 May 2014 at 06:08:18 UTC, Ali Çehreli wrote: We know that most of the time memory is allocated more than the requested amount. Is there a way to take advantage of that extra trailing space? (And potentially the pages that come after that.) import core.memory; void main() { const count = 1; // I think there is extra capacity beyond the 'count' elements int* ptr = cast(int*)GC.malloc(count * int.sizeof); int[] arr = ptr[0 .. count]; assert(arr.capacity == 0); arr.assumeSafeAppend; assert(arr.capacity == 0);// still 0. :( } This is because a block must contain 'used' information in order for capacity and assumeSafeAppend to work. This is enabled not only by adding the flag APPENDABLE to the allocation (or you can set the attribute later), but you must ALSO properly set up the 'used' field. This is best left to druntime. The mechanism to store the used size may change in the future. Is there a reason you wouldn't want to do int[] arr = new int[count]? It's technically the same call. This issue puts std.array.array to a disadvantage compared to proper slices because array() involves the following call chain, the last of which does call GC.malloc: trustedAllocateArray uninitializedArray arrayAllocImpl This is a bug. arrayAllocImpl should alloc using the proper functions and flags. auto arr = array(1, 2, 3); assert(arr.capacity != 0); // should pass Recently, a new function in druntime was added: _d_newarrayU. This void allocates a new array *with* appendable information. We can hope it will be given a more formal and public interface, and it would then be useable by array and/or Appender, to produce slices that have appendable data. Cool, I didn't know this! -Steve
Re: Is it possible to assumeSafeAppend malloced memory?
On Mon, 19 May 2014 14:46:59 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Monday, 19 May 2014 at 13:55:00 UTC, Steven Schveighoffer wrote: On Monday, 19 May 2014 at 06:08:18 UTC, Ali Çehreli wrote: This issue puts std.array.array to a disadvantage compared to proper slices because array() involves the following call chain, the last of which does call GC.malloc: trustedAllocateArray uninitializedArray arrayAllocImpl This is a bug. arrayAllocImpl should alloc using the proper functions and flags. Well, Yes and no. The issue is that there is no interface available to achieve this, that wouldn't completely destroy what `array` is going for anyways. So it's more of a design issue than a bug proper. Yes, I understand. When allocating an array, you need to initialize the array properly, and the standard library should not have the implementation details of the array management leaked into it. I think you can replace the GC.malloc call with the new one you mentioned, no? It's still a bug. The expectation of array(x, y, z) is that it's the same as [x, y, z]. That is not true currently. -Steve
Re: Is there any way to differentiate between a type and an alias?
On Sun, 25 May 2014 04:04:09 -0700, Rene Zwanenburg renezwanenb...@gmail.com wrote: Given alias GLenum = uint; void glSomeFunction(GLenum, uint); Now, is there some way to differentiate between GLenum and uint when using ParameterTypeTuple!glSomeFunction? I'm writing a function which shows the arguments a GL function was called with when an error occurs. The GLenum needs to be printed as a stringified version of the constant's name, while the uint is just an uint. An alias is simply another name for the same thing. There is no type difference. You may be able to do some template trickery with template aliases to detect when an alias is used. But I'd recommend using enum instead of alias: enum GLenum : uint { constant = value} This creates a genuine new type, and also gives you a place to put constants. However, it's not implicitly castable from uint, so it has some drawbacks. You can cast back to uint implicitly though. There is also a library typedef mechanism (in std.typecons perhaps?), you can look into that. It should have the same limitations as enum. -Steve
Re: Is this a bug or illegal code?
On Thu, 29 May 2014 10:45:28 -0400, safety0ff safety0ff@gmail.com wrote: //*** CODE ** mixin(version = foo;); version(foo) { void main(){} } //** END CODE *** If it's illegal in D, what is the reason where is documented? The reason I was considering such a construct is the following: Some C libraries have an associated config.h header that gets generated when it is compiled. I was thinking it may be possible to parse these config.h files at compile time (using text import) and convert some of the #define's into version = foo; Even if that is valid code, you are much better off using enums and static if. enum includeSomeFeature = ... static if(includeSomeFeature) { ... } These work much more like #defines, and can be seen outside the module. -Steve
Re: enums
On Fri, 30 May 2014 13:34:38 -0400, Philippe Sigaud via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Fri, May 30, 2014 at 7:28 PM, Ali Çehreli digitalmars-d-learn@puremagic.com wrote: On 05/30/2014 08:30 AM, Russel Winder via Digitalmars-d-learn wrote: enum double p0 = 0.0045; As others have already said, p0 is a manifest constant. Interestingly, it can be thought of like a C macro, being pasted inside source code. Avoid enums for arrays and associative arrays as they are hidden performance sinks. The constant gets regenerated at runtime every time it is used in an expression. I guess that, in an ideal world, immutable variables could be use at compile-time (template arguments, etc). We could then ditch 'enums-as-manifest-constants'.The best of both worlds. You can as long as the value is known at compile time: http://dpaste.dzfl.pl/5a710bd80ab0 -Steve
Re: Hiding types
On Fri, 30 May 2014 15:50:41 -0400, Philippe Sigaud philippe.sig...@gmail.com wrote: I'm trying to 'hide' a type, so as not to see it outside its module. I want to control the way it's created and used. I know of Voldemort types and '@disable this', but for now I'm just trying to use 'private'. Halas, it seems it can be circumvented: * module A; private struct Hidden {} Hidden foo() { return Hidden();} * module B; import A; void main() { typeof(foo()) h; } * Am I misunderstanding something or is that a bug? Even voldemort types can be declared that way. If you want an opaque struct, you need to return it by pointer. Otherwise, the user must be able to know what type it is (otherwise, how would he use it?) -Steve
Re: Hiding types
On Fri, 30 May 2014 16:09:59 -0400, Philippe Sigaud philippe.sig...@gmail.com wrote: On Friday, 30 May 2014 at 20:02:40 UTC, Steven Schveighoffer wrote: If you want an opaque struct, you need to return it by pointer. What do you mean? Like this? Hidden* foo() { return new Hidden();} ? Yes, this way you can control all aspects of the construction and use. You wouldn't need to make it private even, just don't lay out the struct in the normal import: struct Hidden; I think you would need to use a .di file to do this. Otherwise, the user must be able to know what type it is (otherwise, how would he use it?) I just fear that by using internal, public, functions, the user might get access to a private type. I guess the D answer to that is to make foo private also. That makes sense. You can make the struct's methods and data all private, which would prevent any useful access to it. But I don't know your use case. I now realize that I implicitly considered 'private' to be transitive (or viral). That is that: Hidden foo() { return Hidden();} as foo is returning a value from a private type, it should be considered private also. By the compiler, I mean. No, private just makes the symbol not directly accessible. Since foo is not private, it's accessible. -Steve
Re: delegate issue
On Mon, 02 Jun 2014 10:37:07 -0400, captaindet 2k...@gmx.net wrote: On 2014-06-02 08:03, MrSmith wrote: On Monday, 2 June 2014 at 06:56:54 UTC, captaindet wrote: hi, i stumbled upon something weird - it looks like a bug to me but maybe it is a feature that is unclear to me. so i know i can declare function and delegate pointers at module level. for function pointers, i can initialize with a lambda. BUT for delegates i get an error - see below i found out that using module static this(){...} provides a workaround, but why is this necessary? also, if there is a good reason after all then the error message should make more sense. /det ps: i know there is a shorthand syntax for this. module demo; int function(int) fn = function int(int){ return 42; }; // ok int delegate(int) dg = delegate int(int){ return 666; }; // demo.d(6): Error: non-constant nested delegate literal expression __dgliteral6 void main(){} You can't assign a delegate at compile time now. But you can do this in static constructor like this: int delegate(int) dg; static this() { dg = delegate int(int){ return 666; }; } i knew about the static constructor, mentioned it in my OP ;) tried it in my project proper and got run-time cycle detected between modules ctors/dtors :( something new to figure out now. FYI, the module ctor/dtor cycles thing is an interesting problem. When D decides to call module ctors or dtors, it wants to initialize them in an order where two initializations don't depend on one another. For instance: module a; import b; int x; static this() { x = b.x;} module b; import a; int x; static this() { x = a.x;} But of course, D does not know what exactly is done in module a, and module b. It could be: module a; import b; int x; static this() { x = b.x; } module b; import a; int x; static this() { x = 15;} Which could be perfectly legal, as long as module b is initialized before module a. But D doesn't have the information to sort this out. So at the moment, it has to assume the first situation, and reject the code. And it can only detect this at runtime, since we have no way to tell the linker to refuse to link this code. The typical solution is to put your static ctors into another module, which nothing will import (and therefore cannot be part of a cycle). A module with no static ctors/dtors will not be flagged as causing a problem. -Steve
Re: for, foreach identifier allowed in c throws error in d
On Mon, 02 Jun 2014 15:21:06 -0400, Logesh Pillay lp.court.jes...@gmail.com wrote: It is common in a recursive function to amend a global array using the function parameter to refer to the element eg int[10]; void foo (int i) { foreach (x; 0 .. 9) { t[i] = x; foo (); C in a for loop allows use of t[i] directly as the iterating variable so you don't need the dummy variable x which has no real function. D does not. The error generated is no identifier for declarator t[i]. For a long time, I thought that was specific to foreach but the same thing happens with for. It looks like an unnecessary restriction. Am I missing something? Can you post a full compiling example? I can't figure out what you are trying to do with this code. -Steve
Re: for, foreach identifier allowed in c throws error in d
On Mon, 02 Jun 2014 15:47:02 -0400, Logesh Pillay lp.court.jes...@gmail.com wrote: Issue has nothing to do with recursion. That's only where I keep seeing it. eg a function to generate combinations. import std.stdio; int[3] t; void foo (int i) { if (i == 3) writef(%s\n, t); else foreach (x; 0 .. 3) { t[i] = x; foo(i+1); } } void main() { foo(0); } In C, I could put in the equivalent for statement for foreach, t[i] as the iterating variable. I won't need x which exists as a middleman only and save myself two lines. OK, I get it. You want to do: foreach(t[i]; 0 .. 3) But this doesn't work. This should (the equivalent for C): for(t[i] = 0; t[i] 3; ++t[i]) I'm trying to think of a way to do this without loops, but not sure. Note that foreach is expected to be given a new variable to declare, so you can't foreach with an existing variable on the left. -Steve
Re: for, foreach identifier allowed in c throws error in d
On Mon, 02 Jun 2014 15:58:01 -0400, Steven Schveighoffer schvei...@yahoo.com wrote: I'm trying to think of a way to do this without loops, but not sure. I'm surprised, I looked for some kind of apply function like map, but just calls some function with each element in the range. Something like this would make this a 1 (2?) liner: if(i == t.length) writeln(t) else each!((x) = {t[i] = x; foo(i+1);})(iota(x.length)); But I can't find a phobos primitive for each. Would have expected it in std.algorithm or std.functional? -Steve
Re: for, foreach identifier allowed in c throws error in d
On Mon, 02 Jun 2014 17:25:24 -0400, John Colvin john.loughran.col...@gmail.com wrote: On Monday, 2 June 2014 at 20:23:12 UTC, Steven Schveighoffer wrote: On Mon, 02 Jun 2014 15:58:01 -0400, Steven Schveighoffer schvei...@yahoo.com wrote: I'm trying to think of a way to do this without loops, but not sure. I'm surprised, I looked for some kind of apply function like map, but just calls some function with each element in the range. Something like this would make this a 1 (2?) liner: if(i == t.length) writeln(t) else each!((x) = {t[i] = x; foo(i+1);})(iota(x.length)); But I can't find a phobos primitive for each. Would have expected it in std.algorithm or std.functional? -Steve Its been discussed a few times. There were some objections (IIRC Walter thought that there was no significant advantage over plain foreach). Indeed, foreach is like such a construct: ... else each!((x) {t[i] = x; foo(i+1);})(iota(t.length)); ... else foreach(x; 0 .. t.length) {t[i] = x; foo(i+1);} It's even shorter and clearer. I agree with Walter. Since such a construct by definition wouldn't return anything, you can't chain it. There really is little reason to have it. -Steve
Re: Delegate, scope and associative array
On Mon, 02 Jun 2014 19:43:58 -0400, Rene Zwanenburg renezwanenb...@gmail.com wrote: On Monday, 2 June 2014 at 20:09:12 UTC, Edwin van Leeuwen wrote: I'm probably missing something basic, but I am confused by what is going on in the following code. unittest { size_t delegate()[size_t] events; foreach( i; 1..4 ) { events[i] = { return i; }; } writeln( events[1]() ); // This outputs 3 assert( events[1]() == 1 ); } I thought that i should be copied from the local scope and therefore when I call events[1]() the return value should be 1, but in this case it is 3 (it always seems to be the last value of i in the loop). Cheers, Edwin Yeah this is a known problem. At the moment the foreach loop is internally rewritten to something like int i = 1; while(i 4) { // foreach loop body ++i; } While it usually would be preferrable if it were rewritten as int __compilergeneratedname = 1; while(__compilergeneratedname 4) { auto i = __compilergeneratedname++; // foreach loop body } With the current approach every delegate refers to the same variable. Another problem is that it's possible to alter the iteration index from inside the foreach body. As you may have guessed, a workaround is to copy the iteration variable yourself: unittest { size_t delegate()[size_t] events; foreach(_i; 1..4 ) { auto i = _i; events[i] = { return i; }; } assert( events[1]() == 1 ); } This should work though it's less than ideal. There is an open bug report: https://issues.dlang.org/show_bug.cgi?id=8621 There is a school of thought (to which I subscribe) that says you shouldn't allocate a separate closure for each loop iteration. Basically, a closure will only use the stack frame of the calling function, not any loop iteration. This way, you can clearly delineate what scope the closure has, and avoid unnecessary allocations. -Steve
Re: When is a slice not a slice?
On Thu, 05 Jun 2014 15:56:00 -0400, Philippe Sigaud via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: enum b = DataAndView(1); assert (!sameTail(b.data, b.view)); I suppose it's because enums are manifest constants: the value they represent is 'copy-pasted' anew everywhere it appears in the code. So for arrays and associative arrays, it means recreating a new value each and every time. In your case, your code is equivalent to: assert (!sameTail(DataAndView(1).data,DataAndView(1).view)); And the two DataAndView(1), being completely separated, do not have the same tail. Yes, this should work (and execute the initializer at compile time): static b = ... -Steve
Re: When is a slice not a slice?
On Fri, 06 Jun 2014 06:14:30 -0400, Rene Zwanenburg renezwanenb...@gmail.com wrote: On Friday, 6 June 2014 at 08:17:43 UTC, Alix Pexton wrote: On 05/06/2014 8:58 PM, Steven Schveighoffer wrote: Yes, this should work (and execute the initializer at compile time): static b = ... Ah, the problem with static is that I want to use the values at compile time to create other values. Using static puts construction between compile time and run time. Not exactly (at least I don't think). The static initializer itself is generated at compile time. But the assignment to the static variable is done at run time. Initialising in static this means that the symbols need to be declared without initializers and that means not disabling default construction Immutables should be usable at compile time and not allocate a new instance on every use when in module scope. I was about to say this. But immutable can have its own set of issues. If you want strictly compile-time generation of data, then immutable is the way to go. But if you want to use it at runtime as well, immutable can hamper some things. I'm sure your example is a very small or reduced snippet of what you are actually doing. -Steve
Re: splitter for strings
On Mon, 09 Jun 2014 07:04:11 -0400, Chris wend...@tcd.ie wrote: On Monday, 9 June 2014 at 10:54:09 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 10:23:16 UTC, Chris wrote: Ok, thanks. I'll keep that in mind for the next version. Seems to me to also work with 2.065 and 2.064. From the library reference: assert(equal(splitter(hello world, ' '), [ hello, , world ])); Note the 2 spaces between hello and world and If a range with one separator is given, the result is a range with two empty elements. Right, it allows you to distinguish cases where the range starts or ends with the separator. My problem was that if I have input like auto word = bla-; it will return parts.data.length == 2, so I would have to check parts.data[1] != . This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in bla-) length 2 // do something else One thing you could do is strip any leading or trailing hyphens: assert(-bla-.chomp(-).chompPrefix(-).split('-').length == 1); Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve
Re: splitter for strings
On Mon, 09 Jun 2014 10:39:39 -0400, Chris wend...@tcd.ie wrote: Atm, I have auto parts = appender!(string[]); w.splitter('-').filter!(a = !a.empty).copy(parts); Which looks more elegant and gives me what I want. IMO, the module that handles the splitting of hyphenated words should be able to deal with cases like blah- without the input being prepared in a certain way. It's not mishandled. It's handled exactly as I would have expected. If blah- and blah result in the same thing, then how do you know the difference? Stripping any possible leading or trailing hyphens is much more efficient than checking every single word to see if it's empty. However, if you have an instance of --, your solution will remove the extra empty string, whereas mine does not. Not sure if that's important. -Steve
Re: splitter for strings
On Mon, 09 Jun 2014 12:06:13 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Monday, 9 June 2014 at 15:54:29 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 11:49:29 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer wrote: Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve It's in algorithm, because it's more generic than just strings. Ugh.. This makes things difficult. If I want to work with strings, I import std.string. I understand that the algorithm is applicable to all types, but this makes for some awkward coding. What if you wanted to use both? Surely we can come up with a better solution than this. -Steve I think we are confusing things here, I was talking about strip :) There's 2 different issues: The first, is that split(string) was pre-existing in std.string, and *then* split was introduced in algorithm. Where ideally (?) everything would have been placed in the same module, we true to avoid moving things around now. The second thing is that split without any predicate/item can only make sense for strings, but not for generic ranges. For what it's worth, I find it makes sense. Well, I suppose it should probably work if you try both strip and strip('-')... and indeed it does. It is not as bad as I thought (I thought they would conflict). It still leaves me a bit uneasy that std.string does not provide everything you would need to work with strings. But we don't want std.string importing std.algorithm, or at least we don't want it importing ALL of std.algorithm. If we could split up std.algorithm into individual modules, that would probably help. -Steve
Re: Basic dynamic array question. Use of new versus no new.
On Tue, 10 Jun 2014 23:28:16 -0400, Kapps opantm2+s...@gmail.com wrote: On Wednesday, 11 June 2014 at 02:30:01 UTC, WhatMeWorry wrote: In Mr. Cehreli's book it says Additionally, the length of dynamic arrays can be changed by assigning a value to this property: int[] array; // initially empty array.length = 5; // now has 5 elements while in Mr. Alexandrescu's book, it says To create a dynamic array, use a new expression (§ 2.3.6.1 on page 51) as follows: int[] array = new int[20]; // Create an array of 20 integers Could someone please compare and contrast the two syntaxes. I presume the new command places the 2nd array in heap memory. They both do the same, create an array of n integers on the heap and set the length to n. You can also use .capacity instead of .length to allocate n but not adjust length. This is slightly incorrect. Here is the difference as I see it: 1. Setting length goes through the extra steps of checking the current length, looking up the existing block (obviously with initial value of null, there isn't one), and allocating if necessary. A lot more code is executed. 2. The 'new' call will ALWAYS allocate a new block, even if array previously had data in it. 3. The block size allocated is not always n, it could be more. 4. You meant 'reserve', not 'capacity'. capacity checks how many elements the block can support. Which way is easier/better? If you know you are starting with a blank array, then new is the way to go. This avoids any unnecessary extra checks for existing data. The second way is required if you may already have some data in the array (i.e. prior to setting the length, arr.length != 0). Also, I would recommend to use: auto array = new int[20] To avoid repeating the type. -Steve
Re: Cannot understand deprecation message recently added to Phobos
On Wed, 11 Jun 2014 16:59:24 -0400, Nordlöw per.nord...@gmail.com wrote: Can somebody explain the meaning of split in the error message Deprecation: function core.time.Duration.weeks is deprecated - Please use split instead. weeks was too frequently confused for total!weeks. given by function shortDurationString() at https://github.com/nordlow/justd/blob/master/pprint.d Actually, that may not be a valid deprecation message. All the other unit functions do not get the total number of units, but there are not larger units supported by Duration. In fact, dur.weeks was the equivalent of dur.total!weeks. You can safely change your code to use total!weeks instead. Jonathan, can we update this deprecation message? The function is going away because of the confusion with smaller units. For example, dur.seconds could be confused as the number of seconds in this duration, but it's really the number of seconds that do not make up a whole minute in this duration. Basically, it's the mod remainder for the seconds. -Steve
Re: Cannot understand deprecation message recently added to Phobos
On Wed, 11 Jun 2014 17:06:41 -0400, Kapps opantm2+s...@gmail.com wrote: On Wednesday, 11 June 2014 at 20:59:25 UTC, Nordlöw wrote: Can somebody explain the meaning of split in the error message Deprecation: function core.time.Duration.weeks is deprecated - Please use split instead. weeks was too frequently confused for total!weeks. given by function shortDurationString() at https://github.com/nordlow/justd/blob/master/pprint.d https://github.com/D-Programming-Language/druntime/pull/825 Now fixed, is the message clearer for you? https://github.com/D-Programming-Language/druntime/pull/837 -Steve
Re: Is it normal that unittests of phobos are executed with my project build?
On Sat, 14 Jun 2014 10:32:04 -0400, Xavier Bigand flamaros.xav...@gmail.com wrote: I get a failure on a test in format.d when I build my own project with unittest. I though importing phobos header would not regenerate their unittest modules. Any idea of what can cause this issue? I already have reinstalled dmd with visualD completely. Templates are not compiled fully until you use them. If a unit test is inside a template, and that template wasn't instantiated inside phobos itself (likely for formatting), it will be instantiated, unit test and all, inside your code that used it. This is a big limitation on the unit test system. There is no way to say what unit tests to enable, and what to disable. It's just all or nothing. -Steve
Re: interface is interface
On Tue, 17 Jun 2014 15:02:33 -0400, Pavel phond...@gmail.com wrote: Hello! import std.stdio; interface I { } interface B : I { void test(); } interface C : I { void test1(); } class A : B, C { override void test() {} override void test1() {} } void main() { A a = new A(); I b = cast(B)a; I c = cast(C)a; writeln(cast(void*)a, , cast(void*)b, , cast(void*)c); // 1EE1FE0 1EE1FE8 1EE1FEC b and c should be identical IMO. This means there are 2 entries for I inside the object, which is a waste of space. assert (a is b); // OK This should also fail. It seems like a bug to me. 'is' should compare pointers, not anything else. -Steve
Re: Run child process with null stdin/stdout
On Wed, 18 Jun 2014 16:15:40 -0400, David Nadlinger c...@klickverbot.at wrote: On Wednesday, 18 June 2014 at 20:00:43 UTC, Justin Whear wrote: For POSIX, seems like you could pass `File(/dev/null, r)` for stdin and `File(/dev/null, w)`. On Windows I believe you can use `File (nul)` for the same effect. Implementing this myself is of course always an option, yes, but I would have liked to avoid platform-dependent code. Hm, I just checked the source, and there doesn't seem to be a better option indeed… I think a mechanism to open a null stream in an OS independent way would be a good addition to std.stdio (or perhaps std.process?) -Steve
Re: Question about iteger literals
On Sun, 22 Jun 2014 08:23:45 -0400, Uranuz neura...@gmail.com wrote: If these rules are not so clear and have some exceptions (but I don't understand why they are needed) then some documentation needed about this. See integer promotion rules: http://dlang.org/type.html#Integer%20Promotions And the section below it. -Steve
Re: Passing around a list of differently typed functions
On Mon, 23 Jun 2014 14:30:12 -0400, Ali Çehreli acehr...@yahoo.com wrote: On 06/22/2014 11:32 PM, FreeSlave wrote: On Monday, 23 June 2014 at 01:16:49 UTC, Evan Davis wrote: As the subject says, I would like to pass around an array of functions. The trick is, that the functions have different type signatures. Is there a way to put the two functions int foo(int a, int b); bool bar(bool a, bool b); into one array, that I can pass around and cast as necessary? Thanks, Evan You can pass them as pointers, for example cast to void*. But you still need correct signature to cast pointer to actual type before call function. In C and C++, void* is for data pointers only. As function pointers are a different kind of beast, casting to and from void* is undefined behavior. (Note: It works on all common platforms.) Wow, really? That is strange. I wonder whether D has any decision on that. I would hope it's defined. A pointer is a pointer. -Steve
Re: Converting from C const(dchar*) to dstring
On Tue, 24 Jun 2014 13:37:41 -0400, Danyal Zia catofdan...@yahoo.com wrote: Hi, I like to print the strings from a C function that returns const(dchar*), but I can't make the conversion to dstring. I can convert vice versa by: dstring text = Hello; const(dchar)* str = toUTFz!(const(dchar)*)(text); // passing it to C function prints Hello However, I don't have the idea how can I go the other way. I tried several methods such as using to!dstring, toUTF32 etc which compiles successfully however printing them gives address of them instead of text. const(dchar *)x = ...; // assuming 0 terminated dstring text = x[0..x.strlen].idup; -Steve
Re: Converting from C const(dchar*) to dstring
On Tue, 24 Jun 2014 14:28:58 -0400, Chris Cain zsh...@gmail.com wrote: On Tuesday, 24 June 2014 at 17:59:41 UTC, Steven Schveighoffer wrote: // assuming 0 terminated dstring text = x[0..x.strlen].idup; strlen is only defined for char, not dchar: https://github.com/D-Programming-Language/druntime/blob/master/src/core/stdc/string.d#L44 Right, I forgot about that. -Steve
Re: Is their a way for a Child process to modify its Parent's environment?
On Tue, 24 Jun 2014 21:53:51 -0400, WhatMeWorry kc_hea...@yahoo.com wrote: I open a command line window, and run the following 6 line program void main() { string envPath = environment[PATH]; writeln(PATH is: , envPath); envPath ~= r;F:\dmd2\windows\bin; environment[PATH] = envPath; envPath = environment[PATH]; writeln(PATH is: , envPath); } It prints out the following PATH is: C:\Windows\system32;C:\Windows... PATH is: C:\Windows\system32;C:\Windows...F:\dmd2\windows\bin when the program exits, I'm back at the command line and I do a echo %PATH% which just shows C:\Windows\system32;C:\Windows... Anybody know of a way to make the change stick for the lifetime of the command window? Only the command shell can change it's own environment. When you execute commands that set an environment variable, those are shell builtins, not external programs. You can run a batch file (which is not run in a separate process) which sets environment variables. This may be the only way to affect the environment. Basically, have a program run that dictates what to set, builds a batch file, then run that batch file from the command line. This could be done in another batch file. -Steve
Re: Redirect to different overloads at compile time?
On Sun, 29 Jun 2014 22:24:09 -0400, David Bregman d...@sfu.ca wrote: Suppose I have a C library which implements a function for several types. C doesn't have overloading, so their names will be distinct. extern(C): double foo_double(double); float foo_float(float); Now I want to build a D wrapper, and merge them into a single function with overloading: T foo(T) I could write out the two overloads manually: double foo(double d) { return foo_double(d); } float foo(float f) { return foo_float(f); } but this isn't compile time, it will generate a stub function for each overload, meaning the wrapper will have performance overhead unless inlining can be guaranteed somehow. This is the correct answer. It should be inlined, and inlining should work as long as -inline is passed to the compiler. I don't think there is another way. Is it possible to do something like alias foo = foo_double; alias foo = foo_float; Right, you cannot overload aliases as far as I know. foo either refers to foo_double, or foo_float. You can't bring in those as overloads under the name foo. or template(T) foo { static if(T is double) { alias foo = foo_double; } else { // etc. } } These doesn't work of course. This last one looks like it should work. But IFTI ONLY works if you don't do what you did :) Basically, IFTI cannot see through static if to determine how to instantiate. It needs to be a clear single function. For example, how would IFTI figure it out if you did this? template(T) foo { static if(T is double) { alias foo = foo_float; } else { // etc. } } It can't figure out what T is without looking at what the alias would be, but in order to look at the alias, it needs to decide T! I don't fully understand the template syntax yet, but I have a feeling this is possible with templates. Is it possible to do what I'm trying to do? It seems like it should be possible, but I think we would need a new type of implicit determination for templates that was not a function template. -Steve
Re: linux ipv4 multicast
On 9/18/14 10:55 PM, james wrote: I just started doing D networking today, so I may just be doing something wrong / stupid but I can not find the ip_mreq struct anywhere. I ended up just making my own in my module struct ip_mreq { in_addr imr_multiaddr; in_addr imr_interface; } And then I was able to continue and successfully process multicast. The ipv6 things seem to be available. I was hoping it would be picked up by import std.c.linux.socket; In /usr/include/dmd , running find . -type f -exec grep -Hi ip_mreq {} \; returns no results. Am I doing something wrong or is this just an oversight somehow? DMD v2.065 The vast amount of C declarations that could be done on D simply aren't done until someone needs them. So no, you aren't doing anything wrong, no it's not an oversight :) If you like it to be part of the main library, submit a pull request, and I'll be happy to review. One thing -- you should extern(C) the struct so the symbol is not mangled (extern(C): is probably already done at the top of the file, so you may not need to do this if you add it to std.c.linux.socket) -Steve
Re: How does GC.addRange work?
On 9/21/14 3:00 PM, Gary Willoughby wrote: On Saturday, 20 September 2014 at 23:08:08 UTC, ketmar via Digitalmars-d-learn wrote: On Sat, 20 Sep 2014 22:21:13 + Gary Willoughby via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: So zeroing values will inform the GC the reference has gone? yes. Thanks, i just wanted to make it clear in my mind. Just to be crystal clear, zeroing values in that range will make the GC able to collect the memory that those values previously pointed at. However, you have to remove the range in order for the GC to ignore that data. In other words, if you zero that memory, the GC will continue to scan those zeros until you GC.removeRange it. -Steve
Re: can't understand why code do not working
On 9/22/14 4:37 PM, Cliff wrote: Is stdout threadsafe? Yes, stdout is thread safe, it's based on C's stdout which is thread safe. -Steve
Re: Does remove immutability using cast to pass in a function make sense?
On 9/22/14 10:07 PM, AsmMan wrote: I have this array: static immutable string[] months = [jan, fev, ...]; I need to pass it into canFind(). But it doesn't works with immutables so I need to cast it like in canFind(cast(string[]) months, month) to work. There's a reason related to design why it doesn't work with immutables or a function just wasn't written? What I want to know is if I'm doing something wrong in casting it to work. I know from C which such casts should be done carefully Yes, casting should be used very sparingly, and only when you have no other choice. Ali suggests that the latest version of DMD on git handles this, but just an FYI, you do not need to cast to get a mutable array of strings: canFind(months[], month) should work. -Steve
Re: How to export a deduced template type to the enclosing scope?
On 9/23/14 7:12 PM, Ali Çehreli wrote: Can we get rid of the ResultT template parameter? Tricks with variadic templates, the with statement, etc. come to mind but I could not manage it. I don't think so. yield just returns control back to another fiber. It's not an entry point. What you *could* do is match an expectation function with the yield result. In other words, at the place where you expect the fiber to yield you a result, pass in a pointer to a value for the yield to fill in: expectYield(someint); - fiber runs, yields an int, and then when this yields the result, someint is filled in. I'm not super familiar with how D fibers work, or fibers in general. But perhaps it's the 'call' function that could be made to take parameters. -Steve
Re: Does D has C#'s string.Empty?
On 9/25/14 2:41 AM, SlomoTheBrave wrote: On Thursday, 25 September 2014 at 05:29:37 UTC, AsmMan wrote: Does D has C#'s string.Empty? string.init ? string a; a = string.init; assert( a == ); does the job for the type string at least. null also works. In fact, in the above, a is already string.init or null before assigning (D always initializes variables unless asked not to). a = null; // same as a = string.init; -Steve
Re: immutable T.init, and pointers to mutable data
On 9/25/14 5:47 AM, monarch_dodra wrote: I was playing around with how T.init works. And I think I may have found a type loophole. Given that you may initialize a pointer member to the address to a static global: // __gshared int a = 0; struct S { int* p = a; } // Then, in theory, any variable, be they mutable or const, are initialized to T.init: // void main() { immutable S s; } // This is an issue, because I now have an immutable pointer that points to mutable data: // immutable S s = S.init; immutable int* p = s.p; assert(*p == 0); //OK a = 5; assert(*p == 5); //OK // So this violates the type system... The question here is: Is this legit code? At what point do you think my code should have been rejected? It should be rejected. The declaration of s (the variable) should be the trigger, since it casts the pointer to immutable. Please file a bug report. -Steve
Re: immutable T.init, and pointers to mutable data
On 9/25/14 9:00 AM, monarch_dodra wrote: On Thursday, 25 September 2014 at 12:46:01 UTC, Steven Schveighoffer wrote: On 9/25/14 5:47 AM, monarch_dodra wrote: I was playing around with how T.init works. And I think I may have found a type loophole. Given that you may initialize a pointer member to the address to a static global: // __gshared int a = 0; struct S { int* p = a; } // Then, in theory, any variable, be they mutable or const, are initialized to T.init: // void main() { immutable S s; } // This is an issue, because I now have an immutable pointer that points to mutable data: // immutable S s = S.init; immutable int* p = s.p; assert(*p == 0); //OK a = 5; assert(*p == 5); //OK // So this violates the type system... The question here is: Is this legit code? At what point do you think my code should have been rejected? It should be rejected. The declaration of s (the variable) should be the trigger, since it casts the pointer to immutable. Please file a bug report. -Steve Hum... So that means certain types just *can't* be initialized (as immutable) at all? I wouldn't say that: immutable s = S(null); But clearly, any code that results in an immutable pointer to mutable data without casts is incorrect. We should start by outlawing such code, and if there are ways we can carve out certain usages, we can do that. -Steve
Re: immutable T.init, and pointers to mutable data
On 9/25/14 10:56 AM, monarch_dodra wrote: On Thursday, 25 September 2014 at 13:37:52 UTC, Steven Schveighoffer wrote: But clearly, any code that results in an immutable pointer to mutable data without casts is incorrect. We should start by outlawing such code, and if there are ways we can carve out certain usages, we can do that. Hum... right, but I meant T.init itself would not be valid. As in: alias T = immutable(S); T t = T.init; //Illegal? I would say yes, illegal. There's some interesting issues with this. For instance, what about: T[] t; t.length = 2; This is a runtime function, and the runtime isn't necessarily aware of all the intricacies of a type, it has only blunt instruments (namely the TypeInfo init data). So it really can't be asked to know what to do. I'm kind of leaning towards the notion that immutable(S) should just be illegal on principle. But that is quite limiting if you wanted to just override the type system. If we had better implicit casting mechanisms, there may have been a way to fix this, but I don't know. This might be a borderline case, but I kind of figured that that piece of code was the *only* one that was universally valid in generic code. I think it's very borderline, not likely to affect many projects. -Steve
Re: Does D has C#'s string.Empty?
On 9/25/14 8:24 PM, AsmMan wrote: On Thursday, 25 September 2014 at 12:43:57 UTC, Steven Schveighoffer wrote: On 9/25/14 2:41 AM, SlomoTheBrave wrote: On Thursday, 25 September 2014 at 05:29:37 UTC, AsmMan wrote: Does D has C#'s string.Empty? string.init ? string a; a = string.init; assert( a == ); does the job for the type string at least. null also works. In fact, in the above, a is already string.init or null before assigning (D always initializes variables unless asked not to). a = null; // same as a = string.init; It made me a bit confusing. How is the implementation of string comparasion in D? (if someone could point to actual code used in these comparasion would be really great otherwise I'll check out assembly output, maybe) in no language I know of (including C#) == null is true A string is simply an array of char in D, similar to how it is in C. It is NOT a full-blown class type, unlike many languages, C# included. The code to compare all arrays is somewhere in the runtime, not sure exactly where, but the compiler has some tricks it can use when generating code, so it may not call those functions. Essentially, comparison is a foreach over the length of the arrays. If they are null, then their lengths are 0. But the actual pointers may be different, it doesn't matter. Interestingly: string s = ; string t = []; Note that both are valid, because both are arrays. but... assert(s.ptr !is null); assert(t.ptr is null); Why? Because string literals are special in that they actually point to null terminated memory. So hello is actually an array of 5 chars + a 6th '\0' char. However, the length of hello is set to 5. The reason for this is so you can just pass a string literal into a C function, and it works. But due to this rule, cannot point at null, it must point to valid memory for the terminating '\0'. An array does not need to conform to C rules, so it can safely set the pointer to null. If we compare s and t: assert(s == t); assert(s !is t); this is because == checks to see if the arrays are *equivalent*, meaning they have the same length, and all the elements are equivalent. 'is' checks to see if the arrays are *identical*, meaning they point at the same memory. -Steve
Re: A few questions regarding GC.malloc
On 9/25/14 6:03 PM, Sean Kelly wrote: On Thursday, 25 September 2014 at 21:43:53 UTC, monarch_dodra wrote: On Thursday, 25 September 2014 at 20:58:29 UTC, Gary Willoughby wrote: What does BlkAttr.FINALIZE do when used in the GC.malloc call? I have no idea. I think its for classes though, since we (currently) don't finalize structs anyways. Yes it's for memory blocks containing class instances. It basically tells the GC to call Object.~this() when collecting the block. Just to add to Sean's statement, don't use this flag. It will crash the runtime, unless you have properly set up the classinfo pointer :) It does NOT work on structs, though I think there is a PR in the works to have structs destroyed from the GC. -Steve
Re: Can I make a variable public and readonly (outside where was declared) at same time?
On 9/26/14 1:36 PM, Marc =?UTF-8?B?U2Now7x0eiI=?= schue...@gmx.net wrote: Alternatively, you could create a union with a private and a public member with the same types, but I wouldn't recommend it. Besides, the members would need to have different names: class Foo { union { private int a; public int b; } } Hm.. that doesn't provide readonly access to either a or b. But it gave me an idea: class Foo { union { private int _a; public const int a; } void setA(int x) { _a = x; } } Hot damn! It works too :) Can't access _a from outside the module, can access a, but can't write it (even from within Foo). It's like an auto-inlined property function. I don't know how it would affect the optimizer, or the GC scanner. Unions are ugly things... -Steve
Re: A few questions regarding GC.malloc
On 9/26/14 3:24 PM, monarch_dodra wrote: On Friday, 26 September 2014 at 18:03:40 UTC, Steven Schveighoffer wrote: On 9/25/14 6:03 PM, Sean Kelly wrote: On Thursday, 25 September 2014 at 21:43:53 UTC, monarch_dodra wrote: On Thursday, 25 September 2014 at 20:58:29 UTC, Gary Willoughby wrote: What does BlkAttr.FINALIZE do when used in the GC.malloc call? I have no idea. I think its for classes though, since we (currently) don't finalize structs anyways. Yes it's for memory blocks containing class instances. It basically tells the GC to call Object.~this() when collecting the block. Just to add to Sean's statement, don't use this flag. It will crash the runtime, unless you have properly set up the classinfo pointer :) It does NOT work on structs, though I think there is a PR in the works to have structs destroyed from the GC. Kind of like APPENDABLE I guess, since it only works if you correctly setup the appendable data, and correctly slice at the correct offset, both of which are implementation defined. Well, kind of yes. But the difference here is that if APPENDABLE is set, and you never actually append to an array in that block, then you are going to be fine. Even if you didn't set it up, it's most likely that you will not encounter a problem, because whatever is there is likely not the right size (and that simply results in a reallocation without touching anything). Even if you do manage to use appending on that block, and the data that happens to be where the allocated size is matches the current slice end, it will corrupt some data (or not, the smaller block sizes keep the append data at the end of the block). This could potentially crash, or it could do nothing. If FINALIZE is set, when the GC collects the memory it WILL crash if you didn't set up some sort of mock classinfo. I don't recommend using either, but FINALIZE is a much worse outcome IMO :) -Steve
Re: Can I make a variable public and readonly (outside where was declared) at same time?
On 9/27/14 5:48 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= schue...@gmx.net Yes, that's what I originally intended. Just forgot the const, and didn't even notice it after I reread it :-P I wondered... ;) -Steve
Re: Initialising multidimensional dynamic arrays
On 9/30/14 12:40 PM, Mike James wrote: On Tuesday, 30 September 2014 at 16:07:28 UTC, ketmar via Digitalmars-d-learn wrote: auto a = new int[][](42, 69); ... You'll notice that it's actually a dynamic array of structs containing dynamic arrays - does this change your initializing? That is what his code does. -Steve
Re: What is a sink delegate?
On 9/30/14 1:22 PM, Gary Willoughby wrote: What is a sink delegate? Discussed here: http://forum.dlang.org/thread/m0bdgg$1t7j$1...@digitalmars.com?page=6#post-m0emvc:242av5:241:40digitalmars.com Aside from Adam's answer, the term 'sink' means to draw out something, as in 'heat sink'. So basically a sink delegate is a place to put the string data. -Steve
Re: is there any reason UFCS can't be used with 'new'?
On 9/30/14 2:07 PM, Ali Çehreli wrote: Apparently, a class definition even inside a unittest blocks are considered to be nested classes. Normally, objects of nested classes are created by the 'this.new' syntax, 'this' meaning the object that wraps the nested class. I think unit test blocks are actually functions disguised as attributes. So it makes sense. void foo() { class C {} auto c = New!C; // same error } -Steve
Re: Initialising multidimensional dynamic arrays
On 10/1/14 3:13 AM, Mike James wrote: Hi Steve, It's true that his code initialises an array of arrays - but my array is an array of structs containing a dynamic array. Regards, -=mike=- Ah, ok. There is no trivial way to do it. Unlike C++, struct default ctors cannot be overridden. I see your question has been answered, but I would just tweak it a bit: foreach(ref m; mda) m.data = new short[y]; Only reason for that is, setting length will call some specialized function which eventually ends up doing exactly the same thing. The above is clearer and more correct IMO. -Steve
Re: array append result type
On 10/6/14 7:28 AM, John Colvin wrote: string a; char[] b; pragma(msg, typeof(a ~ b)); // char[] why not string? It really should be whatever you want. a ~ b is going to generate a completely unique independent copy of a and b. What are the rules that determine this? Not sure. I would have expected at least one of a ~ b or b ~ a to be string, but both generate char[]. I filed this ER ages ago: https://issues.dlang.org/show_bug.cgi?id=1654 Not sure if anyone has it on their radar at this point. -Steve
Re: array append result type
On 10/6/14 1:01 PM, monarch_dodra wrote: On Monday, 6 October 2014 at 16:38:37 UTC, Steven Schveighoffer wrote: I filed this ER ages ago: https://issues.dlang.org/show_bug.cgi?id=1654 Not sure if anyone has it on their radar at this point. -Steve I didn't read the whole thing, but wouldn't purity be a major game changer for 1654? Of course! It was immediately what I thought of when purity = unique was introduced (that and dup/idup). This aspect has not been mentioned on the thread, but that issue is really old. -Steve
Re: function not callable using argument types - i disagree
On 10/7/14 3:15 PM, Vlad Levenfeld wrote: Update: I just did a manual cast. Still getting there error. Here's the new argument lists: (void**, const(PaStreamParameters*), const(PaStreamParameters*), double, uint, uint, extern (C) int function(const(void)*, void*, uint, const(PaStreamCallbackTimeInfo)*, uint, void*), void*) (void**, const(PaStreamParameters*), const(PaStreamParameters*), double, uint, uint, extern (C) int function(const(void)*, void*, uint, const(PaStreamCallbackTimeInfo)*, uint, void*), void*) They're identical... unless I'm losing my mind. Yet still its not callable using argument types I would suggest removing each parameter from the function prototype and call, until you find the culprit. Then put everything else back in. Try moving the parameters around. Yes, the compiled code won't work, but this looks to me like a compiler bug (at least a diagnostic issue), and it will help narrow down a simple case you can submit. -Steve
Re: Simple import question
On 10/9/14 3:30 PM, Adam D. Ruppe wrote: On Thursday, 9 October 2014 at 18:21:32 UTC, WhatMeWorry wrote: To import one module from another, specify the name of the module in an import declaration. The name must include the relative path computed from the directory where compilation takes place This is not true. It is a REALLY common misconception, but it is not true. The import name must match the name given in the module declaration of the file. So in the file you're importing, add module your.name; to the top. In the main file, import it as import your.name;. If those two don't match, it will complain cannot import module foo as foo.bar or something like that. Yes, but in order to read the file, it has to be passed to the compiler, or reside at the location dictated by that module name. This is something quite different from C/C++, because the location in the filesystem doesn't matter at all for the compiler, only the preprocessor. Here, the file location AND module declaration are important. It is recommended that the module name match the file name and folder name, but it is the module declaration at the top that matters, not the file/folder name. You will encounter great pains to not do this (match folder/file names with package/module names). -Steve
Re: What is a sink delegate?
On 10/10/14 1:00 AM, Ali Çehreli wrote: On 10/09/2014 08:06 PM, Joel wrote: On Tuesday, 30 September 2014 at 17:27:09 UTC, Adam D. Ruppe wrote: On Tuesday, 30 September 2014 at 17:22:44 UTC, Gary Willoughby wrote: What is a sink delegate? Instead of string toString() { return foo; } for example, you would use: void toString(void delegate(string) sink) { sink(foo); } The sink argument there is then free to view and discard the data or to make a private copy using whatever scheme it desires. How do you use that toString? Maybe an example? Below is my failed effort. import std.stdio; struct Try { string name; long age; void toString(void delegate(string) sink) { sink(foo); } } void main() { Try t = Try(Joel, 35); writeln(t); } The signature of that toString is different from what I have been seeing and using. The following works: void toString(void delegate(const(char)[]) sink) const { The delegate parameter is what is important. The function that is going to be passed in takes a const(char)[], which actually should, but does not, implicitly cast to a delegate(string) (see issue https://issues.dlang.org/show_bug.cgi?id=3075). The const outside is irrelevant to whether it will accept it or not, that is a contract between the toString function and your object. If you want a non-const toString, I think that should work. (actually, testing it...) Yep, it works without the const on the outside. -Steve
Re: What is a sink delegate?
On 10/10/14 11:20 AM, Ali Çehreli wrote: On 10/10/2014 06:30 AM, Steven Schveighoffer wrote: The const outside is irrelevant to whether it will accept it or not, that is a contract between the toString function and your object. If you want a non-const toString, I think that should work. (actually, testing it...) Yep, it works without the const on the outside. But not for const objects. I think that's what I said :) It's a contract between the toString function and your object, it has nothing to do with writeln accepting the function. There are some quirky requirements for certain magic functions in phobos that have to be exactly a certain signature for the compiler to use it. Now, obviously, the toy example can be labeled const. But not one that might, say, cache some state in order to compute the output. The following program does not call the user defined toString: import std.stdio; import std.conv; struct S { int i; void toString(void delegate(const(char)[]) sink) { sink(i.to!string); Don't do this. Do this instead: import std.format; sink.formattedWrite(i); The former allocates memory on the heap, just to throw it away. You are completely losing the benefit of the sink. -Steve
Re: how to call class' template constructor
On 10/12/14 3:46 PM, ketmar via Digitalmars-d-learn wrote: Hello. please, how to call template constructor of a class? it's completely escaped my mind. i.e. i have this class: class A { this(alias ent) (string name) { ... } } and i want to do: void foo () { ... } auto a = new A!foo(xFn); yet compiler tells me that template instance A!foo A is not a template declaration, it is a class yes, i know that i can rewrite constructor to something like this: this(T) (string name, T fn) if (isCallable!T) { ... } and then use autodeduction, but i want the first form! ;-) Hm... I don't think it's very possible, unless you want to call ctor directly and not conflate with new (i.e. define a factory function instead). Unfortunately, some things can only be done within constructors. At least someone else has found a similar issue before: https://issues.dlang.org/show_bug.cgi?id=10689 I'm not sure what proper syntax would be, perhaps: auto a = (new A)!foo(xFn); A good pattern should be able to be discovered here, to help with the existing state of affairs... -Steve
Re: dsource and WinAPI
On 10/13/14 8:17 PM, dcrepid wrote: I've tried to create an account on dsource.org without success, and am wondering if anyone here knows if they are no longer accepting new users or whatnot? dsource is no longer actively maintained. I don't think anyone knows how to contact the admin. Most D projects these days are done on github. I've added a new winhttp.d source file for the win32 folder and would like to somehow contribute it. Which project are you looking at? -Steve
Re: dsource and WinAPI
On 10/14/14 5:03 AM, dcrepid wrote: Which project are you looking at? Bindings for the Windows API: http://www.dsource.org/projects/bindings/wiki/WindowsApi This is a pretty important project, especially for getting more Windows programmers on board.. thanks for your help Looks like they are still using dsource for that project, latest update is 9/7/14. It does have a github mirror though: https://github.com/CS-svnmirror/dsource-bindings You may be able to at least post a pull request there, and maybe get the thing included. The two most recent contributors are regulars here, they may be able to get your code considered. It also looks like the github link is pretty recent (8/16/14), perhaps a move to github is forthcoming? -Steve
Re: Simple import question
On 10/15/14 4:59 AM, Rei Roldan wrote: I don't see how passing all required files to the compiler could possible raise an issue with module discoverability. Unless I'm missing something? In regards to pains if folder|file names / package|module names don't match, imho, physical organization of files should never (ever) be of any concern to the compiler. import a.b.c; If you didn't pass the file for a.b.c to the compiler, how does it know where to find it? The module system is inherently linked to the filesystem. The way around it is to pass all modules to the compiler that you will be importing so it knows where they are. But this can lead to problems if you don't actually want to compile them, just reference them. The simplest thing to do is to make your file organization match your package/module structure. The compiler understands that and works well with it, no matter what you are doing. -Steve
Re: Simple import question
On 10/16/14 6:59 AM, Rei Roldan wrote: On Wednesday, 15 October 2014 at 16:11:22 UTC, Steven Schveighoffer wrote: *snip* You might of missed Adam's response up there: But the best way is to explicitly pass all the file names to the compiler: dmd yourfile.d file2.d folder/file3.d and so on... Doing that will serve you best in the long run, it will work with any module name and will link better too. No, I didn't miss it. As I said, you can do this with mismatched module and file names, but you will encounter issues if your files need to be imported elsewhere. Note, you can send all the files to the compiler, AND name your files/directories after your modules/packages. Matching the names actually gives you the most options. I also prefer explicitly telling the compiler what I want to be compiled instead of the start here and pull everything you can find approach. What I am specifically identifying as a problem is if you purposely do not name your files and directories after your module structure. Then you are REQUIRED to pass all the files to the compiler, and this doesn't work out well if you just want to import them (and not compile them), e.g. for a pre-compiled library. -Steve
Re: Constructor params with same name as members
On 10/23/14 1:03 AM, Shriramana Sharma via Digitalmars-d-learn wrote: Hello. Please see the following code: import std.stdio ; struct Pair { int x, y ; this (int x, int y) { x = x ; y = y ; } } void main() { auto P = Pair(1, 2) ; writeln(P.x, ' ', P.y) ; } This outputs 0 0, whereas the equivalent C++ code outputs 1 2 correctly: # include iostream struct Pair { int x, y ; Pair(int x, int y) : x(x), y(y) {} } ; This is not the same. In the above, the x outside the parens is ALWAYS a member. D does not have this syntax. Change it to the same as your D implementation, and you get the same result (actually worse, because C++ will not initialize x and y for you). int main() { auto P = Pair(1, 2) ; std::cout P.x ' ' P.y std::endl ; } It seems to me that D should either not permit argument names to shadow the member names, since it has no initializer lists and all members are automatically initialized. Comments? You're missing the or part of that statement :) But 2 things: x = x; This should produce an error, or at least a warning I think, as it does nothing. However, even with dmd -w, it does not. I know I have seen the compiler complain about noop statements before, I just don't know under what circumstances and 2, you would use the same mechanism as you use with C++ to initialize the items inside the ctor: this.x = x; Note, the rules for shadowing are the same as for any function parameters to any function vs. members or module variables. Nothing is inconsistent here. -Steve
Re: Bug?
On 10/23/14 1:08 PM, deed wrote: // DMD v2.066.0 // All asserts pass (!) Using equality is not a good idea with floating point. The compiler will on a whim, or depending on whether it can inline or not, use higher precision floats, changing the outcome slightly. I cannot say for certain whether this explains all the issues you have, the very last one seems troubling to me at least. -Steve
Re: Bug?
On 10/23/14 2:18 PM, deed wrote: Using equality is not a good idea with floating point. The compiler will on a whim, or depending on whether it can inline or not, use higher precision floats, changing the outcome slightly. I cannot say for certain whether this explains all the issues you have, the very last one seems troubling to me at least. Sure, in many cases it's a bad idea. While I understand that sin(PI) != 0.0, but approxEqual(sin(PI), 0.0) == true, I would expect the following to pass: assert (0.0 == 0.0); assert (1.2345 == 1.2345); F a = 1.2345, b = 9.8765; assert (a+b == b+a); assert (a*b == b*a); None of these fail on my system F fun (F a) pure; assert (fun(a) + fun(b) == fun(b) + fun(a)); assert (fun(a) * fun(b) == fun(b) * fun(a)); auto a = fun(100); auto b = fun(100); assert (a == b); assert (fun(100) == fun(100)); Not sure what body of fun is, so I cannot test this. Now, if fun's body is { return sin(a); }, the behaviour changes to: auto c = fun(100); auto d = fun(100); assert (c == d); // Ok assert (fun(100) != fun(100)) // I have a hard time understanding // this is correct behaviour Tried that out, it does not fail on my machine. Can you be more specific on your testing? What compiler/platform? Stock compiler, or did you build it yourself? -Steve