Bug 11252 – "in" operator for std.range.iota

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-14T02:47:58Z
Last change time
2019-12-25T12:01:34Z
Assigned to
No Owner
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2013-10-14T02:47:58Z
In Python sometimes I have code like this that I'd like to translate to D, it contains a pattern that was forbidden in D: if (... and 1 < foo(2) < 10 and ...): ... If the call to foo() is not pure or you don't want the risk of calling it two times, in D you have to split that if() in two and use an extra variable: if (...) { const temp = foo(2); if (temp > 1 && temp < 10 && ...) { ... } } To avoid some of such problems I suggest to add the support for the "in" operator to iota(): if (... && foo(2) in iota(1, 11) && ...) { ... } In another ehnancement request I've suggested to support the "[]" syntax in iota(): if (... && foo(2) in iota!"[]"(1, 10) && ...) { ... } This usage of iota is useful only for numerical intervals, so it doesn't cover all usages of the Python x<y<z syntax, but I think it covers most of my translations from Python.
Comment #1 by jack — 2015-08-22T19:00:59Z
This enhancement request makes no sense, as the "in" operator in Python and D do two completely different things. To replicate the Python behavior, you can do the following: import std.stdio, std.range, std.algorithm.searching; void main() { if (iota(1, 10).countUntil(foo(2)) > -1) { "yes".writeln; } } But I don't see why you would want to, as this is much faster: void main() { immutable int temp = foo(2); if (temp >= 1 && temp <= 10) { "yes".writeln; } }
Comment #2 by ag0aep6g — 2015-09-03T13:58:06Z
(In reply to Jack Stouffer from comment #1) > This enhancement request makes no sense, as the "in" operator in Python and > D do two completely different things. > > To replicate the Python behavior, you can do the following: > > import std.stdio, std.range, std.algorithm.searching; > > void main() { > if (iota(1, 10).countUntil(foo(2)) > -1) { > "yes".writeln; > } > } > > But I don't see why you would want to, as this is much faster: > > void main() { > immutable int temp = foo(2); > if (temp >= 1 && temp <= 10) { > "yes".writeln; > } > } The request is not for Python's `in`. The request is for a succinct way to do what Python's `1 < foo(2) < 10` does. The suggested solution with D's `in` would of course not do a linear search. Reopening.
Comment #3 by issues.dlang — 2015-09-04T19:50:18Z
in must be no worse than O(log n) or it is inappropriate to use it. And given how iota works, that can't possibly be done in anything better than O(n) in the general case, though it would be possible to implement it for integers specifically. Honestly though, this seems like an abuse of the in operator to me. in is really intended for lookup in containers. It's definitely not a range operation. A better alternative would be to add find/canFind as a member function to iota in the cases where it would be more efficient than the std.algorithm implementation. Then any code which uses find/canFind with UFCS with iota and integral values would get a performance boost (including in generic code) rather than just this specific case where the code is specifically written for iota.
Comment #4 by bearophile_hugs — 2015-09-18T09:06:48Z
(In reply to Jonathan M Davis from comment #3) > Honestly though, this seems like an abuse of the in > operator to me. in is really intended for lookup in containers. It's > definitely not a range operation. There's a very nice "in" operator in D, that most other languages miss, and it's quite under-used, mostly for irrational reasons. > in must be no worse than O(log n) or it is inappropriate to use it. And > given how iota works, that can't possibly be done in anything better than > O(n) in the general case, though it would be possible to implement it for > integers specifically. I agree. One solution is to not compile the "in" if the search is slower than O(log n), but it doesn't sound very nice. > A better alternative would be to add find/canFind as a member function to iota Using "in" for ranges like iota is more natural (here "natural" means that it requires the programmer to remember less things) than using find/canFind, but they seem acceptable.
Comment #5 by github-bugzilla — 2017-08-03T14:03:14Z
Commits pushed to master at https://github.com/dlang/phobos https://github.com/dlang/phobos/commit/80d1e84453e5a8c20ef53fd459ce641ca8df0d4e Issue 11252 - In operator requested for std.range.iota https://github.com/dlang/phobos/commit/017ca067e668546a5df0d5b45442e44ee225f266 Merge pull request #5629 from dukc/11252 Issue 11252 - In operator requested for std.range.iota merged-on-behalf-of: Jack Stouffer <[email protected]>
Comment #6 by github-bugzilla — 2017-08-16T13:24:33Z
Commits pushed to stable at https://github.com/dlang/phobos https://github.com/dlang/phobos/commit/80d1e84453e5a8c20ef53fd459ce641ca8df0d4e Issue 11252 - In operator requested for std.range.iota https://github.com/dlang/phobos/commit/017ca067e668546a5df0d5b45442e44ee225f266 Merge pull request #5629 from dukc/11252
Comment #7 by github-bugzilla — 2018-01-05T13:31:01Z
Commits pushed to dmd-cxx at https://github.com/dlang/phobos https://github.com/dlang/phobos/commit/80d1e84453e5a8c20ef53fd459ce641ca8df0d4e Issue 11252 - In operator requested for std.range.iota https://github.com/dlang/phobos/commit/017ca067e668546a5df0d5b45442e44ee225f266 Merge pull request #5629 from dukc/11252