Thread overview
How to get type returned by e.g. std.algorithm.iteration.filter
May 19, 2019
Christian Köstlin
May 19, 2019
Jacob Carlborg
May 19, 2019
Christian Köstlin
May 19, 2019
Christian Köstlin
May 19, 2019
I would like to join several sorted files into one big sorted file.

For that I came up with this snippet:

#!/usr/bin/env rdmd
import std.stdio;
import std.algorithm;
import std.typecons;
import std.array;
import std.range;

auto byMinimum(Ranges)(Ranges ranges)
{
    auto getNonEmpty()
    {
        return ranges.filter!("!a.empty");
    }

    auto nonEmpty = getNonEmpty;
    struct ByMinimum(Ranges)
    {
        bool empty()
        {
            return nonEmpty.empty;
        }

        auto front()
        {
            auto minRangeAndLine = nonEmpty.map!(range => tuple!("range",
                    "line")(range, range.front)).minElement!("a.line");
            return minRangeAndLine;
        }

        void popFront()
        {
            auto minRangeAndLine = nonEmpty.map!(range => tuple!("range",
                    "line")(range, range.front)).minElement!("a.line");
            minRangeAndLine.range.popFront;
            nonEmpty = getNonEmpty;
        }
    }

    return ByMinimum!(Ranges)();
}

void main(string[] files)
{
    foreach (n; files[1 .. $].map!(name => File(name).byLine(No.keepTerminator)).array.byMinimum)
    {
        writeln(n.line);
    }
}


I would like to get rid of the duplication that searches for the range with the next minimum in terms of runtime but also in terms of code written out. Unfortunately I have no idea how to even store the result of this search in an attribute of ByMinimum, as I cannot writeout its type.

Kind regards,
Christian

May 19, 2019
On 2019-05-19 15:36, Christian Köstlin wrote:

> Unfortunately I have no idea how to even store the result of this search in an attribute of ByMinimum, as I cannot writeout its type.

In general you can use `typeof(<expression>)`, where `<expression>` is the expression you want to get the type of.

-- 
/Jacob Carlborg
May 19, 2019
On 19.05.19 20:38, Jacob Carlborg wrote:
> On 2019-05-19 15:36, Christian Köstlin wrote:
> 
>> Unfortunately I have no idea how to even store the result of this search in an attribute of ByMinimum, as I cannot writeout its type.
> 
> In general you can use `typeof(<expression>)`, where `<expression>` is the expression you want to get the type of.
> 
Thanks for the hint. The best I could come up with this is:

#!/usr/bin/env rdmd
import std.stdio;
import std.algorithm;
import std.typecons;
import std.array;
import std.range;
import std.traits;

auto byMinimum(Ranges)(Ranges ranges)
{
    auto getNonEmpty()
    {
        return ranges.filter!("!a.empty");
    }

    auto minimumOfRanges(Ranges)(Ranges ranges) {
        // dfmt off
        return ranges
            .map!(range => tuple!("range", "line")(range, range.front))
            .minElement!("a.line");
        // dfmt on
    }
    auto nonEmpty = getNonEmpty;
    ReturnType!(minimumOfRanges!(typeof(nonEmpty))) minRangeAndLine;
    struct ByMinimum(Ranges)
    {
        bool empty()
        {
            return nonEmpty.empty;
        }

        auto front()
        {
            minRangeAndLine = minimumOfRanges(nonEmpty);
            return minRangeAndLine;
        }

        void popFront()
        {
            minRangeAndLine.range.popFront;
            nonEmpty = getNonEmpty;
        }
    }
    return ByMinimum!(Ranges)();
}

void main(string[] files)
{
    foreach (n; files[1 .. $].map!(name => File(name).byLine(No.keepTerminator)).array.byMinimum)
    {
        writeln(n.line);
    }
}


Still it looks a little clumsy. Any ideas?

--
Christian
May 19, 2019
Last version using more from the outer template

#!/usr/bin/env rdmd
import std.stdio;
import std.algorithm;
import std.typecons;
import std.array;
import std.range;
import std.traits;

auto byMinimum(Ranges)(Ranges ranges)
{
    auto getNonEmpty()
    {
        return ranges.filter!("!a.empty");
    }

    auto nonEmpty = getNonEmpty;

    auto minimumOfRanges()
    {
        // dfmt off
        return nonEmpty
            .map!(range => tuple!("range", "line")(range, range.front))
            .minElement!("a.line");
        // dfmt on
    }

    ReturnType!(minimumOfRanges) minRangeAndLine;
    struct ByMinimum
    {
        bool empty()
        {
            return nonEmpty.empty;
        }

        auto front()
        {
            minRangeAndLine = minimumOfRanges;
            return minRangeAndLine;
        }

        void popFront()
        {
            nonEmpty = getNonEmpty;
            minRangeAndLine.range.popFront;
        }
    }

    return ByMinimum();
}

void main(string[] files)
{
    foreach (n; files[1 .. $].map!(name => File(name).byLine(No.keepTerminator)).array.byMinimum)
    {
        writeln(n.line);
    }
}