www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How do you use templates in D?

reply Andrew Pennebaker <andrew.pennebaker gmail.com> writes:
--bcaec51dd153631d7304af967111
Content-Type: text/plain; charset=ISO-8859-1

I'm writing a function called genArray that accepts a function gen and
returns a random array populated by calling gen(). genString builds on this
by returning genArray(&genChar). But my type signatures are wrong.

In dashcheck.d:

char genChar() {
    return cast(char) uniform(0, 128);
}

T[] genArray(T function() gen) {
    int len = uniform(0, 100);
    T[] arr = [];

    for(int i = 0; i < len; i++) {
        arr ~= gen();
    }

    return arr;
}

string genString() {
    return genArray(&genChar);
}

Trace:

dashcheck.d(17): Error: undefined identifier T
dashcheck.d(17): Error: T is used as a type
dashcheck.d(17): Error: undefined identifier T
dashcheck.d(17): Error: T is used as a type

Full code at GitHub <https://github.com/mcandre/dashcheck>

Cheers,

Andrew Pennebaker
www.yellosoft.us

--bcaec51dd153631d7304af967111
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div>I&#39;m writing a function called <font class=3D"Apple-style-span" fac=
e=3D"&#39;courier new&#39;, monospace">genArray</font> that accepts a funct=
ion <font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospa=
ce">gen</font> and returns a random array populated by calling <font class=
=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">gen()</font=
. genString builds on this by returning <font class=3D"Apple-style-span" f=

my type signatures are wrong.</div> <div><br></div><div>In dashcheck.d:</div><div><br></div><div><font class=3D= "Apple-style-span" face=3D"&#39;courier new&#39;, monospace">char genChar()= {</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;courier n= ew&#39;, monospace">=A0 =A0 return cast(char) uniform(0, 128);</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">}</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;couri= er new&#39;, monospace"><br></font></div><div><font class=3D"Apple-style-sp= an" face=3D"&#39;courier new&#39;, monospace">T[] genArray(T function() gen= ) {</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">=A0 =A0 int len =3D uniform(0, 100);</font></div><div><font class=3D"A= pple-style-span" face=3D"&#39;courier new&#39;, monospace">=A0 =A0 T[] arr = =3D [];</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"&#39;co= urier new&#39;, monospace">=A0 =A0 for(int i =3D 0; i &lt; len; i++) {</fon= t></div><div> <font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">= =A0 =A0 =A0 =A0 arr ~=3D gen();</font></div><div><font class=3D"Apple-style= -span" face=3D"&#39;courier new&#39;, monospace">=A0 =A0 }</font></div><div=
<font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace"=
<br>

</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;courier new= &#39;, monospace">=A0 =A0 return arr;</font></div><div><font class=3D"Apple= -style-span" face=3D"&#39;courier new&#39;, monospace">}</font></div><div><= font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace"><= br> </font></div><div><font class=3D"Apple-style-span" face=3D"&#39;courier new= &#39;, monospace">string genString() {</font></div><div><font class=3D"Appl= e-style-span" face=3D"&#39;courier new&#39;, monospace">=A0 =A0 return genA= rray(&amp;genChar);</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">}</font></div><div><br></div><div>Trace:</div><div><br></div><div><fon= t class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">dash= check.d(17): Error: undefined identifier T</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">dashcheck.d(17): Error: T is used as a type</font></div><div><font cla= ss=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">dashcheck= .d(17): Error: undefined identifier T</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">dashcheck.d(17): Error: T is used as a type</font></div><div><br></div=
<div>Full code at <a href=3D"https://github.com/mcandre/dashcheck">GitHub<=

<div><br></div>Cheers,<div><br></div><div>Andrew Pennebaker</div><div><a hr= ef=3D"http://www.yellosoft.us" target=3D"_blank">www.yellosoft.us</a></div> --bcaec51dd153631d7304af967111--
Oct 18 2011
next sibling parent Trass3r <un known.com> writes:
 T[] genArray(T function() gen) {

T[] genArray(T)(T function() gen) {
Oct 18 2011
prev sibling next sibling parent Ali =?iso-8859-1?q?=C7ehreli?= <acehreli yahoo.com> writes:
On Tue, 18 Oct 2011 13:56:09 -0400, Andrew Pennebaker wrote:

 I'm writing a function called genArray that accepts a function gen and
 returns a random array populated by calling gen(). genString builds on
 this by returning genArray(&genChar). But my type signatures are wrong.
 
 In dashcheck.d:
 
 char genChar() {
     return cast(char) uniform(0, 128);

It's a good thing that you are staying within ASCII. Otherwise there might be invalid UTF-8 sequences. :)
 T[] genArray(T function() gen) {

The template parameters are specified in a separate list before the function parameter list: T[] genArray(T)(T function() gen) { Now genArray is a function template with the template parameter T.
 string genString() {
     return genArray(&genChar);

Add .idup to convert from char[] to immutable(char)[] (i.e. string): return genArray(&genChar).idup; Or use std.exception.assumeUnique to communicate that the characters are not going to be mutated by somebody else: import std.exception; // ... auto result = genArray(&genChar); return assumeUnique(result); Ali P.S. There is also the digitalmars.D.learn newsgroup where this post would be appreciated at. ;)
Oct 18 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, October 18, 2011 12:32 Ali Çehreli wrote:
 On Tue, 18 Oct 2011 13:56:09 -0400, Andrew Pennebaker wrote:
 I'm writing a function called genArray that accepts a function gen and
 returns a random array populated by calling gen(). genString builds on
 this by returning genArray(&genChar). But my type signatures are wrong.
 
 In dashcheck.d:
 
 char genChar() {
 
 return cast(char) uniform(0, 128);

It's a good thing that you are staying within ASCII. Otherwise there might be invalid UTF-8 sequences. :)

Yeah. It's generally a very bad sign when code uses char or wchar outside of arrays. They're UTF-8 and UTF-16 code units respectively and are not necessarily full code points (and therefore are not necessarily full characters). That's particularly true of char, since anything outside of ASCII is not going to work. Code which operates on individual characters really should be operating on dchars, not chars or wchars. - Jonathan M Davis
Oct 18 2011
prev sibling next sibling parent Ali =?iso-8859-1?q?=C7ehreli?= <acehreli yahoo.com> writes:
On Tue, 18 Oct 2011 17:56:33 -0400, Jonathan M Davis wrote:

 On Tuesday, October 18, 2011 12:32 Ali Çehreli wrote:
 On Tue, 18 Oct 2011 13:56:09 -0400, Andrew Pennebaker wrote:
 I'm writing a function called genArray that accepts a function gen
 and returns a random array populated by calling gen(). genString
 builds on this by returning genArray(&genChar). But my type
 signatures are wrong.
 
 In dashcheck.d:
 
 char genChar() {
 
 return cast(char) uniform(0, 128);

It's a good thing that you are staying within ASCII. Otherwise there might be invalid UTF-8 sequences. :)

Yeah. It's generally a very bad sign when code uses char or wchar outside of arrays. They're UTF-8 and UTF-16 code units respectively and are not necessarily full code points (and therefore are not necessarily full characters). That's particularly true of char, since anything outside of ASCII is not going to work. Code which operates on individual characters really should be operating on dchars, not chars or wchars.

Good tips, but we can further qualify "Code which operates on individual characters". I think you imply accessing individual characters, likely with the [] operator. It is perfectly fine to use char and wchar strings as ranges when std.array is imported (it is automatically imported by std.range too): import std.stdio; import std.range; import std.array; // <-- empowers (en-ranges :p) char and wchar strings void main() { writeln(take("abcçdeé", 5)); } Outputs 5 Unicode characters, not code units. In other words, e.g. .front on any type of string produces a dchar; and that may very well prove your point. ;)
 - Jonathan M Davis

Ali
Oct 18 2011
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, October 18, 2011 15:37 Ali Çehreli wrote:
 On Tue, 18 Oct 2011 17:56:33 -0400, Jonathan M Davis wrote:
 On Tuesday, October 18, 2011 12:32 Ali Çehreli wrote:
 On Tue, 18 Oct 2011 13:56:09 -0400, Andrew Pennebaker wrote:
 I'm writing a function called genArray that accepts a function gen
 and returns a random array populated by calling gen(). genString
 builds on this by returning genArray(&genChar). But my type
 signatures are wrong.
 
 In dashcheck.d:
 
 char genChar() {
 
 return cast(char) uniform(0, 128);

It's a good thing that you are staying within ASCII. Otherwise there might be invalid UTF-8 sequences. :)

Yeah. It's generally a very bad sign when code uses char or wchar outside of arrays. They're UTF-8 and UTF-16 code units respectively and are not necessarily full code points (and therefore are not necessarily full characters). That's particularly true of char, since anything outside of ASCII is not going to work. Code which operates on individual characters really should be operating on dchars, not chars or wchars.

Good tips, but we can further qualify "Code which operates on individual characters". I think you imply accessing individual characters, likely with the [] operator. It is perfectly fine to use char and wchar strings as ranges when std.array is imported (it is automatically imported by std.range too): import std.stdio; import std.range; import std.array; // <-- empowers (en-ranges :p) char and wchar strings void main() { writeln(take("abcçdeé", 5)); } Outputs 5 Unicode characters, not code units. In other words, e.g. .front on any type of string produces a dchar; and that may very well prove your point. ;)

Yes. When treating arrays of char and wchar as ranges, you're effectively operating on dchars, so you're fine. The problem is when you have a variable which is char or wchar or when youyou access an individual char or wchar in an array. Operating on chars and wchars is fine as long as you decode them to dchar when you do it (as happens when using range operations such as front), but operating on individual chars or wchars is almost always a bug. - Jonathan M Davis
Oct 18 2011