Comment #0 by jrdemail2000-dlang — 2017-09-17T20:34:41Z
Documentation for findSplit says:
---------------------------------
Returns:
A sub-type of Tuple!() of the split portions of haystack (see above for details). This sub-type of Tuple!() has opCast defined for bool. This opCast returns true when the separating needle was found (!result[1].empty) and false otherwise. This enables the convenient idiom shown in the following example.
Example
if (const split = haystack.findSplit(needle))
{
doSomethingWithSplit(split);
}
---------------------------------
However, the example fails to compile with the error message:
Error: mutable method std.algorithm.searching.findSplit!("a == b", string, string).findSplit.Result!(string, string).Result.opCast!bool.opCast is not callable using a const object
Changing the example to use 'auto' rather than 'const' works. There is no unit test of this capability. It does not appear to be a regression, the same error occurs with DMD 2.072.2 through 2.076.0-dirty.
I didn't try it, but declaring the opCast const (and perhaps pure, nothrow, @nogc) would make the example work. Otherwise, the documentation should be change. A unit test would also be appropriate.
This also applies to the sibling functions findSplitBefore and findSplitAfter.
Comment #1 by dunkyp — 2017-09-21T11:17:47Z
Created attachment 1659
test case without described behaviour
I tried to reproduce your issue but couldn't using DMD64 v2.076.0 on mac OS. I've attached my test code to ensure I'm testing the same thing you are.
Comment #2 by jrdemail2000-dlang — 2017-09-21T17:02:01Z
(In reply to Duncan Paterson from comment #1)
> Created attachment 1659 [details]
> test case without described behaviour
>
> I tried to reproduce your issue but couldn't using DMD64 v2.076.0 on mac OS.
> I've attached my test code to ensure I'm testing the same thing you are.
Here's the full test case I used:
--------------------------------
import std.stdio;
import std.algorithm : findSplit;
void main(string[] args)
{
if (args.length <= 1)
writeln("Provide an arg with an 'X' in it.");
else if (const split = args[1].findSplit("X"))
writefln("Before: '%s'; After: '%s'", split[0], split[2]);
else
writefln("No X in '%s'", args[1]);
}
----------------------------------
The 'else if' line generates the compile error. It's the combination of declaring 'split' const and 'if' invoking the 'bool opCast(T : bool)()' operator, which is not declared const. Declaring 'split' as auto works fine. Declaring 'split' const, but not invoking the opCast operator is also fine.
Comment #3 by dunkyp — 2017-09-21T23:53:01Z
Played with this for a while tonight. It seems like the problem is the empty function on a lot of ranges not being defined const. I've written a patch but I think the knock on of this is quite severe so it's probably not worth pushing.
Comment #4 by jrdemail2000-dlang — 2017-09-22T00:33:35Z
(In reply to Duncan Paterson from comment #3)
> Played with this for a while tonight. It seems like the problem is the empty
> function on a lot of ranges not being defined const. I've written a patch
> but I think the knock on of this is quite severe so it's probably not worth
> pushing.
That does make it harder! Perhaps too hard. For example, it might not be pragmatic to ask that user defined ranges declare 'empty' as const.
Perhaps the better step for now is to simply change the documentation. This could be done by changing "const" to "auto" in the example:
------------------
if (const split = haystack.findSplit(needle))
{
doSomethingWithSplit(split);
}
------------------
Comment #5 by jrdemail2000-dlang — 2017-10-01T20:57:58Z