counting characters

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jul 19 07:02:21 PDT 2016


On Tuesday, July 19, 2016 12:23:11 celavek via Digitalmars-d-learn wrote:
> On Tuesday, 19 July 2016 at 09:57:27 UTC, Lodovico Giaretta wrote:
> > On Tuesday, 19 July 2016 at 09:42:40 UTC, celavek wrote:
> >
> > Works for me:
> >
> > size_t[char] counts;
> > const string dna_chain =
> > "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC";
> > counts['A'] = countchars(dna_chain, "A");
>
> It was failing for me as I was using "countchars!". I thought
> that I should use the "!" in order to instantiate a template in
> D. I'm still confused why it is working without the "!". Anyway
> the compiler message was not very helpful.

! is required for explicit template instantiation, but with functions, you
have use IFTI - Implicit Function Template Instantiation. So, when you have
a function like

    auto foo(T)(T bar) {...}

and you call it without a template argument

    foo(42);

the compiler infers the type. You can also explicitly instantiate it if you
want to

    foo!int(42);

Many functions in Phobos have a template argument which is expected to be
explicit (one which is not the type of any of the function's parameters)
whereas all of the ones associated with the function's parameters are
inferred. e.g.

auto result = map!(a => a % 5)([12, 14, 15]);

map takes a template argument for the function that it calls on each of the
elements in the range it's given, and it takes a function argument that is
the range that's being operated on, and while the type of that range is
indeed a template argument, it's inferred by the compiler rather than being
explicitly given by the programmer. You _could_ give it explicitly, but
there really isn't a reason to, and the code is a lot uglier if you do.

In the case of countchars, you attempted to give the function arguments as
template arguments

size_t countchars(S, S1)(S s, in S1 pattern) @safe pure @nogc
    if (isSomeString!S && isSomeString!S1)
{...}

If you do

countchars!(dna_chain, 'A')

then S and S1 are then the template arguments, and they're used as the types
of the function parameters, which doesn't work, since they're not types;
they don't pass the template constraint either (since neither of them is a
type which is a string - they're an actual string and a character, not
types). And to make matters worse, there are then no function arguments. So,
countchars is being given bogus types, the template arguments fail the
template constraint, and it's not being given the function arguments that it
needs.

So, the error is definitely telling you what's going wrong (or at least part
of it) - that the template arguments don't match the template constraint -
but your understanding of D's templates seems to be low enough that I
suppose that it's no surprise that the error message is confusing. I expect
that the reason that it's specifically the template constraints which are
complained about rather than the lack of function arguments or that the
template arguments aren't even types when they're then used as types for the
function parameters is because when you declare

size_t countchars(S, S1)(S s, in S1 pattern) @safe pure @nogc
    if (isSomeString!S && isSomeString!S1)
{...}

the compiler lowers it to

template countchars(S, S1)
    if (isSomeString!S && isSomeString!S1)
{
    size_t countchars(S s, in S1 pattern) @safe pure @nogc
    {...}
}

and that's going to fail to compile at the template constraint before it
even looks at the function, because isSomeString is not true for either
dna_chain or 'A' (even if it would be true for the _type_ of dna_chain, it's
not true for dna_chain itself).

If you haven't already, I would suggest that you read

http://ddili.org/ders/d.en/index.html

I expect that the section

http://ddili.org/ders/d.en/templates.html

would be the most relevant to this discussion, but the book a as a whole
would be good to read if you're new to D.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list