Jump to page: 1 2
Thread overview
delegate object instead of a literal
Aug 14, 2011
Joel Christensen
Aug 14, 2011
Jonathan M Davis
Aug 14, 2011
Jonathan M Davis
Aug 14, 2011
Jonathan M Davis
Aug 15, 2011
Joel Christensen
Aug 15, 2011
Jonathan M Davis
Aug 15, 2011
Joel Christensen
Aug 15, 2011
Joel Christensen
Aug 15, 2011
Joel Christensen
Aug 15, 2011
Jonathan M Davis
Aug 15, 2011
Jonathan M Davis
Aug 16, 2011
Joel Christensen
August 14, 2011
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))))

- Joel
August 14, 2011
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.

- Jonathan M Davis
August 14, 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.

Oh and by the way, isNumber isn't a delegate. It's a function. A delegate has access to its outer scope, which is what you get when you don't use static.

- Jonathan M Davis
August 14, 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
August 15, 2011
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))))

By the way, it looks like std.algorithm.count will do what you want to do (though you'll have to negate the predicate for it to work - either with std.functional.not or by changing it appropriately).

- Jonathan M Davis
August 15, 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
August 15, 2011
On 15-Aug-11 2:55 PM, 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))))
>
> By the way, it looks like std.algorithm.count will do what you want to do
> (though you'll have to negate the predicate for it to work - either with
> std.functional.not or by changing it appropriately).
>
> - Jonathan M Davis

Ok, cool.

I think this is nice:

immutable isNum = `a >= '0' && a <= '9' && a != '"'`;
auto input = "abc123";
auto indexEnd = count!( not!isNum )( input );
assert( indexEnd == 3 );

- Joel
August 15, 2011
On 15-Aug-11 5:21 PM, Joel Christensen wrote:
> On 15-Aug-11 2:55 PM, 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))))
>>
>> By the way, it looks like std.algorithm.count will do what you want to do
>> (though you'll have to negate the predicate for it to work - either with
>> std.functional.not or by changing it appropriately).
>>
>> - Jonathan M Davis
>
> Ok, cool.
>
> I think this is nice:
>
> immutable isNum = `a >= '0' && a <= '9' && a != '"'`;
> auto input = "abc123";
> auto indexEnd = count!( not!isNum )( input );
> assert( indexEnd == 3 );
>
> - Joel

Oops, should be. -- immutable isNum = `( a >= '0' && a <= '9' ) || a == '.'`;
But that's the idea any way. Also forgot to have the variable 'input' declared in a post.

- Joel
August 15, 2011
Ok, this is a good one I think.

import std.string, std.algorithm, std.functional;

bool isANum( dchar chr ) {
        return inPattern( chr, digits ~ `"+-.` );
}

void main() {
    auto input = `abc123`;
    auto indexEnd = -1;

    indexEnd = count!( not!isANum )( input );
    assert( indexEnd == 3 );
}

August 15, 2011
On Monday, August 15, 2011 02:25 Joel Christensen wrote:
> Ok, this is a good one I think.
> 
> import std.string, std.algorithm, std.functional;
> 
> bool isANum( dchar chr ) {
> return inPattern( chr, digits ~ `"+-.` );
> }
> 
> void main() {
> auto input = `abc123`;
> auto indexEnd = -1;
> 
> indexEnd = count!( not!isANum )( input );
> assert( indexEnd == 3 );
> }

Actually, it looks like count counts it for the whole range, not just how many before it finds one which doesn't match. So, it's not quite what you were looking for. I misread what it did.

- Jonathan M Davis
« First   ‹ Prev
1 2