www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - counting characters

reply celavek <cetatzeanum yahoo.com> writes:
Hi,

I am trying to count characters in a string like:

const string dna_chain = 
"AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC";
counts['A'] = countchars!(dna_chain, 'A');

But I get a compilation error:

template instance countchars!(dna_chain, "C") does not match 
template declaration countchars(S, S1)(S s, in S1 pattern) if 
(isSomeString!S && isSomeString!S1)

I cannot figure out why I do get the error. It completely eludes 
me. The documentation of countchars is minimal and it lacks 
examples.
Could someone enlighten me?

dmd version:
DMD64 D Compiler v2.071.1

Thanks
Jul 19 2016
parent reply John <johnch_atms hotmail.com> writes:
On Tuesday, 19 July 2016 at 09:34:11 UTC, celavek wrote:
 Hi,

 I am trying to count characters in a string like:

 const string dna_chain = 
 "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC";
 counts['A'] = countchars!(dna_chain, 'A');
countchars(dna_chain, "A");
Jul 19 2016
next sibling parent reply celavek <cetatzeanum yahoo.com> writes:
On Tuesday, 19 July 2016 at 09:41:32 UTC, John wrote:
 On Tuesday, 19 July 2016 at 09:34:11 UTC, celavek wrote:
 Hi,

 I am trying to count characters in a string like:

 const string dna_chain = 
 "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC";
 counts['A'] = countchars!(dna_chain, 'A');
countchars(dna_chain, "A");
Not working. Same error.
Jul 19 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Tuesday, 19 July 2016 at 09:42:40 UTC, celavek wrote:
 On Tuesday, 19 July 2016 at 09:41:32 UTC, John wrote:
 On Tuesday, 19 July 2016 at 09:34:11 UTC, celavek wrote:
 Hi,

 I am trying to count characters in a string like:

 const string dna_chain = 
 "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC";
 counts['A'] = countchars!(dna_chain, 'A');
countchars(dna_chain, "A");
Not working. Same error.
Works for me: size_t[char] counts; const string dna_chain = "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC"; counts['A'] = countchars(dna_chain, "A");
Jul 19 2016
parent reply celavek <cetatzeanum yahoo.com> writes:
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.
Jul 19 2016
next sibling parent Lodovico Giaretta <lodovico giaretart.net> writes:
On Tuesday, 19 July 2016 at 12:23:11 UTC, celavek 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.
The declaration is: countchars(S, S1)(S str, S1 pattern) So the most verbose way to instantiate it is: countchars!(string, string)(dna_chain, "A") But as S and S1 are the types of the two arguments, the compiler can easily infer them, so you can write: countchars(dna_chain, "A") And have the compiler infer: countchars!(typeof(dna_chain), typeof("A"))(dna_chain, "A") The error message is technically correct: you cannot instantiate countchars with template parameters `dna_chain` and `"A"`, which is what you were actually doing.
Jul 19 2016
prev sibling next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/19/16 8:23 AM, celavek 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.
https://dlang.org/spec/template.html#function-templates Check out the section a little bit down that talks about implicitly deduced template parameters. -Steve
Jul 19 2016
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
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
Jul 19 2016
parent celavek <cetatzeanum yahoo.com> writes:
Thank you!

That clarified a lot of things for me.
Jul 19 2016
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Tuesday, July 19, 2016 09:41:32 John via Digitalmars-d-learn wrote:
 On Tuesday, 19 July 2016 at 09:34:11 UTC, celavek wrote:
 Hi,

 I am trying to count characters in a string like:

 const string dna_chain =
 "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC";
 counts['A'] = countchars!(dna_chain, 'A');
countchars(dna_chain, "A");
That fixes the call to countchars, but given that the OP is only looking to count a specific character and is not really using a "pattern" (which is what countchars looks for), it's bound to be more efficient to just use a function which counts the number of elements in the array which match a certain character rather than seaching for a pattern. std.algorithm.count would be the most idiomatic choice. So, you get something like auto result = count(dna_chain, 'A'); or if you know that the string is always going to just contain ASCII (as seems likely based on the example), then string.representation can be used to convert the string to immutable(ubyte)[] in order to avoid the auto-decoding that occurs with string and range-based functions. e.g. auto result = count(dna_chain.representation, 'A'); That's almost certainly the fastest way to do it with Phobos. - Jonathan M Davis
Jul 19 2016
parent celavek <cetatzeanum yahoo.com> writes:
On Tuesday, 19 July 2016 at 09:55:43 UTC, Jonathan M Davis wrote:
 On Tuesday, July 19, 2016 09:41:32 John via Digitalmars-d-learn 
 wrote:

 auto result = count(dna_chain, 'A');

 or if you know that the string is always going to just contain 
 ASCII (as seems likely based on the example), then 
 string.representation can be used to convert the string to 
 immutable(ubyte)[] in order to avoid the auto-decoding that 
 occurs with string and range-based functions. e.g.

 auto result = count(dna_chain.representation, 'A');

 That's almost certainly the fastest way to do it with Phobos.

 - Jonathan M Davis
Thank you. I used what you suggested as I have only ASCII characters.
Jul 19 2016