Re: implicit conversion
Sorry should add this is on 2.066.0-rc2 and it used to work on 2.064. Cheers, uri On Tuesday, 12 August 2014 at 06:21:19 UTC, uri wrote: Hi, I'm trying to allow implicit conversions for my own type happening. I have the following: import std.math; import std.traits; struct S(T) if(isFloatingPoint!T) { T val; alias val this; } void main() { auto s = S!float(); assert(isNaN(s)); s = 10.0; assert(!isNaN(s)); } But I get a compile time error: Error: template std.math.isNaN cannot deduce function from argument types !()(S!float), candidates are: std/math.d(4171):std.math.isNaN(X)(X x) if (isFloatingPoint!X) Is there a way I can to do this, maybe opCall/opCast (I tried these but failed)? Cheers, uri
implicit conversion
Hi, I'm trying to allow implicit conversions for my own type happening. I have the following: import std.math; import std.traits; struct S(T) if(isFloatingPoint!T) { T val; alias val this; } void main() { auto s = S!float(); assert(isNaN(s)); s = 10.0; assert(!isNaN(s)); } But I get a compile time error: Error: template std.math.isNaN cannot deduce function from argument types !()(S!float), candidates are: std/math.d(4171):std.math.isNaN(X)(X x) if (isFloatingPoint!X) Is there a way I can to do this, maybe opCall/opCast (I tried these but failed)? Cheers, uri
Re: implicit conversion
On Tue, 12 Aug 2014 06:21:17 + uri via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Hi, I'm trying to allow implicit conversions for my own type happening. I have the following: import std.math; import std.traits; struct S(T) if(isFloatingPoint!T) { T val; alias val this; } void main() { auto s = S!float(); assert(isNaN(s)); s = 10.0; assert(!isNaN(s)); } But I get a compile time error: Error: template std.math.isNaN cannot deduce function from argument types !()(S!float), candidates are: std/math.d(4171):std.math.isNaN(X)(X x) if (isFloatingPoint!X) Is there a way I can to do this, maybe opCall/opCast (I tried these but failed)? The problem is that isNaN is now templatized, and its constraint uses isFloatingPoint, which requires that the type _be_ a floating point type, not that it implicitly convert to one. So, as it stands, isNAN cannot work with any type which implicitly converts to a floating point value. Either it will have to be instantiated with the floating point type - e.g. isNaN!float(s) - or you're going to have to explicitly cast s to a floating point type. You can open a bug report - https://issues.dlang.org - and mark it as a regression, and it might get changed, but the reality of the matter is that templates don't tend to play well with implicit conversions. It's _far_ too easy to allow something in due to an implicit conversion and then have it not actually work, because the value is never actually converted. In general, I would strongly advise against attempting to give types implicit conversions precisely because they tend to not play nicely with templates. - Jonathan M Davis
Re: implicit conversion
On Tuesday, 12 August 2014 at 06:37:45 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: On Tue, 12 Aug 2014 06:21:17 + uri via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Hi, I'm trying to allow implicit conversions for my own type happening. I have the following: import std.math; import std.traits; struct S(T) if(isFloatingPoint!T) { T val; alias val this; } void main() { auto s = S!float(); assert(isNaN(s)); s = 10.0; assert(!isNaN(s)); } But I get a compile time error: Error: template std.math.isNaN cannot deduce function from argument types !()(S!float), candidates are: std/math.d(4171):std.math.isNaN(X)(X x) if (isFloatingPoint!X) Is there a way I can to do this, maybe opCall/opCast (I tried these but failed)? The problem is that isNaN is now templatized, and its constraint uses isFloatingPoint, which requires that the type _be_ a floating point type, not that it implicitly convert to one. So, as it stands, isNAN cannot work with any type which implicitly converts to a floating point value. Either it will have to be instantiated with the floating point type - e.g. isNaN!float(s) - or you're going to have to explicitly cast s to a floating point type. You can open a bug report - https://issues.dlang.org - and mark it as a regression, and it might get changed, but the reality of the matter is that templates don't tend to play well with implicit conversions. It's _far_ too easy to allow something in due to an implicit conversion and then have it not actually work, because the value is never actually converted. In general, I would strongly advise against attempting to give types implicit conversions precisely because they tend to not play nicely with templates. - Jonathan M Davis Thanks for the info. I'm happy to change my code and remove the implicit conversion. It was just for a convenience factor (floats with accumulated error). Cheers, uri
Re: Identifying 32 vs 64 bit OS?
On Monday, 11 August 2014 at 06:17:22 UTC, ketmar via Digitalmars-d-learn wrote: On Mon, 11 Aug 2014 05:18:59 + Jeremy DeHaan via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: why do you need that info? D types has well-defined sizes (i.e uint is always 32 bits, and so on). I came up with a better solution for what I actually needed, but I was toying with some things in a rdmd build script for different kinds of compilation.
Very vague compiler error message
I recently got this error messege when building my library: dmd: cppmangle.c:154: void CppMangleVisitor::cpp_mangle_name(Dsymbol*): Assertion `0' failed. I have no idea what it means and haven't found much information about it. I think I have narrowed it down to the file that is giving this error, but does anyone know what the heck causes something like this? Talk about a nondescript error.
Re: Very vague compiler error message
On Tue, 12 Aug 2014 07:16:49 + Jeremy DeHaan via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: but does anyone know what the heck causes something like this? it's internal compiler error, the thing that should never happen. try to use dustmite to build minimalictic test case and fill the bug. signature.asc Description: PGP signature
Re: Very vague compiler error message
On 12/08/2014 7:16 p.m., Jeremy DeHaan wrote: I recently got this error messege when building my library: dmd: cppmangle.c:154: void CppMangleVisitor::cpp_mangle_name(Dsymbol*): Assertion `0' failed. I have no idea what it means and haven't found much information about it. I think I have narrowed it down to the file that is giving this error, but does anyone know what the heck causes something like this? Talk about a nondescript error. That error is being generated from within dmd itself. In other words you've found an edge case congratulations! Look for functions/methods using the extern(C++) mangling. Mock them out into D versions and see which fails maybe?
Re: Sorting algorithms
Rewatching lectures... And a thought came to me. Most sorting algorithms work with handling one element at a time; Although you may do a binary tree to sort getting NlogN, the optimal number of compares is still out of reach due to the number of extra compares done. However to build a proper comparing to try and get the minimal number of compares, you (consciously or not) are effectively doing a binary tree if you want to or not. So what if you merge trees instead of elements? Consider: You have a tree of even numbers. 2 4 6 8 10. 6 would be the top and being balanced. Now you have a tree of odd numbers also evenly distributed, so 1 3 5 7 9 and 5 would be the head. If you are merging the odd with the even, then the first compare of 5 vs 6 which it's less. So you break the tree in half since you know everything on the left side of the odd's tree is already less than 6 so you don't need to compare those. So the tree half of 1 3 5 follows the left tree down and gets slightly restructured so it's evenly distributed once more before doing the comparison with 4. The remainder (7 9) might get re-compared against 6, or passed to the right tree depending on how it handles duplicates. I'm working on a prototype to see if this passes... I just wonder if the overhead would cancel out the potential benefit; Of course that depends on how expensive the compare is. Against ints you might not get much benefit, but large string compares or large numbers you'd get a performance boost. It's probably possible to add this idea/feature to already existing tree structures like red/black trees. So going out of my way to build something new might be a waste except as a concept. Thoughts?
Re: overloads and parents. __traits confusion
On Tuesday, 12 August 2014 at 05:23:53 UTC, Dicebot wrote: On Monday, 11 August 2014 at 13:00:27 UTC, John Colvin wrote: alias Parent = TypeTuple!(__traits(parent, foo!float))[0]; Say hello to optional parens - you are trying to call foo!float() here and apply result to trait. I thought so. Ugh. This works though: void foo(float v){} void foo(int a){} alias Parent = TypeTuple!(__traits(parent, foo))[0]; pragma(msg, __traits(getOverloads, Parent, foo)); so it seems that instantiated function templates in this case are called parenthesis-free, whereas normal functions are passed by name/alias/whatever. All expressions that are used as compile-time args (whether in udas, traits or as template arguments) should require parenthesis to be called. Anything else is madness. A!(foo1().foo2()) //pass result A!(foo1.foo2()) //pass result A!(foo1.foo2) //pass function A!(foo1) //pass function foo(foo1) //pass result
Re: overloads and parents. __traits confusion
On Monday, 11 August 2014 at 13:00:27 UTC, John Colvin wrote: can someone talk me through the reasoning behind this: import std.typetuple; void foo(T)(T v){} void foo(){} version(ThisCompiles) { alias Parent = TypeTuple!(__traits(parent, foo))[0]; pragma(msg, __traits(getOverloads, Parent, foo)); // tuple() } else { alias Parent = TypeTuple!(__traits(parent, foo!float))[0]; pragma(msg, __traits(getOverloads, Parent, foo)); /* /d54/f131.d(8): Error: foo (float v) is not callable using argument types () /d54/f131.d(8): Error: (__error).foo cannot be resolved tuple() */ } (I'm not sure if the following is completely correct, but it makes a lot of sense to me at the moment.) For clarity, the verbose version of that template: template foo(T) /* the (eponymous) template */ { void foo(T v) {} /* the function; the eponymous member */ } foo is the template: `foo.stringof` = foo(T)(T v). Its parent is the module: `__traits(parent, foo).stringof` = module test. This is what you use in version(ThisCompiles). No problems. foo!float is an instance of the template. Since the template is eponymous, instantiations resolve to the eponymous member, always. So foo!float is the function: `foo!float.mangleof.demangle` = pure nothrow @nogc @safe void test7.foo!(float).foo(float) Its parent is the template instance, which resolves right back to the function: `__traits(parent, foo!float).mangleof.demangle` = pure nothrow @nogc @safe void test7.foo!(float).foo(float) (just foo!float again) Apparently, you cannot get out of an eponymous template instantiation with __traits(parent, ...). Maybe __traits(parent, ...) of an eponymous template instance should be the parent of the template. The current behaviour seems useless to me. Simple test case without functions (no additional trouble from optional parentheses): struct S(T) {} /* All print S!int: */ pragma(msg, S!int); pragma(msg, __traits(parent, S!int)); pragma(msg, __traits(parent, __traits(parent, S!int)));
Deprecation: Read-modify-write operations are not allowed for shared variables
dmd 2.066(rc) generates warning: 'Deprecation: Read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!-=(a, 1) instead.' for following code: synchronized { ++a; } Is that correct given that it's inside synchronized?
Re: Destroy two assumptions: interface implementation generated by TMP
On Monday, 11 August 2014 at 18:21:04 UTC, Baz wrote: Hi, I try to get why the last way of generating an interface implementation fails. I've put assumptions: is it right ? --- module itfgen; import std.stdio; interface itf{ void a_int(int p); void a_uint(uint p); } class impl3: itf{ void tmp(T)(T p){}; alias a_int = tmp!int; alias a_uint = tmp!uint; } Part of me feels that ought to work. There may well be good reasons why not though. Currently you do have to have method implementations/overrides written out as normal functions.
Demangling GCC Languages
What's the easiest way to get support for demangling of GCC-supported languages of symbols extracted from GCC compiled ELF files? Are the demangle algorithms complex? Could they be ported to D easily?
Re: Demangling GCC Languages
On Tuesday, 12 August 2014 at 11:30:24 UTC, Nordlöw wrote: What's the easiest way to get support for demangling of GCC-supported languages of symbols extracted from GCC compiled In D, that is.
Re: Destroy two assumptions: interface implementation generated by TMP
On Monday, 11 August 2014 at 18:21:04 UTC, Baz wrote: interface itf{ void a_int(int p); void a_uint(uint p); } [...] // FAILS because: alias are probably generated after the itf check class impl3: itf{ void tmp(T)(T p){}; alias a_int = tmp!int; alias a_uint = tmp!uint; } [...] 'Error: class itfgen.impl3 interface function 'void a_int(int p)' is not implemented'. I think the problem is that impl3.tmp is not virtual because it's a template, and interfaces need to be implemented by virtual methods.
Re: Very vague compiler error message
On Tue, Aug 12, 2014 at 07:16:49AM +, Jeremy DeHaan via Digitalmars-d-learn wrote: I recently got this error messege when building my library: dmd: cppmangle.c:154: void CppMangleVisitor::cpp_mangle_name(Dsymbol*): Assertion `0' failed. I have no idea what it means and haven't found much information about it. I think I have narrowed it down to the file that is giving this error, but does anyone know what the heck causes something like this? Talk about a nondescript error. That's an ICE (Internal Compiler Error). Please reduce your test case and file a critical bug. T -- Stop staring at me like that! It's offens... no, you'll hurt your eyes!
Re: Destroy two assumptions: interface implementation generated by TMP
On Tuesday, 12 August 2014 at 11:34:01 UTC, anonymous wrote: On Monday, 11 August 2014 at 18:21:04 UTC, Baz wrote: interface itf{ void a_int(int p); void a_uint(uint p); } [...] // FAILS because: alias are probably generated after the itf check class impl3: itf{ void tmp(T)(T p){}; alias a_int = tmp!int; alias a_uint = tmp!uint; } [...] 'Error: class itfgen.impl3 interface function 'void a_int(int p)' is not implemented'. I think the problem is that impl3.tmp is not virtual because it's a template, and interfaces need to be implemented by virtual methods. The instantiations of the template are just normal functions though, no?
Re: Destroy two assumptions: interface implementation generated by TMP
On Tuesday, 12 August 2014 at 12:08:14 UTC, John Colvin wrote: I think the problem is that impl3.tmp is not virtual because it's a template, and interfaces need to be implemented by virtual methods. The instantiations of the template are just normal functions though, no? They are not virtual. Ordinary methods (public, not final, not templated) are virtual.
Re: implicit conversion
On Tuesday, 12 August 2014 at 06:37:45 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: The problem is that isNaN is now templatized, and its constraint uses isFloatingPoint, which requires that the type _be_ a floating point type, not that it implicitly convert to one. So, as it stands, isNAN cannot work with any type which implicitly converts to a floating point value. Either it will have to be instantiated with the floating point type - e.g. isNaN!float(s) - or you're going to have to explicitly cast s to a floating point type. You can open a bug report - https://issues.dlang.org - and mark it as a regression, and it might get changed, but the reality of the matter is that templates don't tend to play well with implicit conversions. It's _far_ too easy to allow something in due to an implicit conversion and then have it not actually work, because the value is never actually converted. In general, I would strongly advise against attempting to give types implicit conversions precisely because they tend to not play nicely with templates. - Jonathan M Davis I think this should be considered a bug. A type with alias this should work in all cases that the aliased type would. If the function fails to be instantiated with S!float, then it should be forwarded to the S's val member.
Re: implicit conversion
On Tue, 12 Aug 2014 13:17:37 + Meta via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Tuesday, 12 August 2014 at 06:37:45 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: The problem is that isNaN is now templatized, and its constraint uses isFloatingPoint, which requires that the type _be_ a floating point type, not that it implicitly convert to one. So, as it stands, isNAN cannot work with any type which implicitly converts to a floating point value. Either it will have to be instantiated with the floating point type - e.g. isNaN!float(s) - or you're going to have to explicitly cast s to a floating point type. You can open a bug report - https://issues.dlang.org - and mark it as a regression, and it might get changed, but the reality of the matter is that templates don't tend to play well with implicit conversions. It's _far_ too easy to allow something in due to an implicit conversion and then have it not actually work, because the value is never actually converted. In general, I would strongly advise against attempting to give types implicit conversions precisely because they tend to not play nicely with templates. - Jonathan M Davis I think this should be considered a bug. A type with alias this should work in all cases that the aliased type would. If the function fails to be instantiated with S!float, then it should be forwarded to the S's val member. AFAIK, the only time that the implicit conversion would take place is when the type is being used in a situation where it doesn't work directly but where the aliased type is used. In that case, the compiler sees the accepted types and sees that the type can implicitly convert to one of the accepted types and thus does the conversion. So, it knows that the conversion will work before it even does it. The compiler never attempts to do the conversion just to see whether it will work, which is essentially what it would have to do when attempting to use the type with a templated function. You can certainly create an enhancement request for such behavior, but I have no idea how likely it is get implemented. There are currently _no_ cases where the compiler does anything with template instantiations to try and make them pass if simply trying to instantiate them with the given type failed. - Jonathan M Davis
Re: Deprecation: Read-modify-write operations are not allowed for shared variables
On Tue, 12 Aug 2014 03:01:22 -0700 Timothee Cour via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Is that correct given that it's inside synchronized? yes. synchronized doesn't lock *any* access to a (consider two different shared classes, for example), it just prevents simultaneous access in this given part of code. so to be on the safe side, use atomic operations. besides, using atomic operations will allow you to drop synchronize altogether which makes your code slightly faster. signature.asc Description: PGP signature
Re: implicit conversion
On Tuesday, 12 August 2014 at 14:26:46 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: AFAIK, the only time that the implicit conversion would take place is when the type is being used in a situation where it doesn't work directly but where the aliased type is used. In that case, the compiler sees the accepted types and sees that the type can implicitly convert to one of the accepted types and thus does the conversion. So, it knows that the conversion will work before it even does it. The compiler never attempts to do the conversion just to see whether it will work, which is essentially what it would have to do when attempting to use the type with a templated function. You can certainly create an enhancement request for such behavior, but I have no idea how likely it is get implemented. There are currently _no_ cases where the compiler does anything with template instantiations to try and make them pass if simply trying to instantiate them with the given type failed. - Jonathan M Davis What I mean is that this breaks the Liskov Substitution Principle, which alias this should obey, as it denotes a subtype. Since S!float has an alias this to float, it should behave as a float in all circumstances where a float is expected; otherwise, we've got a big problem with alias this on our hands.
Re: Deprecation: Read-modify-write operations are not allowed for shared variables
On Tuesday, 12 August 2014 at 15:06:38 UTC, ketmar via Digitalmars-d-learn wrote: besides, using atomic operations will allow you to drop synchronize altogether which makes your code slightly faster. ... and potentially quite broken. At the very least, if this value is ready anywhere you'll have to use an atomicLoad there in place of the synchronized block you would have used.
Re: implicit conversion
On Tuesday, 12 August 2014 at 15:39:09 UTC, Meta wrote: What I mean is that this breaks the Liskov Substitution Principle, which alias this should obey, as it denotes a subtype. Since S!float has an alias this to float, it should behave as a float in all circumstances where a float is expected; otherwise, we've got a big problem with alias this on our hands. IMHO, it was a mistake to add alias this to the language. It's occasionally useful, but it's too dangerous. Implicit conversions wreak havoc with templates, because inevitably what happens is that a type is tested for whether it implicitly converts to a particular type, but then the template is instantiated with the original type, not the implicitly converted one, and then the template frequently fails to compile - or if it does compile, it may do weird things, because you're dealing with a type that doesn't act as expected. If you're dealing with a template which doesn't accept implicit conversions (e.g. isNaN), and the implicit conversion were tested after the actual type failed, and the template was then instantiated with the implicitly converted type, then maybe that could work, but that's not how it works now, and in general, I think alias this is just too dangerous to use. - Jonathan M Davis
Re: Deprecation: Read-modify-write operations are not allowed for shared variables
On Tue, 12 Aug 2014 16:02:01 + Sean Kelly via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: ... and potentially quite broken. At the very least, if this value is ready anywhere you'll have to use an atomicLoad there in place of the synchronized block you would have used. sure, *any* access to shared variables should be done with atomic ops. i thought that this is obvious. ;-) signature.asc Description: PGP signature
Re: Very vague compiler error message
Awesome, thanks everyone. I'll take the suggestion to use Dustmite as an excuse to familiarize myself with it, but if normally extern(C++) types cause it I know just where to look.
Re: Linked list as a bidirectional range? I have some questions...
On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via Digitalmars-d-learn wrote: opApplyReverse. Was that a joke or does opApplyReverse exist?
Re: Linked list as a bidirectional range? I have some questions...
On Tue, 12 Aug 2014 16:50:33 + Gary Willoughby via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Was that a joke or does opApplyReverse exist? it's not a joke. http://dlang.org/statement.html ctrl+f, opApplyReverse signature.asc Description: PGP signature
Re: Linked list as a bidirectional range? I have some questions...
On Tuesday, 12 August 2014 at 17:00:26 UTC, ketmar via Digitalmars-d-learn wrote: On Tue, 12 Aug 2014 16:50:33 + Gary Willoughby via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Was that a joke or does opApplyReverse exist? it's not a joke. http://dlang.org/statement.html ctrl+f, opApplyReverse Ha, awesome!
Re: Emacs d-mode cannot handle backquoted backslashe
On Friday, 1 August 2014 at 21:42:02 UTC, Nordlöw wrote: I just posted a d-mode.el fix to Russel Winder. See the recent posts at https://stackoverflow.com/questions/25089090/emacs-d-mode-cannot-handle-backquoted-backslashes If you can't wait ;)
Capture parameter identifier name in a template?
In my JavaScript VM, I have a function whose purpose is to expose D/host constants to the JavaScript runtime code running inside the VM. This makes for somewhat redundant code, as follows: vm.defRTConst(OBJ_MIN_CAPw, OBJ_MIN_CAP); vm.defRTConst(PROTO_SLOT_IDXw, PROTO_SLOT_IDX); vm.defRTConst(FPTR_SLOT_IDXw, FPTR_SLOT_IDX); vm.defRTConst(ATTR_CONFIGURABLEw , ATTR_CONFIGURABLE); vm.defRTConst(ATTR_WRITABLEw , ATTR_WRITABLE); vm.defRTConst(ATTR_ENUMERABLEw, ATTR_ENUMERABLE); vm.defRTConst(ATTR_DELETEDw , ATTR_DELETED); vm.defRTConst(ATTR_GETSETw, ATTR_GETSET); vm.defRTConst(ATTR_DEFAULTw , ATTR_DEFAULT); I'm just wondering if there's a way to template defRTConst so that the name of an identifier I'm passing (e.g.: ATTR_DEFAULT) can be captured by the template, making it so that I don't also need to pass the name as a string. I expect the answer to be no, but maybe someone with more knowledge of D template magic knows better.
Re: Capture parameter identifier name in a template?
On Tue, 12 Aug 2014 17:36:40 + Maxime Chevalier-Boisvert via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I'm just wondering if there's a way to template defRTConst so that the name of an identifier I'm passing (e.g.: ATTR_DEFAULT) seems that this is the work for mixins. signature.asc Description: PGP signature
Re: Capture parameter identifier name in a template?
On Tue, Aug 12, 2014 at 05:36:40PM +, Maxime Chevalier-Boisvert via Digitalmars-d-learn wrote: In my JavaScript VM, I have a function whose purpose is to expose D/host constants to the JavaScript runtime code running inside the VM. This makes for somewhat redundant code, as follows: vm.defRTConst(OBJ_MIN_CAPw, OBJ_MIN_CAP); vm.defRTConst(PROTO_SLOT_IDXw, PROTO_SLOT_IDX); vm.defRTConst(FPTR_SLOT_IDXw, FPTR_SLOT_IDX); vm.defRTConst(ATTR_CONFIGURABLEw , ATTR_CONFIGURABLE); vm.defRTConst(ATTR_WRITABLEw , ATTR_WRITABLE); vm.defRTConst(ATTR_ENUMERABLEw, ATTR_ENUMERABLE); vm.defRTConst(ATTR_DELETEDw , ATTR_DELETED); vm.defRTConst(ATTR_GETSETw, ATTR_GETSET); vm.defRTConst(ATTR_DEFAULTw , ATTR_DEFAULT); I'm just wondering if there's a way to template defRTConst so that the name of an identifier I'm passing (e.g.: ATTR_DEFAULT) can be captured by the template, making it so that I don't also need to pass the name as a string. I expect the answer to be no, but maybe someone with more knowledge of D template magic knows better. I know it's possible to get function (runtime) parameter names using __traits(), but I'm not sure if that can be done for compile-time parameters. See: std.traits.ParameterIdentifierTuple. T -- It said to install Windows 2000 or better, so I installed Linux instead.
Re: implicit conversion
On Tue, Aug 12, 2014 at 04:04:41PM +, Jonathan M Davis via Digitalmars-d-learn wrote: On Tuesday, 12 August 2014 at 15:39:09 UTC, Meta wrote: What I mean is that this breaks the Liskov Substitution Principle, which alias this should obey, as it denotes a subtype. Since S!float has an alias this to float, it should behave as a float in all circumstances where a float is expected; otherwise, we've got a big problem with alias this on our hands. IMHO, it was a mistake to add alias this to the language. It's occasionally useful, but it's too dangerous. I disagree. Alias this is a very powerful tool that we haven't fully leveraged yet. Not only it allows for implicit conversion to native types (which makes it very useful for transparent type wrapping and user-defined numeric types that are on par with built-in types), it also allows for things like transparent safe dereference handling, as I demonstrated some time ago. Implicit conversions wreak havoc with templates, because inevitably what happens is that a type is tested for whether it implicitly converts to a particular type, but then the template is instantiated with the original type, not the implicitly converted one, and then the template frequently fails to compile - or if it does compile, it may do weird things, because you're dealing with a type that doesn't act as expected. That's because the template code was wrongly written. If it expects the basic type, then it should be constrained to take only basic types (is(T==int) instead of is(T : int)). If it wants a member variable to be a basic type, then it should use the converted-to type instead of the original type (if it tests is(T : int) but wants an int, then it should use int as the target type, not T). Problems with carelessly-written template code is no fault of alias this. If you're dealing with a template which doesn't accept implicit conversions (e.g. isNaN), and the implicit conversion were tested after the actual type failed, and the template was then instantiated with the implicitly converted type, then maybe that could work, but that's not how it works now, and in general, I think alias this is just too dangerous to use. [...] I disagree. If a template function can take an implicitly-converted type, then it should assign the original type to the target type if that's what it wants to use. For example: auto badCode(T)(T t) if (is(T : float)) { T u = 1.0; // does anyone expect this to NOT blow up? u += t;// or this? ... } struct S { float toFloat() { ... } alias toFloat this; } auto r = badCode(S.init); // oops auto goodCode(T)(T t) if (is(T : float)) { float tf = t; // now we're talking float u = 1.0; // now this for sure won't blow up u += tf; ... } auto s = goodCode(S.init); // OK Basically, the root of the problem is that the way C++ and D templates work, the template body is free to assume *anything* about the incoming types, with or without verification (mostly without, IME). As a result, template code often makes unfounded assumptions, like: auto myFunc(T)(T t) if (is(T : float)) { float f = t; // this is about the only safe thing we can // do, given the stated assumptions ... T u; // are we sure the type is instantiable? u = 1.0; // are we sure the type accepts literal assignment? auto r = t + 1.0; // are we sure the result type is anything we expect? ... // etc. } This example is blatantly obvious, but in practice, things are a lot more tricky. Classic example: auto myFunc(R)(R range) if (isInputRange!R) { // what makes us think typeof(range.front) is assignable? auto f = range.front; ... range.popFront(); // This fails on transient ranges, but happily compiles // 'cos isInputRange doesn't ensure the assumption that // assigned values of .front persist beyond .popFront. // Basically, it's an unfounded assumption. if (f == range.front) { ... } } Another typical example of poorly-written template code: auto nextColumn(RoR)(RoR rangeOfRanges) if (isForwardRange!RoR isInputRange!(ElementType!RoR)) { foreach (subrange; rangeOfRanges) { // what makes us think this has any persistent // effect past this iteration of the loop? subrange.popFront(); } // For all we
Re: Capture parameter identifier name in a template?
On Tuesday, 12 August 2014 at 17:36:41 UTC, Maxime Chevalier-Boisvert wrote: In my JavaScript VM, I have a function whose purpose is to expose D/host constants to the JavaScript runtime code running inside the VM. This makes for somewhat redundant code, as follows: vm.defRTConst(OBJ_MIN_CAPw, OBJ_MIN_CAP); vm.defRTConst(PROTO_SLOT_IDXw, PROTO_SLOT_IDX); vm.defRTConst(FPTR_SLOT_IDXw, FPTR_SLOT_IDX); vm.defRTConst(ATTR_CONFIGURABLEw , ATTR_CONFIGURABLE); vm.defRTConst(ATTR_WRITABLEw , ATTR_WRITABLE); vm.defRTConst(ATTR_ENUMERABLEw, ATTR_ENUMERABLE); vm.defRTConst(ATTR_DELETEDw , ATTR_DELETED); vm.defRTConst(ATTR_GETSETw, ATTR_GETSET); vm.defRTConst(ATTR_DEFAULTw , ATTR_DEFAULT); I'm just wondering if there's a way to template defRTConst so that the name of an identifier I'm passing (e.g.: ATTR_DEFAULT) can be captured by the template, making it so that I don't also need to pass the name as a string. I expect the answer to be no, but maybe someone with more knowledge of D template magic knows better. Something like this? enum ATTRS { ATTR_GETSET, ATTR_ENUMERABLE, ATTR_CONFIGURABLE } void foo(ATTRS attr) { import std.conv; foo_impl(attr, to!string(attr)); } void foo_impl(ATTRS attr, string name) { import std.stdio; writefln(name = %s, attr = %d, name, attr); } void main() { foo(ATTRS.ATTR_GETSET); }
Re: implicit conversion
On Tuesday, 12 August 2014 at 19:03:58 UTC, H. S. Teoh via Digitalmars-d-learn wrote: tl;dr: there are so many ways template code can go wrong, that I don't it justifies blaming alias this for problems. Allowing implicit conversions makes the problem much worse IMHO. It makes it far too easy to write a template constraint which passes due to the implicit conversion (even if an implicit conversion wasn't explicitly checked for) but then have the function fail to work properly because the implicit conversion never actually takes place within the function (and if the template constraint doesn't explicitly test for an implicit conversion, then the argument that the value should have been explicitly converted doesn't hold). Fortunately, in many cases, the result is a compilation error rather than weird behavior, but in some cases, it will be weird behavior - especially when the code involved is highly templatized and generic. I'm not even vaguely convinced that allowing implicit conversions is worth the pain that they cause with templated code. Sure, they have their uses, and it would be a loss to have nothing like alias this, but on the whole, I'd much rather pay the cost of having no implicit conversions than having to deal with the havoc they wreak on templated code. - Jonathan M Davis
Re: Emacs d-mode cannot handle backquoted backslashe
On Tuesday, 12 August 2014 at 17:28:25 UTC, Nordlöw wrote: And a PR: https://github.com/Emacs-D-Mode-Maintainers/Emacs-D-Mode/pull/22
Re: implicit conversion
On Tue, Aug 12, 2014 at 08:23:30PM +, Jonathan M Davis via Digitalmars-d-learn wrote: On Tuesday, 12 August 2014 at 19:03:58 UTC, H. S. Teoh via Digitalmars-d-learn wrote: tl;dr: there are so many ways template code can go wrong, that I don't it justifies blaming alias this for problems. Allowing implicit conversions makes the problem much worse IMHO. It makes it far too easy to write a template constraint which passes due to the implicit conversion (even if an implicit conversion wasn't explicitly checked for) but then have the function fail to work properly because the implicit conversion never actually takes place within the function (and if the template constraint doesn't explicitly test for an implicit conversion, then the argument that the value should have been explicitly converted doesn't hold). Fortunately, in many cases, the result is a compilation error rather than weird behavior, but in some cases, it will be weird behavior - especially when the code involved is highly templatized and generic. [...] Y'know, after seeing the recent problem with deprecated functions in template code, and now this, I'm starting to reconsider whether Concepts might have been a better way to go. The good thing about concepts is that the template body won't even compile if it makes unfounded assumptions on the type that aren't given by what the concept defines. In the current template system, code like this would easily compile: auto badCode(T)(T t) { // Does T even support such an operation? Who knows. The // compiler will happily accept this code, and if you // only unittest this function with numeric types, // you'll never know there was a problem. return t+1; } In a concepts-based system, however, this code wouldn't compile, even before you instantiate any templates. You'd have to define a concept that supports the opBinary!+(int) operation before the compiler would accept the code. And doing so enforces all incoming types to conform to that concept or be instantly rejected. This causes the templated code to be unable to do anything with the incoming type that isn't explicitly specified in the concept, thus preventing unfounded assumptions. It furthermore solves the alias this problem, because it would be clear to the compiler which concept the function is supposed to be operating on, and if the incoming type implicitly converts to something that implements that concept, then the compiler knows to perform the conversion first before perform an operation on it. Now, it's true that concepts-based systems have their limitations. But I wonder if it's possible to extend a concepts-based system to be more powerful, in the same way D has enhanced and developed C++ templates in novel ways. One way I can think of, that kinda sits between the current duck-typing template system and a full-fledged concepts system, is one where incoming types do not have to declare what concept they implement (thus, a kind of duck-typing), but template functions are not allowed to operate on an incoming type unless they declare a concept it must conform to. Hypothetical syntax: // Concept definition concept InputRange(E) { alias ElementType = E; bool empty; E front; void popFront(); } // Concrete type that implements InputRange(E) // N.B.: don't need to declare what concept it implements: this // makes it compatible with current code. struct MyRange { @property bool empty() { ... } @property int front() { ... } void popFront() { ... } // N.B.: this is *not* part of the concept definition @property MyRange save() { ... } } auto r = rangeFunc(MyRange.init); auto rangeFunc(R : InputRange!E, E)(R range) { while (!range.empty) // OK, .empty defined in InputRange!E { auto e = range.front; // OK, .front defined in InputRange!E if (someCond) { // ERROR: even though MyRange does // define .save, InputRange doesn't, and // we have only declared R to be an // InputRange, so .save is an undefined // operation on R. auto tmp = range.save; } // OK: .popFront is defined in InputRange!E range.popFront(); } return ...; } T -- There are two ways to write error-free programs; only the third one works.
Re: Destroy two assumptions: interface implementation generated by TMP
On Tuesday, 12 August 2014 at 12:43:46 UTC, anonymous wrote: On Tuesday, 12 August 2014 at 12:08:14 UTC, John Colvin wrote: I think the problem is that impl3.tmp is not virtual because it's a template, and interfaces need to be implemented by virtual methods. The instantiations of the template are just normal functions though, no? They are not virtual. Ordinary methods (public, not final, not templated) are virtual. The virtual stuff is right. I've just realized that it's written black on white at the bottom of the manual page which describes templates: Templates cannot be used to add non-static members or virtual functions to classes Templates cannot add functions to interfaces Sorry for the loss of time.
Re: implicit conversion
On 8/12/14, 6:31 PM, H. S. Teoh via Digitalmars-d-learn wrote: On Tue, Aug 12, 2014 at 08:23:30PM +, Jonathan M Davis via Digitalmars-d-learn wrote: On Tuesday, 12 August 2014 at 19:03:58 UTC, H. S. Teoh via Digitalmars-d-learn wrote: tl;dr: there are so many ways template code can go wrong, that I don't it justifies blaming alias this for problems. Allowing implicit conversions makes the problem much worse IMHO. It makes it far too easy to write a template constraint which passes due to the implicit conversion (even if an implicit conversion wasn't explicitly checked for) but then have the function fail to work properly because the implicit conversion never actually takes place within the function (and if the template constraint doesn't explicitly test for an implicit conversion, then the argument that the value should have been explicitly converted doesn't hold). Fortunately, in many cases, the result is a compilation error rather than weird behavior, but in some cases, it will be weird behavior - especially when the code involved is highly templatized and generic. [...] Y'know, after seeing the recent problem with deprecated functions in template code... Duck typing FTW
LuaD + VisualD link issue
I'm having an issue with building programs that link with LuaD using VisualD. If I use Dub, it builds without an issue, but generating a project file and compiling it through VisualD results in Error 162: Bad Type Index reference to type 84A9 when linking luad.lib(base). Anyone has any ideas on what may cause this? I've also tried building using the VisualD project on LuaD's GitHub in case it was a missing configuration setting but that has the same issue (running Windows 8 64 bit in case it's relevant).
Re: Emacs d-mode cannot handle backquoted backslashe
On Mon, 2014-08-04 at 12:25 +, Atila Neves via Digitalmars-d-learn wrote: I took a look and I don't really know if it's possible without using the Emacs 24 only suggestion in the Stack Overflow comment to your question. As far as I can see, before that Emacs syntax tables have a notion of what a string is and what an escape character is. The d-mode code adds the backtick as an alternative to double and single quotes but can't do anything about the backslash. Unless it disables backslash as an escape character everywhere. I tried setting backtick to a function that returns \ instead of the value to see if I could then tailor the function to depend on whether not the point was in a backtick string but that didn't work since `modify-syntax-entry` checks to see if the argument is a string. BTW, python-mode has the same problem, I checked with r\. Per Nordlöw has offered a putative fix via a pull request. I'll check out the claim and if it seems to be true (and I fully expect it to be so) I'll accept the pull request. People using MELPA should see the new package quite quickly. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part