Re: How to partially forward properties of struct array member to struct (disable length property) ?
On Sunday, 6 September 2015 at 10:12:58 UTC, ParticlePeter wrote: In the end all that I want is "just" to disable access to array.length through vector and alias this array. struct Vec(T, size_t n = 3) { T[n] data; alias data this; @disable @property size_t length() const; } void main() { Vec!int v; v[0] = 1; // ok assert(v[0] == 1); // ok int n = v.length; // error } - Kenji
Re: Cannot use the same template arguments on function as the ones on struct
On Wednesday, 11 February 2015 at 22:24:53 UTC, anonymous wrote: On Wednesday, 11 February 2015 at 22:14:44 UTC, MrSmith wrote: http://dpaste.dzfl.pl/5f1d5d5d9e19 Instead I need to use template constraint which is less compact. http://dpaste.dzfl.pl/571ae84d783e Why such behavior happens? Seems to work when you add an empty template argument list to `accepter()`, making it `accepter!()()`: http://dpaste.dzfl.pl/2ec186453907 So, compiler bug, I guess? The error message says it tried !()(), but explicit !()() actually works. And the empty template argument list should be optional anyway. It would be a compiler bug. As far as I know, accepter() and accepter!()() has no difference in IFTI. I filed the issue in bugzilla. https://issues.dlang.org/show_bug.cgi?id=14174 Kenji Hara
Re: class is forward referenced when looking for 'v'
On Friday, 30 January 2015 at 00:09:17 UTC, Amber Thralll wrote: And the errors dmd returns: test.d(16): Error: class test.A!int.A is forward referenced when looking for 'v' test.d(16): Error: class test.A!int.A is forward referenced when looking for 'opDot' test.d(16): Error: class test.A!int.A is forward referenced when looking for 'opDispatch' test.d(29): Error: no property 'v' for type 'test.A!int.A' test.d(10): Error: template instance test.B!int error instantiating test.d(16):instantiated from here: Base!int test.d(35):instantiated from here: A!int Is this a bug in D? Or am I doing something wrong? In D, forward reference resolution should have consistent result for template classes and non-template ones. If the code is rewritten to non-template version: import std.stdio; class Base { public void Foo(A a) { writeln(Base.Foo(A a)); } public void Foo(B a) { writeln(Base.Foo(B a)); } }; class A : Base { public int v; this(int v) { this.v = v; } } class B : Base { public override void Foo(A a) { writeln(A: , a.v); } } int main() { A a = new A(1); B b = new B(); a.Foo(b); b.Foo(a); return 0; } Compiler properly resolves forward references. Therefore, it's definitely a compiler bug, and the template version should be accepted. I filed the issue in bugzilla: https://issues.dlang.org/show_bug.cgi?id=14083 And will open a new pull request to fix compiler. Kenji Hara
Re: Segfault upon modifying immutable AA in static this
On Saturday, 24 January 2015 at 13:29:36 UTC, Nordlöw wrote: The issue originates from module level intialization of static immutable AAs at https://github.com/nordlow/justd/blob/master/conv_ex.d Do I have to change the initialization of the AAs to be explicitly inline at definition of the AAs or can I preserve my convenient foreach over the AAs in the `static this` to automatically get the integer value to be stored? Note that this does not segdefault on latest stable DMD 2.066. It's a regression in git-head. https://issues.dlang.org/show_bug.cgi?id=14038 Kenji Hara
Re: Initialization of structure field w/o default ctor
On Thursday, 22 January 2015 at 12:45:53 UTC, drug wrote: On 22.01.2015 15:30, bearophile wrote: drug: Also can I avoid dummy non-default ctor for Bar? One solution: struct Foo { int foo; @disable this(); this(int foo_) pure nothrow @safe @nogc { this.foo = foo_; } } struct Bar { enum arraySize = 3; Foo[arraySize] foo = Foo(1); } void main() @safe { import std.stdio; Bar bar; bar.writeln; } Bye, bearophile Yes, that's what the doctor prescribed. Thank you! Or you can use block assignment in the constructor. struct Bar { enum ArraySize = 3; Foo[ArraySize] foo; this(string dummy) // == here because compiler demands to initialize field foo { import std.algorithm: fill; //fill(foo[], Foo(0)); foo[] = Foo(0); // == OK } } Compiler can recognize the block assignment as a construction for the field Bar.foo. Kenji Hara
Re: Redirect to different overloads at compile time?
On Monday, 30 June 2014 at 02:24:10 UTC, David Bregman 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. Is it possible to do something like alias foo = foo_double; alias foo = foo_float; In D, you can merge arbitrary overloads by using alias declaration. import std.stdio; extern(C) { double foo_double(double a) { writeln(typeof(a).stringof); return a; } float foo_float (float a) { writeln(typeof(a).stringof); return a; } } alias foo = foo_double; alias foo = foo_float; void main() { double d; float f; foo(d); // prints double foo(f); // prints float } Kenji Hara
Re: Don't Understand why Phobos Auto-Tester fails for PR #3606
On Saturday, 7 June 2014 at 08:56:38 UTC, Nordlöw wrote: My recent https://github.com/D-Programming-Language/dmd/pull/3606 fails in all the Auto-Testers but I don't understand why. Running make unittest locally in phobos using my locally built branch of dmd passes all tests. Please help! I commented in github. Kenji Hara
Re: CTFE error, but I have no idea what it means.
On Monday, 31 March 2014 at 11:51:50 UTC, Olav Lindekleiv wrote: Here's the issue: http://d.puremagic.com/issues/show_bug.cgi?id=12498 Fixed in git-head. https://github.com/D-Programming-Language/dmd/commit/2c4d8ad711ccb7c94d349830523dd500580b0130 Kenji Hara
Re: template interface and delegates
On Tuesday, 1 April 2014 at 19:55:05 UTC, Steven Schveighoffer wrote: On Tue, 01 Apr 2014 15:47:42 -0400, anonymous n...@trash-mail.com wrote: Is this bug allready reported? or can somebody who has a deeper insight to this report it? I don't know. I think you should report it. If it's already reported, someone will close it as a duplicate -Steve I filed it. https://d.puremagic.com/issues/show_bug.cgi?id=12508 Kenji Hara
Re: strange compilation error
On Sunday, 9 March 2014 at 11:21:19 UTC, Jack Applegame wrote: This fails to compile http://dpaste.dzfl.pl/e9a90e808af4 It's a compiler bug. https://d.puremagic.com/issues/show_bug.cgi?id=12334 https://github.com/D-Programming-Language/dmd/pull/3371 Kenji Hara
Re: Type inference and overloaded functions
On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote: Namespace: Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045 This is part of the thread there: Furhtermore, what if we indeed want to pass a dynamic array ? Kenji Use cast. In real world, if overloaded function takes both int[] and int[3], normally int[3] version would provide specialized implementation for 3 length arrays (eg. unroll the loop to operate each elements of the given array). Therefore force to invoke int[] version with array literal is not usual situation. Cast will fit in such case. If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable: void foo(int[]) {} void main() { foo([1, 2, 3]); int[3] tmp = [4, 5, 6]; foo(tmp); } There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in @safe code. With the []s syntax it should become: void foo(int[]) {} void main() { foo([1, 2, 3]); foo([4, 5, 6]s); } But I don't know how much common is such need. In the Rust language when you write an array literal you always prefix it with a symbol, to tell the compiler where you want to allocate it. So I think it's not so useless :-) Bye, bearophile I'm afraid that allowing foo([4, 5, 6]s) would easily cause memory corruption. I don't want to hurt language future by the trivial syntactic sugar. Kenji Hara
Re: Type inference and overloaded functions
On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis wrote: On Tuesday, December 10, 2013 10:10:22 Namespace wrote: auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]); Why do you think this is possible? If an array literal should match _only_ dynamic array types, it would never work. Because compiler will try to match array literal to static array T[n]. The feature which I have described is working here. Kenji Hara
Re: Type inference and overloaded functions
On Tuesday, 10 December 2013 at 07:32:08 UTC, Marco Leise wrote: [1,2,3] looks like a static array to me. And if overload resolution picked the most specialized function it seems natural to call the int[3] version. My reasoning being that static arrays can be implicitly converted to dynamic array, but the reverse is not true. So I think it would be better to have [1,2,3] be a static array and keep the current behavoir, no?) In early D1 age, array literals and string literals had had static array types which corresponding to the literals' element count. However it had caused template code bloat. void foo(T)(T arg) { ... } foo(aaa); // instantiate foo!(char[3]) foo(); // instantiate foo!(char[4]) foo([1,2]);// instantiate foo!(int[2]) foo([1,2,3]); // instantiate foo!(int[3]) So their types were changed to dynamic array by default. Kenji Hara
Re: Type inference and overloaded functions
On Tuesday, 10 December 2013 at 07:15:43 UTC, Jonathan M Davis wrote: On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote: On 12/09/2013 10:52 PM, Jonathan M Davis wrote: On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote: I just found weird D behavior about inference of array types. Let's suppose we have these overloaded functions: import std.stdio; void bar(const(int[3]) arr) { writeln(static array); } void bar(const(int[]) arr) { writeln(array slice); } // In main we have something like that: int main(string[] args) { bar([1,2,3]); writeln(typeof([1,2,3]).stringof); return 0; } Weird thing is that the static array version of bar is called, but typeof().stringof is int[], not int[3]. Array literals are always dynamic arrays. int[3] is a static array. - Jonathan M Davis The original question is valid then: [1,2,3] goes to the static array overload. Then AFAIK, that's a bug. The type of array literals is always a dynamic array, so they should match dynamic array overloads rather than static array overloads, or if they match both due to an implicit conversion, there should be an ambiguity error. Choosing the static array overload over the dynamic one is just plain wrong. This is an intended behavior. An array literal has dynamic array type *by default*. But all of literals in D behave as polymorphic. char c = 'A'; // character literal has char type by default dchar d = 'A'; // but it may be implicitly typed as wchar/dchar string str = hello; dstring dstr = hello; // string literal is implicitly typed as dstring int[] darr = [1,2,3]; int[3] darr = [1,2,3]; // implicitly typed as int[3] So, an array literal [1,2,3] is implicitly convertible both to int[] and int[3]. And, int[3] is more specialized than int[], so overload resolution will choose the first 'bar'. Kenji Hara
Re: Template condition triggers compiler error?
On Sunday, 1 December 2013 at 16:07:18 UTC, Namespace wrote: This code compiles: template gc_free(T) { static if (is(T : U*, U) || is(T : U[], U)) alias Type = T; else alias Type = T*; void gc_free(Type data) { import core.memory : GC; static if (is(Type : U[], U)) { GC.free(data.ptr); GC.minimize(); } else { GC.free(data); } data = null; } } But with a template condition it triggers compiler errors: template gc_free(T) if (!is(T == class)) { static if (is(T : U*, U) || is(T : U[], U)) alias Type = T; else alias Type = T*; void gc_free(Type data) { import core.memory : GC; static if (is(Type : U[], U)) { GC.free(data.ptr); GC.minimize(); } else { GC.free(data); } data = null; } } Errors: share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type share.d(177): Error: template instance share.share!(A) error instantiating share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type share.d(197): Error: template instance share.share!(A) error instantiating share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type share.d(10): Error: undefined identifier Type It seems to work on Linux with 64 bit, but it fails on Windows 7 32 bit. Bug, feature or my fault? Compiler bug. https://d.puremagic.com/issues/show_bug.cgi?id=11662 Kenji Hara
Re: alias this leads to compilation error in one of two similar contexts
On Saturday, 30 November 2013 at 22:28:14 UTC, Carl Sturtivant wrote: I just confirmed the same behavior on Ubuntu amd64. dmd 2.063.2 compiles the example and dmd 2.064.2 produces the same error as the Windows 32 bit version. This is intended behavior change from 2.064. http://dlang.org/class#field-init struct my_integer { int val = 99; alias val this; } void test() { //my_interger num = 1; // NG my_interger num = my_interger(1); // OK // 'alias this' has no effect for object initialization } struct blah { my_integer num; this(int n) { //num = n; // also NG, my_integer cannot *initialize* by int value num = my_interger(n); // OK } } Kenji Hara
Re: Function literal bug?
On Thursday, 28 November 2013 at 09:48:47 UTC, bearophile wrote: Sergei Nosov: Do you have a 64-bit OS at hand? On 64 bit using dmd 2.064.2 it doesn't give the 6 6 output, so it seems a 64 bit bug. This happens because the 64 bit version of dmd is quite more new than the 32 bit version, so it has more bugs. Bye, bearophile It's a known front-end issue. https://d.puremagic.com/issues/show_bug.cgi?id=11545 Kenji Hara
Re: casting as char at CT fail
On Tuesday, 26 November 2013 at 23:31:16 UTC, bioinfornatics wrote: Hi, this time i have so many question about CT … iws and ibuclaw help me for this. I stuck currently about a cast at CT - http://www.dpaste.dzfl.pl/1a28a22c it seem this should works but not… So if you confirm maybe a report is needed thanks to everyone I found two compiler issues: https://d.puremagic.com/issues/show_bug.cgi?id=11627 https://d.puremagic.com/issues/show_bug.cgi?id=11629 Kenji Hara
Re: pure-ifying my code
On Monday, 18 November 2013 at 19:52:42 UTC, Jonathan M Davis wrote: On Monday, November 18, 2013 19:16:11 Daniel Davidson wrote: On Sunday, 17 November 2013 at 10:56:16 UTC, Jonathan M Davis wrote: I think that the typical approach at this point is to just drop purity for the moment, but if you want you really want it, you are indeed going to have to implement it yourself. But we'll get there with Phobos eventually. The primary holdup is some compiler improvements, and we'll get them. It's just a question of when. - Jonathan M Davis Why is it that compiler improvements are the holdup? Honest question. Is it more that the approach taken for the specific implementation went beyond the capabilities of the compiler at the time (like its inferencing capabilities)? Maybe purity was not a focus at the time of writing a lot of phobos and there are not loads of testing on it where purity was a factor. Attribute inferrence was added to the language specifically in order to make it possible for pure, nothrow, and @safe to work with templates and therefore make it possible to use them with Phobos. Without it, they don't, because you're stuck either requiring a specific set of attributes (limiting what the templates work with) or duplicating the templates with different combinations of attributes. We got enough attribute inferrence to reduce the problem, but the feature has yet to be implemented enough to fully fix the problem. It's compiler improvements which made using pure with std.algorithm possible at all. If so, isn't an alternative implementation now an improvement over waiting for the compiler updates. A corollary question would be are the benefits of Voldermort types in phobos worth the purity issues they cause? Voldemort types are just part of the problem. Attribute inferrence is just plain too primitive right now, and really needs to be improved. The problem is reduced if you don't used Voldemort types, but it's not fixed. Noble goal - maybe. But maybe not as noble as users' efforts to realize benefits of purity now. Purity/const/immutable when broken spread virally. It's also the case that none of that has ever worked with pure, so we haven't lost anything. We just haven't yet gained what we should have gained. But the push really needs to be to improve the compiler IMHO, because without that, attribute inferrence in general just isn't going to be good enough, and if Phobos' current situation highlights how poor the attribute inferrence is, all the better, because that puts more pressure on getting it fixed. Some of the newer functions have not used Voldemort types in order to fix similar problems, but I don't think that it's worth going and changing them all just to work around a problem with the compiler. The compiler needs to be fixed. At best, what you're talking about doing is contorting Phobos' implementation in order to make it work better with the half-implemented feature of attribute inferrence, but since it's that feature that makes it possible at all, and it really needs to be fully implemented regardless, it makes by far the most sense IMHO to just finish implementing it. But when that happens is up to the compiler devs, and at this point, I'm a library dev, not a compiler dev. - Jonathan M Davis I opened a new pull request to fix the compiler issue. https://github.com/D-Programming-Language/dmd/pull/2832 Kenji Hara
Re: Calling Base Class Overriden Methods
On Monday, 18 November 2013 at 19:36:07 UTC, Jeroen Bollen wrote: On Monday, 18 November 2013 at 19:34:56 UTC, Adam D. Ruppe wrote: To do it from outside the class, you write the class name: void main() { auto obj = new SubClass(); obj.SuperClass.methodA(); // calls the specific super method } Thanks! :D Why aren't these things in the documentation? :/ http://dlang.org/function#virtual-functions = To avoid dynamic binding on member function call, insert base class name before the member function name. For example: ... void main() { auto d = new D(); assert(d.foo() == 3);// calls D.foo assert(d.B.foo() == 1); // calls B.foo assert(d.C.foo() == 2); // calls C.foo d.test(); } = Kenji Hara
Re: dchar literals?
On Monday, 11 November 2013 at 13:20:04 UTC, bearophile wrote: Philippe Sigaud: And I agree with you than character literals should default to dchar. It's a perpetual source of friction for me. 99% of my char literals need to be of type char. On the other hand once you have suffixes to specify the char type, most of that problem vanishes, because writing 'x'c or 'x'w, 'x'd is good. Bye, bearophile Or, uniform construction for built-in types would be another better way. auto c = char('a'); auto w = wchar('a'); auto d = dchar('a'); auto x = char('à'); // compile-time error Kenji Hara
Re: Bug in RefCounted?
On Tuesday, 29 October 2013 at 11:46:53 UTC, Rene Zwanenburg wrote: On Monday, 28 October 2013 at 19:30:12 UTC, Maxim Fomin wrote: Here is my attempt: import std.stdio; struct S { int i; this(int i) { writefln(ctor, %X, i); this.i = i; } this(this) { writefln(postblit, %X, %X, this, i); } ~this() { writefln(dtor, %X, %X, this, i); } } auto foo() { S s = S(1); return { s = S(2); } ; } void main() { foo()(); } ctor, 1 dtor, 77ED8FF8, 1 ctor, 2 dtor, 7FFFDB30, 1 Inside foo() function object 's' is destroyed twice: first time as a regular struct at the end of block scope, second time before assigning S(2). There are other tools: union bug, control flow tricks, __traits, __dtor but they are move obvious. That's pretty nasty :). But I suspect this is a bug and not by design. __dtor and __traits are, IMHO, the proverbial escape hatch D should provide, so I think that's OK. I take it that by control flow trick you mean the try/catch example in your other post? Anyway, thanks for pointing this out. Will probably save me some debugging in the future. The combination of closure variables + scoped destruction should be rejected, but currently it isn't. It's a compiler bug. http://d.puremagic.com/issues/show_bug.cgi?id=11382 Kenji Hara
Re: Templates with alias param instantiated with null cached by DMD..?
On Wednesday, 23 October 2013 at 07:22:56 UTC, simendsjo wrote: I've stumbled upon a strange bug, and I'm not sure what I should write in the bug report. Could someone explain what's going on here or file the bug for me? template A(alias T) { alias A = T; } void main() { struct S1 { S1* p; } static assert(is(typeof(A!(S1.init.p)) == S1*)); // ok pragma(msg, NULL: , typeof(A!(null))); // fail: S1* struct S2 { S2* p; } static assert(is(typeof(A!(S2.init.p)) == S2*)); // fail: S1* } A!(S1.init.p) is mostly same as A!( cast(S1*)null ), because the expression S1.init.p is interpreted to a null value. 1. But current ABI does not support a typed null template value argument because all of null expression on template argument are mangled to 'n'. So the type of null value will be never encoded in the mangled name, and the three instantiations A!(S1.init.p), A!(null) and A!(S2.init.p) will have exactly same mangling. 2. However, the first instantiation A!(S1.init.p) wrongly caches the null value type (== S1*), and it appears in following instantiations during semantic analysis phase. #2 is definitely a front-end bug. However I'm not sure the current ABI definition issue (== #2) is a language spec bug or not... Kenji Hara
Re: cannot call impure function ~this
On Wednesday, 16 October 2013 at 07:58:09 UTC, Namespace wrote: On Wednesday, 16 October 2013 at 07:32:27 UTC, monarch_dodra wrote: On Wednesday, 16 October 2013 at 07:27:25 UTC, Namespace wrote: On Wednesday, 16 October 2013 at 07:23:45 UTC, monarch_dodra wrote: On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote: I get this error: /d701/f223.d(11): Error: pure function 'f223.getA' cannot call impure function 'f223.A.~this' with this code: import std.stdio; struct A { public: ~this() { writeln(DTor); } } A getA() pure nothrow { return A(); } void main() { A a = getA(); writeln(end of main); } But without pure and nothrow I get this output: end of main DTor Why the compiler thinks that the function should/could call A::~this? It could have something to do with the fact that RVO is an optimization *opportunity* that the compiler is allowed to go for, even if it changes the program output. Hoewever, being an *opportunity*, the compiler still has to make sure the code is valid without said optimization, which in this case, isn't: getA would destroy it's temporary after blitting it on the stac, leading to an impure call. So it _could_ be impure, but mostly it isn't, right? I guess that's one way to put it. I'd say it *is* impure, but all its impure bits have been optimized out. That's my explanation anyways. I'm curious: Is this a problem for you? The function calling getA *can't* be pure either, so marking getA as pure is ... I was going to say useless, but I guess pure is always an optimization opportunity for the compiler. I'd file an ER, you never know. No, I was just curious what's behind it. So specifically why the compiler could call the destructor. In this case, the created struct literal A() will be moved out to the function getA(). So dtor is not called and compiler should not cause cannot call impure function error. I filed a bug report and posted possible compiler fix. http://d.puremagic.com/issues/show_bug.cgi?id=11286 https://github.com/D-Programming-Language/dmd/pull/2677 Kenji Hara
Re: copying const struct
On Monday, 14 October 2013 at 14:18:10 UTC, Maxim Fomin wrote: On Monday, 14 October 2013 at 11:35:32 UTC, Jack Applegame wrote: Why this doesn't compile? http://dpaste.dzfl.pl/21ef5b04 class Foo {} struct Bar1 { const(Foo[]) member; } struct Bar2 { const Foo member; } void main() { const Bar1 bar1; const Bar2 bar2; Bar1 b1 = bar1; // ok Bar2 b2 = bar2; // cannot implicitly convert expression (bar2) of type const(Bar2) to Bar2 } This is compilable using git head. Recently I found a small compiler bug. http://d.puremagic.com/issues/show_bug.cgi?id=11187 And, a week ago it is fixed. 2.064 beta1 contains the fix. Kenji Hara
Re: Phobos - pure, const, safe, nothrow
On Wednesday, 2 October 2013 at 13:31:04 UTC, Joseph Rushton Wakeling wrote: On 29/09/13 11:37, monarch_dodra wrote: On Sunday, 29 September 2013 at 09:00:56 UTC, simendsjo wrote: What is the status of adding these annotations to phobos? It's difficult to use these until phobos gets them. E.g. to! and format is not pure. Most of phobos is templated, meaning it relies on inference. In various recent template-related explorations I have often wished it was possible to infer function attributes from template arguments :-( See e.g. Proxy, which loses all the corresponding attributes of the underlying type's methods. std.typecons.Proxy is designed to work transparently for the underlying method qualifiers. But I also agree that the implementation is still insufficient. Could you show us the not working case? It would be much help. Kenji Hara
Re: Mixin namespace ambiguity?
On Sunday, 15 September 2013 at 18:31:30 UTC, Marek Janukowicz wrote: The code to reproduce the problem consists of 3 modules: mix.d: module mix; mixin template A( alias x) { string a () { return x; } } aux.d: module aux; import mix; mixin A!(a in aux) X; string b () { return b in aux; } main.d: module main; import aux; import mix; import std.stdio; mixin A!(a in main) X; string b () { return b in main; } void main () { writefln( a: %s, X.a ); // Line 1 //writefln( a: %s, a ); // Line 2 writefln( b: %s, b ); // Line 3 } I run it with: dmd -run main.d aux.d mix.d Line 1 works. Line 3 works. Line 2 fails with: main.d(13): Error: main.A!(a in main).a at mix.d(5) conflicts with aux.A! (a in aux).a at mix.d(5) If I omit mixin identifier (X), there is no way I can make the call to a work without prepending module name. My question is: why calling a function with the same name (from different modules) works when: - it is just a regular function - it is a mixed-in function with mixin identifier (even though the identifier is ambiguous) and it doesn't when it's a mixed-in function with no mixin identifier. My first impression is that either both line 1 and 2 should work or neither of them should work. It's no surprise to me that line 3 works (and it matches the documentation), so I basically included that just for reference. Currently this is not a bug. Looking from the module 'main', the mixin identifier 'X' declared in main.d is *closer* than the 'X' declared in aux.d, because the latter exists beyond the module import boundary. Therefore, the use of 'X' in main.d would prefere the `mixin A!(a in main) X`. On the other hand, when the name search, all mixed-in symbols are treated as if they are just imported at the mixed-in scope. Therefore, even from main.d, the two mixed-in functions 'a' have same closeness, and the call is ambiguous because they have exactly same signature. Kenji Hara
Re: Limited type matching?
On Tuesday, 10 September 2013 at 08:04:48 UTC, Namespace wrote: Currently, all of array types does not allow copy-conversion like ushort to short for their elements. In old D1 age, static array did not have value semantics, so the behavior was expected. In D2, static array had changed to value type, but the behavior was not changed. As far as I know, there was no discussion about that, but at least it is not fundamentally wrong. Kenji Hara And what is your personal opinion? I think an implicit cast between signed / unsigned would be acceptable even with static arrays. It were only logical. Hmm, OK. I've taken a look a little deeper about the current behavior. void main() { void f1(short) {} void f2(short[2]) {} void f3(short[]) {} ushort us = 1; short ss = us; // OK ss = us;// OK f1(us); // OK ushort[2] usa = [1,2]; short[2] ssa = usa; // OK - [x] ssa = usa; // NG - [y] f2(usa);// NG - [y] ushort[] uda = [1,2]; short[] sda = uda; // NG, expected sda = uda; // NG, expected f3(uda);// NG, expected } Surely the current state that, [x] is accepted but [y] is rejected, looks weird to me. It would be a bug. Kenji Hara
Re: Limited type matching?
On Monday, 9 September 2013 at 11:36:42 UTC, Andrej Mitrovic wrote: On 9/8/13, Namespace rswhi...@googlemail.com wrote: What is the problem? If the compiler is able to cast implicit from ushort to short, what is the problem of casting ushort[2] to short[2]? Oh I didn't even noticed it was a signed/unsigned issue. I'm not sure whether or not it's a bug. But file it anyways and someone will know what to do with it. Currently, all of array types does not allow copy-conversion like ushort to short for their elements. In old D1 age, static array did not have value semantics, so the behavior was expected. In D2, static array had changed to value type, but the behavior was not changed. As far as I know, there was no discussion about that, but at least it is not fundamentally wrong. Kenji Hara
Re: Struct with opDispatch doesn't dispatch. Is this a bug?
On Friday, 5 July 2013 at 03:12:44 UTC, Meta wrote: I wasn't 100% sure the following is a bug, so I figured I'd ask. struct Fail { void opDispatch(string s)() { static assert(false, Tried to call a method on Fail); } } void main() { auto fail = Fail(); fail.s(); //Error: no property 's' for type 'Fail' } This is a compiler's diagnostic bug. http://d.puremagic.com/issues/show_bug.cgi?id=10546 In this case, opDispatch is _actually_ instantiated. However the static assertion message is suppressed for later UFCS symbol search. But UFCS cannot find module level function 's', then compiler reports irrelevant error message no property 's' Kenji Hara
Re: How to determine if a function is implemented
On Friday, 5 July 2013 at 01:27:06 UTC, JS wrote: the code http://dpaste.dzfl.pl/25bfeeb7 attempts to implement an interface. The current issue is that I need to determine if the user has added the member of the interface to the class or if the mixin needs to add it. so the lines class B : A { A a; //void myfunc(float a, int b, string c) { }; //@property int myvalue() { return 4; } mixin implementInterface!a; } The mixin adds the two commented functions above it which effectively implement the interface A in B. The problem is, I might want to manually specify one, e.g., class B : A { A a; void myfunc(float a, int b, string c) { }; //@property int myvalue() { return 4; } mixin implementInterface!a; } So the mixin needs to be aware and not add a method that is already implemented. I need some way for the mixin to distinguish the two cases above. e.g., isImplemented!(myfunc(float, int, string)) or something like that. It's completely unnecessary. A mixed-in function cannot override properly declared function that has same name in the mixed-in scope. interface I { int foo(); } mixin template Foo() { override int foo() { return 1; } } class C1 : I { mixin Foo!(); } class C2 : I { int foo() { return 10; } mixin Foo!(); // mixed-in foo is not stored in vtbl } void main() { assert(new C1().foo() == 1); assert(new C2().foo() == 10); } Kenji Hara
Re: opDispatch and UFCS
On Tuesday, 2 July 2013 at 00:45:23 UTC, cal wrote: import std.conv, std.stdio, std.algorithm; struct S { void opDispatch(string s, T...)(T t) if (s.startsWith(foo)) { writeln(s); } } void main() { S s; s.foo(); auto p = s.to!string(); // Error: s.opDispatch!(to) isn't a template } Should the constraint on opDispatch allow the UFCS to call on S? That's a compiler bug. http://d.puremagic.com/issues/show_bug.cgi?id=10526 Kenji Hara
Re: Strange error when importing std.regex
On Wednesday, 12 June 2013 at 18:44:12 UTC, bearophile wrote: Dmitry Olshansky: There is no ambiguity, 1 is not a Regex object but it seems like template constraint in std.regex blows up. @Temtaime please file a bug on this. http://d.puremagic.com/issues/ std.algorithm.splitter(arr, 1); I think this bug already surfaced some time ago... Maybe it's already in Bugzilla. Bye, bearophile Right now I cannot see the original code in dpaste, but the issue would be a same bug with 8352. http://d.puremagic.com/issues/show_bug.cgi?id=8352 I have maintained a compiler fix for that, but unfortunately it is not yet merged. https://github.com/D-Programming-Language/dmd/pull/1660 Kenji Hara
Re: Clarification of @trusted attribute?
On Wednesday, 12 June 2013 at 13:09:40 UTC, Gary Willoughby wrote: So would you mark the following with @trusted? The format() function is not @safe but what is @trusted really trying to say? This method is @safe as far as i'm concerned? The arguments make format() @safe? I'm confused. /** * Get the current timestamp for the log. * * Returns: * The current timestamp. */ private string getTimestamp() const { auto time = Clock.currTime(); return format(%d/%02d/%02d %d:%02d:%02d, time.year, time.month, time.day, time.hour, time.minute, time.second); } In this case, format std.string.format function should work under the `safe annotation. I recently worked to make it possible. https://github.com/D-Programming-Language/phobos/pull/1337 Kenji Hara
Re: How to implement this?
On Monday, 10 June 2013 at 09:42:56 UTC, Elvis wrote: class A { enum TypeID = 1; } class B : A { enum TypeID = 2; } class C : A { enum TypeID = 3; } class D : B { enum TypeID = 4; } ... Could anybody shed some light on how to make these TypeIDs auto increment at compile time? version(A) { class A { enum TypeID = 1; } template IncrementTypeID(Class) { class IncrementTypeID : Class { enum TypeID = Class.TypeID + 1; } } alias B = IncrementTypeID!A; alias C = IncrementTypeID!B; alias D = IncrementTypeID!C; } version(B) // more generative way { template MakeContinuousClasses(int endID) { static if (endID 0) { mixin MakeContinuousClasses!(endID - 1); enum className = ABCDEFGHIJKLMNOPQRSTUVWXYZ[endID - 1]; static if (endID == 1) enum baseClass = ; else enum baseClass = : ~ ABCDEFGHIJKLMNOPQRSTUVWXYZ[endID - 2]; import std.conv : to; mixin(class ~className~baseClass~ { enum TypeID = ~endID.to!string~; }); } } mixin MakeContinuousClasses!4; } // test case import std.traits; pragma(msg, A.TypeID, , , BaseClassesTuple!A); // 1, (Object) pragma(msg, B.TypeID, , , BaseClassesTuple!B); // 2, (A, Object) pragma(msg, C.TypeID, , , BaseClassesTuple!C); // 3, (B, A, Object) pragma(msg, D.TypeID, , , BaseClassesTuple!D); // 4, (C, B, A, Object) Kenji Hara
Re: Compiler bug ?
On Sunday, 9 June 2013 at 13:37:45 UTC, Temtaime wrote: Hello guys! It seems that it is bug. And critical for me. http://dpaste.1azy.net/b93f5776 Regards. The code should be rejected. It's a compiler bug. But, you can do what you want as follows. import std.stdio, std.typetuple; struct A { @(1) int a; @(2) int b; @(3) int c; } auto bar(alias expr)() @property { writeln(expr); } void main() { A a; foreach(it; __traits(allMembers, A)) { enum tp = [__traits(getAttributes, mixin(`a.` ~ it))]; // or alias tp = TypeTuple!(__traits(getAttributes, mixin(`a.` ~ it))); writeln(`passing: `, tp[0]); bar!(tp[0])(); } } Kenji Hara
Re: Is this a compiler bug, or a breaking fix/enhancement?
On Wednesday, 29 May 2013 at 04:44:16 UTC, estew wrote: Hi All, I updated to dmd 2.063 today and all has been going smoothly until I decided to try out msgpack.d. I got an error compiling the msgpack.d unittest, so out of interest I decided to check this using dmd2.062 and it compiled and ran fine. I admit I don't really understand whether the code should work or if it is broken and dmd 2.063 now correctly issues an error. To my untrained-D-eye the code looks OK, so any advice would be appreciated. ERROR: --- msgpack.d(3215): Error: cannot resolve type for value.as!(E). EXAMPLE: --- import std.stdio; import std.traits; enum E : int {F = -20} struct S { int val; @trusted @property T as(T)() if(is(Unqual!T == int) !is(Unqual!T == enum)) { return cast(T)(val); } @trusted @property T as(T)() if(is(Unqual!T == enum)) { return cast(T)as!(OriginalType!T); } } void main() { S val = S(-20); assert(val.as!int == -20); assert(val.as!E == E.F); // val.as!E causes a compile time error. } --- This is a compiler regression in 2.063 release. http://d.puremagic.com/issues/show_bug.cgi?id=10197 Kenji Hara
Re: static const and user attribute
On Wednesday, 29 May 2013 at 14:50:36 UTC, bearophile wrote: Dicebot: I think this is a bug. It will be fixed progressively in the next two or three DMD versions. Bye, bearophile Please file it in bugzilla. Kenji Hara
Re: Two questions about assignments
On Monday, 27 May 2013 at 18:00:38 UTC, bearophile wrote: Do you know if it's OK to accept x3 assignment and refuse the a2 assignment? struct Foo { immutable(char)[4] bar; } Foo x1 = { AA };// No error. immutable(char)[4] a1 = AA; // No error. void main() { Foo x2 = { AA };// No error. Foo x3 = Foo(AA); // No error. immutable(char)[4] a2 = AA; // Error: lengths don't match // for array copy, 4 = 2 } This is known static array initializing inconsistency between DeclDefs scope and statement scope. I think it is a bug. - This is a recent change in std.typecons.tuples: // https://github.com/9rnsr/phobos/commit/fdcaba7226c978f281f2d237fc772c6d7913eaf3 But from this test they don't seem to be one a subtype of the other: import std.typecons: Tuple; void main() { alias T1 = Tuple!(int, int); alias T2 = Tuple!(int,x, int,y); auto t1 = T1(10, 20); auto t2 = T2(100, 200); t1 = t2; // OK. t2 = t1; // OK? } std.typecons.Tuple supports structural assignment before the change. The code also works with 2.062. Kenji Hara
Re: Two questions about assignments
On Tuesday, 28 May 2013 at 00:29:04 UTC, bearophile wrote: std.typecons.Tuple supports structural assignment before the change. The code also works with 2.062. I know it's not a regression. But you say: Named-field tuple should be a subtype of unnamed-field tuple. You can have sub-typing, or you can have structural typing, but mixing the two silently seems a mess. Also in your test cases of that commit fdcaba7226c... there is: +Tuple!(int, int)[] arr; +arr ~= tuple(10, 20); // OK +arr ~= Tuple!(int, x, int, y)(10, 20); // NG - OK If I try to do the opposite, that is to append a tuple(10, 20) to an array of tuples with named fields, I get an error: import std.typecons; void main() { Tuple!(int, x, int, y)[] arr; arr ~= tuple(10, 20); // Error. } So here there is a true sub-typing. So sometimes tuples with named fields are sub-types and in other situations they act in a structural typing way. I think this mix of behaviours is a little confusing. Basically Tuple would follow structural typing. Even if it is impossible, it would follow true subtyping right now. That's the purpose of my change. Kenji Hara
Re: Scoped import bug?
On Thursday, 9 May 2013 at 05:01:15 UTC, Mike Linford wrote: I'm not sure whether or not I've encountered a bug or whether my understanding of scoped imports is just faulty. blah.d: 1 module blah; 2 3 version(A) 4 { 5import std.range; 6 } 7 8 struct Blah(R) 9 { 10version(B) 11{ 12 import std.range; 13} 14static assert(isInputRange!R); 15 16void blah(R r) 17{ 18 version(C) 19 { 20 assert(r.front == 'h'); 21 } 22} 23 } 24 25 void main() 26 { 27Blah!string blah; 28blah.blah(hello); 29 } Results: rdmd -version=A -version=C blah Compiles fine. Module-level import works for the static assert on line 14 and the runtime assert on line 20 rdmd -version=B blah Compiles fine! Struct-level import works for the static assert on line 14 rdmd -version=B -version=C blah Fails to compile. I get the following error messages: blah.d(20): Error: no property 'front' for type 'string' blah.d(27): Error: template instance blah.Blah!(string) error instantiating So it appears that when my import is at the struct level like line 12 I'm able to use the static assert but *not* the runtime assert. Why cant the function Blah.blah() find the array implementation of front? This is a known UFCS name look-up issue. In 2.063dev, the bug is fixed. Please wait the release. Kenji Hara
Re: Template alias parameter does not accept types
On Thursday, 9 May 2013 at 12:09:03 UTC, Dicebot wrote: On Thursday, 9 May 2013 at 11:19:38 UTC, bearophile wrote: It will be fixed. Ugh, proof-link? I have always thought it is by design and that actually makes sense. AFAIK, there is no plan for fix. The behavior is currently a part of language design. Kenji Hara
Re: Scoped import bug?
On Thursday, 9 May 2013 at 18:25:39 UTC, Mike Linford wrote: On Thursday, 9 May 2013 at 09:52:12 UTC, Kenji Hara wrote: On Thursday, 9 May 2013 at 05:01:15 UTC, Mike Linford wrote: I'm not sure whether or not I've encountered a bug or whether my understanding of scoped imports is just faulty. blah.d: 1 module blah; 2 3 version(A) 4 { 5import std.range; 6 } 7 8 struct Blah(R) 9 { 10version(B) 11{ 12 import std.range; 13} 14static assert(isInputRange!R); 15 16void blah(R r) 17{ 18 version(C) 19 { 20 assert(r.front == 'h'); 21 } 22} 23 } 24 25 void main() 26 { 27Blah!string blah; 28blah.blah(hello); 29 } Results: rdmd -version=A -version=C blah Compiles fine. Module-level import works for the static assert on line 14 and the runtime assert on line 20 rdmd -version=B blah Compiles fine! Struct-level import works for the static assert on line 14 rdmd -version=B -version=C blah Fails to compile. I get the following error messages: blah.d(20): Error: no property 'front' for type 'string' blah.d(27): Error: template instance blah.Blah!(string) error instantiating So it appears that when my import is at the struct level like line 12 I'm able to use the static assert but *not* the runtime assert. Why cant the function Blah.blah() find the array implementation of front? This is a known UFCS name look-up issue. In 2.063dev, the bug is fixed. Please wait the release. Kenji Hara Thank you for the explanation. Was this the issue? http://d.puremagic.com/issues/show_bug.cgi?id=6185 Yes, that's right! Kenji Hara
Re: Using inout in delegate
On Thursday, 28 March 2013 at 14:16:27 UTC, Steven Schveighoffer wrote: On Thu, 28 Mar 2013 04:34:36 -0400, Jacob Carlborg d...@me.com wrote: The following code fails to compile: void foo (inout int[] arr) { auto dg = { foreach (i, e ; arr) {} }; dg(); } void main () { auto a = [3, 4, 5]; foo(a); } Error message: main.d(9): Error: variable main.foo.__lambda1.__aggr1174 inout variables can only be declared inside inout functions main.d(9): Error: variable main.foo.__lambda1.e inout variables can only be declared inside inout functions If I remove the delegate everything compiles. Am I doing something wrong? Like Timon said, it's a bug in inout design. I think this is not a hole of inout design. In this case, the lambda inside foo should capture 'inout' context pointer. void foo (inout int[] arr) { auto dg = { foreach (i, e ; arr) {} }; pragma(msg, typeof(dg)); // should print void delegate() inout dg(); } I'm assuming the issue is that the compiler is trying to generate a struct to hold the stack data for foo, and struct members cannot be inout. It is true, but in this case, the context which is implicitly captured by closure is not directly accessible from programmers. So qualifying it 'inout' is safe. It is a difficult problem to solve, because inout has two meanings depending on whether it is a parameter/return or a local variable. At some point, we need to address this, because inout has so much potential, but suffers from some large deficiencies. And, inout closure cannot escape from enclosing inout function. auto foo(inout int[] arr) { auto dg = (inout int[] a) { return arr; // returns captured inout 'arr' }; return dg; // escape! (should be rejected statically) } If compiler does not reject escape... void main() { const int[] a = [3, 4, 5]; auto dg = foo(a); // typeof(dg) == inout(int[]) delegate(inout(int[])) int[] b = dg([]); assert(b.ptr == a.ptr); // type-system breaking! } Kenji Hara
Re: isExpression with bool template parameter
On Tuesday, 26 March 2013 at 14:26:59 UTC, cal wrote: I guess the tuple version is fine, it is just surprising that only one of the three parameter types can be directly matched. It is also surprising that this example from the docs works: Because 'Tuple' is a template, not a type. Please recall that: struct Tuple(T...) { ... } is a syntactic sugar of: template Tuple(T...) { struct Tuple { ... } } alias Tuple!(int, string) Tup; static if (is(Tup : TX!TL, alias TX, TL...)) (matching an alias) but the alias can't be directly matched when it appears as a parameter of the type. So, `alias TX` will bind the template Tuple. There is no problem. Kenji Hara
Re: using this instead of typeof(this)
On Tuesday, 26 February 2013 at 16:28:59 UTC, Ivan Kazmenko wrote: Hi! I have recently experimented with ways to express the exact instantiated type of a generic struct, and found that I can in some cases use this as that type. Here is a sample program (DMD 2.062) demonstrating various uses of this as a type: - import std.stdio; struct S { int x = 1; int y = 0; void f () { y = 1; } this (this) // postblit constructor { x = 10; } this (ref this) // not a postblit constructor { x = 100; } this (ref this, this f, typeof (this), this, ref this g) { x = 1000 + _param_0.x + f.x + _param_2.x + _param_3.x + g.x; } } void main () { S a; a.f (); S b = a; S c = S (a); S d = S (a, a, a, a, a); writefln (%s %s, a.x, a.y); // 1 1 writefln (%s %s, b.x, b.y); // 10 1 (copied b.y = a.y) writefln (%s %s, c.x, c.y); // 100 0 (did not copy) writefln (%s %s, d.x, d.y); // 1032 0 (refs add 1, non-refs add 10) } - And so I wonder: (1) Should I refrain from using this as a type, is it a bug? It is definitely a bug. I cannot believe that such horrible bug is still there. If you have a time, could you please file it in bugzilla? http://d.puremagic.com/issues/ (2) A matter of style: what is the idiomatic way to take the exact type of a templated struct? For example, which method signature to return a typeof(this) value is better in which way if all have the same effect: - struct S (A, B, C) { ... auto method () {...} S method () {...} S !(theA, theB, theC) method () {...} typeof (this) method () {...} } - Note that S, theA, theB and theC can get lengthy. Returning S, S!(...), and typeof(this) are identical. You can use them as you favorite. auto return is a little different with others. To infer return type, the method body is aggressively analyzed in compilation. If the method has mutual call with another auto return function, it will cause 'forward reference error'. (3) Is the usage of unnamed parameters and _param_### a language feature or an implementation-specific detail I should not ever use? It is implementation specific. You must not rely on that. Kenji Hara
Re: Delegate type inferred as pure
On Monday, 28 January 2013 at 03:16:24 UTC, cal wrote: This fails: void main() { int z; typeof((int a){return z;}) dg; dg = (int a) {return z;}; } Error: cannot implicitly convert expression (__lambda2) of type int delegate(int a) nothrow @safe to int delegate(int a) pure nothrow @safe But I can't make the delegate pure: dg = (int a) pure {return z;}; because it references z. Is the 'typeof((int a){return z;})' getting it wrong here? Filed: http://d.puremagic.com/issues/show_bug.cgi?id=9415
Re: Need help with storage class definition
On Monday, 14 January 2013 at 14:16:32 UTC, mist wrote: While working on https://github.com/D-Programming-Language/phobos/pull/863 I have noticed that inout breaks ParameterStorageClassTuple and family. I have started working on a fix but quick comparison of http://dlang.org/declaration.html#StorageClass vs http://dlang.org/phobos/std_traits.html#.ParameterStorageClassTuple have left me in confusion without clear understanding what parameter storage classes are supposed to be defined to. There is also InOutX entry in grammar which lists some of storage classes and seems more relevant to parameter storage classes (i.e. includes ref). Can someone give a more structured explanation: what is supposed to be a storage class, what is supposed to be a type storage class and what - a type qualifier? I'd like to update std.traits demanglers to the latest state of things, but grammar description does not seem clear enough. http://dlang.org/declaration.html#StorageClass InOutX is the list of 'syntactically allowed' keywords. Among them, these four are supported as actual 'parameter storage classes'. scope out ref lazy In current, 'in' is directly replaced to 'const', and it is treated as a part of parameter type. 'inout' is also treated as a type qualifier, and then is the same. Kenji Hara
Re: ref return function using foreach ref result segfaults. Compiler bug?
On Tuesday, 13 November 2012 at 08:50:16 UTC, Rob T wrote: Hard to describe this problem, see code and read comments below. class A { private int _v; this( int a_v ) { _v = a_v; } @property size_t length() { return 1; } int opApply( int delegate( ref int a_v ) a_dg ) { int result = 0; for ( ulong i = 0; i length; ++i ) { result = a_dg( this.opIndex( i ) ); if ( result ) break; } return result; } ref int opIndex( size_t a_iPos ) { return _v; } } class B : A { this( int a_v ) { super(a_v); } ref int find( int a_What ) { foreach( val; super ) { if ( val == a_What ) return val; } throw new Exception(value not found); } } main() { auto v_B = new B(500); writefln(Search = %d, v_B.find(500) ); return 0; } When the return value of find() is ref, it segfaults or returns garbage. If the return value is a copy it works OK. The only oddity I can see is that 'val' goes out of scope, but it's a ref return value (pointer) to _v (right?), so it should work anyway. This looks like a bug in the compiler to me. What do you guys think? This issue looks like bug8093. http://d.puremagic.com/issues/show_bug.cgi?id=8093 And the code works correctly in git head (dmd2.061alpha). Therefore, I think that the bug is fixed very recently. Kenji Hara
Re: templated static array
On Monday, 15 October 2012 at 17:05:30 UTC, Simen Kjaeraas wrote: On 2012-35-15 17:10, Namespace rswhi...@googlemail.com wrote: But bar([1, 2, 3]); not. The compiler does not realize that [1, 2, 3] means a static array in this context. You have to write bar(cast(int[3]) [1, 2, 3]); but I think the compiler have to recognize this on it's own. This is true. The problem is, as you say, that the compiler treats array literals as dynamic rather than static arrays. I would argue this is the correct default, but it's obviously not the default you want here. bearophile has posted about this on numerous occasions, and it's among his top thousand wanted features. :p I think this is a bug in IFTE. Please file it into bugzilla. Kenji Hara
Re: offsetof + foreach
On Friday, 7 September 2012 at 17:32:43 UTC, Ellery Newcomer wrote: On 09/07/2012 10:31 AM, Ellery Newcomer wrote: I have a struct buffer, and I want to print out its members' offsetof. This: foreach(i,_t; buffer.tupleof) { writefln(%s@: %s, _t.stringof, _t.offsetof); } complains Error: undefined identifier 'offsetof' what should I be doing? nevermind, I remember tupleof + foreach has always been broken writefln(%s@: %s, buffer.tupleof[i].stringof, buffer.tupleof[i].offsetof); I think this is expected behavior. In foreach body, _t is a copy of field value, and it's not buffer's field itself. Your code is equivalent with: foreach(i,_; buffer.tupleof) { auto _t = buffer.tupleof[i];// _t is a normal variable writefln(%s@: %s, _t.stringof, _t.offsetof); } Then you cannot get offsetof property from _t; Regards. Kenji Hara
Re: How to create TypeTuple/ExpressionTuple from tuple/tuples
On Tuesday, 7 August 2012 at 16:11:05 UTC, Andrej Mitrovic wrote: On 8/7/12, Øivind oivind@gmail.com wrote: How can I call this function with an already-constructed tuple but pass the pule as an expressiontuple? auto v = tuple(1, 2, 3); f(v); Use the .expand property: f(v.expand) You can also use slice operator instead of expand property. import std.stdio, std.typecons; void f(T ...)(T t) { writeln(t.length); } void main(){ auto v = tuple(1, 2, 3); f(v[]); // prints 3 auto v0 = tuple(1, 2, 3); auto v1 = tuple(4, 5, 6); f(v0[], v1[]); // prints 6 }
Re: template - aliasing a member function
On Wednesday, 8 August 2012 at 23:21:32 UTC, Ellery Newcomer wrote: say I have template T(alias fn) { } class Foo { int i(); void i(int); } alias T!(Foo.i) Biz; Is there a way to get a handle to both of the overloads of Foo.i inside T? Actually, all I really need for that is to get 'Foo.i' out of fn. mangleof looks promising.. import std.typetuple : TypeTuple; template Id(alias a) { alias a Id; } template T(alias fn) { alias Id!(__traits(parent, fn)) Parent; // use Id template so we cannot alias __traits result directly static assert(is(Parent == Foo)); enum FnName = __traits(identifier, fn); alias TypeTuple!(__traits(getOverloads, Parent, FnName)) Overloads; // use TypeTuple template so we cannot alias __traits result directly pragma(msg, typeof(Overloads[0])); // prints int() pragma(msg, typeof(Overloads[1])); // prints void(int) } class Foo { int i(); void i(int); } alias T!(Foo.i) Biz;
Re: ~= call copy ctor?
On Friday, 20 July 2012 at 16:02:18 UTC, Namespace wrote: If i @disable the postblit i get a strange behaviour: [code] struct Test { public: int _id; this(int i) { _id = i; writeln(CTOR); } @disable this(this); ~this() { writeln(DTOR); } } void main() { Test[] _arr; _arr ~= Test(42); writeln(_arr[0]._id); writeln(end main); } [/code] prints: CTOR DTOR 42 end main The DTor is called _before_ i write Test's id but i can still print the correct id. Implicit Copy CTor? ;) Array appending and struct postblit behavior is now broken. I've suggested a pull request to fix these bugs. https://github.com/D-Programming-Language/dmd/pull/1037 Bye. Kenji Hara
Re: Literals starting with 0 will not work with UFCS
On Wednesday, 4 July 2012 at 01:53:40 UTC, Jonathan M Davis wrote: On Wednesday, July 04, 2012 03:48:52 ixid wrote: 0.writeln(); This works. It doesn't with 2.058, are we using different versions? Thanks for adding it to the bug list, I am not knowledgeable enough about D to judge if something is a bug or if I've just not understood it. 2.059 is the latest release (and is already nearly 3 months old), but I'm using the latest from github, so I don't know what 2.059 does. - Jonathan M Davis The problem was fixed in 2.060head. http://d.puremagic.com/issues/show_bug.cgi?id=8252 Kenji Hara
Re: Stack overflow / recursive expansion with alias this
On Tuesday, 24 April 2012 at 20:09:32 UTC, Namespace wrote: On Tuesday, 24 April 2012 at 19:34:26 UTC, Timon Gehr wrote: On 04/24/2012 07:09 PM, Namespace wrote: ... And therefore i get the same error, as if i wrote return NotNull!(Foo)(this); instead of return assumeNotNull(this);, in the _convert method of NotNull. The Output is Stack overflow. I think that comes from recursive calls which fills the stack? Is that a bug? Yes. I found nothing like that. Is the bug reported? I remember reporting a similar issue, but that one seems to have been fixed. Feel free to create a new ticket. That's what I do now. Thanks a lot for your help. Today I posted a pull to detect recursive alias this dependency. https://github.com/D-Programming-Language/dmd/pull/1028 Bye. Kenji Hara
Re: Problem about using struct
On Monday, 25 June 2012 at 06:05:34 UTC, Tongzhou Li wrote: Hello! I'm learning D, and wrote some sample codes with D. I wrote: http://ideone.com/VY7ES It failed to compile; I got 2 errors: main.d(19): Error: constructor main.carry!(int,int,int,int,int).carry.this (int delegate(int, int _param_0, int _param_1, int _param_2) _f) is not callable using argument types (int) main.d(19): Error: cannot implicitly convert expression (1) of type int to int delegate(int, int _param_0, int _param_1, int _param_2) Compiler used: DMD v2.059 (I used lambda expression which ideone doesn't support) Don't know what it means, I don't call any constructor in Line 19. Then I tried to use class instead of struct (http://ideone.com/ZI2Tn), it worked fine. So what's wrong with that? Sorry for my poor English:) Unfortunately, this is a dmd bug that yet not fixed. http://d.puremagic.com/issues/show_bug.cgi?id=6036 As far as I know, there is no workaround... Kenji Hara
Re: Retain struct when using alias this and passing using the alias..?
On Sunday, 24 June 2012 at 13:16:53 UTC, simendsjo wrote: import std.exception; import std.traits; struct Ranged(T, T min, T max) { T _value = min; typeof(this) opAssign(V : T)(V value) { enforce(value = min); enforce(value = max); _value = value; return this; } alias _value this; } void f(int i) { i = 1000; } void g(T)(T i) if(isIntegral!T){ i = 1000; } void main() { Ranged!(int, 10, 20) v; v = 10; // ok v = 20; // ok f(v); // auch g(v); // ok, exception } Is there a way to ensure the struct is used in f() without using templates as in g()? The type of 'alias this' symbol works as like the super class of user defined class. Therefore, Ranged!(...) is always implicitly convertible to int by 'alias _value this', and there is no way to disable such conversion. Kenji Hara
Re: front doesn't compile for arrays of immutable data
On Monday, 25 June 2012 at 14:23:25 UTC, Roman D. Boiko wrote: import std.range; struct Element { //immutable // uncomment to break compilation int _i; this(int i) { _i = i; } } void main() { auto arr = [Element.init]; arr.front; } Declaring _i immutable yields the following compilation error: /usr/include/x86_64-linux-gnu/dmd/phobos/std/array.d(460): Error: a[0LU] isn't mutable sample.d(11): Error: template instance std.array.front!(Element) error instantiating Is this a bug, or I misunderstand something? This is a bug of the compiler, and it is already filed. http://d.puremagic.com/issues/show_bug.cgi?id=6336 I've already posted a pull request to fix the bug, but it has been hold a while. Kenji Hara
Re: to!(ubyte[])()
On Friday, 22 June 2012 at 09:18:38 UTC, simendsjo wrote: Bug or by design? (using dmd head) import std.conv; void main() { to!(ubyte[])(); } std/array.d(493): Attempting to fetch the front of an empty array of immutable(char) [snip] It is design. With the conversion from string to non-string type, std.conv.to runs parsing. import std.conv; void main() { auto arr = to!(ubyte[])([1,2,3]); // parse given string as a representation of ubyte[] value. assert(arr == [1,2,3]); } And, the representation string of a value should have one or more characters. So empty string always throws exception. Kenji Hara
Re: Object Cast
On Thursday, 21 June 2012 at 10:33:41 UTC, Namespace wrote: To solve the problem of converting a Object to a specific template class i wrote this little function. But the mixin disturbs me. How i can get the type (in this example Vector2D) without to mix a mixin and T.stringof? [code] T object_cast(T : Object)(Object value) { T val = cast(T) value; if (val !is null) { return val; } // if cast fails it is a template class import std.typetuple; foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real)) { mixin( if (auto vec = cast( ~ T.stringof ~ !( ~ Type.stringof ~ ))(value)) { return cast(T) vec; }); } return null; } [/code] If you use 2.060head (git version), you can get template from the instantiated type. class Vec(T) {} void main() { alias Vec!int IntVec; static if (is(IntVec _unused : V!T, alias V, T)) { // V is class template Vec alias V!double DoubleVec; // another type instantiation test static assert(is(DoubleVec == Vec!double)); // equal! } else static assert(0); }
Re: Why doesn't alias this work with arrays?
On Monday, 18 June 2012 at 16:51:11 UTC, Andrej Mitrovic wrote: struct Wrap { string wrap; alias wrap this; } void main() { Wrap x; x = foo; // ok Wrap[] y = [foo, bar]; // fail } Error: cannot implicitly convert expression ([foo,bar]) of type string[] to Wrap[] Any special reason why this doesn't work? I hope it's just a bug or unfinished implementation. This kind conversions should be possible with std.conv.to. import std.conv; struct Wrap { string wrap; alias wrap this; } void main() { Wrap[] y = to!(Wrap[])([foo, bar]); // shold work } If you can construct Wrap object with the syntax Wrap(foo), std.conv.to runs 'conversion by construction'. And if S is convertible to T, std.conv.to!(T[])(S[] source) runs 'element-wise array conversion'. As a result, string[] to Wrap[] will be converted. ...but, this does not work in 2.060head, it is a bug. Kenji Hara
Re: alias this with property enforce
On Wednesday, 6 June 2012 at 18:12:39 UTC, Namespace wrote: If i have this code: class Bar { public: Foo GetFoo() { return this._foo; } alias GetFoo this; } to allow access to Foo methods from Bar i get the error, that GetFoo isn't a property if i use -property. Why? The solution is to set @property before Foo GetFoo() but why must GetFoo a property? What if i don't want to declare GetFoo as a property? I cannot use it with alias this? Because name lookup with alias this is implemented as simple rewriting of expressions. auto bar = new Bar(); bar.hoge; If class Bar doesn't have member hoge, it is rewritten as: bar.GetFoo.hoge; After that, if Bar.GetFoo.hoge is a property, bar.GetFoo is converted to bar.GetFoo().hoge as like other property functions. If Bar.GetFoo is not a property and you use -property switch, compiler shows not a property error because GetFoo is not a property. There is no magic.
Re: How to test for equality of types?
On Saturday, 19 May 2012 at 18:17:16 UTC, Matthias Walter wrote: 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 It seems to me that is a regression by fixing bug 6475. Now I'm trying to fix them.
Re: How to test for equality of types?
On Sunday, 20 May 2012 at 06:57:20 UTC, Kenji Hara wrote: On Saturday, 19 May 2012 at 18:17:16 UTC, Matthias Walter wrote: 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 It seems to me that is a regression by fixing bug 6475. Now I'm trying to fix them. I've filed the bug in bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=8123 And posted a pull request to fix it: https://github.com/D-Programming-Language/dmd/pull/957 Thanks. Kenji Hara
Re: How to test for equality of types?
On Sunday, 20 May 2012 at 06:57:20 UTC, Kenji Hara wrote: On Saturday, 19 May 2012 at 18:17:16 UTC, Matthias Walter wrote: 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 It seems to me that is a regression by fixing bug 6475. Now I'm trying to fix them. Fixed in git head: https://github.com/D-Programming-Language/dmd/commit/76543ef60f3b871612ddc0c87999859f427ba6f9
Re: Make all functions from std.typecons Proxy inout
On Thursday, 10 May 2012 at 07:32:42 UTC, Namespace wrote: Can you explain me how TemplateThisParameter works? I read in the manual but a more detail explanation would help me a lot. Hmm, I have thought following code should work about foo, but doesn't. import std.stdio; struct Proxy { void foo(this T)() { writeln(T.stringof); static assert(is(typeof(this) == T)); // I have thought this should pass with all cases... } void bar(this T)() inout { writeln(T.stringof); //static assert(is(typeof(this) == T)); static assert(is(typeof(this) == inout(Proxy))); } void bar(this T)() shared inout { writeln(T.stringof); //static assert(is(typeof(this) == T)); static assert(is(typeof(this) == shared(inout(Proxy; } } void main() { Proxy mp; const Proxy cp; immutable Proxy ip; shared Proxy sp; shared const Proxy scp; mp.foo(); // expects: Proxy - OK /+ cp.foo(); // expects: const(Proxy) - NG! ip.foo(); // expects: immutable(Proxy) - NG! sp.foo(); // expects: shared(Proxy) - NG! scp.foo(); // expects: shared(const(Proxy)) - NG! +/ mp.bar(); // expects: Proxy - OK cp.bar(); // expects: const(Proxy) - OK ip.bar(); // expects: immutable(Proxy) - OK sp.bar(); // expects: shared(Proxy) - OK scp.bar(); // expects: shared(const(Proxy)) - OK } The spec: http://dlang.org/template#TemplateThisParameter doesn't talk about typeof(this). I think current behavior is less useful than I have thought. And, current std.typecons.Proxy doesn't work as expected for non-mutable objects...
Re: Make all functions from std.typecons Proxy inout
On Wednesday, 9 May 2012 at 06:42:09 UTC, Namespace wrote: On Wednesday, 9 May 2012 at 04:49:39 UTC, Kenji Hara wrote: On Tuesday, 8 May 2012 at 22:58:07 UTC, Namespace wrote: In my development of the Ref / NotNull structure, I came across a problem: All the methods of Proxy aren't inout. Has this a reason or will change? In my opinion they should all be inout. I mentioned previous self fixes in my corresponding Ref / NotNull thread already. It is necessary. See following conceptual code: struct S { void f() {} void g() {} } struct Proxy(T) { T o; void f()() inout { return o.f(); } void g(this T)() { return o.g(); } } void main() { Proxy!S p; //p.f(); // inside Proxy.f, typeof(o) == inout p.g(); } 'Proxy' object should forward its 'this' type to original object. For the purpose, TemplateThisParameter ('this T') works as expected. Kenji Hara I thought, inout is evaluated by the compiler and make the method either const or not If not, then I understand, inout probably not yet complete. But in this case you would have to offer just two methods: void f () () {return o.f ();} void f () () const {return o.f ();} Yes. *In this case*, we should define two member function 'f' in Proxy to forward the call to original object. But, in general case, it is not sufficient. struct S { void f() {} void f() const{} void f() immutable {} void f() shared {} void f() shared const {} } struct Proxy(T) { T o; // forward to original f, need *five* thunks. Terrible! void f1()() { return o.f(); } void f1()() const{ return o.f(); } void f1()() immutable{ return o.f(); } void f1()() shared { return o.f(); } void f1()() shared const { return o.f(); } // cannot forward, this calls only S.f() const void f2()() inout { return o.f(); } // needs only one thunk. Excellent! void f3(this T)() { return o.g(); } } void main() { Proxy!S p; p.f1(); // call mutable f p.f2(); // CANNOT call mutable f p.f3(); // call mutable f } My first version of Proxy had such duplicates, but it was hard maintainable. After that, in review phase, I've discovered the way using TemplateThisParameter. It makes code readable and easy maintainable. After all, it is the reason why I use TempalteThisParameter instead of inout. Kenji Hara
Re: Make all functions from std.typecons Proxy inout
On Tuesday, 8 May 2012 at 22:58:07 UTC, Namespace wrote: In my development of the Ref / NotNull structure, I came across a problem: All the methods of Proxy aren't inout. Has this a reason or will change? In my opinion they should all be inout. I mentioned previous self fixes in my corresponding Ref / NotNull thread already. It is necessary. See following conceptual code: struct S { void f() {} void g() {} } struct Proxy(T) { T o; void f()() inout { return o.f(); } void g(this T)() { return o.g(); } } void main() { Proxy!S p; //p.f(); // inside Proxy.f, typeof(o) == inout p.g(); } 'Proxy' object should forward its 'this' type to original object. For the purpose, TemplateThisParameter ('this T') works as expected. Kenji Hara
Re: Extending std.format.formattedRead
On Tuesday, 24 April 2012 at 21:50:03 UTC, H. S. Teoh wrote: What's the correct way of implementing formattedRead support for user-defined types? I tried overloading the unformatValue() template, but for some reason the compiler doesn't seem to be picking it up. Unfortunately, there is not yet general way. The definition of unformatValue for user-defined type in different module isn't considered by std.format module. D's module system is closed in basic. Kenji Hara
Re: appending newly initialized struct to array
On Wednesday, 18 April 2012 at 04:55:23 UTC, Ali Çehreli wrote: On 04/17/2012 02:00 PM, simendsjo wrote: Sounds like a bug. C style initializers work in other cases: I try not to use them. I think they have this 'feature' of leaving unspecified members uninitialized: struct S { int i; double d; } void main() { S s = { 42 }; // -- no initializer for S.d assert(s.i == 42); assert(s.d == double.nan); // -- fails (may work for you) You should use std.math.isNaN whether a floating point value is NaN. assert(isNaN(s.d)); // -- success } Is that a bug or a feature? I might have opened it but I don't remember now. :) Ali Bye. Kenji Hara
Re: Metaprogramming work around
On Tuesday, 17 April 2012 at 12:04:44 UTC, Erèbe wrote: [snip] There is something I still don't understand : mixin template Foo( T... ) { //Code here } mixin Foo!( Hello, Word ); Good T is TemplateTypeParameter, and matches any kind of template arguments - types, values, and symbols. The both arguments Hello and World are values, so you can bind them with T. http://dlang.org/template.html#TemplateTupleParameter mixin template Foo( A, T... ) { //code here } mixin Foo!( Hello, Word ); --- Fail ! mixin Foo!( string, Word ); Good 'A' is TemplateTypeParameter, and it matches only types. In the first instantiation of Foo, A doesn't match with the value hello. In the second instantiation, string is type, and T matches with it. http://dlang.org/template.html#TemplateTypeParameter mixin template Foo( alias A, T... ) { //code here } mixin Foo!( Hello, world ); --- Good mixin Foo!( string, world ); --- Fail ! - 'alias A' is TemplateAliasParameter, and it matches both symbols and values. Then A matches with the value Hello, but doesn't with the type string. (string is an aliased name of immutable(char)[], and it is built-in array type.) http://dlang.org/template.html#TemplateAliasParameter Kenji Hara
Re: appending newly initialized struct to array
On Tuesday, 17 April 2012 at 21:00:55 UTC, simendsjo wrote: On Tue, 17 Apr 2012 22:28:31 +0200, maarten van damme maartenvd1...@gmail.com wrote: Just for fun I decided to complete some codejam challenges in D. At some point I wanted to add structs to an array but I got a compiler error. What am I doing wrong? code: struct test{ int x; int y; } void main(){ test[] why; why~={3,5}; } error: wait.d(7): found '}' when expecting ';' following statement wait.d(8): found 'EOF' when expecting ';' following statement wait.d(8): found 'EOF' when expecting '}' following compound statement Is there any reason a why this wouldn't work? Sounds like a bug. C style initializers work in other cases: struct S { int i; } void main() { S[] arr; S s = { 1 }; arr ~= S(1); // But the following barfs //arr ~= { 1 }; //arr ~= { i:1 }; //arr[0] = { 1 }; } No, it is designed. {3,5} is struct initializer: http://dlang.org/declaration.html#StructInitializer And it is only allowed in initializer of variable declarations. why~={3,5}; This is concat assign expression, so you should use test(3,5) instead of {3,5}. That is StructLiteral: http://dlang.org/struct.html#StructLiteral and it is an expression. Bye. Kenji Hara
Re: const AB c = {a,20, numbers};
On Monday, 16 April 2012 at 14:50:43 UTC, sclytrack wrote: struct AB { int a; int b; int [] numbers; } int main() { int a = 300; const int [] numbers = new int[2]; const AB c = {a,20, numbers}; // line 66 writeln(c); return 0; } -debug -unittest src/main.d(66): Error: cannot implicitly convert expression (numbers) of type const(int[]) to int[] --- const AB c; typeof(c.a) is const(int); typeof(c.numbers) is const(int []); Shouldn't the code above accept the const(int []) ? Should do. It is a compiler bug. I've filed this issue in bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=7929 And posted a pull request to fix compiler code: https://github.com/D-Programming-Language/dmd/pull/884 Thanks. Kenji Hara
Re: Templates in classes = what is wrong?
On Monday, 16 April 2012 at 18:48:52 UTC, Xan wrote: On Sunday, 15 April 2012 at 19:30:27 UTC, Ali Çehreli wrote: On 04/15/2012 11:39 AM, Xan wrote: On Sunday, 15 April 2012 at 11:23:37 UTC, John Chapman wrote: On Sunday, 15 April 2012 at 11:16:43 UTC, Xan wrote: int main(string [] args) { auto alg = Algorisme!(int,int); Should be: auto alg = new Algorisme!(int, int); alg.nom = Doblar; alg.versio = 1; alg.funcio = (int a) {return 2*a}; Should be: alg.funcio = (int a) { return 2 * a; }; or: alg.funcio = a = 2 * a; } It does not work: $ gdmd-4.6 algorisme.d algorisme.d:18: Error: variable algorisme.main.alg voids have no value algorisme.d:18: Error: expression class Algorisme is void and has no value with the code https://gist.github.com/2394274 What fails now? Thanks, Xan. Your code is still missing 'new': auto alg = new Algorisme!(int, int); With only this change, I receive this error: $ gdmd-4.6 algorisme.d algorisme.d:21: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) Unrelated recommendations: - Return 0 from main() for successful exit, anything else by convention means some sort of error. - Take advantage of constructors (and 'alias') to simplify syntax and risk of bugs: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V) { string nom; uint versio; alias V function (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } } int main(string [] args) { alias Algorisme!(int, int) MeuAlgorism; auto alg = new MeuAlgorism(Doblar, 1, (int a) { return 2 * a; }); return 0; } Ali With all of your suggestion [https://gist.github.com/2394274], I get: $ gdmd-4.6 algorisme.d algorisme.d:30: Error: constructor algorisme.Algorisme!(int,int).Algorisme.this (string nom, uint versio, int function(int) funcio) is not callable using argument types (string,int,int delegate(int a) pure nothrow) algorisme.d:30: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) algorisme.d:27: Error: function D main has no return statement, but is expected to return a value of type int What fails? PS: Thanks for your recommendations... PPS: By the other hand, I see you have learned catalan (MeuAlgorisme?) ;-) Problem may be here: alg.funcio = (int a) { return 2 * a; }; 2.057 and earlier (You may use gdc 2.057 and command line wrapper gdmd), function literal always deduced as 'delegate'. So this expression raises an error about type mismatching Lhs of 'int function(int)' and Rhs of 'int delegate(int) pure nothrow'. Then, specifying explicit 'function' will resolve issue: alg.funcio = function(int a) { return 2 * a; }; Bye. Kenji Hara
Re: A problem with mutable toString
On Monday, 9 April 2012 at 00:25:57 UTC, bearophile wrote: Currently this code compiles and runs with no errors: class Foo { override string toString() const { return Foo; } } void main() { import std.stdio; const Foo[] foos = [new Foo]; writeln(foos); } Output, DMD 2.059beta2: [Foo] While this gives errors: class Foo { override string toString() /*const*/ { return Foo; } } void main() { import std.stdio; const Foo[] foos = [new Foo]; writeln(foos); } Output, DMD 2.059beta2: [snip] Current std.format doesn't support const class formatting with upcasting to mutable Object and using mutable toString(). Is this good/expected? It is a gap between language const system and object.Object class interface. I think Phobos should not break const system in basic. Kenji Hara
Re: Problem about lambda expressions
On Tuesday, 27 March 2012 at 13:42:30 UTC, Tongzhou Li wrote: Hello again! I'm learning D, and I encountered a problem. I tried this code: http://ideone.com/hkpT6 It works well. (Have no idea why codepad.org failed to compile it) I tried to write a lambda instead of function f, but I got nothing printed. Did I make something wrong? Compiler used: DMD32 D Compiler v2.058 (Win7 SP1 x64) Sorry for my poor English :) (obj x, int a0, int a1) = { x.setxxx(a0); x.setyyy(a1); } This lambda expression returns *a delegate has no parameter*. Instead: (obj x, int a0, int a1) = (x.setxxx(a0), x.setyyy(a1)) or: (obj x, int a0, int a1){ x.setxxx(a0); x.setyyy(a1); }
Re: Confused by refusal to expand template
On Friday, 23 March 2012 at 23:01:43 UTC, Timon Gehr wrote: On 03/23/2012 11:58 PM, David wrote: Am 23.03.2012 23:52, schrieb H. S. Teoh: Code: struct S { int f(K)(K x) { return 1; } void func(K)(inout(K) x) { auto h = f(x); } } void main() { S s; s.func(abc); // This is line 44 } This refuses to compile: test2.d(44): Error: template test2.S.func(K) does not match any function template declaration test2.d(44): Error: template test2.S.func(K) cannot deduce template function from argument types !()(string) Removing 'inout' fixes the problem. But I don't understand why. T I've never really used inout, but don't you need it also for the return-type? Not any more (DMD 2.059). See http://d.puremagic.com/issues/show_bug.cgi?id=7105 Furthermore you don't the the inout here, since this template does match const/immutable/nothing anyways. His intention probably is to prevent multiple instantiation of a template based on different constness. This is definitely a bug. I've filed it in bugzilla, and posted a pull to fix it. http://d.puremagic.com/issues/show_bug.cgi?id=7769
Re: Regarding writefln formatting
On Wednesday, 21 March 2012 at 01:26:23 UTC, bearophile wrote: import std.stdio; void main() { auto mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; writefln(%(%(%d %)\n%), mat); writeln(); writefln([%(%(%d %)\n%)], mat); writeln(); writefln([%([%(%d %)]\n%)], mat); writeln(); } Prints: 1 2 3 4 5 6 7 8 9 [1 2 3 4 5 6 7 8 9] [[1 2 3] [4 5 6] [7 8 9] Do you know why the last closed square bracket is missing? You can use %| format specifier to specify element separator. (It was proposed in https://github.com/D-Programming-Language/phobos/pull/298 . It is not yet documented, but already merged in Phobos.) import std.stdio; void main() { auto mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; writefln([%([%(%d %)]%|\n%)], mat); // specify \n as a separator } Prints: [[1 2 3] [4 5 6] [7 8 9]]