delegate object instead of a literal

Jonathan M Davis jmdavisProg at gmx.com
Sun Aug 14 03:44:30 PDT 2011


On Sunday, August 14, 2011 03:23:39 Jonathan M Davis wrote:
> On Sunday, August 14, 2011 20:50:03 Joel Christensen wrote:
> > Hi,
> > 
> > This program loops through a string until it finds a number and gives
> > the position of it.
> > 
> > The first assert works, but not the second one.
> > 
> > import std.algorithm;
> > 
> > void main() {
> > 
> > 	static bool isNumber( char input, char dummy ) {
> > 	
> > 		if ( ( input >= '0' && input <= '9' ) || input == '.' )
> > 		
> > 			return true;
> > 		
> > 		else
> > 		
> > 			return false;
> > 	
> > 	}
> > 	
> > 	string str = "abc123";
> > 	assert( countUntil!( ( input, b ) {
> > 	
> > 		if ( ( input >= '0' && input <= '9' ) || input == '.' ) return true;
> > 
> > else return false;
> > 
> > 		} )(str, 0) == 3 ); // works
> > 	
> > 	assert( countUntil!( isNumber, string, string )( str, 0 ) == 3 );
> > 
> > }
> > 
> > This is the error:
> > parse.d(15): Error: template instance
> > countUntil!(isNumber,string,string) does not match template declaration
> > countUntil(alias pred = "a == b",R1,R2) if
> > (is(typeof(startsWith!(pred)(haystack,needle))))
> 
> Okay. Several things here. One, don't ever declare an individual char. char
> is a UTF-8 code unit, not a code point. And characters are code points.
> ASCII characters only require one UTF-8 code unit, so they can be held in a
> single char, but that's not true of characters in general. When dealing
> with individual characters, always use dchar. So, if you're using foreach
> for a string, use dchar as the iteration type. e.g.
> 
> foreach(dchar c; str) {...}
> 
> Youre code will be wrong if it iterates over char or wchar, since those
> aren't full characters. And because of that, _all_ strings are ranges of
> dchar, not char or wchar. So, the fact that you're using string instead of
> dstring with a range-based function like countUntil is irrelevant. You're
> still dealing with a range of dchars. So, isNumber should definitely be
> taking dchars, not chars.
> 
> Two, don't pass 0 as a string. 0 is an int. _None_ of those countUntil calls
> shouldn't be compiling at all. It's actually a bit disturbing thath the
> first one compiles. It definitely looks like a bug. countUntil takes two
> ranges with the same element type. 0 is not a range, let alone a range of
> dchars. 0 shouldn't even really be used as a dchar, since 0 is an int, not
> a character.
> 
> Third, you really shouldn't be using if statements like that. It looks like
> you don't know what you're doing if you do
> 
> if(condition)
>     return true;
> else
>     return false;
> 
> The condition is already a bool. You can simply do
> 
>     return condition;
> 
> Plenty of newbie programmers make that mistake, and I don't know how
> experienced a programmer you are, but I'd advise you not to do that anymore.
> 
> In any case, I'm a bit shocked that the first call to countUntil compiles,
> let alone works. That's quite disturbing actually. It looks like countUntil
> has a bug. However, your usage of countUntil here does imply that it could
> use an overload which takes a unary function and only one range.

Okay. countUntil is _supposed_ to be able to take a single value as its second 
argument. However, the names for the templated types implied that it took a 
range for its second value (it could take either a range or just an element, 
just so long as startsWith(haystack, needle) compiles). So, that may need some 
clarifying in the documentation. I misread it.

In any case, if you change isNumber to two dchars, your code will work. The 
problem you're having is because a string is a range of dchars, not chars. But 
still, you probably shouldn't be passing 0. Apparently, the compiler is doing 
an implicit conversion from int to dchar to allow it to work, but it's 
generally better to not do that.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list