February 08, 2007
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);
> }
You can use a foreach-over-tuple instead of recursion:

bool ordered(T...)(T data)
{
    foreach(i, d; data)
    {
       static if (i < data.length - 1)
           if (! (d < data[i+1])) return false;
    }
    return true;
}
February 08, 2007
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
February 08, 2007
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


February 08, 2007
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.
>>> 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?

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
February 08, 2007
> 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.
February 08, 2007
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.
>> 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?

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...
February 08, 2007
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
February 13, 2007
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)
February 13, 2007
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 >.
February 14, 2007
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