Bug 16034 – map should be possible with a reference only
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2016-05-17T12:31:17Z
Last change time
2022-09-20T13:27:47Z
Keywords
pull
Assigned to
No Owner
Creator
Seb
Comments
Comment #0 by greensunny12 — 2016-05-17T12:31:17Z
the following doesn't work:
void main()
{
struct One
{
int entry = 1;
@disable this(this);
}
One[] ones = [One(), One()];
import std.algorithm.iteration: map;
import std.algorithm.comparison: equal;
assert(ones.map!`a.entry + 1`.equal([2, 2]));
}
foo.d(12): Error: template std.algorithm.iteration.map!"a.entry + 1".map cannot deduce function from argument types !()(One[]), candidates are:
/usr/include/dlang/dmd/std/algorithm/iteration.d(450): std.algorithm.iteration.map!"a.entry + 1".map(Range)(Range r) if (isInputRange!(Unqual!Range))
(It doesn't matter whether string or real lambda are used)
Comment #1 by ag0aep6g — 2016-05-17T12:52:57Z
Underlying issue: isInputRange!(One[]) is false.
Comment #2 by petar.p.kirov — 2016-05-19T11:39:07Z
IMO, the language limitation that ref is not part of the type (but is instead only a storage class), prevents making ranges work (among other things) work with non-copyable types.
If that wasn't the case ElementType!(One[]) could return ref(One), and you could use map with a lambda whose paramter is ref(One).
Comment #3 by snarwin+bugzilla — 2022-09-18T21:27:49Z
The problem is not the lambda's parameter, but its return value.
Essentially, we would like the lambda to return by `ref` when `r.front` returns by `ref`, so that it does not create an unnecessary copy. For a normal function, the solution would be to use `auto ref`, but the lambda syntax does not support this (issue 21243), so we must either fix that issue first or find a workaround.
One workaround is to use a string mixin, like this:
private enum getFrontLambda = q{(return ref R r) => r.front};
enum bool isInputRange(R) =
/* ... */
&& (
is(typeof(mixin("ref ", getFrontLambda)))
|| is(typeof(mixin(getFrontLambda)))
)
/* ... */
This essentially replicates the logic of inferring `ref` in user code: attempt to compile with `ref`, then fall back to non-`ref` if it fails.
Comment #4 by dlang-bot — 2022-09-19T16:26:47Z
@jamesragray updated dlang/phobos pull request #8573 "Fix issue 16034: map should be possible with a reference only" fixing this issue:
- Fix issue 16034: map should be possible with a reference only
https://github.com/dlang/phobos/pull/8573
Comment #5 by dlang-bot — 2022-09-20T13:27:47Z
dlang/phobos pull request #8573 "Fix issue 16034: map should be possible with a reference only" was merged into master:
- 41959deae627dba93a88f6c59ec9200d35684106 by james:
Fix issue 16034: map should be possible with a reference only
https://github.com/dlang/phobos/pull/8573