This is code I have had to write:
auto arr = genArray();
schwartzSort!("...")(arr);
return result;
Often you know your array is small (or you don't want to sort the original
array/range), so you can add a functional-style variant that sorts a copy, 33%
of the code lines, a big saving of code:
return schwartzSorted!("...")(genArray());
---------------
schwartzSorted isn't a nice name, maybe you can find something shorter can
simpler to write, like "keySort" (key is the mapping function).
---------------
The toString of one Tuple gives me:
Tuple!(immutable(char)[],float)(hi, 1)
But I think that's a bit overkill and very long, in most situations you know
the type, so something like the following is better and much less noisy
(especially if you have to print an array of them (also notice the useful ""
around the string):
tuple("hi", 1)
I have seen than D2 writeln() prints [] around associative arrays, but not
around arrays, while D1 prints [] around both of them. This is a regression
even compared to the raw behavior of D1.
---------------
Tuple misses opCmp and toHash. I don't want to post pages of code here, but I
suggest you to take a look at:
- Record() struct in module templates
- hash() function template in module func
- structCmp() function template in module func
The code is here still:
http://www.fantascienza.net/leonardo/so/libs_d.zip
If you have questions about that please ask.
This allows people to use Tuples as keys of AA/sets and to sort them, even if
they recursively contain other Tuples (or even if they contain normal structs).
This allows to use Tuple in a *much* more flexible way in programs, increasing
their usefulness three-fold.
Bye,
bearophile

Tuple misses opCmp and toHash. I don't want to post pages of code here, but I

- Record() struct in module templates
- hash() function template in module func
- structCmp() function template in module func
The code is here still:
http://www.fantascienza.net/leonardo/so/libs_d.zip
If you have questions about that please ask.
This allows people to use Tuples as keys of AA/sets and to sort them, even if

This allows to use Tuple in a *much* more flexible way in programs, increasing
their usefulness three-fold.

Bye,
bearophile

Vote++ for giving Tuple a decent default implementation of opCmp and toHash.
Then
maybe I could use Tuple to represent joint samples from a probability
distribution
(I often want to use hash tables to count the frequency of each observation
using
hash tables). Right now, I use a really ad-hoc struct to do this, and I'm sure
that my scheme for taking the hashes of the elements of the struct and turning
them into one hash is sub-optimal, but it works.
As far as opCmp, here's a useful snippet for a default opCmp for tuples. It
works
well when all you need is an arbitrary transitive ordering for use in a binary
tree or something.
int opCmp(const ref typeof(this) other) const {
foreach(ti, elem; other.tupleof) {
if(this.tupleof[ti] < elem) {
return -1;
} else if(this.tupleof[ti] > elem) {
return 1;
}
}
return 0;
}

Vote++ for giving Tuple a decent default implementation of opCmp and toHash.

I have a much better idea (that I have expressed here more than one year ago):
let's add good *recursive* opCmp, toHash, opEqual, toString to all structs.
Similar "small" things are able to improve the flexibility of D2 a lot.
Bye,
bearophile

Vote++ for giving Tuple a decent default implementation of opCmp and toHash.

I have a much better idea (that I have expressed here more than one year ago):
let's add good *recursive* opCmp, toHash, opEqual, toString to all structs.
Similar "small" things are able to improve the flexibility of D2 a lot.

I have used the word recursive because the functions I have designed (and I
think they are designed correctly) call themselves until they stop calling
themselves because a stopping criterion is met. That's recursivity, I think.
Bye,
bearophile

I have used the word recursive because the functions I have designed (and I
think they are designed correctly) call themselves until they stop calling
themselves because a stopping criterion is met. That's recursivity, I think.

But then what if you have a web of class objects that ultimately will
close a cycle?
Transitive: you'd use a worklist. Recursive: you'd recurse forever.
Andrei

I have used the word recursive because the functions I have designed
(and I think they are designed correctly) call themselves until they
stop calling themselves because a stopping criterion is met. That's
recursivity, I think.

But then what if you have a web of class objects that ultimately will
close a cycle?
Transitive: you'd use a worklist. Recursive: you'd recurse forever.
Andrei

bearophile explicitly said "structs". I assume it would extend to
primitives, treating pointers as integer types. I also assume it would
call .toHash on any object.
This would still allow you to recurse infinitely, but it would require
added effort:
struct S
{
C c;
}
class C
{
S s;
this () { s.c = this; }
auto toHash () { return s.toHash; }
}

I have used the word recursive because the functions I have designed
(and I think they are designed correctly) call themselves until they
stop calling themselves because a stopping criterion is met. That's
recursivity, I think.

But then what if you have a web of class objects that ultimately will
close a cycle?
Transitive: you'd use a worklist. Recursive: you'd recurse forever.
Andrei

bearophile explicitly said "structs". I assume it would extend to
primitives, treating pointers as integer types. I also assume it would
call .toHash on any object.

No matter. As soon as a class is reached, the problem appears. I wanted
more to fix a terminological issue than to naysay.
Andrei