digitalmars.D.learn - Supporting inout haystack in array-overload of findSplitBefore without
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (104/104) Oct 27 2019 Is it possible to make this array-overload of findSplitBefore
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (61/73) Oct 27 2019 A non-templated and less bloated but still suboptimal solution is
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (71/79) Oct 27 2019 Made it work! :)
Is it possible to make this array-overload of findSplitBefore support `inout`-qualified `haystack` parameter and return type without using a templated `Result`? auto findSplitBefore(T)(scope const T[] haystack, // TODO support inout? scope const T needle) { struct Result { private alias Haystack = typeof(haystack); private Haystack _haystack; private size_t _offset; inout(Haystack) pre() inout trusted { return _haystack.ptr[0 .. _offset]; } inout(Haystack) post() inout trusted { if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[_offset .. _haystack.length]; } bool opCast(T : bool)() const { return !_isMiss; } private bool _isMiss() const { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return Result(haystack, offset); } } return Result(haystack, haystack.length); } /// safe pure nothrow nogc unittest { const r = "a*b".findSplitBefore('*'); assert(r); assert(r.pre == "a"); assert(r.post == "*b"); } This is my attempt so far auto findSplitAfter(T)(scope inout(T)[] haystack, // TODO support inout? scope const T needle) trusted { struct Result { private T[] _haystack; private size_t _offset; inout(T)[] pre() inout trusted { if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } inout(T)[] post() inout trusted { if (_isMiss) { return _haystack[0 .. $]; } return _haystack.ptr[_offset + 1 .. _haystack.length]; } bool opCast(T : bool)() const trusted { return !_isMiss; } private bool _isMiss() const trusted { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return inout(Result)(haystack, offset); } } return inout(Result)(haystack, haystack.length); } /// safe pure nothrow nogc unittest { const r = "a*b".findSplitAfter('*'); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); } which results in the following interesting compiler error: array_algorithm.d(506,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function assert(r.pre == "a*"); ^ array_algorithm.d(507,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function assert(r.post == "b"); ^ array_algorithm.d(514,5): Error: static assert: `is(typeof(r.pre()) == const(char)[])` is false static assert(is(typeof(r.pre()) == const(char)[]));
Oct 27 2019
On Sunday, 27 October 2019 at 14:29:01 UTC, Per Nordlöw wrote:which results in the following interesting compiler error: array_algorithm.d(506,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function assert(r.pre == "a*"); ^ array_algorithm.d(507,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function assert(r.post == "b"); ^ array_algorithm.d(514,5): Error: static assert: `is(typeof(r.pre()) == const(char)[])` is false static assert(is(typeof(r.pre()) == const(char)[]));A non-templated and less bloated but still suboptimal solution is to defined inlined overloads for the member functions, this case `pre()`: auto findSplitAfter_inout(T)(scope inout(T)[] haystack, scope const T needle) trusted { static struct Result { private T[] _haystack; private size_t _offset; auto pre() trusted { pragma(inline, true); if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } auto pre() const trusted { pragma(inline, true); if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } auto pre() immutable trusted { pragma(inline, true); if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } auto post() const trusted { if (_isMiss) { return _haystack[0 .. $]; } return _haystack.ptr[_offset + 1 .. _haystack.length]; } bool opCast(T : bool)() const { return !_isMiss; } private bool _isMiss() const { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return inout(Result)(haystack, offset); } } return inout(Result)(haystack, haystack.length); } /// safe pure nothrow nogc unittest { auto r = "a*b".findSplitAfter_inout('*'); static assert(is(typeof(r.pre()) == string)); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); }
Oct 27 2019
On Sunday, 27 October 2019 at 14:57:29 UTC, Per Nordlöw wrote:safe pure nothrow nogc unittest { auto r = "a*b".findSplitAfter_inout('*'); static assert(is(typeof(r.pre()) == string)); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); }Made it work! :) /** Array-overload for `findSplitAfter` with default predicate. * * See_Also: https://forum.dlang.org/post/dhxwgtaubzbmjaqjmnmq forum.dlang.org */ auto findSplitAfter(T)(scope inout(T)[] haystack, // TODO support inout? See_Also: https://forum.dlang.org/post/jtpchtddgenhjuwhqdsq forum.dlang.org scope const T needle) trusted { static struct Result { private T[] _haystack; private size_t _offset; pragma(inline, true): inout(T)[] pre() trusted inout { if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } inout(T)[] post() trusted inout { if (_isMiss) { return _haystack[0 .. $]; } return _haystack.ptr[_offset + 1 .. _haystack.length]; } bool opCast(T : bool)() const { return !_isMiss; } private bool _isMiss() const { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return inout(Result)(haystack, offset); } } return inout(Result)(haystack, haystack.length); } /// safe pure nothrow nogc unittest { char[] haystack; auto r = haystack.findSplitAfter('*'); static assert(is(typeof(r.pre()) == char[])); static assert(is(typeof(r.post()) == char[])); } /// safe pure nothrow nogc unittest { const(char)[] haystack; auto r = haystack.findSplitAfter('*'); static assert(is(typeof(r.pre()) == const(char)[])); static assert(is(typeof(r.post()) == const(char)[])); } /// safe pure nothrow nogc unittest { auto r = "a*b".findSplitAfter('*'); static assert(is(typeof(r.pre()) == string)); static assert(is(typeof(r.post()) == string)); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); }
Oct 27 2019