delegate object instead of a literal

Joel Christensen joelcnz at gmail.com
Sun Aug 14 21:54:23 PDT 2011


On 14-Aug-11 10:44 PM, Jonathan M Davis wrote:
> 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

Hi,

Thanks Jonathan for your help. I've taken the things you've said on board.

I think I'm getting some where with D. I also mean to work more at C# too.

So this works:
import std.algorithm;

bool isNumber( dchar chr, dchar dummy ) {
	return  ( ( chr >= '0' && chr <= '9' ) || chr == '.'  || chr == '-' || 
chr == '+' || chr == '"' );
}

void fun() {
	dchar dummy = '\0';
	auto indexEnd = countUntil!( isNumber )( input, dummy );
}

- Joel


More information about the Digitalmars-d-learn mailing list