Fluent APIs

Nicholas Wilson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat May 20 23:24:25 PDT 2017


On Sunday, 21 May 2017 at 05:18:33 UTC, Russel Winder wrote:
> I am having a crisis of confidence. In two places I have 
> structurally:
>
>     datum.action()
>       .map!(…)
>
> and then the fun starts as I need to actually do a flatMap. In 
> one of the two places I have to:
>
>     .array
>     .joiner;
>
> but in the other place I have to:
>
>     .joiner
>     .array;
>
> in order to stop the compiler spewing out a mass of (to me 
> anyway) incomprehensible messages with types I have no 
> knowledge of. So why does the fluent API chain break in 
> different ways in the two cases. A Priori this seems like a 
> breakage of the abstraction.
>
> Full code is at
> https://github.com/russel/ApproxGC/blob/master/source/main.d
> The comparison is between the functions 
> createGenerationsDeleteList and
> createListOfPlaces.
>
> Any help rebuilding my knowledge would be good.
>
> Also error message comprehensible to programmers rather than 
> compiler writers  might help.

For this kind of errors I find that it helps to break the 
pipeline into individual stages and reason about the type 
separately.

Function createGenerationsDeleteList returns auto.
{
groups.byPair() // This gives a range of Tuple!(string, string[])
.map!(func) // this gives a sorted range of string[]
.array // this gives a string[][]
.joiner; // this gives a range of string[]
}

all is good. If we swap the array and joiner we get
{
.map!(func) // this gives a sorted range of string[]
.joiner // range of range of string(?)
.array; // array of range of string
}

return type is auto, no problems.

Function createListOfPlaces return string[]  <------
{
path.dirEntries(SpanMode.shallow) // range of DirEntries
.map!(p => p.name) // range of strings
.map!(p =>  // range of
            p.dirEntries("*.deb", SpanMode.depth). // range of dir 
entires
                        map!(a => a.dirName).uniq) // goes to a 
range of strings
// have a range of range of strings here
.joiner  // range of string
.array  // string[]
}

all is good.

swap the array and joiner and we have
{
// have a range of range of strings here
.array  // array of range of string
.joiner // range of string
}
range of string is NOT string[], hence you get an error.

TL;DR you specified the return type in the second case, changing 
the order of the operations yields a different type -> type error.


More information about the Digitalmars-d-learn mailing list