inout type constructor applied to this-reference
Hi, I read about inout functions in the language documentation which allows to use inout in order to set the constness of the return type based on the constness of some argument. What is not mentioned is that this also works for the this-reference by marking the function itself inout: So instead of class C { OtherClass foo; const(OtherClass) getOther() const { return foo; } OtherClass getOther() { return foo; } } we can write class C { OtherClass foo; inout(OtherClass) getOther() inout { return foo; } } Since the documentation only talks about marking arguments inout, can I nevertheless rely on its behavior? Anyways, I think it is worth to be included in the docs. Best regards, Matthias
Re: Getting a range over a const Container
On 07/19/2012 06:44 AM, Jonathan M Davis wrote: On Thursday, July 19, 2012 04:39:26 Francisco Soulignac wrote: So, my question is how can I (correctly) traverse a const SList, const DList, etc? Right now? I'm pretty sure that that's impossible. Hopefully that will change, but getting const and ranges to work together can be rather difficult, and std.container needs more work in that regard. Well it doesn't work yet. But in principle it could since we can always copy a const pointer to a non-const one to const data: Node* actual; // but 'this' is const and hence the type is const(Node*) const(Node)* i_will_traverse = actual; Best regards, Matthias
Re: ~= call copy ctor?
On 07/19/2012 02:27 PM, Namespace wrote: I have a 2 questions. I have this code: [code] import std.stdio; struct Test { public: this(int i = 0) { writeln(Test CTor.); } this(this) { writeln(Test Copy CTor); } ~this() { writeln(Test DTor); } } Test[] _arr; void copy_save(Test t) { _arr ~= t; } void by_ref_save(ref Test t) { _arr ~= t; } [/code] Why get i with [code] void main() { Test t = 42; by_ref_save(t); } [/code] this output: Test CTor. Test Copy CTor Test DTor As you mentioned in the subject the copy constructor is not called while the struct is passed by reference but on array concatenation. But this must occur since the array has its memory region and the original variable t in main() also has. Since they are different, at some point the struct must be copied from t in main() into the array. The ref only ensures that it is passed via reference (a pointer to the memory of t in main()) to the function by_ref_save(). And the same if i have this: [code] void main() { Test t = 42; copy_save(t); } [/code] t is already a clone. Why it is copied again? Here it is once copied from t in main() into the local variable t in copy_save() and then copied (as in your 1st example) into the array. Imagine the copy_save routine is in a different module and only its signature is exposed to main. When calling the function, the compiler does not know what happens inside copy_save but it must put the variable onto the stack at the position of the first parameter (well, in this case it is probably put into a CPU register, but that doesn't matter here). Then, when copy_save is invoked it only knows the local variable which it then copies into the array memory (after enlarging the array). It *may* be the when you enable compiler optimizations (-O -inline) that copy_save gets inlined and hence the compiler can optimize one of the copy calls away. But that I don't know for sure. Best regards, Matthias
Re: ~= call copy ctor?
On 07/19/2012 03:00 PM, Namespace wrote: Is there any way to avoid the implizit copy ctor by array concatenation? Or is the only way to use a pointer? Yes, in some way you have to. If you want to not copy a lot of data (or avoid additional on-copy effort) you either have to you pointers explicitly (Test*[]) or implicitly. The latter works e.g. by making Test a class which means that the variable actually does store a pointer to the instance. Note that for struct pointers you should not escape them, i.e. have a variable local in a function, puts its address into some array and returning that array. Since the local variable is gone, the pointer is invalid as well. (Nothing happens if you do not access it). Best regards, Matthias
Re: foreach syntax
On 06/29/2012 12:47 PM, Namespace wrote: A friend of mine ask me why D's foreach isn't like C# Means, why is it like int[] arr = [1, 2, 3]; foreach (int val; arr) { and not foreach (int val in arr) { which it is more intuitive. I could give him no clever answer to, so maybe someone here knows the reasons. I suppose it is because the usual 'for' loop is a relative of 'foreach'. And there we (and the C world) uses ';'.
Getting a range over a const Container
Hi, I have a const std.container object (e.g., a const(Array!int)) of which I'd like to have a range which can traverse that container having read-only access. This does not seem to be possible with opSlice(). Is there an alternative? Best regards, Matthias
Re: const version for foreach/opApply
On 06/10/2012 12:30 AM, Era Scarecrow wrote: On Saturday, 9 June 2012 at 10:09:25 UTC, Matthias Walter wrote: First, thank you for your answer. I've already made some tiny modifications in order to make BitArray work for my purposes: https://github.com/xammy/phobos/commit/eb46d99217f2bf1e6d173964e2954248b08146d6 If you plan to create pull requests for your changes - please consider my changes as well. When do you expect to finish, I.e., create a pull request for phobos? Curious... Almost all of the changes you proposed I've already added in my version, the toHash is the only one missing and I don't know if I can work that very well. The new version is going to include 'slice-like' features, which is mostly a couple extra numbers specifying the offset in bits from the beginning to the end; The problem with that is hashing would have a huge speed drop. I'm adding an 'realign' function that handles those cases, but the downside is shared slices where you would want to make changes may or may not work. Caching the result would also be useful... Hmmm... I don't suppose you have a toHash where I can enter the odd bits and then also bulk ones and have the hash return the same could you? I can I see the problem. I don't know whether my hash function is a good one - I just needed it to make AAs work with BitArray as a key type. But the question is interesting. Finding a good hash function for bit arrays which is invariant under realignment. see xor easily having this type of effect... Anyways, here's some things I can do so far; Got a few improvements left to do, but not many. (const immutable friendly of course :) ) -- const BitArray ba = BitArray([1,1,0,0,1]); const BitArray slice = ba[1 .. ba.length]; BitArray m = slice.dup; immutable BitArray im = slice.idup; assert(slice == ba[1 .. ba.length]); assert(slice == [1,0,0,1]); assert(slice == m); assert(slice == im); assert(slice.isCompact); writeln(GC not used); Looks interesting!
Re: const version for foreach/opApply
On 2012-06-08 22:47, Era Scarecrow wrote: On Friday, 8 June 2012 at 16:33:28 UTC, Matthias Walter wrote: Hi, trying to traverse the entries of a std.bitmanip.BitArray I stumbled upon the following problem: In case I want to accept const(BitArray) objects, it shall look like the following (maybe using ref const(bool) for the delegate parameter?): int opApply(scope int delegate(bool) dg) const Can one glue both things together into a single routine (using inout magic or whatever)? I want to say you can't, because ref bool. If you ignore the reference, you don't need the non-const version (I think). I am currently working on BitArray updates, and it is const/immutable friendly according to as many tests as I could come up with for valid usage; This has taught me a lot on using templates, traits, constraints and how inout actually works. I haven't tried for a bit but I can try once more to send my code to GitHub, then you can give it a try. First, thank you for your answer. I've already made some tiny modifications in order to make BitArray work for my purposes: https://github.com/xammy/phobos/commit/eb46d99217f2bf1e6d173964e2954248b08146d6 If you plan to create pull requests for your changes - please consider my changes as well. When do you expect to finish, i.e., create a pull request for phobos?
const version for foreach/opApply
Hi, trying to traverse the entries of a std.bitmanip.BitArray I stumbled upon the following problem: The original code is as follows: int opApply(scope int delegate(ref bool) dg) { int result; for (size_t i = 0; i len; i++) { bool b = opIndex(i); result = dg(b); this[i] = b; if (result) break; } return result; } In case I want to accept const(BitArray) objects, it shall look like the following (maybe using ref const(bool) for the delegate parameter?): int opApply(scope int delegate(bool) dg) const { int result; for (size_t i = 0; i len; i++) { bool b = opIndex(i); result = dg(b); if (result) break; } return result; } Can one glue both things together into a single routine (using inout magic or whatever)? Best regards, Matthias Walter
Re: How to test for equality of types?
On 2012-05-19 09:05, Philippe Sigaud wrote: On Fri, May 18, 2012 at 11:51 PM, Simen Kjaeraas simen.kja...@gmail.com wrote: Because Wrapper!(AliasStruct).Wrap does not exist. And _error_ is not equal to any other type. Yes. Wrap is included in the complete template name (Wrapper!(Wrap)) and has no independent existence. You _can_ get access to it by exposing it as an alias, as you do in AliasStruct: struct Wrapper(Wrap) { alias Wrap Wrapped; // cannot call it 'Wrap' ... } Yes, of course you are right. This was my fault - after exposing it via an alias, it prints true. (third case) false And here I disagree. This prints true on 2.059. Regression? AFAICT, this should print true. And, concerning Artur questio, on 2.059 (Linux): pragma(msg, is(w._wrap.Alias == AliasStruct.Alias));// - true pragma(msg, typeof(w._wrap).Alias.stringof); // - MyStruct pragma(msg, AliasStruct.Alias.stringof); // - MyStruct I would open a bug report with the following code which is a bit smaller than my first wrong version: = module main; struct MyStruct { } struct AliasStruct { alias MyStruct Alias; } struct Wrapper { AliasStruct aliasStruct; } void main() { Wrapper w; pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct pragma(msg, AliasStruct.Alias.stringof); // - MyStruct static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true static assert(is(typeof(w.aliasStruct).Alias == AliasStruct.Alias)); // - false } = Best regards, Matthias
Re: How to test for equality of types?
On 2012-05-19 15:28, Philippe Sigaud wrote: On Sat, May 19, 2012 at 12:23 PM, Matthias Walter xa...@xammy.homelinux.net wrote: I would open a bug report with the following code which is a bit smaller than my first wrong version: = (...) pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct pragma(msg, AliasStruct.Alias.stringof); // - MyStruct static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true static assert(is(typeof(w.aliasStruct).Alias == AliasStruct.Alias)); // - false } Seems like a pb concerning whether Alias is a type or a symbol. See A,B,C,D below: void main() { Wrapper w; pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct pragma(msg, AliasStruct.Alias.stringof); // - MyStruct static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true static assert(is(w.aliasStruct.Alias == AliasStruct.Alias)); // - true alias typeof(w.aliasStruct) A; // - OK //alias typeof(w.aliasStruct).Alias B; // - NOK //alias A.Alias C; // - NOK alias w.aliasStruct.Alias D; // - OK static assert(is(A.Alias == AliasStruct.Alias)); // - true //static assert(is(B == AliasStruct.Alias)); //static assert(is(C == AliasStruct.Alias)); static assert(is(D == AliasStruct.Alias)); // - true } I think A is enough for your need, but I don't get why B and C are not accepted (DMD 2.059, Linux) Using the current git version of dmd I realized that C works! Hence, as a workaround it can be used by creating a local alias A and subsequently using A.Alias in the is-expressions. But it seems odd that alias typeof(X).A B; does not work but alias typeof(X) Y; alias Y.A B; does. Is this considered as a bug? Best regards, Matthias
How to test for equality of types?
Hi, how do I test two types for equality? Suppose I have A and B aliasing some type(s), how do I find out if they are aliases the same thing? I tried the is(A == B) expression, but this does not always work (tell me if I shall give an example). On the other hand, according to the spec the IsExpression is not supposed to compare two aliases with each other. Best regards, Matthias
Re: How to test for equality of types?
On 2012-05-18 16:12, Steven Schveighoffer wrote: On Fri, 18 May 2012 06:06:45 -0400, Matthias Walter wrote: how do I test two types for equality? Suppose I have A and B aliasing some type(s), how do I find out if they are aliases the same thing? I tried the is(A == B) expression, but this does not always work (tell me if I shall give an example). I would expect this to work. What situation does it not (maybe you aren't actually testing for equality there). It could be a bug... = struct MyStruct { } struct Wrapper(Wrap) { Wrap _wrap; this(Wrap wrap) { _wrap = wrap; } } struct AliasStruct { public: alias MyStruct Alias; } int main(char[][] args) { auto w = Wrapper!(AliasStruct)(AliasStruct.init); pragma(msg, is(Wrapper!(AliasStruct).Wrap == AliasStruct) ? true : false); pragma(msg, is(typeof(w._wrap) == AliasStruct) ? true : false); pragma(msg, is(typeof(w._wrap).Alias == AliasStruct.Alias) ? true : false); return 0; } = prints out false true false during compilation using current git version of dmd. In my application I used the third case, i.e., wanted to find out whether they alias the same thing. On the other hand, according to the spec the IsExpression is not supposed to compare two aliases with each other. where does it say that? Okay, this seems to be my fault. It states different cases for the RHS operator of is(LHS == RHS), e.g., Type == TypeSpecialization, but nothing like Type == Type. But TypeSpecialization includes Type as well... Best regards, Matthias
Remarks on std.container
Hi, I wanted to have a binary heap where I can update entries and restore the heap structure. 1. First I observed that due to the implementation of std.container.BinaryHeap, keeping track of the position of a certain value in the heap cannot be done directly, but it would be helpful to pass a Swapper object (or function) to the methods that may change the order of the elements such that this Swapper is called for every swap() operation such that the user of the BinaryHeap can keep track of the permutation. 2. I tried to create a heap structure on my own, using std.container.Array as a store. Of course, it I also needs to perform swap operations, but the following did not work: std.algorithm.swap(arrayInstance[i], arrayInstance[j]); Also there is no usable swap() method of Array. So do I really have to perform the swap on my own? I mean, 3 lines of code aren't that much but I really expected an easy way. 3. For my structure I wanted to check the heap structure in an invariant(). Unfortunately, accessing stored elements of Array is no const operation, hence I could not implement such an invariant. Maybe I'm not using it correctly, so any help or comments would be nice. Best regards, Matthias
Mixture of type tuple and expression tuple
Hi, I'd like to have a function foo which shall depend on several compile-time expressions (e.g. strings) and gets several arguments whose types are templatized. Here, several means in both cases that the number of expressions/arguments are to be determined at compile-time. Here is an example: foo!(a, b, c)(42, new MyClass(), 7.0); At compile-time, some template parameters (strings a, b and c) shall be given explicitly and some more template parameters (types of arguments int, MyClass, double) shall be deduced from the function arguments. Is that possible? Of course, I cannot setup two TemplateTupleParameters. Best regards, Matthias
dup method const or not?
Hi, Recently, I realized that several dup methods in D2's phobos are declared like the one for BitArray: @property BitArray dup() My question is why it is declared without const? Is it a bug or is there a reason for it? I can think of a case where one only has implemented a shallow copy and wants to omit the const due to the involved transitivity, but this shouldn't be the case for BitArray (the underlying array is dup'ed). Is there a general rule/recommendation when to make a dup method const and when not? My problem arises in a copy constructor for a struct S which takes a const(S) instance. But as S has a BitArray member, duping is not allowed, so I need a way to duplicate a const(BitArray) object. Matthias
Re: dup method const or not?
On 2011-11-27 23:48, mta`chrono wrote: that's a real good question. it fails with the following error: Error: function std.bitmanip.BitArray.dup () is not callable using argument types () const here is a hack: --- import std.bitmanip; import core.stdc.string; void main() { const(BitArray) foo; BitArray bar; memcpy(bar, foo, BitArray.sizeof); } Well, this hack doesn't even work - as it does a shallow copy only, immediately setting bits of bar also changes bits of foo! Matthias
BinaryHeap usage
Hi all, suppose I have an array of comparable Foo structs which I want to access in a sorted order (e.g. a priority queue) using a BinaryHeap object (I know that for just sorting, the BinHeap is not the right tools), but I do not want to change the order of the objects in the original array. I have two ideas on how to do this and just want to know whether they are the right way: a) Have an array of Foo*, initialize it from the original and instantiate the BinaryHeap with a Comparision-predicate that dereferences first. b) Have an array of indices that are indicies in the original array (like a permutation in a permutation group) and access the corresponding index of the original array for comparison. Any further ideas for this problem, or did I cover everything already? Matthias
Re: D2 byChunk
On 12/11/2010 01:00 AM, Christopher Nicholson-Sauls wrote: On 12/10/10 22:36, Matthias Walter wrote: On 12/10/2010 09:57 PM, Matthias Walter wrote: Hi all, I currently work on a parser for some file format. I wanted to use the std.stdio.ByChunk Range to read from a file and extract tokens from the chunks. Obviously it can happen that the current chunk ends before a token can be extracted, in which case I can ask for the next chunk from the Range. In order to keep the already-read part in mind, I need to dup at least the unprocessed part of the older chunk and concatenate it in front of the next part or at least write the code that works like they were concatenated. This looks like a stupid approach to me. Here is a small example: file contents: Hello world chunks: Hello w orld First I read the token Hello from the first chunk and maybe skip the whitespace. Then I have the w (which I need to move away from the buffer, because ByChunk fill overwrite it) and get orld. My idea was to have a ByChunk-related Object, which the user can tell how much of the buffer he/she actually used, such that it can move this data to the beginning of the buffer and append the next chunk. This wouldn't need further allocations and give the user contiguous data he/she can work with. I coded something that works like this: foreach (ref ubyte[] data; byBuffer(file, 12)) { writefln([%s], cast(string) data); data = data[$-2 .. $]; } The 2nd line in the loop tells ByBuffer that we didn't process the last two chars and would like to get them again along with newly read data. And as long as we do process something, the internal buffer does not get reallocated. It works and respects the formal requirements of ranges. Whether it respects the intended semantics, one can discuss about. Any comments whether the above things make sense or is an evil exploit of the provided syntax sugar? I don't think it's a bad approach, but I have a suggestion. It leaves a lot of room for abuse or misuse if you require the user code to modify the data[] array in order to send this protect some characters message. I think it would be better to provide an explicit function/method that means precisely that. Maybe return a transparent struct wrapping a view to the buffer's data, that further provides a function for doing precisely this. foreach( data; byBuffer( file, 12 )) { // do things with data, decide we need to keep 2 chars data.save( 2 ); } Or something like it. With regards to this, you may want to allow the internal buffer to grow (if you aren't already) as needed. Imagine what would otherwise happen if you needed to 'save' the entire current buffer. -- Chris N-S Thank you! This is a really good idea. So I basically wrap the buffer-array and implement it such that the default behavior (without explicitely doing something) is like the ByChunk mechanism. Matthias
Re: setting array dimensions at runtime
The only thing I've been able to think of is byte[][] a; a.length = size; for (int i; i size; i++) { a[i].length = size; } Well, you can do at least: auto a = new byte[][size]; foreach (ref row; a) row = new byte[size]; Matthias
Re: bigint
On 11/27/2010 02:05 PM, bearophile wrote: Reduced case for bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=5281 I investigated into the bug and the reason is the signature of opEquals, which currently is bool opEquals(Tdummy=void)(ref const BigInt y) const bool opEquals(T: int)(T y) const The only working sigature for array-of-structs-comparison to work is bool opEquals(ref const BigInt y) const But this removes the ability to compare against ints. (btw, it should probably be long in the 2nd signature?!) array-comparison should definitely take templated opEquals functions into account, or is there something mentioned in the spec? Matthias
Current status of toString in phobos
Hi, I'm currently using DMD v2.049 with phobos. I found an old discussion about how toString should be designed and how it is supposed to work. As the following code does not print out the number, I wonder what is the current status of how to implement a toString function for a struct/class: | auto n = BigInt(42); | writefln(%s, n); Thanks Matthias
Re: A module comprehensive template-specialization
On 06/28/2010 05:32 AM, Simen kjaeraas wrote: Matthias Walter xa...@xammy.homelinux.net wrote: Can I handle this in another way (like making the template a conditional one)? Template constraints[1] sounds like what you want. Basically, you want the following: == Module a == | module a; | | template Base (T) if (!is(T t : t*)) | { | alias T Base; | } == Module b == | module b; | | import a; | | template Base(T) if (is(T t : t*)) | { | alias Base !(T) Base; | } == Main module == | | import a, b; | | int main(char[][] args) | { | alias Base !(int*) foo; | | return 0; | } Not tested, ymmv. [1]: http://digitalmars.com/d/2.0/template.html#Constraint The problem with constraints arises when I want to make an existing class (who's code I cannot modify) match a Concept, in which case I would just add another template specialization for this class. Here I would have to add further conditions to the template constraints, which would also mean to modify a library. A prominent example for Boost Graph Library is the LEDA graph class, which can be enabled to be used by BGL by more or less just specializing the graph_traits template. Any further ideas?
Re: A module comprehensive template-specialization
On 06/28/2010 09:49 AM, Justin Spahr-Summers wrote: On Sun, 27 Jun 2010 18:51:35 +0200, Matthias Walter xa...@xammy.homelinux.net wrote: Hi list, I tried to write a traits class comparable to iterator_traits in C++ STL or graph_traits in Boost Graph Library in D 2.0, but failed to do so via template specialization which is put into different modules. Putting everything into one module interferes with extensibility. I tried the following: == Module a == | module a; | | template Base (T) | { | alias T Base; | } == Module b == | module b; | | import a; | | template Base(T: T*) | { | alias Base !(T) Base; | } == Main module == | | import a, b; | | int main(char[][] args) | { | alias Base !(int*) foo; | | return 0; | } The error message is: bug.d(8): Error: template instance ambiguous template declaration b.Base(T : T*) and a.Base(T) Can I handle this in another way (like making the template a conditional one)? best regards Matthias Walter I believe this is intended behavior, as it prevents template hijacking and the like. Using alias to import the two templates into the same scope might help, though I'm not sure exactly how it should be done. I tried to do so in some variants but did not succeed unfortunately. If you have a precise idea, please let me know! On another note, though, have you looked at __traits() and std.traits? I looked at them but didn't find them helpful for this precise problem. The whole reason for doing this is to make it possible to make another existing class model the concept (i.e. have some aliases / typedefs done) of my library class without editing any of them. As I mentioned in my other response, a prominent example for Boost Graph Library is the LEDA graph class, which can be enabled to be used by BGL by more or less just specializing the graph_traits template. I'd like to have this kind of technique available, too. Any further suggestions?
A module comprehensive template-specialization
Hi list, I tried to write a traits class comparable to iterator_traits in C++ STL or graph_traits in Boost Graph Library in D 2.0, but failed to do so via template specialization which is put into different modules. Putting everything into one module interferes with extensibility. I tried the following: == Module a == | module a; | | template Base (T) | { | alias T Base; | } == Module b == | module b; | | import a; | | template Base(T: T*) | { | alias Base !(T) Base; | } == Main module == | | import a, b; | | int main(char[][] args) | { | alias Base !(int*) foo; | | return 0; | } The error message is: bug.d(8): Error: template instance ambiguous template declaration b.Base(T : T*) and a.Base(T) Can I handle this in another way (like making the template a conditional one)? best regards Matthias Walter