digitalmars.D - foreach and filter
- Russel Winder (41/41) Apr 11 2012 Doing something along the lines of:
- Jakob Ovrum (10/46) Apr 11 2012 An array/slice has indirection, you can't implicitly convert it
- Russel Winder (44/47) Apr 16 2012 [...]
- Timon Gehr (2/34) Apr 16 2012 Have you filed a bug report against Phobos for this?
- Russel Winder (13/14) Apr 16 2012 Not as yet, after lunch 'twill be done.
- Simen Kjaeraas (17/24) Apr 11 2012 The answer to #1 is easy. Nothing is implicitly castable to immutable.
- Jakob Ovrum (10/25) Apr 11 2012 Value types with no indirection are implicitly convertible to
- bearophile (13/22) Apr 11 2012 And far more, even with immutable reference types, in this
- Jakob Ovrum (13/27) Apr 11 2012 I mentioned this as a side-note in my other reply in the thread.
- Timon Gehr (7/15) Apr 12 2012 popFront cannot be const. (And Phobos is not very const correct
- Steven Schveighoffer (7/16) Apr 12 2012 It's implied pure if filter is pure. Templates are auto-pure if all the...
- Timon Gehr (2/18) Apr 12 2012 Yes, that is what I meant.
- Jonathan M Davis (9/18) Apr 12 2012 Probably a result of various array-related stuff which should be pure bu...
Doing something along the lines of: const a =3D array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const. Question 2 is why I can't do: const a =3D filter! ... ; foreach ( i ; a ) { ... } if I try this I get messages along the lines of: ./signatures_sequential.d(33): Error: function signatures_sequential.main.f= ilter!(delegate system bool(string item) { return isDir(cast(const(char[]))item); } ).filter!(const(immutable(char)[])[]).filter.Result.empty () is not callabl= e using argument types () ./signatures_sequential.d(33): Error: function signatures_sequential.main.f= ilter!(delegate system bool(string item) { return isDir(cast(const(char[]))item); } ).filter!(const(immutable(char)[])[]).filter.Result.popFront () is not call= able using argument types () ./signatures_sequential.d(33): Error: function signatures_sequential.main.f= ilter!(delegate system bool(string item) { return isDir(cast(const(char[]))item); } ).filter!(const(immutable(char)[])[]).filter.Result.front () is not callabl= e using argument types () which, it has to be said, isn't exactly informative to the user. Thanks. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Apr 11 2012
On Wednesday, 11 April 2012 at 16:08:25 UTC, Russel Winder wrote:Doing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const.An array/slice has indirection, you can't implicitly convert it to immutable. (IIRC, there is actually an exception for the return type of strongly pure functions, but your instantiation of 'array' is evidently not pure enough)Question 2 is why I can't do: const a = filter! ... ; foreach ( i ; a ) { ... } if I try this I get messages along the lines of: ./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate system bool(string item) { return isDir(cast(const(char[]))item); } ).filter!(const(immutable(char)[])[]).filter.Result.empty () is not callable using argument types () ./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate system bool(string item) { return isDir(cast(const(char[]))item); } ).filter!(const(immutable(char)[])[]).filter.Result.popFront () is not callable using argument types () ./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate system bool(string item) { return isDir(cast(const(char[]))item); } ).filter!(const(immutable(char)[])[]).filter.Result.front () is not callable using argument types () which, it has to be said, isn't exactly informative to the user.Ranges are iterated in-place. You can't mutate a const range, hence you cannot advance it by one (`popFront`), which is required by the lowering of foreach using the range interface.Thanks.You should be using the D.learn group for these questions.
Apr 11 2012
On Wed, 2012-04-11 at 18:32 +0200, Jakob Ovrum wrote: [...]Ranges are iterated in-place. You can't mutate a const range,=20 hence you cannot advance it by one (`popFront`), which is=20 required by the lowering of foreach using the range interface.[...] I think I am still trying to recover from the shock of this; it is very likely to turn anyone interested in any form of declarative expression away from D. Also the internal activity is being exposed at the API level. Not to mention the history of iteration being one of working with mutable object on immutable structures. Trying to create the smallest possible example: auto r =3D iota ( 0 , 10 ) ; writeln ( map ! ( i =3D> i * i ) ( r ) ) ; works fine. Let us try: const r =3D iota ( 0 , 10 ) ; writeln ( map ! ( i =3D> i * i ) ( r ) ) ; works fine. Great. Now=20 auto r =3D iota ( 0 , 10 ) ; writeln ( reduce ! ( ( a, b ) =3D> a + b ) ( 10 , r ) ) ; works fine. Let's try: const r =3D iota ( 0 , 10 ) ; writeln ( reduce ! ( ( a, b ) =3D> a + b ) ( 10 , r ) ) ; Oh dear: /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos/std/algorit= hm.d(725): Error: function std.range.iota!(int,int).iota.Result.popFront ()= is not callable using argument types () /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos/std/algorit= hm.d(725): Error: function std.range.iota!(int,int).iota.Result.front () is= not callable using argument types () example.d(7): Error: template instance example.main.reduce!(__lambda3).redu= ce!(int,const(Result)) error instantiating Not only is the error message incomprehensible to someone who doesn't know the details of the internal workings (OK not a killer blow), but the very inconsistency of behaviour between map and reduce is a violation of the Principle of Least Surprise, and seems like a killer blow. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Apr 16 2012
On 04/16/2012 01:20 PM, Russel Winder wrote:On Wed, 2012-04-11 at 18:32 +0200, Jakob Ovrum wrote: [...]Have you filed a bug report against Phobos for this?Ranges are iterated in-place. You can't mutate a const range, hence you cannot advance it by one (`popFront`), which is required by the lowering of foreach using the range interface.[...] I think I am still trying to recover from the shock of this; it is very likely to turn anyone interested in any form of declarative expression away from D. Also the internal activity is being exposed at the API level. Not to mention the history of iteration being one of working with mutable object on immutable structures. Trying to create the smallest possible example: auto r = iota ( 0 , 10 ) ; writeln ( map ! ( i => i * i ) ( r ) ) ; works fine. Let us try: const r = iota ( 0 , 10 ) ; writeln ( map ! ( i => i * i ) ( r ) ) ; works fine. Great. Now auto r = iota ( 0 , 10 ) ; writeln ( reduce ! ( ( a, b ) => a + b ) ( 10 , r ) ) ; works fine. Let's try: const r = iota ( 0 , 10 ) ; writeln ( reduce ! ( ( a, b ) => a + b ) ( 10 , r ) ) ; Oh dear: /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos/s d/algorithm.d(725): Error: function std.range.iota!(int,int).iota.Result.popFront () is not callable using argument types () /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos/s d/algorithm.d(725): Error: function std.range.iota!(int,int).iota.Result.front () is not callable using argument types () example.d(7): Error: template instance example.main.reduce!(__lambda3).reduce!(int,const(Result)) error instantiating Not only is the error message incomprehensible to someone who doesn't know the details of the internal workings (OK not a killer blow), but the very inconsistency of behaviour between map and reduce is a violation of the Principle of Least Surprise, and seems like a killer blow.
Apr 16 2012
On Mon, 2012-04-16 at 14:58 +0200, Timon Gehr wrote: [...]Have you filed a bug report against Phobos for this?Not as yet, after lunch 'twill be done. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Apr 16 2012
On Wed, 11 Apr 2012 18:08:14 +0200, Russel Winder <russel winder.org.uk> wrote:Doing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const. Question 2 is why I can't do: const a = filter! ... ; foreach ( i ; a ) { ... }popFront cannot be const. I have (long ago, probably not usable in this day and age), written an implementation of tail const for ranges, but it is invasive[1]. For now, the solution is simply to not use const/immutable with ranges other than arrays. Some solution really should be created for this problem. One simple solution would be for all ranges to support opSlice with an empty parameter list, which would return a non-const version of the range. The problems are: 1. The elements should still be const. 2. If this range wraps another range, that other range should also be sliced, and so on. [1]http://d.puremagic.com/issues/show_bug.cgi?id=5377
Apr 11 2012
On Wednesday, 11 April 2012 at 16:33:42 UTC, Simen Kjaeraas wrote:On Wed, 11 Apr 2012 18:08:14 +0200, Russel Winder <russel winder.org.uk> wrote:Value types with no indirection are implicitly convertible to immutable. ----------- void main() { int a = 2; immutable int b = a; } -----------Doing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const. Question 2 is why I can't do: const a = filter! ... ; foreach ( i ; a ) { ... }immutable.
Apr 11 2012
Jakob Ovrum:Value types with no indirection are implicitly convertible to immutable. ----------- void main() { int a = 2; immutable int b = a; } -----------And far more, even with immutable reference types, in this program 'a' has to be immutable, no just const: int[] foo(immutable int[] a) pure { return a.dup; } void main() { immutable b = foo([1, 2]); } There is the desire to extend this idea a bit more, I think Hara has something on this. Bye, bearophile
Apr 11 2012
On Wednesday, 11 April 2012 at 17:00:43 UTC, bearophile wrote:Jakob Ovrum:I mentioned this as a side-note in my other reply in the thread. It's a truly neat feature which I feel has much potential, I hope to see some compelling use-cases with standard library functions in the future as Phobos becomes more pure-correct. If the parameter to `array` in the original problem had presented a pure interface, he should have been able to get an immutable result like he tried initially thanks to this feature and pure inference, which is exciting to think about. Of course, it's useless in this particular case as his parameter to `array` cannot have a pure interface (it's lazily evaluated, right?), and secondly, an immutable range is not usable with foreach.Value types with no indirection are implicitly convertible to immutable. ----------- void main() { int a = 2; immutable int b = a; } -----------And far more, even with immutable reference types, in this program 'a' has to be immutable, no just const: -snip-
Apr 11 2012
On 04/11/2012 06:08 PM, Russel Winder wrote:Doing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const.'array' is not pure for some reason. This should be fixed.Question 2 is why I can't do: const a = filter! ... ; foreach ( i ; a ) { ... }popFront cannot be const. (And Phobos is not very const correct anyways). You can try auto a = filter!foo(cast(const)data); foreach( i ; a ) { ... } (Assuming data is a built-in array slice)
Apr 12 2012
On Thu, 12 Apr 2012 13:44:36 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:On 04/11/2012 06:08 PM, Russel Winder wrote:It's implied pure if filter is pure. Templates are auto-pure if all the functions they call are pure. array should not be specifically marked pure. This may be what you meant (i.e. it's not being implied as pure), but I want to be clear what it *should* be. -SteveDoing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const.'array' is not pure for some reason. This should be fixed.
Apr 12 2012
On 04/12/2012 08:08 PM, Steven Schveighoffer wrote:On Thu, 12 Apr 2012 13:44:36 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:Yes, that is what I meant.On 04/11/2012 06:08 PM, Russel Winder wrote:It's implied pure if filter is pure. Templates are auto-pure if all the functions they call are pure. array should not be specifically marked pure. This may be what you meant (i.e. it's not being implied as pure), but I want to be clear what it *should* be. -SteveDoing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const.'array' is not pure for some reason. This should be fixed.
Apr 12 2012
On Thursday, April 12, 2012 19:44:36 Timon Gehr wrote:On 04/11/2012 06:08 PM, Russel Winder wrote:Probably a result of various array-related stuff which should be pure but isn't (e.g. Appender and some of what's in object_.d), but I'd have to go dig through the implementation to see. We have some pull requests though that should improve that situation for 2.060, and a number of them _must_ be sorted out for 2.060, because we're looking at making toString pure, and too many string-related functions (particularly format, text, and to) can't be pure yet for that to work. - Jonathan M DavisDoing something along the lines of: const a = array ( filter! ... ) ; foreach ( i ; a ) { ... } works fine. Question 1 though is why I can't use immutable here, why I have to use const.'array' is not pure for some reason. This should be fixed.
Apr 12 2012