ctfe bug?
Hi, the following code is reduced from a parser generated with Ragel (http://www.complang.org/ragel/). That's also the reason why it's using pointers instead of array access, but Ragel guarantees that there won't be any out-of-bound reads. AFAIK pointers are supported in CTFE now as long as they're pointing to an array and there are no out-of-bounds reads. Still, the following code fails: ubyte[4] testCTFE() { ubyte[4] data; string input = "8ab3060e2cba4f23b74cb52db3bdfb46"; auto p = input.ptr; p++; p++; data[0] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; data[1] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; data[2] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; data[3] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; return data; } enum ctfe = testCTFE(); void main() { import std.stdio; writeln(testCTFE()); //[138, 179, 6, 14] writeln(ctfe); //[138, 138, 138, 138] } Has this bug already been filed? I could possibly circumvent it by making ragel use array indexing instead of pointers, but that'd be a performance issue for runtime code as well.
Re: test if object is instance of class at compile time
On 2011-12-21 21:15, Elvis Maehren wrote: This works fine at runtime, but explodes in CTFE: --- bool isInstanceOf(T, O)(O o) { return (cast(T) o) !is null; } --- CTFE doesn't like "!is null" ("cannot compare [...] at compile time"). Moreover, in CTFE a failed cast terminates the interpretation ("cannot reinterpret class from [...] to [...] at compile time"). Is this somehow catchable? If so, I could do something along these lines: --- if(__ctfe) { try { auto t = cast(T) o; return true; } catch { return false; } } --- I don't think you can do a test like that during compile time. In your above function, isInstanceOf, "o" will always be of the type "O". You can always do a comparisons to see if O is the same type as T. -- /Jacob Carlborg
Re: Are D classes always garbage collected?
On Wed, Dec 21, 2011 at 10:20 PM, Froglegs wrote: > >>> Which returned me a nice fat null pointer.. wth? Perhaps that should be a >>> compile time error if you aren't supposed to use classes.. >> >> >> Strange... I'm not sure what the deal is with that overload. I meant the >> last one on the page (that takes a void[]). > > > > Hum I've tried the array version but I believe it contains a rather serious > bug... > > T emplace(T, Args...)(void[] chunk, Args args) if (is(T == class)) > { > enforce(chunk.length >= __traits(classInstanceSize, T), > new ConvException("emplace: chunk size too small")); > ... > > This fails whenever the size is greater or equal to the amount of memory > required :( > > > Anyway I need the pointer version for what I was hoping to do, unless there > is some way to convert a pointer into an array? > > Is there any way to do something like this.. > > void* pData = some_c_function(); > void [] fakeArray = pData, size; > > Yes: void* pData = some_c_function(); void[] fakeArray = pData[0..size]; Although Vladimir's solution is safer.
Re: Are D classes always garbage collected?
On Thursday, 22 December 2011 at 06:43:33 UTC, Froglegs wrote: T emplace(T, Args...)(void[] chunk, Args args) if (is(T == class)) { enforce(chunk.length >= __traits(classInstanceSize, T), new ConvException("emplace: chunk size too small")); ... This fails whenever the size is greater or equal to the amount of memory required :( Hum nevermind that, got confused by the IDE behavior. Anway this emplace function crashes when I call it with a very meaningless callstack. This works for me: import std.conv; class C { int i; this() { i = 42; } } unittest { void[__traits(classInstanceSize, C)] data = void; auto c = emplace!C(data[]); assert(c.i == 42); }
Re: Are D classes always garbage collected?
T emplace(T, Args...)(void[] chunk, Args args) if (is(T == class)) { enforce(chunk.length >= __traits(classInstanceSize, T), new ConvException("emplace: chunk size too small")); ... This fails whenever the size is greater or equal to the amount of memory required :( Hum nevermind that, got confused by the IDE behavior. Anway this emplace function crashes when I call it with a very meaningless callstack.
Re: Are D classes always garbage collected?
Which returned me a nice fat null pointer.. wth? Perhaps that should be a compile time error if you aren't supposed to use classes.. Strange... I'm not sure what the deal is with that overload. I meant the last one on the page (that takes a void[]). Hum I've tried the array version but I believe it contains a rather serious bug... T emplace(T, Args...)(void[] chunk, Args args) if (is(T == class)) { enforce(chunk.length >= __traits(classInstanceSize, T), new ConvException("emplace: chunk size too small")); ... This fails whenever the size is greater or equal to the amount of memory required :( Anyway I need the pointer version for what I was hoping to do, unless there is some way to convert a pointer into an array? Is there any way to do something like this.. void* pData = some_c_function(); void [] fakeArray = pData, size;
Re: Are D classes always garbage collected?
On Thursday, 22 December 2011 at 04:15:25 UTC, Froglegs wrote: You can allocate classes anywhere, if you're OK with forfeiting safety guarantees. For example, see emplace in std.conv: http://dlang.org/phobos/std_conv.html#emplace Hum calling emplace ending up calling this bit of code.. T* emplace(T)(T* chunk) if (is(T == class)) { *chunk = null; return chunk; } Which returned me a nice fat null pointer.. wth? Perhaps that should be a compile time error if you aren't supposed to use classes.. Strange... I'm not sure what the deal is with that overload. I meant the last one on the page (that takes a void[]). I tried placement new syntax but this tells me I need an allocator, whatever that means.. http://www.d-programming-language.org/memory.html#newdelete Note that this feature is on its way to be deprecated. emplace and clear are the future-proof method.
Re: Are D classes always garbage collected?
You can allocate classes anywhere, if you're OK with forfeiting safety guarantees. For example, see emplace in std.conv: http://dlang.org/phobos/std_conv.html#emplace Hum calling emplace ending up calling this bit of code.. T* emplace(T)(T* chunk) if (is(T == class)) { *chunk = null; return chunk; } Which returned me a nice fat null pointer.. wth? Perhaps that should be a compile time error if you aren't supposed to use classes.. I tried placement new syntax but this tells me I need an allocator, whatever that means.. I swear D is google proof sigh
Re: Are D classes always garbage collected?
You can allocate classes anywhere, if you're OK with forfeiting safety guarantees. For example, see emplace in std.conv: http://dlang.org/phobos/std_conv.html#emplace Ah thanks Value type polymorphism has shown to be problematic. One notable problem is object slicing: http://en.wikipedia.org/wiki/Object_slicing I see... seems like a pretty weak reason, I've never found that to be an issue in C++ as it is exactly what I'd expect to happen if I did something like that. I *think* the language allows implementing something akin to value type polymorphism (sans syntax sugar), but currently the required compiler features (alias this, compile-time symbol/address evaluation) are not implemented well-enough to test my idea. Ah, faking it, hopefully that works out someday :)
Re: test if object is instance of class at compile time
On Wednesday, 21 December 2011 at 20:15:36 UTC, Elvis Maehren wrote: Is this somehow catchable? I believe that's what __traits(compiles, ...) is for: http://dlang.org/traits.html#compiles
Re: Are D classes always garbage collected?
On Thursday, 22 December 2011 at 02:29:10 UTC, Froglegs wrote: From what I understand D classes are reference types, which would imply to me that they are either always garbage collected or rather less likely, reference counting. They are garbage-collected. Which is fine and all, but since structs don't support virtual functions, doesn't this pretty much force you to use classes and therefor GC if you want virtual functions? You can allocate classes anywhere, if you're OK with forfeiting safety guarantees. For example, see emplace in std.conv: http://dlang.org/phobos/std_conv.html#emplace So why don't structs support virtual funtions? I would like to have a type that is not GC'd or ref counted or any other nonsense, but supports virtual functions.. Value type polymorphism has shown to be problematic. One notable problem is object slicing: http://en.wikipedia.org/wiki/Object_slicing Am I missing something here? Thanks I *think* the language allows implementing something akin to value type polymorphism (sans syntax sugar), but currently the required compiler features (alias this, compile-time symbol/address evaluation) are not implemented well-enough to test my idea.
Are D classes always garbage collected?
From what I understand D classes are reference types, which would imply to me that they are either always garbage collected or rather less likely, reference counting. Which is fine and all, but since structs don't support virtual functions, doesn't this pretty much force you to use classes and therefor GC if you want virtual functions? So why don't structs support virtual funtions? I would like to have a type that is not GC'd or ref counted or any other nonsense, but supports virtual functions.. Am I missing something here? Thanks
test if object is instance of class at compile time
This works fine at runtime, but explodes in CTFE: --- bool isInstanceOf(T, O)(O o) { return (cast(T) o) !is null; } --- CTFE doesn't like "!is null" ("cannot compare [...] at compile time"). Moreover, in CTFE a failed cast terminates the interpretation ("cannot reinterpret class from [...] to [...] at compile time"). Is this somehow catchable? If so, I could do something along these lines: --- if(__ctfe) { try { auto t = cast(T) o; return true; } catch { return false; } } ---
Re: writing iterators without code duplication. inout?
"pompei2" , dans le message (digitalmars.D.learn:31164), a écrit : > This is what I have, which works but has severe code duplication. > I hoped inout would help me here, but I just can't figure it out. > I also gave a try to ranges, but same thing again: I can only get > it to work if I define my things twice. It's not optimal, and there is an ugly cast, but maybe this is a suitable workarrond for you : int delegate(int delegate(ref int)) doIter() const { return (int delegate(ref int) dg) { cast(typeof(this))(this).doIter()((ref int i) { int copy = i; dg(copy); }); } } Until int delegate(ref inout int) opApply() inout; and int delegate(int delegate(ref inout int)) doIter() inout; are made to work. (I actually don't know if there is any obstacles to do this).
Re: writing iterators without code duplication. inout?
On Wednesday, 21 December 2011 at 16:07:55 UTC, Timon Gehr wrote: Just remove the non-const overload. const member functions work with mutable, immutable and const receivers. The const version does not allow using 'ref' when iterating.
Re: writing iterators without code duplication. inout?
On Wednesday, 21 December 2011 at 16:05:24 UTC, Trass3r wrote: Can't really answer your original question, but 1. Why don't you use opApply? 2. Why do you use ref int even in the const version? 3. You could also use alias this to allow iteration, don't know if that's what you want in general though. 1&3: Because there are different things in my class to iterate over. Think foreach(p ; obj.properties()) and foreach(c ; obj.components()). (I know, I can make those @property so I don't need the ().) 2. Because if not, it says: Error: cannot implicitly convert expression (__foreachbody1315) of type int delegate(ref int) to int delegate(int)
Re: writing iterators without code duplication. inout?
On Wednesday, 21 December 2011 at 16:31:01 UTC, Jakob Ovrum wrote: On Wednesday, 21 December 2011 at 16:07:55 UTC, Timon Gehr wrote: Just remove the non-const overload. const member functions work with mutable, immutable and const receivers. The const version does not allow using 'ref' when iterating. In light of pompei2's recent reply; the const version *should not* allow using 'ref' when iterating.
Re: writing iterators without code duplication. inout?
Just remove the non-const overload. const member functions work with mutable, immutable and const receivers. Doing this, it compiles but it doesn't do what it should in two ways: 1. I leave the code as-is. It compiles but "e" in the first foreach loop in "main" is a copy, not a reference. This shows by the second loop still displaying the original values, not the +1 values. 2. To fix 1., I can change the "i" in the foreach loop in "doTheIter" to "ref i", which will allow the first foreach loop in "main" to successfully modify the array elements. But now, add the line "e++;" into the second loop and it still compiles! Change it to "ref e" (still in the second loop) and add a third loop and it actually does modify the elements! It shouldn't be allowed to, as "cc" is const and const is supposed to be transitive. I'm not even using a cast. So either this is not the solution, or I'm doing it wrong.
Re: writing iterators without code duplication. inout?
On 12/21/2011 04:54 PM, pompei2 wrote: Hello. I want to add the option to iterate objects of my class using foreach. I need them to be iterable as view-only const and as mutable too. I would prefer to iterate using the "return a delegate" but if that's not possible, ranges are fine too. Also, I'd prefer a template-less solution over a templated one. This is what I have, which works but has severe code duplication. I hoped inout would help me here, but I just can't figure it out. I also gave a try to ranges, but same thing again: I can only get it to work if I define my things twice. (syntax highlight for the coming month: http://pastebin.com/TNmWWgsj) import std.conv, std.stdio; class Container { this(int from, int to) { while(from <= to) { _arr ~= from; from++; } } // FIXME: severe code duplication for const/nonconst/ref // and I'm not even trying immutable yet int delegate(int delegate(ref int)) doIter() { writeln("calling non-const"); int doTheIter(int delegate(ref int) dg) { int result = 0; foreach(ref i ; this._arr) { result = dg(i); if(result) break; } return result; } return &doTheIter; } int delegate(int delegate(ref int)) doIter() const { writeln("calling const"); int doTheIter(int delegate(ref int) dg) { int result = 0; foreach(i ; this._arr) { result = dg(i); if(result) break; } return result; } return &doTheIter; } int[] _arr; } int main(string[] args) { Container c = new Container(1, 9); const Container cc = c; foreach(ref e ; c.doIter()) { writeln(e); e++; } foreach(e ; cc.doIter()) { writeln(e); } return 0; } Just remove the non-const overload. const member functions work with mutable, immutable and const receivers.
Re: writing iterators without code duplication. inout?
Can't really answer your original question, but 1. Why don't you use opApply? 2. Why do you use ref int even in the const version? 3. You could also use alias this to allow iteration, don't know if that's what you want in general though.
writing iterators without code duplication. inout?
Hello. I want to add the option to iterate objects of my class using foreach. I need them to be iterable as view-only const and as mutable too. I would prefer to iterate using the "return a delegate" but if that's not possible, ranges are fine too. Also, I'd prefer a template-less solution over a templated one. This is what I have, which works but has severe code duplication. I hoped inout would help me here, but I just can't figure it out. I also gave a try to ranges, but same thing again: I can only get it to work if I define my things twice. (syntax highlight for the coming month: http://pastebin.com/TNmWWgsj) import std.conv, std.stdio; class Container { this(int from, int to) { while(from <= to) { _arr ~= from; from++; } } // FIXME: severe code duplication for const/nonconst/ref //and I'm not even trying immutable yet int delegate(int delegate(ref int)) doIter() { writeln("calling non-const"); int doTheIter(int delegate(ref int) dg) { int result = 0; foreach(ref i ; this._arr) { result = dg(i); if(result) break; } return result; } return &doTheIter; } int delegate(int delegate(ref int)) doIter() const { writeln("calling const"); int doTheIter(int delegate(ref int) dg) { int result = 0; foreach(i ; this._arr) { result = dg(i); if(result) break; } return result; } return &doTheIter; } int[] _arr; } int main(string[] args) { Container c = new Container(1, 9); const Container cc = c; foreach(ref e ; c.doIter()) { writeln(e); e++; } foreach(e ; cc.doIter()) { writeln(e); } return 0; }
Re: newbie question: Can D do this?
Timon Gehr , dans le message (digitalmars.D.learn:31142), a écrit : > On 12/20/2011 03:18 PM, clk wrote: >> Thank you for your quick replies. I'm impressed by the helpfulness and >> dedication of the D community! >> Here's another one. Is there a way to pass arguments to functions by >> keyword as in the calls to f and g below? >> >> void f(int a = 0, int b = 1) {} >> void g(int a) {} >> >> void main() { >> f(b = 1, a = 0); // compile error >> g(a = 0); // also compile error >> } >> >> > > No, there are no named arguments in D. Having them would sometimes be > useful, > but the drawback is that the parameter names become part of the > public interface. Well, that's precisely the point. And it is a drawback if parameters are systematically names, but not if it is triggered only on demand. Example : void foo(int a, int b:, int c:); void main() { foo(1, 2, 3); foo(1, c: 3, b: 2; foo(a: 1, b: 2, c: 3); // error : a is not a named parameter. } In the example, ":" is used to make a named parameter to recall the use when you call the function.
Re: How to mixin each element of tuple
On 20. 12. 2011 16:20, Timon Gehr wrote: struct Item1(T){} struct Item2(T){} mixin template getItems(Items ...){ static if(Items.length) { private alias Items[0] _item; mixin _item!int; mixin getItems!(Items[1..$]); } } struct Group(Items...) { mixin getItems!Items; } void main(){ alias Group!(Item1, Item2) G; } Thank you. Solution 1 worked well. The need to introduce new symbol '_item' using alias because one cannot mixin Items[0]!int directly seems to me as a bug. Do you happen to know if it is already reported?
Re: newbie question: Can D do this?
In PHP frameworks often use $option arrays which are some kind of key value pairs. they are merged with the default valuzes inside the function. pro: - you can pass an argument by name - you only need to pass those who needed. cons: - hash arrays it should be possible to create a similar method in d. but I really don't like this solution in d. it feels bad and looks ugly. query(array( 'firstname' => 'John', 'country' => 'France', 'order' => 'asc' )); class Model { function query($options = array()) { // merge with defaults $options = array_merge(array( 'deep' => true, 'order' => 'desc', 'type' => 'sql', 'backend' => 'mysql' ... ), $options); } } ?>