On Fri, Oct 24, 2014 at 09:56:18PM +0000, "Nordlöw" via Digitalmars-d-learn 
wrote:
> I would appreciate comments on my palindrome predicate function
> 
> bool isPalindrome(R)(in R range) @safe pure
>     if (isBidirectionalRange!(R))
> {
>     import std.range: retro, take;
>     import std.algorithm: equal;
>     static if (hasLength!R)
>     {
>         const mid = range.length/2; // too long for string
>         return equal(range.retro.take(mid),
>                      range.take(mid));
>     }
>     else
>     {
>         return range.retro.equal(range);
>     }
> }
[...]

I'd just do it the simple way using range primitives:

        bool isPalindrome(R)(in R range)
                if (isBidirectionalRange!R)
        {
                auto r = range.save;
                while (!r.empty)
                {
                        if (r.front != r.back)
                                return false;
                        r.popFront();
                        r.popBack();
                }
                return true;
        }

This is guaranteed to work on all bidirectional ranges in single-pass,
handles odd/even lengths correctly, and doesn't depend on .length.

Offhand remark: in general you shouldn't annotate template functions
with @safe or pure. Instead, let the compiler infer those attributes,
and use @safe/pure unittests with known @safe/pure ranges to ensure your
code itself doesn't introduce any un-@safe or impure operations.
Otherwise, your function cannot be used with a range that has un-@safe
or impure range methods.


T

-- 
Государство делает вид, что платит нам зарплату, а мы делаем вид, что работаем.

Reply via email to