Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On Wednesday, 18 August 2021 at 05:33:13 UTC, james.p.leblanc wrote: If I wanted to ensure that a function accepts only arguments of byte, int, uint, long, etc. (i.e. integer-like types). Is the accepted way to do this like so?: **auto foo( T : long )(T a, T b){ ... }** I very much prefer the ususal constraint syntax **auto foo(T)(T a, T b) if(isIntegral!T) { ... }**
Re: GC.addRange in pure function
On Tuesday, 9 February 2021 at 21:00:39 UTC, Paul Backus wrote: On Tuesday, 9 February 2021 at 19:53:27 UTC, Temtaime wrote: pure is broken. Just don't [use it] Allowing memory allocation in pure code in a language that can distinguish between pointer equality and value equality is, let's say, "unprincipled." pure in D is a very useful concept, even if it's not literally the same as pure in functional languages. Recommending not to use it is bad advice IMHO.
Re: List of exceptions?
On Saturday, 10 October 2020 at 19:51:10 UTC, DMon wrote: This is where I'm at: import std.stdio; import std.conv; // StdioException // ConvException // StringException // ErrnoException // FormatException // UnicodeException // UTFException // FileMissingException // DataCorruptionException // FE_INEXACT // FE_UNDERFLOW // FE_OVERFLOW // - You should not care about exceptions someone else defined in his library (maybe except for printing out their message in main(), for which you don't need to know the exact type). - You should not reuse exceptions defined by someone else. Define your own. - Throw exceptions only if you have a plan what to do with them if you catch them. - If you have no plan, better throw error, just to get an idea where and why the program crashed (and don't try to catch them) Therefore a list of possible exceptions doesn't make any sense.
Re: Why is BOM required to use unicode in tokens?
On Wednesday, 16 September 2020 at 07:38:26 UTC, Dominikus Dittes Scherkl wrote: We only need to define which properties a character need to be allowed in an identifier. I think the following change in the grammar would be sufficient: Identifier: IdentifierStart IdentifierStart IdentifierChars IdentifierChars: IdentifierChar IdentifierChar IdentifierChars IdentifierStart: _ Any Unicode codepoint with general category Lu, Ll, Lt, Lo, Nl or No IdentifierChar: IdentifierStart Any Unicode codepoint with general category Lm, Mn, Me, Mc or Nd
Re: Why is BOM required to use unicode in tokens?
On Wednesday, 16 September 2020 at 00:22:15 UTC, Steven Schveighoffer wrote: Someone should verify that the character you want to use for a symbol name is actually considered a letter or not. Using phobos to prove this is kind of self-defeating, as I'm pretty sure it would be in league with DMD if there is a bug. UnicodeData.txt (a data file provided by the unicode organization itself since version 1) contains exactly the necessary properties (in an easy parsable format), so we don't need to hard-code the list of allowed identifier characters, but can instead use the latest version provided by unicode (changing every year!). We only need to define which properties a character need to be allowed in an identifier.
Re: Why is BOM required to use unicode in tokens?
On Tuesday, 15 September 2020 at 06:49:08 UTC, Jon Degenhardt wrote: On Tuesday, 15 September 2020 at 02:23:31 UTC, Paul Backus wrote: Identifiers start with a letter, _, or universal alpha, and are followed by any number of letters, _, digits, or universal alphas. Universal alphas are as defined in ISO/IEC 9899:1999(E) Appendix D of the C99 Standard. I was unable to find the definition of a "universal alpha", or whether that includes non-ascii alphabetic characters. ISO/IEC 9899:1999 (E) Annex D Universal character names for identifiers - Latin: 00AA, 00BA, 00C0-00D6, 00D8-00F6, 00F8-01F5, 01FA-0217, 0250-02A8, 1E00-1E9B, 1EA0-1EF9, 207F Greek: 0386, 0388-038A, 038C, 038E-03A1, 03A3-03CE, 03D0-03D6, 03DA, 03DC, 03DE, 03E0, 03E2-03F3, 1F00-1F15, 1F18-1F1D, 1F20-1F45, 1F48-1F4D, 1F50-1F57, 1F59, 1F5B, 1F5D, 1F5F-1F7D, 1F80-1FB4, 1FB6-1FBC, 1FC2-1FC4, 1FC6-1FCC, 1FD0-1FD3, 1FD6-1FDB, 1FE0-1FEC, 1FF2-1FF4, 1FF6-1FFC Cyrillic: 0401-040C, 040E-044F, 0451-045C, 045E-0481, 0490-04C4, 04C7-04C8, 04CB-04CC, 04D0-04EB, 04EE-04F5, 04F8-04F9 Armenian: 0531-0556, 0561-0587 Hebrew: 05B0-05B9, 05BB-05BD, 05BF, 05C1-05C2, 05D0-05EA, 05F0-05F2 Arabic: 0621-063A, 0640-0652, 0670-06B7, 06BA-06BE, 06C0-06CE, 06D0-06DC, 06E5-06E8, 06EA-06ED Devanagari: 0901-0903, 0905-0939, 093E-094D, 0950-0952, 0958-0963 Bengali: 0981-0983, 0985-098C, 098F-0990, 0993-09A8, 09AA-09B0, 09B2, 09B6-09B9, 09BE-09C4, 09C7-09C8, 09CB-09CD, 09DC-09DD, 09DF-09E3, 09F0-09F1 Gurmukhi: 0A02, 0A05-0A0A, 0A0F-0A10, 0A13-0A28, 0A2A-0A30, 0A32-0A33, 0A35-0A36, 0A38-0A39, 0A3E-0A42, 0A47-0A48, 0A4B-0A4D, 0A59-0A5C, 0A5E, 0A74 Gujarati: 0A81-0A83, 0A85-0A8B, 0A8D, 0A8F-0A91, 0A93-0AA8, 0AAA-0AB0, 0AB2-0AB3, 0AB5-0AB9, 0ABD-0AC5, 0AC7-0AC9, 0ACB-0ACD, 0AD0, 0AE0 Oriya: 0B01-0B03, 0B05-0B0C, 0B0F-0B10, 0B13-0B28, 0B2A-0B30, 0B32-0B33, 0B36-0B39, 0B3E-0B43, 0B47-0B48, 0B4B-0B4D, 0B5C-0B5D, 0B5F-0B61 Tamil: 0B82-0B83, 0B85-0B8A, 0B8E-0B90, 0B92-0B95, 0B99-0B9A, 0B9C, 0B9E-0B9F, 0BA3-0BA4, 0BA8-0BAA, 0BAE-0BB5, 0BB7-0BB9, 0BBE-0BC2, 0BC6-0BC8, 0BCA-0BCD Telugu: 0C01-0C03, 0C05-0C0C, 0C0E-0C10, 0C12-0C28, 0C2A-0C33, 0C35-0C39, 0C3E-0C44, 0C46-0C48, 0C4A-0C4D, 0C60-0C61 Kannada: 0C82-0C83, 0C85-0C8C, 0C8E-0C90, 0C92-0CA8, 0CAA-0CB3, 0CB5-0CB9, 0CBE-0CC4, 0CC6-0CC8, 0CCA-0CCD, 0CDE, 0CE0-0CE1 Malayalam: 0D02-0D03, 0D05-0D0C, 0D0E-0D10, 0D12-0D28, 0D2A-0D39, 0D3E-0D43, 0D46-0D48, 0D4A-0D4D, 0D60-0D61 Thai: 0E01-0E3A, 0E40-0E5B Lao: 0E81-0E82, 0E84, 0E87-0E88, 0E8A, 0E8D, 0E94-0E97, 0E99-0E9F, 0EA1-0EA3, 0EA5, 0EA7, 0EAA-0EAB, 0EAD-0EAE, 0EB0-0EB9, 0EBB-0EBD, 0EC0-0EC4, 0EC6, 0EC8-0ECD, 0EDC-0EDD Tibetan: 0F00, 0F18-0F19, 0F35, 0F37, 0F39, 0F3E-0F47, 0F49-0F69, 0F71-0F84, 0F86-0F8B, 0F90-0F95, 0F97, 0F99-0FAD, 0FB1-0FB7, 0FB9 Georgian: 10A0-10C5, 10D0-10F6 Hiragana: 3041-3093, 309B-309C Katakana: 30A1-30F6, 30FB-30FC Bopomofo: 3105-312C CJK Unified Ideographs: 4E00-9FA5 Hangul: AC00-D7A3 Digits: 0660-0669, 06F0-06F9, 0966-096F, 09E6-09EF, 0A66-0A6F, 0AE6-0AEF, 0B66-0B6F, 0BE7-0BEF, 0C66-0C6F, 0CE6-0CEF, 0D66-0D6F, 0E50-0E59, 0ED0-0ED9, 0F20-0F33 Special characters: 00B5, 00B7, 02B0-02B8, 02BB, 02BD-02C1, 02D0-02D1, 02E0-02E4, 037A, 0559, 093D, 0B3D, 1FBE, 203F-2040, 2102, 2107, 210A-2113, 2115, 2118-211D, 2124, 2126, 2128, 212A-2131, 2133-2138, 2160-2182, 3005-3007, 3021-3029 --- This is outdated to the brim. Also it doesn't allow for letter-like symbols (which is debatable, but especially the mathematical ones like double-struck letters are intended for such use). Instead of some old C-Standard, D should better rely directly on the properties from UnicodeData.txt, which is updated with every new unicode version.
Re: Named parameters in function call
On Tuesday, 8 September 2020 at 13:28:22 UTC, Cecil Ward wrote: int xcoord; int ycoord; You can define your own types, of course: struct xcoord { int x; alias x this; } struct ycoord { int y; alias y this; } void myfunc(xcoord x; ycoord y, color c) {}
Re: Idiomatic D code to avoid or detect devision by zero
On Monday, 3 August 2020 at 14:50:36 UTC, Steven Schveighoffer wrote: On 8/3/20 5:53 AM, Martin Tschierschke wrote: I prefer putting additional bracket around For really long expressions you could also split it on multiple lines: c = (b_expression == 0) ? (d_longer_expression) : (a_expression/b_expression);
Re: how to assign to shared obj.systime?
On Tuesday, 14 July 2020 at 07:05:43 UTC, Arafel wrote: *However*, for this to work, you shouldn't use `shared` member variables unless absolutely necessary, much less whole `shared` classes/structs This is generally true. Avoid sharing many variables! Tasks should be as independent from each other as possible. Anything else is bad design doomed to run into problems sooner or later. Also there is really almost never a good reason to share whole classes or nested structures.
Re: How can I make executeShell ask for Admin Elevation?
On Monday, 13 July 2020 at 19:32:33 UTC, Marcone wrote: alias runas = compose!(x => to!bool((cast(int) x) > 32), x => ShellExecute(null, "runas", "cmd", cast(wchar*) "/c \"cd /d %s && %s\"".format(getcwd(), x).to!wstring, null, SW_HIDE).WaitForSingleObject(WAIT_TIMEOUT)); runas("netsh winhttp set proxy 127.0.0.1:9666") Use backticks instead of doublequotes, than you don't have to escape the doublequotes within the string. So: alias runas = compose!(x => to!bool((cast(int) x) > 32), x => ShellExecute(null, "runas", "cmd", cast(wchar*)`/c "cd /d %s && %s"`.format(getcwd(), x).to!wstring, null, SW_HIDE);
Re: opBinary : Static ifs or specialization?
On Wednesday, 24 June 2020 at 09:01:28 UTC, claptrap wrote: On Wednesday, 24 June 2020 at 00:53:58 UTC, H. S. Teoh wrote: On Tue, Jun 23, 2020 at 11:53:36PM +, claptrap via If your implementations are based on built-in operators, you could use mixins to unify the implementations into one, e.g.: Ah yeah thats useful, to expand a bit what about if the RHS is a different type? Point!T opBinary(string op, RHS)(RHS rhs) { static if (is(RHS == Point!float) || is(RHS == Point!double)) { // .. etc.. } else static if (is(RHS == float) || is(RHS == double)) { // etc... } else static if (is(RHS == float[2]) || is(RHS == double[2])) { // .. etc... } assert(0); // type not supported } should that be split up? I would say, depends on how you can implement what you need in the shortest way (with lest code-duplication). If one operator works with several types on RHS, but others don't, split the operators. If all operators work the same for same RHS type but different for different RHS types, split the types.
Re: __init unresolved external when using C library structs converted with dstep
On Friday, 17 April 2020 at 08:59:41 UTC, Robert M. Münch wrote: How would that look like? myStruct ms = void; // ??? Exactly.
Re: @safe std.file.read
On Monday, 6 January 2020 at 10:07:37 UTC, WebFreak001 wrote: I was wondering, how are you supposed to use std.file : read in @safe code when it returns a void[] but you want to get all bytes in the file? Is void[] really the correct type it should be returning instead of ubyte[] when it just reads a (binary) file to memory? Or should void[] actually be castable to ubyte[] in @safe code? I definitely think it should return ubyte[]. void[] is a very special abstraction that shouldn't be used at all if you don't know very well what you're doing.
Re: Using map result type
On Tuesday, 10 December 2019 at 07:23:56 UTC, AA wrote: Would the second solution of declaring a template constraint like that be considering strange/out of place in D? e.g. do people normally try and declare the template constraints on a function or just rely on compile time failure from to instantiate template. No, you can do "normal" OOP as you like. But you will encounter the constraint approach often in phobos and other libraries, as is provides some advantages.
Re: Getting rid of const/immutable
On Monday, 16 September 2019 at 05:22:14 UTC, Cecil Ward wrote: I have a particular type name and that type may or may not be const and/or immutable. How do I make a new type based on this that is mutable, ie getting rid of both const and immutable, but not knowing what the original type is ? I don’t want to repeat information from the definition of the original type as this would introduce a bug if the original definition is later changed. Something like alias immutable_cash_t = immutable(float); alias mutable_cash_t = float; // better, in case the original were ever to be changed from ‘float’ to ‘real’ some day alias mutable_cash_t = GetRidOfImmutable!( GetRidOfConst!( mutable_cash_t ) ); If T is you const or immutable type, Unqual!T should be what you want (from std.traits) but this will also remove shared and I don't know what other modifiers there are.
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Saturday, 17 March 2018 at 18:36:35 UTC, Jonathan wrote: On Tuesday, 19 January 2016 at 23:36:14 UTC, Adam D. Ruppe wrote: On Tuesday, 19 January 2016 at 22:12:06 UTC, Soviet Friend wrote: I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. x86 actually doesn't need to do math that way, if you were writing assembly, it would just work. This is just an annoying rule brought over by C. Can I prevent the initial implicit casts? Nope, though you can help tell the compiler that you want it to fit there by doing stuff like ubyte a = 200; ubyte b = 100; ubyte c = (a+b)&0xff; or something like that, so the expression is specifically proven to fit in the byte with compile time facts. `(a+b)&0xff` What is this syntax?! Could you give a link to this in the D documentation? I am not even sure how to look it up... & is the normal binary and operation, same in C, C++, Java, ... 0xFF is a hexadecimal constant (255), which the compiler knows fit in an ubyte So what do you not understand about this syntax?
Re: Run-time initialised static variables
On Wednesday, 7 February 2018 at 12:10:38 UTC, dekevin wrote: struct ℚ{ ℤ num, den; //cannot call constructors on these, since they require gmp_init, which requires runtime code //Default initialiser disabled, since else num=0,den=0 You can use a different default initializer: ℤ num = 0, den = 1; Thus avoiding the bad denominator.
Re: New integer promotion rules
On Thursday, 18 January 2018 at 06:05:08 UTC, rumbu wrote: On Thursday, 18 January 2018 at 02:30:17 UTC, Rubn wrote: On Wednesday, 17 January 2018 at 22:30:11 UTC, rumbu wrote: code like "m = n < 0 ? -n : n" doesn't worth a wrapper That code is worth a wrapper, it's called "abs"... m = abs(n); Well, since I'm in the learn forum and you seem to have a response to anything, can you help me translate this line under the new integer promotion rules? https://github.com/rumbu13/decimal/blob/master/src/decimal/decimal.d#L7804 Thanks. target = isNegative ? cast(Unsigned!T)(-c) : cast(Unsigned!T)c; That would have been better even before the change, because the operator '-' used on unsigned types is likely to produce unexpected results, if the behaviour is defined at all.
Re: How to specify a template that uses unqualified type, like any normal function
On Tuesday, 15 August 2017 at 14:24:57 UTC, Steven Schveighoffer wrote: What IFTI would need is a mechanism to change the parameter types to mutable similar to how you can do this: foo(T)(const(T) t); This now generates one function for int, const(int), immutable(int), and t is const within the function. What we need is something like: foo(T)(mutable(T) t) // fictitious type constructor, doesn't work. In fact, that was the first thing I tried, but it doesn't exist. Would be a pretty useful addition anyway, because it would allow (some time in the far future) to move from mutable by default to immutable by default. Or a more general mechanism to modify IFTI when it is deciding the parameters to use based on the call. In my case, I've run into this when I'm trying to use short or ubyte, and someone uses literals: void foo(short s) { ...} void fooT(T)(T t) { foo(s); } foo(1); // ok fooT(1); // error. It would be nice if there was some way to tell IFTI to infer T as short in this case. Yes, that would also be very nice. And would be easy to solve: A literal should always be assumed to be the smallest type that can represent it, not int. May be, if compatibilitpy to old bad C is really still so important, integer propagation can be done later on if neccessary, but don't start out with int. That's just so oldschool and most of the time just annoying and there's no technical reason to do so.
Re: How to specify a template that uses unqualified type, like any normal function
On Monday, 14 August 2017 at 17:43:44 UTC, Dominikus Dittes Scherkl wrote: On Monday, 14 August 2017 at 15:20:28 UTC, Steven Schveighoffer wrote: What you can do, is: auto foo(T)(T n) if (is(T == Unqual!T)) { // normal implementation } auto foo(T)(T n) if (!is(T == Unqual!T) && isImplicitlyConvertible!(T, Unqual!T)) { return foo!(Unqual!T)(n); } Ok, I'll try that out. Yeah, works fine. I've improved this to T foo(T)(T n) { static if(!is(Unqual!T == T)) return foo!(Unqual!T)(n); else { // normal implementation } } So it's basically 2 lines of overhead. That's acceptable. The check for isImplicitlyConvertible is not necessary, because if it's not it will error out anyway. As this in fact leads to some decrease in code size (as the instances for const or shared parameters are now much smaller or in fact completely removed by the inliner, much less template code duplication happens), I will add this to a lot of templates - seems this will become some sort of standard D boilerplate code. Thanks for the help!
Re: How to specify a template that uses unqualified type, like any normal function
On Monday, 14 August 2017 at 15:20:28 UTC, Steven Schveighoffer wrote: On 8/14/17 9:48 AM, Dominikus Dittes Scherkl wrote: > uint foo(T)(Unqual!T n) // first try > { > ++n; // modify should be possible > return 42; > } > Any ideas what I need to do to make this work? This isn't exactly supported. Implicit Function Template Instantiation (IFTI) will deduce the parameters to be the types that you pass in. You can't deduce them and then change the parameter types. This is a limitation of IFTI that I have struggled with in the past. A little unfortunate, because I would consider this the standard usecase. You only overload functions if they do something special with const or shared or immutable parameters, but for templates you get a different implementation for these all the time, and you didn't even have a chance to avoid that useless code-bloat? What a pitty. What you can do, is: auto foo(T)(T n) if (is(T == Unqual!T)) { // normal implementation } auto foo(T)(T n) if (!is(T == Unqual!T) && isImplicitlyConvertible!(T, Unqual!T)) { return foo!(Unqual!T)(n); } Ok, I'll try that out.
How to specify a template that uses unqualified type, like any normal function
if I use fixed-type functions, I can do the following: uint foo(uint n) { ++n; // modify n - as this function has received a copy of n, this is always possible return 42; } uint bar(const uint n) { assert(foo(n)==42); return 17; } void main() { bar(3); } But if I try the same with a template parameter, it doesn't work: import std.traits; // Unqual uint foo(T)(Unqual!T n) // first try { ++n; // modify should be possible return 42; } uint foo2(T)(T n) // second try { ++n; // modify fails, as T is const return 42; } uint bar(T)(const T n) { assert(foo(n)==42u); // cannot deduce arguments - why?!? assert(foo2(n)==42u); // here it can deduce the arguments, but the function cannot modify n return 17; } void main() { bar(3); } Any ideas what I need to do to make this work?
Re: Returning the address of a reference return value in @safe code - 2.072 regression?
On Monday, 20 February 2017 at 21:05:17 UTC, Jack Stouffer wrote: On Monday, 20 February 2017 at 20:54:31 UTC, Jack Stouffer wrote: On Monday, 20 February 2017 at 20:49:43 UTC, Johan Engelen wrote: ... Yeah, this is another regression caused by DIP1000. Christ. For the record, the current list of regressions caused by DIP1000 https://issues.dlang.org/show_bug.cgi?id=17213 https://issues.dlang.org/show_bug.cgi?id=17188 https://issues.dlang.org/show_bug.cgi?id=17123 https://issues.dlang.org/show_bug.cgi?id=17117 17117 and 17123 are already fixed on HEAD, no? So only two regressions remaining - I hope DIP1000 can be used to build new container libraries soon.
Re: Comparison operator overloading
On Monday, 7 December 2015 at 13:31:52 UTC, Mike Parker wrote: On Monday, 7 December 2015 at 11:49:51 UTC, Dominikus Dittes Scherkl wrote: On the other hand the chapter also states that opCmp() should always return "int" - which is a bad idea if you e.g. want to provide a "NaN" value in your type. For that "float" is a much better return type for opCmp(). So you should not weight in gold for the words in the cited book, I think. This is not something the author is just making up. opCmp is expected to return int because of the way the compiler rewrites comparison expressions. See the table at [1]. It wouldn't do to return NaN from opCmp. [1] http://dlang.org/spec/operatoroverloading.html#compare Hmm. But it works just fine! It overloads also the special floatingpoint operators <> !<> !<= and so on. And how else could I handle a self-defined type that happens to have a NaN value (like my save-signed intergers do)?
Re: Comparison operator overloading
On Sunday, 6 December 2015 at 15:01:08 UTC, cym13 wrote: Don't use opCmp, all binary operators should be overriden using opBinary. For more information I recommend this page http://ddili.org/ders/d.en/operator_overloading.html Why should we don't use opCmp() ? I can't see any recommendation about this in the cited book. In the chapter is only mentioned that opSliceAssign() and the like are discouraged - but without stating a reason or a replacement. On the other hand the chapter also states that opCmp() should always return "int" - which is a bad idea if you e.g. want to provide a "NaN" value in your type. For that "float" is a much better return type for opCmp(). So you should not weight in gold for the words in the cited book, I think.
Re: Preventing implicit conversion
On Thursday, 5 November 2015 at 22:15:46 UTC, Dominikus Dittes Scherkl wrote: On Thursday, 5 November 2015 at 13:23:34 UTC, Adam D. Ruppe wrote: On Thursday, 5 November 2015 at 10:07:30 UTC, Dominikus Dittes Scherkl wrote: ubyte d = b + (ubyte)1; Sorry, should of course be: ubyte d = b + ubyte(1); Too much C lately :-/
Re: Preventing implicit conversion
On Thursday, 5 November 2015 at 13:23:34 UTC, Adam D. Ruppe wrote: On Thursday, 5 November 2015 at 10:07:30 UTC, Dominikus Dittes Scherkl wrote: ubyte b = 1u; auto c = b + 1u; I expect the 1u to be of type ubyte - and also c. This won't work because of the one-expression rule. In the second line, it doesn't know for sure what b is, it just knows it is somewhere between 0 and 255. So it assumes the worst, that it is 255, and you add one, giving 256... which doesn't fit in a byte. That would be fine - but c is not ushort (which the worst-case 256 would fit in), not even uint, but int! A signed type! Just because of the crazy C interger propagation rules! And, ok, one needs to accept that auto may not do exactly what I wish for, but if I give an exact type that is likely to fit (and has to if all operands are of the same type), I expect it to work without extra casts: ubyte d = b + 1u; // doesn't compile ubyte d = b + (ubyte)1; // works - and overflows to 0 if b is 255
Re: Preventing implicit conversion
And I want to have small number litterals automatically choosing the smallest fitting type. If I write ubyte b = 1u; auto c = b + 1u; I expect the 1u to be of type ubyte - and also c.
Re: Preventing implicit conversion
On Thursday, 5 November 2015 at 09:33:40 UTC, ixid wrote: In C++ I can add two shorts together without having to use a cast to assign the result to one of the two shorts. It just seems super clunky not to be able to do basic operations on basic types without casts everywhere. +1 If automatic shrink is droped from the C legacy stuff, so interger propagation should also be dropped (or changed to propagate no further than to the actual size of a type). D has a far better type system, throw away bad old C habits! -> this would also make the defect comparison of signed to unsigned types visible for small types and hopefully force the introduction of the correct comparison!
Re: foreach loop
On Monday, 19 October 2015 at 14:28:06 UTC, Namal wrote: Is it possible to create a foreach loop with a breakstetemen? I mean something like that for the second loop where i want to break if element from: int [] g = [9,15,21]; int [] v = [2,3,5,7,8,9,11,13,17,19]; foreach(j;1..10) for(int i = 0; v[i] Of course. D uses even the same keyword for this as C does: break.
Re: Bug? 0 is less than -10
On Wednesday, 7 October 2015 at 16:25:02 UTC, Marc Schütz wrote: Lionello Lunesu posted a PR that should fix this: https://github.com/D-Programming-Language/dmd/pull/1913 See also the discussion in the linked bug report. Unfortunately it seems it's been forgotten since then... Meanwhile I have even improved my solution posted to fix bug #259 to use less casts: int opCmp(T, U)(const(T) a, const(U) b) pure @safe @nogc nothrow if(isIntegral!T && isIntegral!U && !is(Unqual!T == Unqual!U)) { static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof) { return (a < 0) ? -1 : opCmp(cast(U)a, b); } else static if(isUnsigned!T && isSigned!U && T.sizeof >= U.sizeof) { return (b < 0) ? 1 : opCmp(a, cast(T)b); } else // both signed or both unsigned or the unsigned type is smaller { // do what the compiler always did so far: alias C = CommonType!(T, U); // use the larger of the both return opCmp(cast(C)a, cast(C)b); } } And on comparison with number literals everything will be optimized away, so no execution timer overhead at all!
Re: Why 1f.iota(100f).array returns double[] not float[]?
On Tuesday, 8 September 2015 at 07:17:01 UTC, Ali Çehreli wrote: https://github.com/D-Programming-Language/phobos/blob/master/std/range/package.d#L4630 auto iota(B, E)(B begin, E end) if (isFloatingPoint!(CommonType!(B, E))) { return iota(begin, end, 1.0); } Such kind of stuff would better be written as auto iota(B, E)(B begin, E end) { return iota(begin, end, cast(CommonType!(B, E))1.0); } this doesn't need a constraint anymore, or maybe use if(isNumeric!(CommonType!(B, E))) I tend to use the above kind of cast often, because I like to work with ubyte or ushort, and every f***ing number literal changes the type to uint :-/
Re: What's the "right" way to do openmp-style parallelism?
On Tuesday, 8 September 2015 at 05:50:30 UTC, Russel Winder wrote: void main() { immutable imax = 10; immutable jmax = 10; float[imax][jmax] x; foreach(int j; 1..jmax){ foreach(int i, ref item; parallel(x[j-1])){ x[j][i] = complicatedFunction(i, item); } } } (though sadly, this doesn't compile for a reason I can't fathom instantly) Hmm. Shouldn't you instead parallel the outer loop?
Re: Prefer Signed or Unsigned in D?
On Wednesday, 2 September 2015 at 09:47:16 UTC, BBasile wrote: On Tuesday, 1 September 2015 at 23:06:50 UTC, John Carter wrote: C/C++ discussion here http://blog.robertelder.org/signed-or-unsigned-part-2/ D rules here... http://dlang.org/type.html#integer-promotions It depends on the context. You should take care of blending signed and unsigned: comparison error, a is > b but... --- uint a = 1; int b = -1; assert(a < b); // does not throw --- You should take care to the index type in a loop: loop that doesn't run at all because of an infered unsigned index... --- auto array = new int[](8); for (auto i = array.length - 1; i > -1; i--) array[i] = 8; assert(array[0] == 0); // does not throw --- I wish the following would be the standard D behaviour (for T == U or if floats are involved neither C nor D have a problem)): int opCmp(T, U)(const(T) a, const(U) b) pure @safe @nogc nothrow if(isIntegral!T && isIntegral!U && !is(Unqual!T == Unqual!U)) { alias C = CommonType!(T, U); static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof) return (a < 0) ? -1 : opCmp(cast(U)a, b); else static if(isUnsigned!T && isSigned!U && T.sizeof >= U.sizeof) return (b < 0) ? 1 : opCmp(a, cast(T)b); else return opCmp(cast(C)a, cast(C)b); } this is really almost equally fast, but always correct.
Re: observation: D getting a bit complex
On Sunday, 30 August 2015 at 07:36:55 UTC, BBasile wrote: On Sunday, 30 August 2015 at 02:42:30 UTC, Spacen Jasset wrote: immutable(ElementEncodingType!(ElementType!Range))[] buildPath(Range)(Range segments) if (isInputRange!Range && isSomeString!(ElementType!Range)); pure nothrow @safe immutable(C)[] buildPath(C)(const(C)[][] paths...) if (isSomeChar!C); this is stodgy, particularly in a console with line wrapping at 80 chars. Could have been written as auto buildPath(Range)(Range segments) if (isInputRange!Range && isSomeString!(ElementType!Range)); but having an explicit return type is super valuable information. But the opportunity to omit it makes implementing a first working version so fast that it is pure joy. And the constraints you need not read - unless you want to understand why your call to the function failed. C++ is just lacking without them. Having them avoids that you always have to handle ridiculous input within your functions and allows to concentrate on meaningful code.
Re: Why does not my program is not running?
On Thursday, 20 August 2015 at 21:15:36 UTC, anonymous2 wrote: On Thursday, 20 August 2015 at 21:11:07 UTC, anonymous wrote: I severely limited the range of integer. I don't know off the top of my head how large you can make it without hitting overflow. I removed the file writing, because I'm not sure if you want to write it only when it doesn't exist, or only overwrite when it does exist. with integer == 66 the factorial overflows and becomes 0 (on my machine) => integer division by 0... The overflow happens at lower values, too. 66! has 2 64times as prime-factor, so a long becomes zero at that point. The overflow occures long ago (at 21!), but with 66! if becomes obvious, because you get a division by zero error.
Re: Problem with dmd 2.068 Win 32
On Tuesday, 11 August 2015 at 15:04:29 UTC, MGW wrote: Hi! My project has an error link: Error 42: Symbol Undefined _D6object9Exception6__ctorMFNaNbNfAyaAyakC6object9ThrowableZC9Exception On dmd 2.067.* everything gathered without mistakes. Where to look for a mistake? See the changelog. The compiler is now pickier if you forgot to link something explicitly.
Re: Speed of horizontal flip
On Wednesday, 1 April 2015 at 14:00:52 UTC, bearophile wrote: If you have to perform performance benchmarks then use ldc or gdc. Also disable bound tests with your compilation switches. Add the usual pure/nothrow/@nogc/@safe annotations where you can (they don't increase speed much, usually). if you are using classes don't forget to make the method final. Profile the code and look for the performance bottlenecks. This very text should be placed somewhere prominent at the D homepage if we don't want to constantly dissapoint people who come with the impession that D should be at the same speed level as C/C++ but their test programs aren't.
Re: BigFloat?
On Tuesday, 17 February 2015 at 09:08:17 UTC, Vlad Levenfeld wrote: On Tuesday, 17 February 2015 at 08:05:49 UTC, Kagamin wrote: Periodic fractions. Or transcendental numbers, for that matter, but arbitrary != infinite. A max_expansion template parameter could be useful here. For my use case I'm less concerned with absolute resolution than with preserving the information in the smaller operand when dealing with large magnitude differences. We have rational (two bigint, one for the numerator and one for the denominator), which I like better than floatingpoint (it's more expressive).
Re: shared Variant[string]
On Wednesday, 28 January 2015 at 12:29:09 UTC, Fyodor Ustinov wrote: On Wednesday, 28 January 2015 at 11:27:53 UTC, Kagamin wrote: Associative array doesn't support thread-safe operations, that's why they don't work on shared instance. You should use std.concurrency or implement low-level concurrency mechanism. If associative array does not support "share" attribute, this code should not be compiled without any warning or error, I think: shared string[string] t; void main() { t["t"] = "bebebe"; } But will. string is a shorthand for "immutable char" - and immutables are shared by default. No thread can modify them, so default shared is safe for them.
Re: using the full range of ubyte with iota
On Sunday, 25 January 2015 at 18:59:04 UTC, ketmar wrote: auto x2 = (x>>4) | (x<<4); // swap nibbles - but result in an int! this is true for C and C++ too, as all three languages doing "integer promotion". the only difference is that D forbids potentially lossy assigns. you best bet is to not use `auto`, but specify required type explicitly. or use ints/uints and cast to bytes only when it is necessary. in normal assignments I never use auto - it's not simpler than writing the type explicit but later makes it more complicated to see what type it is. But in a function you need the cast anyway: ubyte swapNibbles(ubyte x) { return (x>>4) | (x>>4); } // compiler not happy or if you index with a long, even after explicit check: int foo(ulong x) { int[10] a; return (x < 10) ? a[x] : 0; // cannot index with long } So there are plenty of places in D where cast is necessary but should not be. I think both of above cases should be safe without cast, and enhancing the compilerr that it can handle these cases is more important than a iota!"[]". Until then I prefer paramCast!fn, because this is more flexible than the iota extension and my code is full of casts anyway.
Re: using the full range of ubyte with iota
On Sunday, 25 January 2015 at 13:03:16 UTC, bearophile wrote: Dominikus Dittes Scherkl: Because this is useful in more situations, Right, but it's still a cast. And in D you want to minimize the number of usages of casts. The proposed syntax iota!"[]" is cast-safe. I don't case too much, if I have ensured the cast is safe by constraints beforehand. I need to cast often anyway, because I work with small types and most operators permanently change everything to "int", especially the bit-operations for which a signed type makes no sense at all: ubyte x = 50; auto y = x & 0x11; // y is int! I hate that! even if I use unsigned literals: auto z = x & 0x12u; // z is uint - better but still bad. More so as & should result in the smaller of the two types!! But I need not even use literals (which unfortunately cannot be makred as "ubyte" or "short"). Look at this: auto x2 = (x>>4) | (x<<4); // swap nibbles - but result in an int!
Re: using the full range of ubyte with iota
On Sunday, 25 January 2015 at 12:56:14 UTC, Tobias Pankrath wrote: On Sunday, 25 January 2015 at 12:25:35 UTC, Dominikus Dittes Scherkl wrote: map!(x => fn(cast(ParameterTypeTuple!fn[0])x) but instead with map!(paramCast!fn) Because this is useful in more situations, e.g. in every place where you know the values would fit into the parameter (and for a single call would use a cast). But so far I couldn't manage to make this work :-/ http://dpaste.dzfl.pl/07b1fa3c2dad Hey cool. With unary function I can even remove the string and mixin magic: template paramCast(alias fn) { ReturnType!fn paramCast(T)(T x) { return fn(cast(ParameterTypeTuple!fn[0])x); } } Many Thanks!
unittest with Visual D
I finaly got managed to install Visual D on my Windows PC (thanks to the new community version of Visual Studio), but the cool point "Compile and Run" seems to have a problem with some of my unittests: I get the error "template instance xy is not defined" if a specific instantiation is not used in my main program. But shouldn't the compiler build all instantiations used within a unittest?!? What am I missing?
Re: using the full range of ubyte with iota
On Sunday, 25 January 2015 at 10:42:51 UTC, bearophile wrote: Vlad Levenfeld: What's this about !`[]` and std.range.uniform?? It's not in the documentation. It's an enhancement I have proposed. Hm. I had more something in mind like "paramCast" - a kind of big scissors that cut everything a function is called with to the size it can cope with, so replacing map!fn not with map!(x => fn(cast(ParameterTypeTuple!fn[0])x) but instead with map!(paramCast!fn) Because this is useful in more situations, e.g. in every place where you know the values would fit into the parameter (and for a single call would use a cast). But so far I couldn't manage to make this work :-/
Re: using the full range of ubyte with iota
On Saturday, 24 January 2015 at 23:19:11 UTC, ketmar wrote: people that are new to D aren't used to D lambdas, so it's fairly common. Oh, I am aware, but I didn't thought it would be necessary in this pace. if you'll stay with D, you'll find yourself dreaming about such handy thing in another compiled languages very soon. ;-) I don't consider to use any other language as long as I have a choice :-) But in the end, my one short and beautiful solution auto myRange = iota(start, end).map!foo; changed into something quite klumsy: auto myRange = iota(start, end).map!(x => foo(cast(ParameterTypeTuple!foo[0])x)); which I think is against the philosophy of D as it turns away the eye of the reader from what is really going on, especially if previous constraints ensured that start and end-1 are of the correct type :-( But ok, still far, far better than what would be neccessary in C++
Re: using the full range of ubyte with iota
On Saturday, 24 January 2015 at 21:00:06 UTC, Tobias Pankrath wrote: On Saturday, 24 January 2015 at 20:49:03 UTC, Dominikus Dittes Scherkl wrote: I would have no problem using an explicit cast, but where should I apply it? iota(0, 256).map!(x => foo(cast(ubyte) x)) Ok, thank you very much. 4 times exactly the same answer - seems to be a common solution to a well known problem. :-/
using the full range of ubyte with iota
Maybe I'm just too stupid, but I cannot manage to call a simple function with all 256 possible values of ubyte with iote: int foo(ubyte c); auto myRange = iota(0,256).map!foo; --> Error: function foo(ubyte c) is not callable using argument types (int) and this is because of the f*** end-type cannot be ubyte because in phobos everywhere end is excluded, so I have to define it too large by one. Has anyone any idea how to work around this? I would have no problem using an explicit cast, but where should I apply it?
Re: Number of Bits Needed to Represent a Zero-Offset Integer
On Monday, 19 January 2015 at 21:23:47 UTC, Nordlöw wrote: On Monday, 19 January 2015 at 20:54:50 UTC, Steven Schveighoffer wrote: Cool. I would point out that the commented code suggests you should be handling the 0 case, but you are not (when T.min == T.max) I believe that should trigger a failing static assert with a good error message as it doesn't make any sense to call the function in that case. Thanks. I would recommend to use something like this: /// returns the number of the highest set bit +1 in the given value or 0 if no bit is set size_t bitlen(T)(const(T) a) pure @safe @nogc nothrow if(isUnsigned!T) { static if(T.sizeof <= size_t.sizeof) // doesn't work for ulong on 32bit sys { return x ? core.bitop.bsr(x)+1 : 0; } else static if(T.sizeof == 8) // ulong if size_t == uint { return x ? x>>32 ? core.bitop.bsr(x)+33 : core.bitop.bsr(x)+1 : 0; } }
Re: reinterpret array
On Tuesday, 13 January 2015 at 23:36:51 UTC, Artur Skawina via Digitalmars-d-learn wrote: It's neat, but the real problems with it are: 1) obfuscation - it hides those trivial bit ops behind layers of functions and operator overloads, which everyone reading the code must then figure out; Ok, but this is the case with any function - and this modulo stuff is easy but not so trivial that a function is not justified. 2) safety - `a.bit` could potentially outlive `a`; D does not handle object lifetimes, so there's no 100% safe way to prevent such bugs. This can be addressed with the newer proposed mechanisms and a little more information-hiding (generator function): Hence you probably don't actually want to use this. [...] I had something pretty close to that in mind: @property inout bit(T)(inout ref T a) pure @safe @nogc nothrow if(isUnsigned!T || (isArray!T && isUnsigned!T[0])) { struct BitArray(T) { private: enum s = std.bitop.bsr(T.sizeof)+2; enum m = (1<>s]>>(idx & m))&1u : false; } static if(isMutable!T) { void opIndexAssign(bool b, size_t idx) // set or clear bit { if(idx < len) { if(b) r[idx>>s] |= 1u<<(idx & m); else r[idx>>s] &= ~(cast(T)1<<(idx & m)); } } } } static if(isUnsigned!T) return BitArray(&a, 1); else return BitArray(&a[0], a.length); }
Re: reinterpret array
On Tuesday, 13 January 2015 at 20:11:45 UTC, anonymous wrote: On Tuesday, 13 January 2015 at 20:00:57 UTC, Dominikus Dittes Scherkl wrote: So if I have a function that allowes to do this: uint a; a.bit[16] = true; writeln(a); // 65536 Is it also already available? a |= 1 << 16; Of course you can calculate it, but the syntax looks quite different if you want to do a.bit[22] = false: a &= ~(1<<16); Or if you want to test a bit: if(a.bit[16]) instead of if(a & (1<<16)) much more convenient for arrays: ulong[100] a; a.bit[3000] = true; doing this directly with shifts is lousy (and error prone) But ok. I see, it's not really awesome :-/
Re: reinterpret array
On Tuesday, 13 January 2015 at 18:25:38 UTC, ketmar via Digitalmars-d-learn wrote: On Tue, 13 Jan 2015 17:09:31 + Dominikus Dittes Scherkl via Digitalmars-d-learn wrote: /// interpret an array of one type as an array of a different type. may i point you to this? import std.stdio; void main () { ubyte[] a = [42,0,0,0, 155,2,0,0]; auto b = cast(uint[])a; writeln(b); // "[42, 667]" } I see. So this function is completely superfluous :-/ Good to know. So if I have a function that allowes to do this: uint a; a.bit[16] = true; writeln(a); // 65536 Is it also already available? Because I somewhat hate it that with D I can create great stuff, but it is not necessary because D already has something much cooler...
Re: reinterpret array
On Tuesday, 13 January 2015 at 17:12:42 UTC, Adam D. Ruppe wrote: On Tuesday, 13 January 2015 at 17:09:32 UTC, Dominikus Dittes Scherkl wrote: I assume taking a slice of a pointer uses the GC, so this cannot be @nogc, am I right? Nope, slicing never allocates, it just takes an address and length. If you append to a slice or increase the length though, the GC might reallocate it. Cool. So I can make the above even @nogc ? Great.
reinterpret array
Does the following construct hold water? version(LittleEndian) { /// interpret an array of one type as an array of a different type. /// if the array has odd length, the highest elements are /// not accessible, at worst an empty slice is returned inout ref T[] arrayOf(T, V: U[])(inout ref V a) pure @safe nothrow if(isUnsigned!T && isUnsigned!U) { return (cast(T*)a.ptr)[0 .. a.length * U.sizeof / T.sizeof]; } unittest { ubyte a[5] = { 1, 2, 3, 4, 5 }; auto b = a.arrayOf!uint; assert(typeof(b) == uint[]); assert(b.length == 1); assert(b[0] == 0x04030201); assert(&b[0] == &a[0]); // b is a slice of a b[0] = 0x0a0b0c0d; // this will change a assert(a == { 13, 12, 11, 10, 5 }); ushort c[2] = { 257, 512 }; auto d = c.arrayOf!ubyte; assert(d.length == 4); assert(d[0] == 1); assert(d[1] == 1); assert(d[2] == 0); assert(d[3] == 2); } } I assume taking a slice of a pointer uses the GC, so this cannot be @nogc, am I right? And I assume it is @save, because if I would increase the length of the returned value, the GC will automatically re-allocate, but then of course the adress is no more the same, yes?
Re: Conditional functions
On Monday, 5 January 2015 at 17:55:49 UTC, Justin Whear wrote: On Mon, 05 Jan 2015 17:47:09 +, Dominikus Dittes Scherkl wrote: Is it possible to use static if in a template structure to have some member functions only for specific types? Yep. This is actually a frequently used pattern in functions that return ranges. Cool. I'm every day again astonished how cool D really is.
Conditional functions
Is it possible to use static if in a template structure to have some member functions only for specific types? E.g.: struct Foo(T) { ... T get() { ... } static if(isMutable!T) { void set(T x) { ... } } }
Re: Dynamic array head const in library code?
On Friday, 28 November 2014 at 10:55:27 UTC, bearophile wrote: In D code it's a good idea to set as const/immutable (where possible) all variables that don't need to change, for both safety and compiler-enforced code documentation. In my D functions sometimes I create dynamic arrays that later don't have to change length nor to be reassigned, but I have to mutate or assign their items. Why you don't use static arrays for such a purpose? I thought this is exactly what they are made for, aren't they?
Re: accessing numeric template parameters
On Monday, 3 November 2014 at 21:17:09 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: struct polynomial(uint base) { private: uint[] N; public: this(uint x) { base = x; } base is part of the type. polynomial is just a 'recipe' for a type, the real struct would be Polynomial!(0), Polynomial!(1), etc. Note that Polynomial!0, Polynomial!1, ... are all different types. Yes, that's what I intend. Being part of the type means it's defined only at compile-time, you cannot use a runtime value (like 'x') to initialize it. Note that with your current code, `base' is not visible outside Polynomial. You can alias it to a field to make it visible: struct Polynomial(uint base) { alias b = base; // b is visible outside (but set at Ah, ok. Thank you! compile-time !) ... } You can create one like this: Polynomial!2 poly; poly.N = [0,1,0,0,1,1]; Ok, now I remember, struct doesn't need an explicit constructor. (in this case)
accessing numeric template parameters
If I have a struct with numeric template parameter, how can I access it within member functions? Like normal member variables? And how about the constructor? struct polynomial(uint base) { private: uint[] N; public: this(uint x) { base = x; } ... void add(Polynomial!base P) { if(N.length < P.N.length) N.length = P.N.length; foreach(i; 0..P.N.length) { N[i] = (N[i]+P.N[i]) % base; } } } This doesn't work for me :-/
Re: 'idiomatic' porting of c and or c++ code that does NULL checking
On Wednesday, 27 August 2014 at 05:45:34 UTC, eles wrote: While this may be true in this case, I think that, in general, you cannot draw such a clear line between what's recoverable and what's not. If you really want to push things to the extreme, the sole unrecoverable error shall be assertion failure and the SIGKILL. That's exactly the line I would draw. _Nothing_ else is an error, so _everything_ is an exception. Best forget about that something else even exist.
Re: Variadic parameter of length 1
On Wednesday, 20 August 2014 at 15:37:18 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: No better solution that I know of. alias template parameters (alias a) match symbols (names, user-defined types) whereas type parameter (T) match only pure types. So when we need to match anything, we use (T...) if (T.length == 1) Ok, now it's clear. Thank you very much. Sometimes D is really a little weird...
Re: Variadic parameter of length 1
On Wednesday, 20 August 2014 at 15:26:14 UTC, monarch_dodra wrote: AFAIK, it's a historical workaround to accept T as either alias or not alias, as varargs have "auto alias". EG: foo!int //OK foo!"hello" //OK too Ah, ok. And why historical? Is that not necessary anymore? What better solution is there today?
Variadic parameter of length 1
I have several times seen a construct template foo(T...) if(T.length == 1) { ... } What is that good for? Why using variadic parameter if anyway exactly one parameter is required?!?
Re: simple question about function call syntax
On Monday, 18 August 2014 at 16:30:13 UTC, Nikolay wrote: I found this code sample in vibe: void connect(NetworkAddress addr) { enforce(.connect(m_ctx.socketfd, addr.sockAddr, addr.sockAddrLen) == 0, "Failed to connect UDP socket."~to!string(getLastSocketError())); } What does mean ".connect"? Where I can find description of this syntax (dot + function name)? . is the module-scope. Use it to dis-ambiguate between a module-global symbol and a function local symbol with same name.
Re: Separate Printing Mantissa and Exponent of a Floating Point
On Monday, 11 August 2014 at 14:15:05 UTC, Nordlöw wrote: Here's my current try: string toMathML(T)(T x) @trusted /** pure */ if (isFloatingPoint!T) { import std.conv: to; import std.algorithm: findSplit; // immutable parts = to!string(x).findSplit("e"); if (parts[2].length == 0) return parts[0]; else return parts[0] ~ "*10^" ~ parts[2]; } Should be patrs[1], he? I had the same problem, but not for printing, but to do some math on them. Unfortunately math.h uses this internal (e.g. in trunc()) but doesn't give it to outside. I think it would be a good abstaction between the hardware-realated stuff and the interface - at the moment almost the same code is repeated three times over math.h always with the same version switches.
Re: funny behavior of ".."
On Friday, 8 August 2014 at 15:17:25 UTC, seany wrote: The .., range operator, when used like this : string a = "abcd"; string b = a[0 .. a.count()-1]; sets b to "abc". is this the expected behavior? Yes. [..] is exclusive the last element. So [0..1] is a single element [0] That allows to avoid to always writing the "-1". BTW: you can even use $ instead of a.count(): string b = a[0..$]; And if you like to slice the whole string, leave even the backets out: string b = a;
Re: new properties for basic types
On Tuesday, 15 July 2014 at 05:26:57 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: @property allows you to call a function without the parenthesis (), to imitate a field in a struct or class. Ah, ok. That means without @property I would need to write defaultInit!T() instead of defaultInit!T Hmm. I'm not sure that I like this syntax that hides a function call. In this particular case, I don't know what defaultInit is used for. It seems to compile to a forward declaration of a function, but I don't know what for. I cannot find it on my copy of std.traits. What DMD version are you using? Hmm. Ok it was in 2.064. I should update my setup it seems :-)
Re: new properties for basic types
On Monday, 14 July 2014 at 11:28:15 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: Halas, that's not what the OP wants. He needs properties on the *type* itself: int.foo instead of foo!int. Yes, exactly. So no, this is not possible. Hmm. So how do I use stuff like this: template defaultInit(T) { static if (!is(typeof({ T v = void; })))// inout(U) @property T defaultInit(T v = T.init); else @property T defaultInit(); } (this is from std.traits - ok, it's private, but anyway) Because I have seen nowhere anything like defaultInit!T (or T.defaultInit) and don't understand why here the attribute @property is used. Why does it make a difference, and how?
new properties for basic types
Is it possible to write custom properties for basic types, so that I can write e.g. "int.myProp" instead of "myProp!int()" [analogue to x.myProp instead of myProp(x)]?
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
So at all the implementation will look something like this: int opCmp(T, U)(const(T) a, const(U) b) @primitive if(isIntegral!T && isIntegral!U) { alias CommonType!(Signed!T, Signed!U) C; static if(isSigned!T && isUnsigned!U) { return (b > cast(Unsigned!C)C.max) ? -1 : cast(C)a - cast(C)b; } else static if(isUnsigned!T && isSigned!U) { return (a > cast(Unsigned!C)C.max) ? 1 : cast(C)a - cast(C)b; } else // both signed or both unsigned { return cast(C)a - cast(C)b; } } And it will be just as fast as ever, except if you compare apples with peaches where it take a tick longer but give the correct result anyway
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
Should of course be: int compare2(uint x, int y) { return (x > int.max) ? 1 : (cast(int)x - y); }
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
On Wednesday, 9 July 2014 at 19:54:47 UTC, H. S. Teoh via Digitalmars-d-learn wrote: [...] The problem is that the function needs to return int, but given two uints, their difference may be greater than int.max, so simply subtracting them will not work. So the best I can come up with is: int compare2(int x, uint y) { return (x < 0) ? -1 : (y > int.max) ? -1 : (x - y); } which requires 2 comparisons. Hmm. Diff works for compare(int,int). So how about this: int compare2(int x, uint y) { return (y > int.max) ? -1 : (x - cast(int)y); } int compare2(uint x, int y) { return (x > int.max) ? -1 : (cast(int)x - y); }
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
On Wednesday, 9 July 2014 at 17:13:21 UTC, H. S. Teoh via Digitalmars-d-learn wrote: The branched version would look something like this: mov eax, [] mov ebx, [] cmp ebx, $#0 jge label1 ; first branch mov eax, $# jmp label2 ; 2nd branch label1: sub eax, ebx label2: (ret) Why? I would say: mov eax, [] ; mov directly compares to zero jl lable; less -> jump to return sub eax, [] neg eax ; because we subtracted in the wrong order lable: ret
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
On Wednesday, 9 July 2014 at 17:13:21 UTC, H. S. Teoh via Digitalmars-d-learn wrote: On Wed, Jul 09, 2014 at 04:24:38PM +, Dominikus Dittes Scherkl via Digitalmars-d-learn wrote: /// Returns -1 if a < b, 0 if they are equal or 1 if a > b. /// this will always yield a correct result, no matter which numeric types are compared. /// It uses one extra comparison operation if and only if /// one type is signed and the other unsigned but the signed value is >= 0 /// (that is what you need to pay for stupid choice of type). [...] Yeah, I don't see what's the problem with comparing signed and unsigned values, as long as the result is as expected. Currently, however, this code asserts, which is wrong: uint x = uint.max; int y = -1; assert(x > y); Yes, this is really bad. But last time I got the response that this is so to be compatible with C. That is what I really thought was the reason why D throw away balast from C, to fix bugs. static if(Unqual!T == Unqual!U) Nitpick: should be: static if(is(Unqual!T == Unqual!U)) Of course. [...] else static if(isSigned!T && isUnsigned!U) { alias CommonType!(Unsigned!T, U) C; return (a < 0) ? -1 : opCmp!(cast(C)a, cast(C)b); } else static if(isUnsigned!T && isSigned!U) { alias CommonType!(T, Unsigned!U) C; return (b < 0) ? 1 : opCmp!(cast(C)a, cast(C)b); } [...] Hmm. I wonder if there's a more efficient way to do this. I'm sure. But I think it should be done at the compiler, not in a library. {...] opCmp is just a single sub instruction (this is why opCmp is defined the way it is, BTW), whereas the "smart" signed/unsigned comparison is 4 instructions long. [...] you can see, the branched version is 5 instructions long, and always causes a CPU pipeline hazard. So I submit that the unbranched version is better. ;-) I don't think so, because the branch will only be taken if the signed type is >= 0 (in fact unsigned). So if the signed/unsigned comparison is by accident, you pay the extra runtime. But if it is intentional the signed value is likely to be negative, so you get a correct result with no extra cost. Even better for constants, where the compiler can not only evaluate expressions like (uint.max > -1) correct, but it should optimize them completely away! (So much for premature optimization... now lemme go and actually benchmark this stuff and see how well it actually performs in practice. Yes, we should do this. Often, such kinds of hacks often perform more poorly than expected due to unforeseen complications with today's complex CPU's. So for all I know, I could've just been spouting nonsense above. :P) I don't see such a compiler change as a hack. It is a strong improvement IMHO.
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
Of course without the ! after opCmp in the several cases.
Re: Opinions: The Best and Worst of D (for a lecture/talk I intend to give)
On Wednesday, 9 July 2014 at 14:51:41 UTC, Meta wrote: One of the uglier things in D is also a long-standing problem with C and C++, in that comparison of signed and unsigned values is allowed. I would like that, if it would be implemented along this line: /// Returns -1 if a < b, 0 if they are equal or 1 if a > b. /// this will always yield a correct result, no matter which numeric types are compared. /// It uses one extra comparison operation if and only if /// one type is signed and the other unsigned but the signed value is >= 0 /// (that is what you need to pay for stupid choice of type). int opCmp(T, U)(const(T) a, const(U) b) @primitive if(isNumeric!T && isNumeric!U) { static if(Unqual!T == Unqual!U) { // use the standard D implementation } else static if(isFloatingPoint!T || isFloatingPoint!U) { alias CommonType!(T, U) C; return opCmp!(cast(C)a, cast(C)b); } else static if(isSigned!T && isUnsigned!U) { alias CommonType!(Unsigned!T, U) C; return (a < 0) ? -1 : opCmp!(cast(C)a, cast(C)b); } else static if(isUnsigned!T && isSigned!U) { alias CommonType!(T, Unsigned!U) C; return (b < 0) ? 1 : opCmp!(cast(C)a, cast(C)b); } else // both signed or both unsigned { alias CommonType!(T, U) C; return opCmp!(cast(C)a, cast(C)b); } }
overloading operations for enums
Hello. I want to create some finite algebra, where the elements are enumerated but operations on them are defined (with composition tables). e.g.: enum color = { white, yellow, red, blue, orange, violet, green, black }; color a = blue; a += yellow; assert(a == green); is this possible in D? Because, if I define a struct, I can define operation overloads, but then I have no enumeration of possible values. But if I enumerate, I cannot overload operations. What have I missed?
Re: Question about @nogc
On Tuesday, 20 May 2014 at 17:14:31 UTC, John Colvin wrote: On Tuesday, 20 May 2014 at 12:25:11 UTC, Dominikus Dittes Scherkl wrote: Did I understand correct that a function can only be @nogc if also all functions that it calls are @nogc too (and of course it doesn't use the GC itself)? If so, should this be possible: string foo() { // use GC to allocate some string } bar @nogc { mixin(foo()); } Because, bar() didn't really call foo() but instead foo() is evaluated during compile time and it's result is now part of the code, right? Yes, that should be allowed. Thanks. This is nice to know, because I will use this a lot in the future: /// create a fixed size array with the given name and with *max* entries /// of immutable values of the same type as the return value of the /// given function. /// it contains the values of that function in the range [0..max]. string makeLookupTable(alias fn, uint max=255)(string name) pure @safe if(is(typeof(fn(max { string table = "immutable " ~ to!string(typeof(fn(max))) ~ "[" ~ to!string(max+1) ~ "] " ~ name ~"= [ "; foreach(i; 0..max) table ~= to!string(fn(i) ~ ", "; return table ~ to!string(fn(max) ~" ]"; }
Question about @nogc
Did I understand correct that a function can only be @nogc if also all functions that it calls are @nogc too (and of course it doesn't use the GC itself)? If so, should this be possible: string foo() { // use GC to allocate some string } bar @nogc { mixin(foo()); } Because, bar() didn't really call foo() but instead foo() is evaluated during compile time and it's result is now part of the code, right?
Re: Nobody understands templates?
On Monday, 3 March 2014 at 16:40:09 UTC, Chris wrote: I'm always willing to use templates, but maybe in fact the use cases are limited. I have a class for html elements (that implements DOM functionality), and a class for building trees with the tags. Of course, for html tags only string as a type makes sense. Really? Did you consider that there are three different flavors of "string"? Does your function really only deal with string? Or would someone need wstring or dstring? class HTMLElement(T) if (is (T == string)) { } [...] I don't know [...] if I won't have to modify the template to adapt to new data types (which kinda defeats the purpose). Not much if the different types have common features. Most times it is still a big save of code to implement, even if the types need to be handled different in some places.
Re: Is this reasonable?
The best that could be done would arguably be to simply do the comparison the 'right' way. E.g. static assert(-1 < 0u). What's the 'right' way? assert(-1 < uint.max) will always fail because no matter whether you convert to int or uint, the comparison simply cannot be carried out at the machine code level. But the compiler should be able to do such things at compile time. If you compare an unsigned variable with a negative literal, "-1 < x" or "x > -1": the whole expression can be rewritten to "true", "-1 == x" or "-1 > x" or "-1 >= x" etc. can be rewritten to "false". This is not only no performance problem but instead extremely efficient!