Re: Doubt - Static multidimension arrays
On Tuesday, 19 January 2016 at 07:46:59 UTC, Mike Parker wrote: It's not that he's seeing them as special, it's just that indexing them in D is different than doing so in C or C++. It trips a lot of people up. No, the difference is actually in C/C++ 's declaration syntax; the way that indexing works is exactly the same as in D. This C++ code (http://codepad.org/XeVSndBP): #include #include class Row { int data[10]; public: int& operator[](int x) { return data[x]; } }; int main(void) { int arr2d[5][10]; Row arrOfArrs[5]; for(int r = 0; r < 5; ++r) { for(int c = 0; c < 10; ++c) { arr2d[r][c] = (r * 10) + c; arrOfArrs[r][c] = (r * 10) + c; } } cout << (arr2d[4][9] == arrOfArrs[4][9]) << endl; cout << (memcmp(arr2d, arrOfArrs, sizeof(int)*5*10) == 0) << endl; return 0; } Does exactly the same thing as this D code (http://dpaste.dzfl.pl/1731eb86bc83): import std.stdio; import core.stdc.string; alias Row = int[10]; int main() { int[10][5] arr2d; Row[5] arrOfArrs; for(int r = 0; r < 5; ++r) { for(int c = 0; c < 10; ++c) { arr2d[r][c] = (r * 10) + c; arrOfArrs[r][c] = (r * 10) + c; } } writeln(arr2d[4][9] == arrOfArrs[4][9]); writeln(memcmp(arr2d.ptr, arrOfArrs.ptr, int.sizeof*5*10) == 0); return 0; } The only relevant difference between the two, is that the order of the row and column specification is swapped in *the declaration*, not when indexing.
Re: Unions and Structs
On Mon, 2016-01-18 at 21:50 +0100, Jacob Carlborg via Digitalmars-d- learn wrote: > On 2016-01-18 19:11, Russel Winder via Digitalmars-d-learn wrote: > > > It seems DStep is producing somewhat strange D from complicated C > > unions. > > Please report any issues to [1] with a test case. C code, expected D > code, actual D code. > > [1] https://github.com/jacob-carlborg/dstep/issues I made a start, but they aren't full reports as yet. https://github.com/jacob-carlborg/dstep/issues/46 https://github.com/jacob-carlborg/dstep/issues/47 -- 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
Re: foreach( i, e; a) vs ndslice
On Monday, 18 January 2016 at 23:33:53 UTC, Jay Norwood wrote: I'm playing with the example below. I noticed a few things. 1. The ndslice didn't support the extra index, i, in the foreach, so had to add extra i,j. 2. I couldn't figure out a way to use sliced on the original 'a' array. Is slicing only available on 1 dim arrays? 3. Sliced parameter order is different than multi-dimension array dimension declaration. import std.stdio; import std.experimental.ndslice.slice; void main() { int[4][5] a = new int[20]; foreach(i,ref r; a){ foreach(j,ref c; r){ c= i+j; writefln("a(%d,%d)=%s",i,j,c); } } writefln("a=%s",a); auto b = new int[20].sliced(5,4); int i=0; foreach( ref r; b){ int j=0; foreach( ref c; r){ c= i+j; writefln("b(%d,%d)=%s",i,j,c); j++; } i++; } writefln("b=%s",b); } Hi, 1. You can use std.range.enumerate or just use a normal foreach: foreach(i; 0..slice.length!0) { /// use slice[i] ... } 2. Yes (A 2D D array is an array of arrays, so slice would be a slice composed of arrays) 3. Order is correct: void main() { auto a = new long[][](5, 4); auto b = new long[20].sliced(5, 4); foreach(i, ref r; a) { foreach(j, ref c; r) { c = i+j; b[i, j] = c; writefln("a(%d,%d)=%s", i, j, c); writefln("b(%d,%d)=%s", i, j, b[i, j]); } } writefln("a=%s",a); writefln("b=%s",b); } Ilya
Can't add ubytes together to make a ubyte... bug or feature?
I just attempted to add one ubyte to another and store the result in a ubyte but apparently ubytes get converted to ints when being added... and converting what becomes an int becomes impossible to store in a ubyte without an explicit cast... ubyte a, b; ubyte c = a + b; // Error: cannot implicitly convert expression (cast(int)a + cast(int)b) of type int to ubyte On principal I'm not casting to fix this. I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. I'm really hoping this is a bug because trying to use any type other than ints is going to make for some really ugly code otherwise... Can I prevent the initial implicit casts? On the topic of complaining about casting... array lengths as ulongs is painful... any chance of an array[].lengthi being a thing?
Re: Doubt - Static multidimension arrays
On Tuesday, 19 January 2016 at 19:14:30 UTC, alb wrote: So guys: Ali, Mike Parker and tsbockman thanks for all your explanation, in fact looking now I and after making some tests I really got it. So: int[2]a1; // Array of 2 elements of type int int[2][5] a2; // Array of 2 elements of type int divided in 5 rows writeln(a2[0]); // = accessing row 0 = [0,0] writeln(a2[4]); // = accessing row 4 = [0,0] One other thing you may want to keep in mind when working on this kind of thing - when you loop over a multi-dimensional array, the order matters. For large arrays, this: int[c_max][r_max] arr; foreach(r; 0 .. r_max) { foreach(c; 0 .. c_max) { // do something with arr[r][c] here } } Can be *much* faster than this: int[c_max][r_max] arr; foreach(c; 0 .. c_max) { foreach(r; 0 .. r_max) { // do something with arr[r][c] here } } The reason is that the first version access the elements in the order that they are actually stored in memory, whereas the second forces the CPU to jump between rows for each element. If that in mind, now it all makes sense for me, and of course it's consistent as well. Sorry to bother about this, but I think this will help other newcomers. Thanks again for help/tips which helped turn my mindset. Albert. You're welcome. And yes, it can definitely be confusing. I understand why the array syntax in D is the way it is, but that still doesn't always save me from mixing things up once in a while anyway.
Re: Can't add ubytes together to make a ubyte... bug or feature?
Soviet Friend píše v Út 19. 01. 2016 v 22:12 +: > I just attempted to add one ubyte to another and store the result > in a ubyte but apparently ubytes get converted to ints when being > added... and converting what becomes an int becomes impossible to > store in a ubyte without an explicit cast... > > ubyte a, b; > ubyte c = a + b; // Error: cannot implicitly convert expression > (cast(int)a + cast(int)b) of type int to ubyte > Problem is that compiler does not know that a + b would fit in ubyte. For example if a would be 200 and b would be 100 it would not fit in ubyte. But if compiler can verify it will fit it makes cast implicit. immutable ubyte a = 0; ubyte b = 0; ubyte c = a + b; or ubyte a = 0; ubyte c = a + 0; or immutable ubyte a = 1; immutable ubyte b = 5; ubyte c = a + b; works ok but immutable ubyte a = 1; ubyte b = 0; ubyte c = a + b; can't works because b could be 255 and 255 + 1 does not fit to ubyte > On principal I'm not casting to fix this. I don't care if my > computer needs to do math on a 4 byte basis, I'm not writing > assembly. I'm really hoping this is a bug because trying to use > any type other than ints is going to make for some really ugly > code otherwise... > > Can I prevent the initial implicit casts? > > > On the topic of complaining about casting... array lengths as > ulongs is painful... any chance of an array[].lengthi being a > thing? array.length is not ulong is it size_t and I do not see any problem with that, can you be more specific.
Re: Doubt - Static multidimension arrays
So guys: Ali, Mike Parker and tsbockman thanks for all your explanation, in fact looking now I and after making some tests I really got it. So: int[2]a1; // Array of 2 elements of type int int[2][5] a2; // Array of 2 elements of type int divided in 5 rows writeln(a2[0]); // = accessing row 0 = [0,0] writeln(a2[4]); // = accessing row 4 = [0,0] If that in mind, now it all makes sense for me, and of course it's consistent as well. Sorry to bother about this, but I think this will help other newcomers. Thanks again for help/tips which helped turn my mindset. Albert.
Re: core.time Duration how to get units in double/float format?
On Tuesday, January 19, 2016 14:07:50 Borislav Kosharov via Digitalmars-d-learn wrote: > On Monday, 18 January 2016 at 12:46:31 UTC, Jonathan M Davis > wrote: > > In general, using floating point values with time is an > > incredibly bad idea. It can certainly make sense when printing > > stuff out, but using it in calculations is just asking for > > trouble given all of the unnecessary imprecision that it adds. > > So, Duration does not directly support floating point values at > > all, and that's very much on purpose. I'd strongly argue that > > the fact that TickDuration does was a mistake. > > > > So, if you're doing floating point calculations with time, I'd > > strongly urge you to rethink your code. And if you're just > > trying to print out the a duration as a floating point value, > > because it's nice to view that way, then that's fine, but > > you'll need to do the conversion yourself. And it's not that > > hard. It just isn't handed to you directly, because aside from > > printing, code really shouldn't be using floating point values > > for time. e.g. > > > > string toFloatingSeconds(Duration d) > > { > > import std.conv; > > enum hnsecsPerSecond = convert!("seconds", "hnsecs")(1); > > auto s = d.split!("seconds", "hnsecs")(); > > return to!string(s.seconds + cast(real)(s.hnsecs) / > > hnsecsPerSecond); > > } > > > > And yes, that's a bit more of a pain than using to!("seconds", > > float) with TickDuration, but it's also the sort of thing that > > most code really shouldn't be doing. So, adding that > > functionality to Duration would just encourage folks to write > > buggy code. > > > > - Jonathan M Davis > > I want to use float time in a game where I call the update method > passing the delta time as float seconds. It's more easy to > multiply the dt with a speed constant meaning how much the object > will move after 1 second. Such float delta time is used in many > game engines and it's somewhat standart way of doing it. Also the > method you wrote returns a string and I need a float to multiply > it with a number. > Thanks for the reply anyway Using floating point as a delta for time is inherently buggy. Depending on what you're doing, you may get away with it, but it means that error is going to creep into your timing. And the bugs introduced by using floating point like that can be quite subtle. I would strongly urge anyone using floating point values with timing like that to rework their code to use integral values. Aside from TickDuration, all of core.time and std.datetime quite carefully avoids floating point values - even functions like convClockFreq (which converts one clock frequency to another). So, if you want to use floating point values with time stuff, that's obviously your prerogative, but Duration does not directly support it and isn't ever going to directly support it precisely because it's error-prone. - Jonathan M Davis
Re: core.time Duration how to get units in double/float format?
On Tuesday, 19 January 2016 at 15:25:58 UTC, wobbles wrote: On Tuesday, 19 January 2016 at 14:07:50 UTC, Borislav Kosharov wrote: On Monday, 18 January 2016 at 12:46:31 UTC, Jonathan M Davis wrote: [...] I want to use float time in a game where I call the update method passing the delta time as float seconds. It's more easy to multiply the dt with a speed constant meaning how much the object will move after 1 second. Such float delta time is used in many game engines and it's somewhat standart way of doing it. Also the method you wrote returns a string and I need a float to multiply it with a number. Thanks for the reply anyway Checkout out how DSFML handles this. You simply pass around a Clock object that you can restart every frame using clock.restart(); You then call your update function with update(Clock.getElapsedTime()); Then in each objects update(Time t) method you just get the time in whatever unit you want. Works pretty well. http://www.dsfml.com/ Yes that's exactly what I'm using. But they changed it to return a Duration instead of Time and that broke my code. See the source https://github.com/Jebbs/DSFML/blob/master/src/dsfml/system/clock.d#L65
Re: Functions that return type
On 01/17/2016 08:09 PM, data pulverizer wrote: On Sunday, 17 January 2016 at 02:08:06 UTC, Timon Gehr wrote: On 01/16/2016 11:50 PM, data pulverizer wrote: I guess the constraints are that of a static language. (This is not true.) Could you please explain? E.g., a few of the systems discussed at https://ncatlab.org/nlab/show/pure+type+system would be a fine basis for a "static language" that supports returning types from functions.
Re: Partial application of compile time args type deduction
On 01/19/2016 03:37 PM, QAston wrote: Hi, I have the following code: auto appendMapped(alias f, R, T)(R r, T elem) { r ~= f(elem); return r; } int minus(int i) { return -i; } unittest { int[] ar; // here I do partial application of minus function alias appendMinus(S,T) = appendMapped!(minus, S, T); assert (appendMinus!(int[], int)(ar, 10) == [-10]); // compiles assert (appendMinus(ar, 10) == [-10]); // doesn't compile } Which gives me following error: Error: template transduced.__unittestL111_2.appendMinus cannot deduce function from argument types !()(int[], int), candidates are: transduced.__unittestL111_2.appendMinus(S, T) Is there a way to do partial template arg application which does template type deduction correctly? I don't know whether it's possible with 'alias' but the following trivial wrapper works: auto appendMinus(S,T)(S s, T t) { return appendMapped!minus(s, t); } Ali
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Tue, 19 Jan 2016 23:32:57 +0100, Daniel Kozak wrote: > Soviet Friend píše v Út 19. 01. 2016 v 22:12 +: >> I just attempted to add one ubyte to another and store the result in a >> ubyte but apparently ubytes get converted to ints when being added... >> and converting what becomes an int becomes impossible to store in a >> ubyte without an explicit cast... >> >> ubyte a, b; >> ubyte c = a + b; // Error: cannot implicitly convert expression >> (cast(int)a + cast(int)b) of type int to ubyte >> >> > Problem is that compiler does not know that a + b would fit in ubyte. > For example if a would be 200 and b would be 100 it would not fit in > ubyte. But if compiler can verify it will fit it makes cast implicit. This is true for all integer types. The reason this isn't in effect for other types is that most values are small (eg array lengths), and most integer types can hold the sum of two small values. But there are plenty of small values where a [u]byte can't hold their sum.
Re: Partial application of compile time args type deduction
On 01/19/2016 04:22 PM, QAston wrote: On Wednesday, 20 January 2016 at 00:12:16 UTC, Ali Çehreli wrote: On 01/19/2016 03:37 PM, QAston wrote: Hi, I have the following code: auto appendMapped(alias f, R, T)(R r, T elem) { r ~= f(elem); return r; } int minus(int i) { return -i; } unittest { int[] ar; // here I do partial application of minus function alias appendMinus(S,T) = appendMapped!(minus, S, T); assert (appendMinus!(int[], int)(ar, 10) == [-10]); // compiles assert (appendMinus(ar, 10) == [-10]); // doesn't compile } Which gives me following error: Error: template transduced.__unittestL111_2.appendMinus cannot deduce function from argument types !()(int[], int), candidates are: transduced.__unittestL111_2.appendMinus(S, T) Is there a way to do partial template arg application which does template type deduction correctly? I don't know whether it's possible with 'alias' but the following trivial wrapper works: auto appendMinus(S,T)(S s, T t) { return appendMapped!minus(s, t); } Ali I think I've reduced my case too much: the wrapper needs to be generic so that I can do something like this (basically a closure but compile time) void wrapper(minus) { alias appendMinus(S,T) = appendMapped!(minus, S, T); assert (appendMinus(ar, 10) == [-10]); } Anyway, thanks for help Ali, love your book:) Is this it? If so, is it already in std.functional? (I could not find it. :) ) auto appendMapped(alias f, R, T)(R r, T elem) { r ~= f(elem); return r; } int minus(int i) { return -i; } unittest { int[] ar; template bindFirstParam(alias original, alias func, Args...) { auto bindFirstParam(Args...)(Args args) { return original!(func, Args)(args); } } alias appendMinus = bindFirstParam!(appendMapped, minus); assert (appendMinus!(int[], int)(ar, 10) == [-10]); // compiles assert (appendMinus(ar, 10) == [-10]); // doesn't compile } void main() { } Ali
Re: Can't add ubytes together to make a ubyte... bug or feature?
On 01/19/2016 02:12 PM, Soviet Friend wrote: > ubytes get converted to ints when being added... It's a common feature involving all integral type in languages like C, C++, and D: https://dlang.org/spec/type.html#integer-promotions > On the topic of complaining about casting... array lengths as ulongs is > painful... any chance of an array[].lengthi being a thing? That is a topic sometimes with hot debate without any resolution. Chances of it being changed in D is zero. :) Luckily, it's pretty easy in :D ;) long lengthi(T)(T[] arr) { import std.exception : enforce; import std.conv : to; // No overflow here because this comparison is performed in 'ulong' enforce(arr.length.to!ulong < long.max); return arr.length.to!long; } unittest { import std.traits; auto arr = [ 1, 2 ]; static assert(isSigned!(typeof(arr.lengthi))); assert(arr.lengthi == 2); } void main() { } Ali
Re: Functions that return type
On Sunday, 17 January 2016 at 02:08:06 UTC, Timon Gehr wrote: On 01/16/2016 11:50 PM, data pulverizer wrote: I guess the constraints are that of a static language. (This is not true.) I'm playing with the design of such a language myself. Basically, anything can create/use/return type objects, but a variable of a particular type can only be instantiated using an immutable type object whose value is known at compile time. It's not very far along, though. Right now, I have a "compiler" that parses integers and parentheses. ;)
Re: core.time Duration how to get units in double/float format?
On Monday, 18 January 2016 at 12:46:31 UTC, Jonathan M Davis wrote: In general, using floating point values with time is an incredibly bad idea. It can certainly make sense when printing stuff out, but using it in calculations is just asking for trouble given all of the unnecessary imprecision that it adds. So, Duration does not directly support floating point values at all, and that's very much on purpose. I'd strongly argue that the fact that TickDuration does was a mistake. So, if you're doing floating point calculations with time, I'd strongly urge you to rethink your code. And if you're just trying to print out the a duration as a floating point value, because it's nice to view that way, then that's fine, but you'll need to do the conversion yourself. And it's not that hard. It just isn't handed to you directly, because aside from printing, code really shouldn't be using floating point values for time. e.g. string toFloatingSeconds(Duration d) { import std.conv; enum hnsecsPerSecond = convert!("seconds", "hnsecs")(1); auto s = d.split!("seconds", "hnsecs")(); return to!string(s.seconds + cast(real)(s.hnsecs) / hnsecsPerSecond); } And yes, that's a bit more of a pain than using to!("seconds", float) with TickDuration, but it's also the sort of thing that most code really shouldn't be doing. So, adding that functionality to Duration would just encourage folks to write buggy code. - Jonathan M Davis I want to use float time in a game where I call the update method passing the delta time as float seconds. It's more easy to multiply the dt with a speed constant meaning how much the object will move after 1 second. Such float delta time is used in many game engines and it's somewhat standart way of doing it. Also the method you wrote returns a string and I need a float to multiply it with a number. Thanks for the reply anyway
Re: Doubt - Static multidimension arrays
On Tuesday, 19 January 2016 at 08:27:56 UTC, tsbockman wrote: The only relevant difference between the two, is that the order of the row and column specification is swapped in *the declaration*, not when indexing. Newcomers to D tend to think in terms of C when they declare arrays, so the confusion comes when they find out they have to index it in a way that is the reverse of what they expect. Yes, it's because the declaration syntax is different, but it's always the indexing that trips them up. That's all I meant. It usually isn't obvious what the root of the misunderstanding is until someone explains it.
Re: core.time Duration how to get units in double/float format?
On Tuesday, 19 January 2016 at 14:07:50 UTC, Borislav Kosharov wrote: On Monday, 18 January 2016 at 12:46:31 UTC, Jonathan M Davis wrote: [...] I want to use float time in a game where I call the update method passing the delta time as float seconds. It's more easy to multiply the dt with a speed constant meaning how much the object will move after 1 second. Such float delta time is used in many game engines and it's somewhat standart way of doing it. Also the method you wrote returns a string and I need a float to multiply it with a number. Thanks for the reply anyway Checkout out how DSFML handles this. You simply pass around a Clock object that you can restart every frame using clock.restart(); You then call your update function with update(Clock.getElapsedTime()); Then in each objects update(Time t) method you just get the time in whatever unit you want. Works pretty well. http://www.dsfml.com/
Re: Doubt - Static multidimension arrays
On Tuesday, 19 January 2016 at 13:00:19 UTC, Mike Parker wrote: Newcomers to D tend to think in terms of C when they declare arrays, so the confusion comes when they find out they have to index it in a way that is the reverse of what they expect. Yes, it's because the declaration syntax is different, but it's always the indexing that trips them up. That's all I meant. It usually isn't obvious what the root of the misunderstanding is until someone explains it. I guess my problem is that I'm assuming that people who've worked with C++ will understand that this: `int arr[5][10]` is *not* an "array of arrays"; my point would be clearer if I'd written this: template class Array { T data[size]; public: T& operator[](int x) { return data[x]; } }; int arr2d[5][10]; Array< Array< int, 10 >, 5 > arrOfArrs; Notice that an actual "array of arrays" declaration has the dimensions listed in the same order as D. I'd hope that expressing it this way would make it obvious to any experienced C/C++ programmer why D's declaration syntax is the way that it is. Anyway, I'll give it a rest now. I thought this way of looking at it would make things easier to understand, but I guess not...
Re: Doubt - Static multidimension arrays
On Tuesday, 19 January 2016 at 14:58:51 UTC, tsbockman wrote: Anyway, I'll give it a rest now. I thought this way of looking at it would make things easier to understand, but I guess not... In my experience, it's focusing on the types in the D array syntax, rather than the actual ordering, that helps people over the hump. The rows vs. columns bit is useful to demonstrate the difference, but the focus on types clarifies it. That's how I approached it in the section on arrays in Learning D.
Re: Can't add ubytes together to make a ubyte... bug or feature?
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.
Partial application of compile time args type deduction
Hi, I have the following code: auto appendMapped(alias f, R, T)(R r, T elem) { r ~= f(elem); return r; } int minus(int i) { return -i; } unittest { int[] ar; // here I do partial application of minus function alias appendMinus(S,T) = appendMapped!(minus, S, T); assert (appendMinus!(int[], int)(ar, 10) == [-10]); // compiles assert (appendMinus(ar, 10) == [-10]); // doesn't compile } Which gives me following error: Error: template transduced.__unittestL111_2.appendMinus cannot deduce function from argument types !()(int[], int), candidates are: transduced.__unittestL111_2.appendMinus(S, T) Is there a way to do partial template arg application which does template type deduction correctly?
Re: Partial application of compile time args type deduction
On Wednesday, 20 January 2016 at 00:12:16 UTC, Ali Çehreli wrote: On 01/19/2016 03:37 PM, QAston wrote: Hi, I have the following code: auto appendMapped(alias f, R, T)(R r, T elem) { r ~= f(elem); return r; } int minus(int i) { return -i; } unittest { int[] ar; // here I do partial application of minus function alias appendMinus(S,T) = appendMapped!(minus, S, T); assert (appendMinus!(int[], int)(ar, 10) == [-10]); // compiles assert (appendMinus(ar, 10) == [-10]); // doesn't compile } Which gives me following error: Error: template transduced.__unittestL111_2.appendMinus cannot deduce function from argument types !()(int[], int), candidates are: transduced.__unittestL111_2.appendMinus(S, T) Is there a way to do partial template arg application which does template type deduction correctly? I don't know whether it's possible with 'alias' but the following trivial wrapper works: auto appendMinus(S,T)(S s, T t) { return appendMapped!minus(s, t); } Ali I think I've reduced my case too much: the wrapper needs to be generic so that I can do something like this (basically a closure but compile time) void wrapper(minus) { alias appendMinus(S,T) = appendMapped!(minus, S, T); assert (appendMinus(ar, 10) == [-10]); } Anyway, thanks for help Ali, love your book:)