I apologize for what I'm sure is a very basic question. How
should I do this elegantly?
bool set[char[]];
//Stuff
char[][] words = set.keys;
It gives the error:
Error: cannot implicitly convert expression (set.keys()) of type
const(char)[][] to char[][]
and I'm not sure why I can't copy const data to normal data.

If you have a const array, you can create a non-const copy of the array using
the
.dup property of the array. The reason that you need this is that dynamic-length
arrays share data when you assign them between variables, and you can't have a
non-const variable using something else's const data without running into some
really nasty problems.
In your specific case, though, the .dup property might not convert the inner
levels of the nested array. If it doesn't work, you could try something like
this:
char[][] words;
words.length = set.keys.length;
foreach(size_t i, const char[] text; set.keys) {
words[i] = text.dup;
}
If you don't really need to modify the individual characters in the array, you
might just want to stick with const; it will be more efficient. You might also
want to define the set as bool[string] because associative arrays prefer
const/immutable keys for some reason.

If you have a const array, you can create a non-const copy of the array
using the .dup property of the array. The reason that you need this is that
dynamic-length arrays share data when you assign them between variables,
and you can't have a non-const variable using something else's const data
without running into some really nasty problems.
In your specific case, though, the .dup property might not convert the inner
levels of the nested array. If it doesn't work, you could try something
like this:
char[][] words;
words.length = set.keys.length;
foreach(size_t i, const char[] text; set.keys) {
words[i] = text.dup;
}
If you don't really need to modify the individual characters in the array,
you might just want to stick with const; it will be more efficient. You
might also want to define the set as bool[string] because associative
arrays prefer const/immutable keys for some reason.

The inner characters are going to need to be immutable anyway.
bool[char[]] set;
doesn't work, because the key isn't immutable. When he tries to use it the
compiler will scream at him (though ideally, it wouldn't even let him declare
it - there's a bug report on that). So, his AA is going to need to be
bool[string] set;
Then there's not need to dup the inner array unless he really insists on
having the chars be mutable. But it would be far more normal to leave them as
immutable - i.e. as string. So, all he should need is
auto words = set.keys.dup;
and he'll get a string[].
- Jonathan M Davis

doesn't work, because the key isn't immutable. When he tries to
use it the compiler will scream at him (though ideally, it
wouldn't even let him declare it - there's a bug report on that).

When I use a key with it I use:
set[cast(immutable) key] = true;
This doesn't generate any compiler errors.
auto words2 = set.keys.sort;
auto words2 = set.keys.dup.sort;
both did what I wanted using string. Thank you, I'll convert
everything to strings. I guess I created my own difficulties by
using char arrays.

BLM:
const(char)[][] words = set.keys.sort;
Converting the function's return type to const and doing this did
what I wanted elegantly, I didn't realise I could apply sort to a
const like this.
Trying to use .dup like this:
char[][] words = set.keys.dup;
gives this error message:
Error: cannot implicitly convert expression (_adSort(_adDupT(&
D13TypeInfo_AAxa6__initZ,set.keys()),& D11TypeInfo_Aa6__initZ))
of type const(char)[][] to char[][]
Isn't there any sort of cast(nonconst) equivalent?

1. Don't use the built-in sort. It's going to be deprecated. Use
std.algorithm.sort.
2. You should pretty much _never_ cast away const or immutable in D unless you
really know what you're doing. Casting away const or immutable and then
modifying a variable is undefined (unlike in C++). It violates the compiler's
guarantees and risks segfaulting and the like.

bool[char[]] set;
doesn't work, because the key isn't immutable. When he tries to
use it the compiler will scream at him (though ideally, it
wouldn't even let him declare it - there's a bug report on that).

When I use a key with it I use:
set[cast(immutable) key] = true;
This doesn't generate any compiler errors.
auto words2 = set.keys.sort;
auto words2 = set.keys.dup.sort;

_Don't_ cast to immutable unless you can _guarantee_ that there are no other
references to the variable being cast. You're going to get bugs otherwise. In
general, if you're doing any casts to or from const or immutable, you're doing
something wrong (there are exceptions - primarily involving passing stuff
across threads - but again, you have to know what you're doing).
If the key is not already immutable (or has immutable elements in the case of
an array), then you need to actually get an immutable version, not cast it. In
the case of an array, that would mean using idup. However, even better would
be to use std.conv.to. That way, if the array or its elements are already
immutable, you don't end up needlessly copying the array.
For instance,
bool[string] set;
set[to!string(key)] = value;

both did what I wanted using string. Thank you, I'll convert
everything to strings. I guess I created my own difficulties by
using char arrays.

Yes. In general, you should be using string (which is immutable(char)[])
rather than char[]. In general, modifying an array of char just doesn't make
sense (particularly in light of unicode), and you'll generally run into fewer
difficulties. It also helps avoid duplication, because you never need to copy
arrays of immutable elements unless you need a mutable copy, whereas you tend
to have to copy arrays of mutable elements to avoid having stuff modify them.
Also, more functions in the standard library support string than char[].
This question on stackoverflow would be good to look at for a more detailed
explanation with regards to AAs and immutability:
http://stackoverflow.com/questions/4611477/why-cant-i-store-string-keys-in-an-
associative-array
Also, if you haven't read it yet, you should read this article on arrays:
http://www.dsource.org/projects/dcollections/wiki/ArrayArticle
It should help you understand how they work, which will hopefully help you
avoid some headaches.
- Jonathan M Davis

Thank you, I'll read those articles. Is there a more elegant way
than this to get the string[] out of a range after using the
algorithms sort? Ranges are a bit of a mystery.
string[] temp;
foreach(i;sort(set.keys))
temp ~= to!string(i);
I'm a little worried that the very basic level of my posts is
spamming the forum, is there a D community forum for absolute
beginners?

Thank you, I'll read those articles. Is there a more elegant way
than this to get the string[] out of a range after using the
algorithms sort? Ranges are a bit of a mystery.
string[] temp;
foreach(i;sort(set.keys))
temp ~= to!string(i);

Sort returns a SortedRange, so if you passed it to a function which could take
advantage of that (such as find), it would be more efficient to use the result
of
sort, but sort sorts in place. So, if you want a new array, what you should
probably do is simply
auto temp = set.keys.dup;
sort(temp);
However, I think that .keys returns a newly allocated array such that you
don't need to dup it at all if you don't want to, which means that you'd do
something more like
auto temp = set.keys;
sort(temp);

I'm a little worried that the very basic level of my posts is
spamming the forum, is there a D community forum for absolute
beginners?

This pretty much _is_ the forum for absolute beginners. The whole point of
this forum is to answer questions for those learning D. It's digitalmars.D
which is for general discussion on D. You're in the right place.
- Jonathan M Davis

Assuming you change the declaration to bool set[string], your error will
look like:
Error: cannot implicitly convert expression (set.keys()) of type
string[] to char[][].
(string is the same as immutable(char)[])
The reason for the immutable key requirement is that associative arrays
are impossible to be implemented efficiently if their keys can be
changed randomly from outside the data structure.
Here is why the assignment would make this possible:
Dynamic arrays are reference types. This means that they don't contain
the data. They just point to it. This means that multiple dynamic array
variables can point to the same data. This is called aliasing:
import std.stdio;
void main() {
int[] x = [1,2,3]; // a [...] literal creates a new array
writeln(x); // "[1,2,3]"
int[] y = x; // y now refers to ('aliases') the same array
y[0] = 2; // this therefore changes the data x refers to
writeln(x); // "[2,2,3]"
}
Now assume assigning immutable data to a mutable reference would succeed:
import std.stdio;
void main() {
immutable int[] x = [1,2,3]; // creates a new immutable array
int[] y = x; // creates mutable-immutable aliasing (compile error)
y[0] = 2; // this would then change x, which is illegal because
it is immutable
}
import std.stdio;
void main() {
immutable int[] x = [1,2,3]; // create a new array
int[] y = x.dup;// make a mutable copy of it; this actually copies
the data
y[0]=2;
writeln(x); // "[1,2,3]" (x is unchanged, good)
}
The general issue is still there if immutable is burried two references
deep.
import std.stdio;
void main(){
immutable(int)[][] x = [[1],[2],[3]];
int[][] y = x; // error
y[0][0] = 2;
}
However, there is no built-in functionality to copy all the immutable
data that is reachable from the top.
import std.stdio;
void main(){
immutable(int)[][] x = [[1],[2],[3]];
auto y = new int[][](x.length); // create an array of the
appropriate length
foreach(i,e; x){
y[i] = e.dup; // e is of type immutable(int)[]
}
}