www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - make (a < b < c) illegal?

reply Walter Bright <newshound digitalmars.com> writes:
Right now, in D (as well as C and C++), when you see the expression:

	if (a < b < c)

what is your first thought? Mine is that it was written by a newbie who 
didn't realize that (a < b) returns true or false, and that it does NOT 
mean ((a < b) && (b < c)). The odds approach certainty that this is a 
logic error in the code, and even if it was intentional, it raises such 
a red flag that it shouldn't be used anyway.

Andrei has proposed (and I agreed) that this should be done away with in 
the language, i.e. comparison operators should no longer be associative. 
  It's a simple change to the grammar. If one really did want to write 
such code, it could be done with parentheses:

	if ((a < b) < c)

to get the original behavior. At least, that looks intentional.

I don't think this will break existing code that isn't already broken.
Feb 07 2007
next sibling parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Walter Bright wrote:
 Right now, in D (as well as C and C++), when you see the expression:
 
     if (a < b < c)
 
 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.
 
 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
  It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:
 
     if ((a < b) < c)
 
 to get the original behavior. At least, that looks intentional.
 
 I don't think this will break existing code that isn't already broken.

For the record, (clears throat) let me add that I initially suggested to make them associative with the right meaning, but was shot down. Making the comparison operators (and that includes != and ==) nonassociative is the next best thing to do. Andrei
Feb 07 2007
parent reply Steve Horne <stephenwantshornenospam100 aol.com> writes:
On Wed, 07 Feb 2007 17:06:07 -0800, "Andrei Alexandrescu (See Website
For Email)" <SeeWebsiteForEmail erdani.org> wrote:

Walter Bright wrote:

 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative.


For the record, (clears throat) let me add that I initially suggested to 
make them associative with the right meaning, but was shot down. Making 
the comparison operators (and that includes != and ==) nonassociative is 
the next best thing to do.

Agreed, but with an extra note - once the operators have been nonassociative for a while, maybe making them associative again (but with the right meanings) might be more palatable. -- Remove 'wants' and 'nospam' from e-mail.
Feb 07 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Steve Horne wrote:
 On Wed, 07 Feb 2007 17:06:07 -0800, "Andrei Alexandrescu (See Website
 For Email)" <SeeWebsiteForEmail erdani.org> wrote:
 
 Walter Bright wrote:

 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative.


 For the record, (clears throat) let me add that I initially suggested to 
 make them associative with the right meaning, but was shot down. Making 
 the comparison operators (and that includes != and ==) nonassociative is 
 the next best thing to do.

Agreed, but with an extra note - once the operators have been nonassociative for a while, maybe making them associative again (but with the right meanings) might be more palatable.

My thoughts exactly.
Feb 08 2007
parent "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Frits van Bommel wrote:
 Steve Horne wrote:
 On Wed, 07 Feb 2007 17:06:07 -0800, "Andrei Alexandrescu (See Website
 For Email)" <SeeWebsiteForEmail erdani.org> wrote:

 Walter Bright wrote:

 Andrei has proposed (and I agreed) that this should be done away 
 with in the language, i.e. comparison operators should no longer be 
 associative.


 For the record, (clears throat) let me add that I initially suggested 
 to make them associative with the right meaning, but was shot down. 
 Making the comparison operators (and that includes != and ==) 
 nonassociative is the next best thing to do.

Agreed, but with an extra note - once the operators have been nonassociative for a while, maybe making them associative again (but with the right meanings) might be more palatable.

My thoughts exactly.

Never thought of that. Very interesting. The good cop/bad cop routine all over again :o). Andrei
Feb 08 2007
prev sibling next sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:

 Right now, in D (as well as C and C++), when you see the expression:
 
 	if (a < b < c)
 
 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.
 
 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
   It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:
 
 	if ((a < b) < c)
 
 to get the original behavior. At least, that looks intentional.
 
 I don't think this will break existing code that isn't already broken.

First thought: Yes, your proposed change makes sense. Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) ) -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 8/02/2007 12:01:13 PM
Feb 07 2007
next sibling parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Derek Parnell wrote:
 On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:
 
 Right now, in D (as well as C and C++), when you see the expression:

 	if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.

 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
   It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:

 	if ((a < b) < c)

 to get the original behavior. At least, that looks intentional.

 I don't think this will break existing code that isn't already broken.

First thought: Yes, your proposed change makes sense. Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) )

What's the intended meaning of: a < b == c < d ? Andrei
Feb 07 2007
next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Derek Parnell wrote:
 On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:

 Right now, in D (as well as C and C++), when you see the expression:

     if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie 
 who didn't realize that (a < b) returns true or false, and that it 
 does NOT mean ((a < b) && (b < c)). The odds approach certainty that 
 this is a logic error in the code, and even if it was intentional, it 
 raises such a red flag that it shouldn't be used anyway.

 Andrei has proposed (and I agreed) that this should be done away with 
 in the language, i.e. comparison operators should no longer be 
 associative.   It's a simple change to the grammar. If one really did 
 want to write such code, it could be done with parentheses:

     if ((a < b) < c)

 to get the original behavior. At least, that looks intentional.

 I don't think this will break existing code that isn't already broken.

First thought: Yes, your proposed change makes sense. Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) )

What's the intended meaning of: a < b == c < d ? Andrei

It's worth pointing out that Python handles these operations just like Derek suggests. Take the following from Python's interactive mode:
 a=1
 b=2
 c=2
 d=3
 a<b==c<d



-- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Feb 07 2007
parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Kirk McDonald wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Derek Parnell wrote:
 On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:

 Right now, in D (as well as C and C++), when you see the expression:

     if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie 
 who didn't realize that (a < b) returns true or false, and that it 
 does NOT mean ((a < b) && (b < c)). The odds approach certainty that 
 this is a logic error in the code, and even if it was intentional, 
 it raises such a red flag that it shouldn't be used anyway.

 Andrei has proposed (and I agreed) that this should be done away 
 with in the language, i.e. comparison operators should no longer be 
 associative.   It's a simple change to the grammar. If one really 
 did want to write such code, it could be done with parentheses:

     if ((a < b) < c)

 to get the original behavior. At least, that looks intentional.

 I don't think this will break existing code that isn't already broken.

First thought: Yes, your proposed change makes sense. Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) )

What's the intended meaning of: a < b == c < d ? Andrei

It's worth pointing out that Python handles these operations just like Derek suggests. Take the following from Python's interactive mode: >>> a=1 >>> b=2 >>> c=2 >>> d=3 >>> a<b==c<d True

Obligatory comment: it would return true also if it were interpreted as (a < b) == (c < d) or as ((a < b) == c) < d. So the example is unclear. :o) Andrei
Feb 07 2007
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Obligatory comment: it would return true also if it were interpreted as 
 (a < b) == (c < d) or as ((a < b) == c) < d. So the example is unclear.
 
 :o)
 
 
 Andrei

For ultimate clarity, I refer you to the Python language reference on the topic: http://docs.python.org/ref/comparisons.html It's probably better to point you there than for me to attempt to explain it poorly. :-) -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Feb 07 2007
parent "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Kirk McDonald wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Obligatory comment: it would return true also if it were interpreted 
 as (a < b) == (c < d) or as ((a < b) == c) < d. So the example is 
 unclear.

 :o)


 Andrei

For ultimate clarity, I refer you to the Python language reference on the topic: http://docs.python.org/ref/comparisons.html It's probably better to point you there than for me to attempt to explain it poorly. :-)

Oh, I did run the interpreter (gotta love Linux - all the cool stuff is one command away) and figured how chained comparisons work. Thanks a lot for the reference. BTW, Perl 6 is slated to implement chain comparisons as well: http://en.wikipedia.org/wiki/Perl_6#Chained_comparisons Andrei
Feb 07 2007
prev sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 07 Feb 2007 17:09:35 -0800, Andrei Alexandrescu (See Website For
Email) wrote:

 Derek Parnell wrote:
 On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:
 
 Right now, in D (as well as C and C++), when you see the expression:

 	if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.

 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
   It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:

 	if ((a < b) < c)

 to get the original behavior. At least, that looks intentional.

 I don't think this will break existing code that isn't already broken.

First thought: Yes, your proposed change makes sense. Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) )

What's the intended meaning of: a < b == c < d

Well that *obvious*! (((a < b) && (b == c)) < d) <G> Okay, okay, I see your point. But it would be useful (one day) to easily code the idiom (a op b) && (b op c), no? How about someone knocking up a mixin template for expressions of this format? I haven't got a clue how it could be done as the mixin/template/meta-programming syntax and semantics of D is still so obtuse and confusing to me that I can only do the very simplest things and then only after many false starts. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 8/02/2007 1:28:00 PM
Feb 07 2007
next sibling parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Derek Parnell wrote:
 On Wed, 07 Feb 2007 17:09:35 -0800, Andrei Alexandrescu (See Website For
 Email) wrote:
 
 Derek Parnell wrote:
 On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:

 Right now, in D (as well as C and C++), when you see the expression:

 	if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.

 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
   It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:

 	if ((a < b) < c)

 to get the original behavior. At least, that looks intentional.

 I don't think this will break existing code that isn't already broken.

Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) )

a < b == c < d

Well that *obvious*! (((a < b) && (b == c)) < d) <G> Okay, okay, I see your point. But it would be useful (one day) to easily code the idiom (a op b) && (b op c), no? How about someone knocking up a mixin template for expressions of this format? I haven't got a clue how it could be done as the mixin/template/meta-programming syntax and semantics of D is still so obtuse and confusing to me that I can only do the very simplest things and then only after many false starts.

It's very easy to implement as a straight template function: ordered(a, b, c) returns true iff a <= b <= c, and strictly_ordered(a, b, c) returns true iff a < b < c. The functions can be nicely accommodate multiple arguments. Other functions can define STL-style in-range. Andrei
Feb 07 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 07 Feb 2007 19:02:06 -0800, Andrei Alexandrescu (See Website For
Email) wrote:

 Derek Parnell wrote:
 On Wed, 07 Feb 2007 17:09:35 -0800, Andrei Alexandrescu (See Website For
 Email) wrote:
 
 Derek Parnell wrote:
 On Wed, 07 Feb 2007 16:55:15 -0800, Walter Bright wrote:

 Right now, in D (as well as C and C++), when you see the expression:

 	if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.

 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
   It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:

 	if ((a < b) < c)

 to get the original behavior. At least, that looks intentional.

 I don't think this will break existing code that isn't already broken.

Second thought: Why not make it do what the coder is wanting it to do? Namely, make the idiom: expression1 relopA expression2 relopB expression3 translate as ( auto temp = expression2, (expression1 relopA temp) && (temp relopB expression3) )

a < b == c < d

Well that *obvious*! (((a < b) && (b == c)) < d) <G> Okay, okay, I see your point. But it would be useful (one day) to easily code the idiom (a op b) && (b op c), no? How about someone knocking up a mixin template for expressions of this format? I haven't got a clue how it could be done as the mixin/template/meta-programming syntax and semantics of D is still so obtuse and confusing to me that I can only do the very simplest things and then only after many false starts.

It's very easy to implement as a straight template function: ordered(a, b, c) returns true iff a <= b <= c, and strictly_ordered(a, b, c) returns true iff a < b < c. The functions can be nicely accommodate multiple arguments. Other functions can define STL-style in-range.

Right ... class Foo { . . . } class Bar { . . . } Foo f = new Foo; Foo g = new Foo; Bar b = new Bar; if (ordered( f,b,g ) ) ... BANG! The template doesn't know about Foo and Bar, so there is no match. In fact, just getting a template for built-in types requires a few thousand combinations of a,b,c signatures and aliases to make it palatable. That is why I thought mixin-expressions might be more useful in this case - working at the textual level rather than the template-matching level. But I do know how to do it. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 8/02/2007 2:39:20 PM
Feb 07 2007
parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Derek Parnell wrote:
 class Foo { . . . }
 class Bar { . . . }
 
 Foo f = new Foo;
 Foo g = new Foo;
 Bar b = new Bar;
 
 if (ordered( f,b,g ) ) ...
 
 BANG! The template doesn't know about Foo and Bar, so there is no match. In
 fact, just getting a template for built-in types requires a few thousand
 combinations of a,b,c signatures and aliases to make it palatable.
 
 That is why I thought mixin-expressions might be more useful in this case -
 working at the textual level rather than the template-matching level. But I
 do know how to do it.

It's really simple: bool ordered(T, U, V)(T a, U b, V c) { return a < b && b < c; } Expanding this to multiple arguments is also quite simple, but left as an exercise. :o) Andrei
Feb 07 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 07 Feb 2007 19:51:06 -0800, Andrei Alexandrescu (See Website For
Email) wrote:


 It's really simple:
 
 bool ordered(T, U, V)(T a, U b, V c)
 {
    return a < b && b < c;
 }

Thanks. It wasn't clear to me in the docs how this would be achieved. I've read the template docs many times and it still doesn't make much clear.
 Expanding this to multiple arguments is also quite simple, but left as 
 an exercise. :o)

Okay, I'll give it a go, but I'm not confident. I'd have a go at updating the docs but *Doc* changes are even harder to get accepted than phobos changes <G> Walter, would it be too hard to make the documentation source available too? I'm not talking about the embedded phobos docs but all the other stuff. e.g. The source that generates the "template.html". -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 8/02/2007 4:29:42 PM
Feb 07 2007
next sibling parent "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Derek Parnell wrote:
 On Wed, 07 Feb 2007 19:51:06 -0800, Andrei Alexandrescu (See Website For
 Email) wrote:
 
 
 It's really simple:

 bool ordered(T, U, V)(T a, U b, V c)
 {
    return a < b && b < c;
 }

Thanks. It wasn't clear to me in the docs how this would be achieved. I've read the template docs many times and it still doesn't make much clear.

A tutorial for template code would indeed be great. A lil bird told me the mythical "The D Programming Language" book will definitely include one :o). Andrei
Feb 07 2007
prev sibling next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Derek Parnell wrote:
 Walter, would it be too hard to make the documentation source available
 too? I'm not talking about the embedded phobos docs but all the other
 stuff. e.g. The source that generates the "template.html".

It's already up there! http://ftp.digitalmars.com/doc.zip
Feb 07 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 07 Feb 2007 22:12:50 -0800, Walter Bright wrote:

 Derek Parnell wrote:
 Walter, would it be too hard to make the documentation source available
 too? I'm not talking about the embedded phobos docs but all the other
 stuff. e.g. The source that generates the "template.html".

It's already up there!

And I assume that this fact is documented somewhere obvious. I'm not in the habit of browsing FTP sites on the off chance that something useful might be there. Also, if I had have seen "doc.zip" I would have assumed it was the distributed documentation and not the documentation source. Plus "doc.zip" doesn't exactly yell out "D PROGRAMMING LANGUAGE" either.
 http://ftp.digitalmars.com/doc.zip

Hmmm... your server doesn't think it is. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 8/02/2007 5:17:21 PM
Feb 07 2007
parent Walter Bright <newshound digitalmars.com> writes:
Derek Parnell wrote:
 http://ftp.digitalmars.com/doc.zip

Hmmm... your server doesn't think it is.

It was in the wrong directory... try again.
Feb 07 2007
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 8 Feb 2007 16:36:47 +1100, Derek Parnell wrote:

 On Wed, 07 Feb 2007 19:51:06 -0800, Andrei Alexandrescu (See Website For
 Email) wrote:
 
 
 It's really simple:
 
 bool ordered(T, U, V)(T a, U b, V c)
 {
    return a < b && b < c;
 }
 Expanding this to multiple arguments is also quite simple, but left as 
 an exercise. :o)

Okay, I'll give it a go, but I'm not confident.

I give up. I can't work out how to create this functionality for an arbitary number of arguments. e.g. When I code ... ordered(a,b,c,d,e) I want generated ... (a < b) && (b < c) && (c < d) && (d < e) I can't work out how to loop through the tuple. I started with template ordered(T ...) { } And everything I tried after that just didn't work. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Feb 08 2007
parent reply Michiel <nomail hotmail.com> writes:
 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

You need to use recursion, not loops. I'm not sure how the syntax works exactly, but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }
Feb 08 2007
next sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Michiel wrote:
 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

You need to use recursion, not loops. I'm not sure how the syntax works exactly, but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

How about: bool ascending(T ...)(T t) { static if (t.length > 0) { foreach (i, x; t[0..$-1]) { if (x >= t[i+1]) return false; } } return true; } void main() { assert (ascending(1, 2, 3, 4)); assert (ascending(1, 2)); assert (ascending(1.2, 2.1, 3.5, 4.7, 8.6)); assert (!ascending(1.2, 1.0)); assert (!ascending(1.2, 1.5, 0.5)); assert (ascending(1)); assert (ascending()); } ? -- Tomasz Stachowiak
Feb 08 2007
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 08 Feb 2007 12:27:58 +0100, Tom S wrote:

 Michiel wrote:
 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

You need to use recursion, not loops. I'm not sure how the syntax works exactly, but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

How about: bool ascending(T ...)(T t) { static if (t.length > 0) { foreach (i, x; t[0..$-1]) { if (x >= t[i+1]) return false; } } return true; } void main() { assert (ascending(1, 2, 3, 4)); assert (ascending(1, 2)); assert (ascending(1.2, 2.1, 3.5, 4.7, 8.6)); assert (!ascending(1.2, 1.0)); assert (!ascending(1.2, 1.5, 0.5)); assert (ascending(1)); assert (ascending()); }

Yes this works, but I don't know why. Is the 'foreach' executed at compile time or run time? If compile time, where is this documented? Its not in the template docs, nor the conditional compilation page, or on the statements page. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Feb 08 2007
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Derek Parnell wrote:
 On Thu, 08 Feb 2007 12:27:58 +0100, Tom S wrote:
 
 Michiel wrote:
 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

bool ascending(T ...)(T t) { static if (t.length > 0) { foreach (i, x; t[0..$-1]) { if (x >= t[i+1]) return false; } } return true; } void main() { assert (ascending(1, 2, 3, 4)); assert (ascending(1, 2)); assert (ascending(1.2, 2.1, 3.5, 4.7, 8.6)); assert (!ascending(1.2, 1.0)); assert (!ascending(1.2, 1.5, 0.5)); assert (ascending(1)); assert (ascending()); }

Yes this works, but I don't know why. Is the 'foreach' executed at compile time or run time?

Both :D It executes at runtime but is completely unrolled, afaics.
 If compile time, where is this documented? Its not in the
 template docs, nor the conditional compilation page, or on the statements
 page. 

Here's some stuff: http://digitalmars.com/d/tuple.html
Feb 08 2007
prev sibling next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 8 Feb 2007 10:50:56 +0000 (UTC), Michiel wrote:

 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

You need to use recursion, not loops. I'm not sure how the syntax works exactly, but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

Maybe ... I tried many combinations based on that. Still no luck. Show me something that compiles and runs, anyone? -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Feb 08 2007
next sibling parent reply "Daniel Giddings" <daniel.giddings gmail.com> writes:
To get recursion going you need add a 1 element case and a static if to 
handle the degeneration of the recursion to Michiel's version...

import std.stdio;

bool ordered( T )( T a )
{
 return true;
}

bool ordered( T1, T2, R... )( T1 a, T2 b, R remainder )
{
 static if( remainder.length > 0 )
  return a < b && ordered( b, remainder );
 else
  return a < b;
}

void main()
{
 writefln( ordered(1,2,4) );
 writefln( ordered(1,4,2) );
}



"Derek Parnell" <derek psych.ward> wrote in message 
news:<mqx61f4cfl24.yz4pjbrcs05z.dlg 40tude.net>...
 On Thu, 8 Feb 2007 10:50:56 +0000 (UTC), Michiel wrote:

 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

You need to use recursion, not loops. I'm not sure how the syntax works exactly, but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

Maybe ... I tried many combinations based on that. Still no luck. Show me something that compiles and runs, anyone? -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell

Feb 08 2007
parent Michiel <nomail hotmail.com> writes:
 To get recursion going you need add a 1 element case and a static if to
 handle the degeneration of the recursion to Michiel's version...

Of course! Stupid, stupid.
Feb 08 2007
prev sibling parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Derek Parnell wrote:
 On Thu, 8 Feb 2007 10:50:56 +0000 (UTC), Michiel wrote:
 
 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

Maybe ... I tried many combinations based on that. Still no luck. Show me something that compiles and runs, anyone?

Besides the foreach approaches already posted, this works as well: ----- bool ordered(R...)(R args) { static if (args.length < 2) return true; else return (args[0] < args[1]) && ordered(args[1..$]); } ----- It seems DMD just doesn't like it if the first two parameters have separately templated types...
Feb 08 2007
prev sibling parent Reiner Pope <xxxx xxx.xxx> writes:
Michiel wrote:
 I give up. I can't work out how to create this functionality
 for an arbitary number of arguments.

You need to use recursion, not loops. I'm not sure how the syntax works exactly, but it might look something like this: bool ordered(T1, T2, Trest ...)(T1 first, T2 second, Trest rest) { return (first < second) && ordered(second, rest); }

bool ordered(T...)(T data) { foreach(i, d; data) { static if (i < data.length - 1) if (! (d < data[i+1])) return false; } return true; }
Feb 08 2007
prev sibling parent reply Russell Lewis <webmaster villagersonline.com> writes:
Derek Parnell wrote:
 On Wed, 07 Feb 2007 17:09:35 -0800, Andrei Alexandrescu (See Website For

 What's the intended meaning of:

 a < b == c < d

Well that *obvious*! (((a < b) && (b == c)) < d) <G> Okay, okay, I see your point. But it would be useful (one day) to easily code the idiom (a op b) && (b op c), no? How about someone knocking up a mixin template for expressions of this format? I haven't got a clue how it could be done as the mixin/template/meta-programming syntax and semantics of D is still so obtuse and confusing to me that I can only do the very simplest things and then only after many false starts.

The chain that I'm concerned about is this: a==b == c==d which (the spacing makes clear) is meant to be (a==b) == (c==d) but which could me misread as (a==b) && (b==c) && (c==d) and which is probably (I'm not sure) currently implemented by the compiler as: ((a==b) ==c) ==d IMHO, C should have allowed comparison chaining from the start, but since it didn't, I don't think that it would be a good idea to start allowing it. There will always be the newbies from C who will misread it. (sigh)
Feb 13 2007
parent reply Russell Lewis <webmaster villagersonline.com> writes:
Russell Lewis wrote:
 Derek Parnell wrote:
 On Wed, 07 Feb 2007 17:09:35 -0800, Andrei Alexandrescu (See Website For

 What's the intended meaning of:

 a < b == c < d

Well that *obvious*! (((a < b) && (b == c)) < d) <G> Okay, okay, I see your point. But it would be useful (one day) to easily code the idiom (a op b) && (b op c), no? How about someone knocking up a mixin template for expressions of this format? I haven't got a clue how it could be done as the mixin/template/meta-programming syntax and semantics of D is still so obtuse and confusing to me that I can only do the very simplest things and then only after many false starts.

The chain that I'm concerned about is this: a==b == c==d which (the spacing makes clear) is meant to be (a==b) == (c==d) but which could me misread as (a==b) && (b==c) && (c==d) and which is probably (I'm not sure) currently implemented by the compiler as: ((a==b) ==c) ==d IMHO, C should have allowed comparison chaining from the start, but since it didn't, I don't think that it would be a good idea to start allowing it. There will always be the newbies from C who will misread it. (sigh)

Addendum: I would be ok with making the less than/greater than operators be chainable (since those operators are nonsense when used with boolean values), but I would ask that no expression be able to mix less-than and greater-than. It would be ok to mix < with <=, but not < with >.
Feb 13 2007
parent reply "Joel C. Salomon" <JoelCSalomon Gmail.com> writes:
Russell Lewis wrote:
 The chain that I'm concerned about is this:
     a==b == c==d
 which (the spacing makes clear) is meant to be
     (a==b) == (c==d)
 but which could me misread as
     (a==b) && (b==c) && (c==d)
 and which is probably (I'm not sure) currently implemented by the 
 compiler as:
     ((a==b) ==c) ==d

 IMHO, C should have allowed comparison chaining from the start, but 
 since it didn't, I don't think that it would be a good idea to start 
 allowing it.  There will always be the newbies from C who will misread 
 it.  (sigh)

Addendum: I would be ok with making the less than/greater than operators be chainable (since those operators are nonsense when used with boolean values), but I would ask that no expression be able to mix less-than and greater-than. It would be ok to mix < with <=, but not < with >.

Why this prejudice? With the chaining as people have discussed it, a < b > c expands to (a < b) && (b > c) — why would you prohibit this? --Joel
Feb 14 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Joel C. Salomon wrote:
 Russell Lewis wrote:
 The chain that I'm concerned about is this:
     a==b == c==d
 which (the spacing makes clear) is meant to be
     (a==b) == (c==d)
 but which could me misread as
     (a==b) && (b==c) && (c==d)
 and which is probably (I'm not sure) currently implemented by the 
 compiler as:
     ((a==b) ==c) ==d

 IMHO, C should have allowed comparison chaining from the start, but 
 since it didn't, I don't think that it would be a good idea to start 
 allowing it.  There will always be the newbies from C who will 
 misread it.  (sigh)

Addendum: I would be ok with making the less than/greater than operators be chainable (since those operators are nonsense when used with boolean values), but I would ask that no expression be able to mix less-than and greater-than. It would be ok to mix < with <=, but not < with >.

Why this prejudice? With the chaining as people have discussed it, a < b > c expands to (a < b) && (b > c) — why would you prohibit this?

I would assume the reason is because it's not used in math. --bb
Feb 14 2007
parent Joel Salomon <JoelCSalomon Gmail.com> writes:
 With the chaining as people have discussed it,
     a < b > c
 expands to
     (a < b) && (b > c)
 — why would you prohibit this?

I would assume the reason is because it's not used in math.

I’ve used it — and hairier stuff besides. ∅ ≠ A ⊆ (Ω ∋ α) ⊆ℝⁿ (No, I don’t actually expect any programming language to accept this.) “I do it all because I’m evil…” — Voltaire, “When you’re evil”
Feb 14 2007
prev sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Derek Parnell" <derek nomail.afraid.org> wrote in message 
news:ytund437jnul$.1nx7qfyf3zj8u$.dlg 40tude.net...

 Second thought: Why not make it do what the coder is wanting it to do?

I'd really like to be able to say if(0.5 <= x <= 1.5) ... :)
Feb 07 2007
prev sibling next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Walter Bright wrote:
 Right now, in D (as well as C and C++), when you see the expression:
 
     if (a < b < c)
 
 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). 

So your first thought, the newbie's first thought and my first thought all agree: it means a<b && b<c As was pointed out already, let's make it that way. Adding these chained comparisons improves readability* and adds another popular feature from scripting languages. L. * compare with: if (a < b && c > b)
Feb 07 2007
parent "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Lionello Lunesu wrote:
 Walter Bright wrote:
 Right now, in D (as well as C and C++), when you see the expression:

     if (a < b < c)

 what is your first thought? Mine is that it was written by a newbie 
 who didn't realize that (a < b) returns true or false, and that it 
 does NOT mean ((a < b) && (b < c)). 

So your first thought, the newbie's first thought and my first thought all agree: it means a<b && b<c As was pointed out already, let's make it that way. Adding these chained comparisons improves readability* and adds another popular feature from scripting languages. L. * compare with: if (a < b && c > b)

I personally would like that. It is a good example of a dwim feature that doesn't add to the complexity of the language. Andrei
Feb 07 2007
prev sibling next sibling parent Henning Hasemann <hhasemann web.de> writes:
Another way to solve this problem might be the following:

- Say Comparsion operators are not defined for booleans
- Instead define a few new operations on booleans such as
  Aequivalence (for example "<->" instead of "==").
  Note for example that xor (is it ^^ in D too?) already has
  the same meaning as != for booleans.

implications whould be:
- new operator symbols may have to be introduced
- this change might break some code, but the compiler
  should spot every line thats affected by the change
- it should lead to a much 'cleaner' grammar, think of
  the reason why its "hello " ~ "world" not "hello " + "world"!

Henning
 
Feb 08 2007
prev sibling next sibling parent reply Peter Modzelewski <peter.modzelewski gmail.com> writes:
Walter Bright napisał(a):
 Right now, in D (as well as C and C++), when you see the expression:
 
     if (a < b < c)
 
 what is your first thought? Mine is that it was written by a newbie who 
 didn't realize that (a < b) returns true or false, and that it does NOT 
 mean ((a < b) && (b < c)). The odds approach certainty that this is a 
 logic error in the code, and even if it was intentional, it raises such 
 a red flag that it shouldn't be used anyway.
 
 Andrei has proposed (and I agreed) that this should be done away with in 
 the language, i.e. comparison operators should no longer be associative. 
  It's a simple change to the grammar. If one really did want to write 
 such code, it could be done with parentheses:
 
     if ((a < b) < c)
 
 to get the original behavior. At least, that looks intentional.
 
 I don't think this will break existing code that isn't already broken.

It's cool when language makes it easy not to make mistakes (maybe not as java by not letting programmer to do anything serious but still handy idea) but isn't it (on small scale but always) losing compatibility with C, which could complicate making bindings etc? Libraries creators could have used them in the right meaning for some strange reason... As if making "the real meaning". "The real meaning" can be different for each person. some would like to use a<b<c in c style, some in python, some will have own ideas. and if i understand correctly, macros will do it. every man could write his own macro to change it in any way he like. So if it will not make problems with C compatibility vote ++ with no "real meanings" --------------------------- Peter Modzelewski www.team0xf.com www.keyer.team0xf.com
Feb 08 2007
parent Lionello Lunesu <lio lunesu.remove.com> writes:
Peter Modzelewski wrote:
 some would like to use a<b<c in c style

Find me one person :) You may use google code-search: find one example where a<b<c is not a bug. (Challenge #4 :D ) L.
Feb 08 2007
prev sibling next sibling parent Miles <_______ _______.____> writes:
Walter Bright wrote:
 Right now, in D (as well as C and C++), when you see the expression:
 
     if (a < b < c)
 
 what is your first thought?

In C, C++ and D, the way they are now, my first thought is the programmer needs to be replaced.
 and that it does NOT
 mean ((a < b) && (b < c)).

In a perfect language, the language should understand exactly what the programmer meant. I would love to be able to type thinks like: if (1 < x <= 10)... It makes a lot of sense. Python, ruby and other languages take it correctly.
 and even if it was intentional, it raises such
 a red flag that it shouldn't be used anyway.

Someone doing this intentionally points to a bug in the D spec.
 Andrei has proposed (and I agreed) that this should be done away with in
 the language, i.e. comparison operators should no longer be associative.
  It's a simple change to the grammar. If one really did want to write
 such code, it could be done with parentheses:
 
     if ((a < b) < c)

I don't think so. Considering a, b and c of scalar type, if (a < b) returns a boolean result, it should NOT be comparable with a scalar. This is why I insist again that not having a true boolean type in D is a big minus. In my opinion: (a < b < c) -> (a < b) && (b < c) (a < b == c > d) -> (a < b) && (b == c) && (c > d) ((a < b) < c) -> ERROR: comparing non-scalar and scalar types
Feb 08 2007
prev sibling next sibling parent Nicolai Waniek <no.spam thank.you> writes:
Walter Bright wrote:
 Right now, in D (as well as C and C++), when you see the expression:
 
     if (a < b < c)
 
 what is your first thought? Mine is that it was written by a newbie who
 didn't realize that (a < b) returns true or false, and that it does NOT
 mean ((a < b) && (b < c)). The odds approach certainty that this is a
 logic error in the code, and even if it was intentional, it raises such
 a red flag that it shouldn't be used anyway.
 
 Andrei has proposed (and I agreed) that this should be done away with in
 the language, i.e. comparison operators should no longer be associative.
  It's a simple change to the grammar. If one really did want to write
 such code, it could be done with parentheses:
 
     if ((a < b) < c)
 
 to get the original behavior. At least, that looks intentional.
 
 I don't think this will break existing code that isn't already broken.

I'd like to have if (a < b < c) ... automatically expanding to if ((a < b) && (b < c)) ... and if ((a < b) < c) raising some exception. Well, i can't give you any serious reasons for why, but i'm used to a < b < c from math. I tried to find something else that would make it possible to write something like if (b in [a,c]) where [a,b] is a compact interval (that means a <= b <= c). But this would let it not be distinguished from an interval's declaration as well as you wouldn't be able to write something like: if (b in (a,c]) // a < b <= c Perhaps someone has a nice, good looking, easy readable solution.
Feb 14 2007
prev sibling parent Henning Hasemann <hhasemann web.de> writes:
On Thu, 8 Feb 2007 09:49:56 +0100
Henning Hasemann <hhasemann web.de> wrote:

 
 Another way to solve this problem might be the following:
 
 - Say Comparsion operators are not defined for booleans
 - Instead define a few new operations on booleans such as
   Aequivalence (for example "<->" instead of "==").
   Note for example that xor (is it ^^ in D too?) already has
   the same meaning as != for booleans.
 
 implications whould be:
 - new operator symbols may have to be introduced
 - this change might break some code, but the compiler
   should spot every line thats affected by the change
 - it should lead to a much 'cleaner' grammar, think of
   the reason why its "hello " ~ "world" not "hello " + "world"!
 

If I remember correctly this is also what eiffel does btw, AND it whould be possible to realize additionally to the chaining. see: a < b < c means (a < b) && (b < c) a == b == c == d means (a == b) && (b == c) && (c == d) if you whould want to test if a == b yields the same boolean value as c == d, i.e. (a == b) == (c == d) you would write (a == b) <-> (c == d) note how clear this reads, you see at a first glance that results of boolean expressions are compared, which, as it is not used very often can not happen by accident (as up to now in a < b < c) anymore. I'm not that sure if the <-> - Symbol is a good idea though, but Im sure it whould be possible to find alternatives to it. Henning
Feb 15 2007