digitalmars.D.learn - Static arrays and std.algorithm.sort
- D Apprentice (42/42) Feb 20 2014 Greetings, D wizards.
- Stanislav Blinov (2/3) Feb 20 2014 sort(a[]);
- D Apprentice (8/12) Feb 20 2014 That's still using the slice syntax though? I just reread the
- Stanislav Blinov (5/14) Feb 20 2014 No. To be honest, I'm not fully agreeing with sort(a) not working
- Stanislav Blinov (25/25) Feb 20 2014 Note that you can create your own overload. Though it has to be
- Jesse Phillips (4/7) Feb 20 2014 Guess we will find out:
- Meta (33/33) Feb 20 2014 I believe the problem is that std.algorithm.sort requires a
- John Colvin (6/50) Feb 21 2014 static arrays are not slices. Using [] gives you a slice from a
Greetings, D wizards.
Given a static array, int[5] a, presumed to be filled with random
numbers, how does one sort it using std.algorithm.sort? Calling
sort(a) by itself errors out with:
test.d(7): Error: template std.algorithm.sort does not match any
function template declaration. Candidates are:
/usr/share/dmd/src/phobos/std/algorithm.d(8387):
std.algorithm.sort(alias less = "a < b", SwapStrategy ss =
SwapStrategy.unstable, Range)(Range r) if ((ss ==
SwapStrategy.unstable && (hasSwappableElements!Range ||
hasAssignableElements!Range) || ss != SwapStrategy.unstable &&
hasAssignableElements!Range) && isRandomAccessRange!Range &&
hasSlicing!Range && hasLength!Range)
test.d(7): Error: template std.algorithm.sort(alias less = "a <
b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if
((ss == SwapStrategy.unstable && (hasSwappableElements!Range ||
hasAssignableElements!Range) || ss != SwapStrategy.unstable &&
hasAssignableElements!Range) && isRandomAccessRange!Range &&
hasSlicing!Range && hasLength!Range) cannot deduce template
function from argument types !()(int[5])
This is a general interest question. As I understand it, D static
arrays are value types, as opposed to their dynamic siblings
which are reference types, and I suspect that is the underlying
issue here.
One little idiom I found, though I do not know if it's very
efficient, is using the array slice syntax:
sort (a[0..a.length]);
This works, but I'm curious if there's another (better) way? The
biggest advantage that I can see to the slice syntax is that it
allows the programmer to sort only part of the array, which one
could do in C with qsort.
Source:
import std.stdio;
import std.algorithm;
void main ()
{
int[5] a = [9, 5, 1, 7, 3];
//sort (a); //Fails
//sort (a[0..a.length]); //Works
writeln (a);
}
Thank you for your time.
Feb 20 2014
On Thursday, 20 February 2014 at 17:24:55 UTC, D Apprentice wrote:This works, but I'm curious if there's another (better) way?sort(a[]);
Feb 20 2014
On Thursday, 20 February 2014 at 17:29:44 UTC, Stanislav Blinov wrote:On Thursday, 20 February 2014 at 17:24:55 UTC, D Apprentice wrote:That's still using the slice syntax though? I just reread the documentation and it says that slicing does not copy any data, so there shouldn't be any issues with this method. But I'm curious, are there any other known ways, or is this the only one? Thank you for your reply.This works, but I'm curious if there's another (better) way?sort(a[]);
Feb 20 2014
On Thursday, 20 February 2014 at 17:34:37 UTC, D Apprentice wrote:On Thursday, 20 February 2014 at 17:29:44 UTC, Stanislav Blinov wrote:Yup.sort(a[]);That's still using the slice syntax though? I just reread the documentation and it says that slicing does not copy any data, so there shouldn't be any issues with this method.But I'm curious, are there any other known ways, or is this the only one?No. To be honest, I'm not fully agreeing with sort(a) not working too, but it seems unlikely it'd be supported. See http://d.puremagic.com/issues/show_bug.cgi?id=4114
Feb 20 2014
Note that you can create your own overload. Though it has to be
done "the long way", because dmd doesn't (yet?) allow overloading
templates imported from other modules:
import std.stdio;
import std.algorithm;
import std.traits;
template sort(alias less = "a < b", SwapStrategy ss =
SwapStrategy.unstable)
{
auto sort(Arr)(ref Arr arr) if (isStaticArray!Arr) {
return std.algorithm.sort!(less, ss)(arr[]);
}
auto sort(Range)(Range r) if (!isStaticArray!Range) {
return std.algorithm.sort!(less, ss)(r);
}
}
void main ()
{
int[5] a = [ 9, 5, 1, 7, 3 ];
int[] b = [ 4, 2, 1, 6, 3 ];
sort(a);
sort(b);
writeln(a);
writeln(b);
}
Feb 20 2014
On Thursday, 20 February 2014 at 18:33:02 UTC, Stanislav Blinov wrote:Note that you can create your own overload. Though it has to be done "the long way", because dmd doesn't (yet?) allow overloading templates imported from other modules:Guess we will find out: https://d.puremagic.com/issues/show_bug.cgi?id=12216
Feb 20 2014
I believe the problem is that std.algorithm.sort requires a
range, and fixed-size arrays are not ranges in D. I believe it's
because the most basic range functionality is the ability to do
this:
int[] arr = [0, 1, 2, 3];
while (arr.length > 0)
{
arr = arr[1..arr.length];
}
In other words, shrink the range size, which is obviously not
possible with a fixed-size array, since its size is... fixed. The
reason your example code works:
void main ()
{
int[5] a = [9, 5, 1, 7, 3];
//sort (a); //Fails
//Note that `a[0..a.length]` is equivalent to the shorter
syntax `a[]`
//sort (a[0..a.length]); //Works
writeln (a);
}
Is because while int[5] is not a range, int[] *is* a range, as I
demonstrated above. Although int[5] is not a range, you can
obtain a range "view" of it with the square brackets syntax. This
is referred to as slicing. The following are all valid slices of
an int[5]:
int[5] arr = [0, 1, 2, 3];
auto slice1 = arr[0..$]; //$ means arr.length in this context.
//slice1 == [0, 1, 2, 3]
auto slice2 = arr[1..$]; //slice2 == [1, 2, 3]
auto slice3 = arr[1..3]; //slice3 == [1, 2]
auto slice4 = arr[0..0]; //slice4 == [] empty slice, length == 0
but ptr != null
Feb 20 2014
On Thursday, 20 February 2014 at 17:24:55 UTC, D Apprentice wrote:
Greetings, D wizards.
Given a static array, int[5] a, presumed to be filled with
random
numbers, how does one sort it using std.algorithm.sort? Calling
sort(a) by itself errors out with:
test.d(7): Error: template std.algorithm.sort does not match any
function template declaration. Candidates are:
/usr/share/dmd/src/phobos/std/algorithm.d(8387):
std.algorithm.sort(alias less = "a < b", SwapStrategy ss =
SwapStrategy.unstable, Range)(Range r) if ((ss ==
SwapStrategy.unstable && (hasSwappableElements!Range ||
hasAssignableElements!Range) || ss != SwapStrategy.unstable &&
hasAssignableElements!Range) && isRandomAccessRange!Range &&
hasSlicing!Range && hasLength!Range)
test.d(7): Error: template std.algorithm.sort(alias less = "a <
b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if
((ss == SwapStrategy.unstable && (hasSwappableElements!Range ||
hasAssignableElements!Range) || ss != SwapStrategy.unstable &&
hasAssignableElements!Range) && isRandomAccessRange!Range &&
hasSlicing!Range && hasLength!Range) cannot deduce template
function from argument types !()(int[5])
This is a general interest question. As I understand it, D
static
arrays are value types, as opposed to their dynamic siblings
which are reference types, and I suspect that is the underlying
issue here.
One little idiom I found, though I do not know if it's very
efficient, is using the array slice syntax:
sort (a[0..a.length]);
This works, but I'm curious if there's another (better) way? The
biggest advantage that I can see to the slice syntax is that it
allows the programmer to sort only part of the array, which one
could do in C with qsort.
Source:
import std.stdio;
import std.algorithm;
void main ()
{
int[5] a = [9, 5, 1, 7, 3];
//sort (a); //Fails
//sort (a[0..a.length]); //Works
writeln (a);
}
Thank you for your time.
static arrays are not slices. Using [] gives you a slice from a
static array. I often find myself writing this:
int[5] aStatic = [9, 5, 1, 7, 3];
auto a = aStatic[];
and just being careful not to leak references.
Feb 21 2014









"Stanislav Blinov" <stanislav.blinov gmail.com> 