digitalmars.D - Mixed int/BigInt foreach interval
- bearophile (65/65) Sep 26 2011 In my opinion it's important to make BigInts work in most places where n...
- Paul D. Anderson (5/8) Sep 26 2011 Yes, it would be nice to allow isIntegral, isArithmetic, etc. to recogni...
- Jonathan M Davis (15/29) Sep 26 2011 change, and there changes needed in iota too, because it can't use the c...
- Timon Gehr (7/36) Sep 26 2011 The issue is that isIntegral does not actually check if the data type
- Andrej Mitrovic (7/9) Sep 26 2011 I thought it's just hardcoded:
- Timon Gehr (2/11) Sep 26 2011 Yes, of course, that is how it is implemented.
- Andrej Mitrovic (2/6) Sep 26 2011 Not *there easily could be* but *there is*. At least in my code..
- Jonathan M Davis (13/20) Sep 26 2011 What I probably meant to say was "Code could easily assume that..." but ...
- Mehrdad (4/16) Sep 26 2011 IMHO that's a pretty bad constraint check.
- Jonathan M Davis (5/24) Sep 26 2011 Why is it bad? isIntegral was specifically designed for testing that a t...
- bearophile (5/8) Sep 26 2011 Going back to my original post, is changing the semantics of isIntegral ...
- Jonathan M Davis (11/20) Sep 26 2011 No. That's foreach. BigInt isn't going to work with the .. syntax regard...
- bearophile (6/12) Sep 27 2011 I'm asking about foreach, not about iota. Fixing iota is easy, it's just...
- Jonathan M Davis (11/28) Sep 27 2011 I'd be _very_ surprised to see that happen, since BigInt is in Phobos as...
- kennytm (6/36) Sep 27 2011 foreach (a; b .. c) d; is also a lowering, and i'd say the 'int + BigI...
- bearophile (5/13) Sep 27 2011 Thank you for your answer. This was the real topic of my original post :...
- bearophile (7/9) Sep 27 2011 Multi-precision integers are important. In several languages they are ev...
- travert phare.normalesup.org (Christophe) (34/38) Sep 28 2011 It makes some time that I think the .. syntax should be improved.
- Timon Gehr (8/33) Sep 28 2011 This would probably be a breaking language change, because currently
- travert phare.normalesup.org (Christophe) (15/24) Sep 28 2011 If by breaking language change, you mean that this would break existing
- bearophile (17/24) Sep 28 2011 I'd like a function template like this to work even if T is BigInt:
- travert phare.normalesup.org (Christophe) (19/47) Sep 29 2011 That seems to be a very reasonable workarround.
- bearophile (5/10) Sep 29 2011 The threshold between compiler and library is not fully sharp. Complex n...
- Andrei Alexandrescu (7/15) Sep 26 2011 Well isIntegral was designed indeed for primitive integral types. The
- Peter Alexander (9/31) Sep 27 2011 I think this is the best route, although it is unfortunate that
- Simen Kjaeraas (9/12) Sep 26 2011 The name indicates it checks for generic integral-ness, not for built-in...
- Don (8/18) Sep 26 2011 Well, actually BigInt behaves like an integer, unlike the built-in
In my opinion it's important to make BigInts work in most places where normal ints work. I think it's even worth modifying D language a bit (if and where necessary) to allow this. Time ago I've asked to use BigInt with iota too (no D changes needed here): http://d.puremagic.com/issues/show_bug.cgi?id=6447 because currently this doesn't work (std.traits.isIntegral needs to change, and there changes needed in iota too, because it can't use the current std.traits.unsigned, because a BigInt has no ".min" field): import std.bigint, std.range; void main() { foreach (i; iota(BigInt(10))) {} } Recently I've seen another situation where foreach can't be used in generic code that works with ints. This useless reduced code shows the situation: import std.stdio, std.bigint; void foo(T)(T n) { //for (T i = 1; i < n; i++) foreach (i; 1 .. n) // line 4 writeln(i); } void main() { foo(5); foo(BigInt(5)); } The error given: test.d(4): Error: incompatible types for ((2) + (n)): 'int' and 'BigInt' This too doesn't work: import std.stdio, std.bigint; void foo(T)(T n) { foreach (T i; 1 .. n) // line 3 writeln(i); } void main() { foo(BigInt(5)); } The error: test.d(3): Error: cannot implicitly convert expression (1) of type int to BigInt And even this doesn't work: import std.stdio, std.bigint; void foo(T)(T n) { foreach (i; T(1) .. n) // line 3 writeln(i); } void main() { foo(BigInt(5)); } The error: ...\dmd2\src\phobos\std\traits.d(3312): Error: static assert "Type BigInt does not have an Unsigned counterpart" And the "int(10)" syntax is not supported in D (it is supported in Python). The sum of int and BigInt is supported, this works: import std.bigint; void main() { auto x = 1 + BigInt(1); } And this too works: import std.stdio, std.bigint; void main() { foreach (i; BigInt(1) .. BigInt(5)) writeln(i); } That foreach error message looks similar to this type unification error: import std.bigint; void main() { BigInt x = BigInt(1); auto y = true ? 1 : x; } test.d(4): Error: incompatible types for ((1) ? (x)): 'int' and 'BigInt' So is this foreach problem worth fixing? Is it fixable? Is all this fit for Bugzilla? Bye, and thank you, bearophile
Sep 26 2011
bearophile Wrote:Time ago I've asked to use BigInt with iota too (no D changes needed here): http://d.puremagic.com/issues/show_bug.cgi?id=6447 because currently this doesn't work (std.traits.isIntegral needs to change, and there changes needed in iota too, because it can't use the current std.traits.unsigned, because a BigInt has no ".min" field):Yes, it would be nice to allow isIntegral, isArithmetic, etc. to recognize library types and not just built-in types. This would be helpful for, for instance, rational numbers and decimal numbers (BigDecimal and decimal32, decimal64, decimal128. As an aside, for those who are interested, the Decimal library implementing the numbers listed above is very near completion. Just some testing and tidying to do before it can go on the review queue. Paul
Sep 26 2011
On Monday, September 26, 2011 13:47 Paul D. Anderson wrote:bearophile Wrote:change, and there changes needed in iota too, because it can't use the current std.traits.unsigned, because a BigInt has no ".min" field):Time ago I've asked to use BigInt with iota too (no D changes needed here): http://d.puremagic.com/issues/show_bug.cgi?id=6447because currently this doesn't work (std.traits.isIntegral needs toYes, it would be nice to allow isIntegral, isArithmetic, etc. to recognize library types and not just built-in types. This would be helpful for, for instance, rational numbers and decimal numbers (BigDecimal and decimal32, decimal64, decimal128. As an aside, for those who are interested, the Decimal library implementing the numbers listed above is very near completion. Just some testing and tidying to do before it can go on the review queue.I think that we need to be _very_ careful about the implications of making isIntegral and other similar traits functions work with non-primitive types. There could _easily_ be code which assumes that it's going to get primitive types when isIntegral is true. Take the integer swapping code in std.bitmanip. It would fail miserably if all of a sudden BigInt worked with isIntegral, and you tried to use BigInt with it. I can see we might want to have isIntegral work with BigInt, but I do _not_ think it's necessarily the case that it's actually a good idea. We need to be careful about the implications of all of that and make very informed decisions about the changes that we make to std.traits, or a lot of code is going to break in non-obvious ways. - Jonathan M Davis
Sep 26 2011
On 09/26/2011 11:05 PM, Jonathan M Davis wrote:On Monday, September 26, 2011 13:47 Paul D. Anderson wrote:The issue is that isIntegral does not actually check if the data type represents integers, it checks if the type is some sort of bit vector with two's complement arithmetics defined on it. Therefore, BigInt should never be included into isIntegral. But I totally agree with bearophile that some solution has to be found to make BigInt work with generic functions in Phobos.bearophile Wrote:change, and there changes needed in iota too, because it can't use the current std.traits.unsigned, because a BigInt has no ".min" field):Time ago I've asked to use BigInt with iota too (no D changes needed here): http://d.puremagic.com/issues/show_bug.cgi?id=6447because currently this doesn't work (std.traits.isIntegral needs toYes, it would be nice to allow isIntegral, isArithmetic, etc. to recognize library types and not just built-in types. This would be helpful for, for instance, rational numbers and decimal numbers (BigDecimal and decimal32, decimal64, decimal128. As an aside, for those who are interested, the Decimal library implementing the numbers listed above is very near completion. Just some testing and tidying to do before it can go on the review queue.I think that we need to be _very_ careful about the implications of making isIntegral and other similar traits functions work with non-primitive types. There could _easily_ be code which assumes that it's going to get primitive types when isIntegral is true. Take the integer swapping code in std.bitmanip. It would fail miserably if all of a sudden BigInt worked with isIntegral, and you tried to use BigInt with it. I can see we might want to have isIntegral work with BigInt, but I do _not_ think it's necessarily the case that it's actually a good idea. We need to be careful about the implications of all of that and make very informed decisions about the changes that we make to std.traits, or a lot of code is going to break in non-obvious ways. - Jonathan M Davis
Sep 26 2011
On 9/26/11, Timon Gehr <timon.gehr gmx.ch> wrote:it checks if the type is some sort of bit vector with two's complement arithmetics defined on it.I thought it's just hardcoded: template isIntegral(T) { enum bool isIntegral = staticIndexOf!(Unqual!(T), byte, ubyte, short, ushort, int, uint, long, ulong) >= 0; }
Sep 26 2011
On 09/26/2011 11:46 PM, Andrej Mitrovic wrote:On 9/26/11, Timon Gehr<timon.gehr gmx.ch> wrote:Yes, of course, that is how it is implemented.it checks if the type is some sort of bit vector with two's complement arithmetics defined on it.I thought it's just hardcoded: template isIntegral(T) { enum bool isIntegral = staticIndexOf!(Unqual!(T), byte, ubyte, short, ushort, int, uint, long, ulong)>= 0; }
Sep 26 2011
On 9/26/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:I think that we need to be _very_ careful about the implications of making isIntegral and other similar traits functions work with non-primitive types. There could _easily_ be code which assumes that it's going to get primitive types when isIntegral is true.Not *there easily could be* but *there is*. At least in my code..
Sep 26 2011
On Monday, September 26, 2011 14:13 Andrej Mitrovic wrote:On 9/26/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:What I probably meant to say was "Code could easily assume that..." but you get the idea. Certainly, there's no question that there's code out there that would be broken by such a change - including code in Phobos. So, we need to be very careful about any such changes. But since it would be easy to have a template constraint check if(isIntegral!T || is(Unqual!T == BigInt)) I don't see much benefit in making isIntegral return true for BigInt anyway. BigInt is _not_ the same as the built-in integral types. Code which uses integral types could easily not work with BigInt. Yes, there is plenty of code that could work with both, but it needs to be designed with that level of genericness in mind, and much of the code using isIntegral is _not_. - Jonathan M DavisI think that we need to be _very_ careful about the implications of making isIntegral and other similar traits functions work with non-primitive types. There could _easily_ be code which assumes that it's going to get primitive types when isIntegral is true.Not *there easily could be* but *there is*. At least in my code..
Sep 26 2011
On 9/26/2011 2:25 PM, Jonathan M Davis wrote:What I probably meant to say was "Code could easily assume that..." but you get the idea. Certainly, there's no question that there's code out there that would be broken by such a change - including code in Phobos. So, we need to be very careful about any such changes. But since it would be easy to have a template constraint check if(isIntegral!T || is(Unqual!T == BigInt)) I don't see much benefit in making isIntegral return true for BigInt anyway. BigInt is _not_ the same as the built-in integral types. Code which uses integral types could easily not work with BigInt. Yes, there is plenty of code that could work with both, but it needs to be designed with that level of genericness in mind, and much of the code using isIntegral is _not_. - Jonathan M DavisIMHO that's a pretty bad constraint check. What it should instead be is something along the lines of: isIntegral!T && isPrimitive!T
Sep 26 2011
On Monday, September 26, 2011 18:33:22 Mehrdad wrote:On 9/26/2011 2:25 PM, Jonathan M Davis wrote:Why is it bad? isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing. - Jonathan M DavisWhat I probably meant to say was "Code could easily assume that..." but you get the idea. Certainly, there's no question that there's code out there that would be broken by such a change - including code in Phobos. So, we need to be very careful about any such changes. But since it would be easy to have a template constraint check if(isIntegral!T || is(Unqual!T == BigInt)) I don't see much benefit in making isIntegral return true for BigInt anyway. BigInt is _not_ the same as the built-in integral types. Code which uses integral types could easily not work with BigInt. Yes, there is plenty of code that could work with both, but it needs to be designed with that level of genericness in mind, and much of the code using isIntegral is _not_. - Jonathan M DavisIMHO that's a pretty bad constraint check. What it should instead be is something along the lines of: isIntegral!T && isPrimitive!T
Sep 26 2011
Jonathan M Davis:Why is it bad? isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing.Going back to my original post, is changing the semantics of isIntegral enough to allow code like this to compile and run? foreach (i; 1 .. BigInt(10)) {} Bye, bearophile
Sep 26 2011
On Monday, September 26, 2011 21:49:49 bearophile wrote:Jonathan M Davis:No. That's foreach. BigInt isn't going to work with the .. syntax regardless of what isIntegral does. I assume what you're really asking is whether foreach(i; iota(1, BigInt(10))) {} would work. And the answer is definitely no. iota is too complex for simply changing isIntegral to work. For instance, CommonType would fail, because BigInt and int are not implicitly convertible between one another. I'm sure that iota could be reworked such that it could work with BigInt and work with a combination of int and BigInt, but it's definitely not as simple as simply messing around with the template constraint. - Jonathan M DavisWhy is it bad? isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing.Going back to my original post, is changing the semantics of isIntegral enough to allow code like this to compile and run? foreach (i; 1 .. BigInt(10)) {}
Sep 26 2011
Jonathan M Davis:I'm asking about foreach, not about iota. Fixing iota is easy, it's just a matter of changing Phobos. This is why at the top of my original post I have written:foreach (i; 1 .. BigInt(10)) {}No. That's foreach. BigInt isn't going to work with the .. syntax regardless of what isIntegral does. I assume what you're really asking is whetherIn my opinion it's important to make BigInts work in most places where normal ints work. I think it's even worth modifying D language a bit (if and where necessary) to allow this.The point of my post was to talk about foreach. The title of this thread is "Mixed int/BigInt foreach interval". Bye, bearophile
Sep 27 2011
On Tuesday, September 27, 2011 12:22 bearophile wrote:Jonathan M Davis:I'd be _very_ surprised to see that happen, since BigInt is in Phobos as opposed to being at the language level. Ranges could be added to foreach, because they're entirely API-based, and so the compiler doesn't have to care about what Phobos is doing. It just has to do the appropriate lowerings. But BigInt is a specific type in Phobos. Making it work with foreach would mean that the compiler would have to know and understand about BigInt. I don't expect that to ever happen. Best case, I would think that you could get it to work by having BigInt be implicitly convertible to int, but since that's a narrowing conversion, that's a _bad_ idea IMHO. - Jonathan M DavisI'm asking about foreach, not about iota. Fixing iota is easy, it's just a matter of changing Phobos. This is why at the top of my original post I have written:foreach (i; 1 .. BigInt(10)) {}No. That's foreach. BigInt isn't going to work with the .. syntax regardless of what isIntegral does. I assume what you're really asking is whetherIn my opinion it's important to make BigInts work in most places where normal ints work. I think it's even worth modifying D language a bit (if and where necessary) to allow this.The point of my post was to talk about foreach. The title of this thread is "Mixed int/BigInt foreach interval".
Sep 27 2011
"Jonathan M Davis" <jmdavisProg gmx.com> wrote:On Tuesday, September 27, 2011 12:22 bearophile wrote:foreach (a; b .. c) d; is also a lowering, and i'd say the 'int + BigInt' not able to typeCombine (statement.c:2282) a bug. By the way, the statement foreach (a; BigInt(1) .. 10) ... does compile and work, at least for the toolset from git master.Jonathan M Davis:I'd be _very_ surprised to see that happen, since BigInt is in Phobos as opposed to being at the language level. Ranges could be added to foreach, because they're entirely API-based, and so the compiler doesn't have to care about what Phobos is doing. It just has to do the appropriate lowerings. But BigInt is a specific type in Phobos. Making it work with foreach would mean that the compiler would have to know and understand about BigInt. I don't expect that to ever happen. Best case, I would think that you could get it to work by having BigInt be implicitly convertible to int, but since that's a narrowing conversion, that's a _bad_ idea IMHO. - Jonathan M DavisI'm asking about foreach, not about iota. Fixing iota is easy, it's just a matter of changing Phobos. This is why at the top of my original post I have written:foreach (i; 1 .. BigInt(10)) {}No. That's foreach. BigInt isn't going to work with the .. syntax regardless of what isIntegral does. I assume what you're really asking is whetherIn my opinion it's important to make BigInts work in most places where normal ints work. I think it's even worth modifying D language a bit (if and where necessary) to allow this.The point of my post was to talk about foreach. The title of this thread is "Mixed int/BigInt foreach interval".
Sep 27 2011
kennytm:foreach (a; b .. c) d; is also a lowering, and i'd say the 'int + BigInt' not able to typeCombine (statement.c:2282) a bug. By the way, the statement foreach (a; BigInt(1) .. 10) ... does compile and work, at least for the toolset from git master.Thank you for your answer. This was the real topic of my original post :-) Sorry for the confusion. Bye, bearophile
Sep 27 2011
It seems my original post of this thread was confused and not clear enough. In that post I have also mixed two different things (a Phobos enhancement request that doesn't require a lot of discussion, and a more complex discussion about usefulness of possible D language changes. See below). Jonathan M Davis:I'd be _very_ surprised to see that happen, since BigInt is in Phobos as opposed to being at the language level.Multi-precision integers are important. In several languages they are even built-in (like in Lisp/Scheme languages, Haskell, Python, some modern variants of Forth, and so on). I didn't ask to turn BigInts into D built-ins. What I was asking is if there are generic ideas worth changing in D language to allow a better creation and integration of library-defined multi-precision integers :-) (example: ideas like opCast(bool) are not specific to BigInts, but they allow to implement better BigInts). Maybe there are no ways to improve the situation. Bye, bearophile
Sep 27 2011
Jonathan M Davis , dans le message (digitalmars.D:145520), a écrit :It makes some time that I think the .. syntax should be improved. I wanted to make a post about that but I have done it yet. First, Range are such a part of the langage now that I think 0..10 deserves to be a Range, and not a syntax sugar for opSlice and foreach. It could be a type called int..int that behaves like iota!(int, int), and .. be an operator that takes for example two ints and return an int..int(*). | auto OpSlice(size_t, size_t); could be renamed | auto OpIndex(size_t..size_t); and we could also make overloads for multidimensional arrays: | auto OpIndex(size_t..size_t, size_t..size_t); which is IMHO much more meaningful and satisfying than: | auto OpIndex(size_t, size_t, size_t, size_t); or | auto OpSlice(size_t[2], size_t[2]); People might say this makes the langage more complicated, because we create a new type in the language. I think on the contrary that this makes the language simpler: it unifies foreach(i; 1..n), opSlice(size_t, size_t), opIndex (and iota in many cases). -- Christophe (*) Notes: - compose type like char..int should be forbidden in a way. In char a; a..1000, the char a should be promoted to int to make an int..int. - the .. operator could be overloaded for types like BigInt, like normal binary operator overloads. This overload may returned a user-defined type (that we ask to be a Range), or, alternatively, the langage could allow to have a BigInt..BigInt type, with the library being able to overload operations (empty, front, popFront, etc) on BigInt..BigInt like we can do for arrays (like: popFront(BigInt..BigInt r) { r[0] = r[0] + 1; } ).foreach (i; 1 .. BigInt(10)) {}BigInt isn't going to work with the .. syntax regardless of what isIntegral does.
Sep 28 2011
On 09/28/2011 03:33 PM, Christophe wrote:Jonathan M Davis , dans le message (digitalmars.D:145520), a écrit :This would probably be a breaking language change, because currently '..' has no operator precedence associated with it (it is just a delimiter token, much like ';'). Topic: In practice, I have never felt the need to use BigInt's as foreach iterator variables. What is the use for such a feature? I mean, eg. the following is hardly useful: foreach(i;0..BigInt("10000000000000000000000000"){}It makes some time that I think the .. syntax should be improved. I wanted to make a post about that but I have done it yet. First, Range are such a part of the langage now that I think 0..10 deserves to be a Range, and not a syntax sugar for opSlice and foreach. It could be a type called int..int that behaves like iota!(int, int), and .. be an operator that takes for example two ints and return an int..int(*). | auto OpSlice(size_t, size_t); could be renamed | auto OpIndex(size_t..size_t); and we could also make overloads for multidimensional arrays: | auto OpIndex(size_t..size_t, size_t..size_t); which is IMHO much more meaningful and satisfying than: | auto OpIndex(size_t, size_t, size_t, size_t); or | auto OpSlice(size_t[2], size_t[2]); People might say this makes the langage more complicated, because we create a new type in the language. I think on the contrary that this makes the language simpler: it unifies foreach(i; 1..n), opSlice(size_t, size_t), opIndex (and iota in many cases).foreach (i; 1 .. BigInt(10)) {}BigInt isn't going to work with the .. syntax regardless of what isIntegral does.
Sep 28 2011
Timon Gehr , dans le message (digitalmars.D:145614), a écrit :This would probably be a breaking language change, because currently '..' has no operator precedence associated with it (it is just a delimiter token, much like ';').If by breaking language change, you mean that this would break existing code, I don't think so. if we exclude the ugly case:..case: syntax, a..b can only be found between ; or ( and ), so there is no precedence issue if the precedence is low enough (although a too low precedence might not be the best place...). By the way, is there some place we can find operator's precedence in D? Anyway, I guess introducing this change would imply a lot of work, that has no real priority. But it's worth giving it a thought.Topic: In practice, I have never felt the need to use BigInt's as foreach iterator variables. What is the use for such a feature? I mean, eg. the following is hardly useful: foreach(i;0..BigInt("10000000000000000000000000"){}The copy on write behavior of BigInt makes it very poorly efficient to iterate on. In addition, I guess the compiler won't be able to optimize anything. Someone could say this is a good reason to make the .. syntax on BigInt harder to use. -- Christophe
Sep 28 2011
Timon Gehr:I mean, eg. the following is hardly useful: foreach(i;0..BigInt("10000000000000000000000000"){}I'd like a function template like this to work even if T is BigInt: T binomial(T)(T n, T k) { if (k > n/2) k = n - k; T bc = n - k + 1; foreach (i; 2 .. k+1) bc = (bc * (n - k + i)) / i; return bc; } Current workaround: use this instead of the foreach: for (T i = 2; i <= k; i++) ---------------------------- Christophe:The copy on write behavior of BigInt makes it very poorly efficient to iterate on. In addition, I guess the compiler won't be able to optimize anything. Someone could say this is a good reason to make the .. syntax on BigInt harder to use.I'd like to use BigInts often in D. So some compiler optimizations are welcome here. Bye, bearophile
Sep 28 2011
bearophile , dans le message (digitalmars.D:145640), a écrit :Timon Gehr:That seems to be a very reasonable workarround. Does foreach(i; (cast(T) 2) .. k+1) work ?I mean, eg. the following is hardly useful: foreach(i;0..BigInt("10000000000000000000000000"){}I'd like a function template like this to work even if T is BigInt: T binomial(T)(T n, T k) { if (k > n/2) k = n - k; T bc = n - k + 1; foreach (i; 2 .. k+1) bc = (bc * (n - k + i)) / i; return bc; } Current workaround: use this instead of the foreach: for (T i = 2; i <= k; i++)Christophe:BigInt is in the library, not in the language. I hardly see a way the compiler could optimize this. At the best, it could recognise that the BigInt is wasted at the end of each iteration and destroy/reuse it's content right away. Reusing can be hard, since the size of the BigInt can get bigger. The best way to optimize this is at the library level. Eventually, since iota and BigInt are in the same library, iota could provided an overload for BigInt that uses a kind of mutable BigInt. BigInt reused the Python idiom of immutable data and copy-on-write. I am not sure this is such a good idea in D, where the garbage collector is different, types are not all supposed to be immutable, and the performance expectations are higher, and optimization opportunities are different. -- ChristopheThe copy on write behavior of BigInt makes it very poorly efficient to iterate on. In addition, I guess the compiler won't be able to optimize anything. Someone could say this is a good reason to make the .. syntax on BigInt harder to use.I'd like to use BigInts often in D. So some compiler optimizations are welcome here.
Sep 29 2011
Christophe:That seems to be a very reasonable workarround. Does foreach(i; (cast(T) 2) .. k+1) work ?It seems to work. It is a variant I have not tried. Thank you. But probably I'll write a low-priority enhancement request any way.BigInt is in the library, not in the language. I hardly see a way the compiler could optimize this.The threshold between compiler and library is not fully sharp. Complex numbers will become fully library types. Associative arrays are mostly defined in D code, they have literals defined in the language. Both of them have changed their position. Hopefully D2 will add some syntax sugar to manage tuples a bit better (for their unpacking, mostly). So there are movements in both directions. Bye, bearophile
Sep 29 2011
On 9/26/11 6:49 PM, bearophile wrote:Jonathan M Davis:Well isIntegral was designed indeed for primitive integral types. The problem with having isIntegral!BigInt dilutes the meaning of isIntegral because there are significant differences between Without having thought a lot of this, my impression is we need a sort of isMonoid!(T, "+", 0) as a guard for iota. AndreiWhy is it bad? isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing.Going back to my original post, is changing the semantics of isIntegral enough to allow code like this to compile and run? foreach (i; 1 .. BigInt(10)) {} Bye, bearophile
Sep 26 2011
On 27/09/11 3:06 AM, Andrei Alexandrescu wrote:On 9/26/11 6:49 PM, bearophile wrote:I think this is the best route, although it is unfortunate that is*Integral* fails on Big*Integer*. If an integer isn't integral then I don't know what is :-) isIntegral should have been called isIntegralPrimitive or isMachineInteger or something along those lines if that was what it was designed for. I guess it's too late for that now. Or could it be deprecated then re-purposed at the end of the deprecation period?Jonathan M Davis:Well isIntegral was designed indeed for primitive integral types. The problem with having isIntegral!BigInt dilutes the meaning of isIntegral because there are significant differences between Without having thought a lot of this, my impression is we need a sort of isMonoid!(T, "+", 0) as a guard for iota. AndreiWhy is it bad? isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing.Going back to my original post, is changing the semantics of isIntegral enough to allow code like this to compile and run? foreach (i; 1 .. BigInt(10)) {} Bye, bearophile
Sep 27 2011
On Tue, 27 Sep 2011 03:38:11 +0200, Jonathan M Davis <jmdavisProg gmx.com> wrote:isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing.The name indicates it checks for generic integral-ness, not for built-in types. Given that changing isIntegral is likely to break a lot of code (is it?), perhaps we should also add behavesLikeIntegral, which checks for behavior instead of concrete types. -- Simen
Sep 26 2011
On 27.09.2011 04:08, Simen Kjaeraas wrote:On Tue, 27 Sep 2011 03:38:11 +0200, Jonathan M Davis <jmdavisProg gmx.com> wrote:Well, actually BigInt behaves like an integer, unlike the built-in types, which don't <g>. BigInt and the built-ins have quite different semantics. But there is also a substantial overlap. We definitely need some generic check for that common subset of functionality. Another interesting case is a FixedLengthInt, which follows the same arithmetic as the built-in types, but isn't built-in.isIntegral was specifically designed for testing that a type was one of byte, ubyte, short, ushort, int, uint, long, and ulong, and that's exactly what it's doing.The name indicates it checks for generic integral-ness, not for built-in types. Given that changing isIntegral is likely to break a lot of code (is it?), perhaps we should also add behavesLikeIntegral, which checks for behavior instead of concrete types.
Sep 26 2011