"with" still sucks + removing features + adding features
bearophile
bearophileHUGS at lycos.com
Mon May 18 17:25:26 PDT 2009
Andrei Alexandrescu:
Thank you for bringing a "real" example that gives something to work on.
>Awful!<
Well, one of your cases was wrong. Using the +1 at the end one of those cases become:
case 'A' .. 'Z'+1, 'a' .. 'z'+1:
Instead of what you have written:
case 'A' .. 'Z'+1: case 'a' .. 'z'+1:
I agree that that syntax with +1 isn't very nice looking. But the advantage of +1 is that it introduces (almost) no new syntax, it's not easy to miss, its meaning is easy to understand. AND you don't have to remember that in a case the .. is inclusive while in foreach is exclusive on the right, keeping the standard way in D to denote ranges.
-------------------------
We can introduce in D a syntax that maps on the semantics of iota(start, stop) or even iota(start, stop, step) (I don't remember if iota() supports opIn_r, and has length, if not then it's better to add them).
So you can do:
foreach (i; somerangesyntax) {...}
(So this replaces the current ranged foreach syntax).
case somerangesyntax: ...
if (x in somerangesyntax) {...}
map(fun, somerangesyntax);
And more, using only one (or two) general syntaxes.
-------------------------
The simple exclusive range syntax, with +1:
void classify(char c) {
write("You passed ");
switch (c) {
case '#':
writeln("a hash sign.");
break;
case '0' .. '9'+1:
writeln("a digit.");
break;
case 'A' .. 'Z'+1, 'a' .. 'z'+1:
writeln("an ASCII character.");
break;
case '.', ',', ':', ';', '!', '?':
writeln("a punctuation mark.");
break;
default:
writeln("quite a character!");
break;
}
}
Using Chapel closed range syntax:
void classify(char c) {
write("You passed ");
switch (c) {
case '#':
writeln("a hash sign.");
break;
case '0' ..# '9':
writeln("a digit.");
break;
case 'A' ..# 'Z', 'a' ..# 'z':
writeln("an ASCII character.");
break;
case '.', ',', ':', ';', '!', '?':
writeln("a punctuation mark.");
break;
default:
writeln("quite a character!");
break;
}
}
An alternative to that Chapel syntax:
void classify(char c) {
write("You passed ");
switch (c) {
case '#':
writeln("a hash sign.");
break;
case '0' ..> '9':
writeln("a digit.");
break;
case 'A' ..> 'Z', 'a' ..> 'z':
writeln("an ASCII character.");
break;
case '.', ',', ':', ';', '!', '?':
writeln("a punctuation mark.");
break;
default:
writeln("quite a character!");
break;
}
}
It may be easy to miss the third point (but it's not a noisy syntax)
void classify(char c) {
write("You passed ");
switch (c) {
case '#':
writeln("a hash sign.");
break;
case '0' ... '9':
writeln("a digit.");
break;
case 'A' ... 'Z', 'a' ... 'z':
writeln("an ASCII character.");
break;
case '.', ',', ':', ';', '!', '?':
writeln("a punctuation mark.");
break;
default:
writeln("quite a character!");
break;
}
}
Using something more explicit (interval() is lazy and inclusive on the right. The D compiler optimizes away at compile time the following calls):
void classify(char c) {
write("You passed ");
switch (c) {
case '#':
writeln("a hash sign.");
break;
case interval('0', '9'):
writeln("a digit.");
break;
case interval('A', 'Z'), interval('a', 'z'):
writeln("an ASCII character.");
break;
case '.', ',', ':', ';', '!', '?':
writeln("a punctuation mark.");
break;
default:
writeln("quite a character!");
break;
}
}
void classify(char c) {
write("You passed ");
switch (c) {
case '#':
writeln("a hash sign.");
break;
case ['0' .. '9']:
writeln("a digit.");
break;
case ['A' .. 'Z'], ['a' .. 'z']:
writeln("an ASCII character.");
break;
case '.', ',', ':', ';', '!', '?':
writeln("a punctuation mark.");
break;
default:
writeln("quite a character!");
break;
}
}
Such syntaxes are meant to be used in every other situation too (and I'd like to have another syntax that is non-inclusive, possibly like the current one):
foreach (i; 'A' .. 'Z'+1) {...}
case 'A' .. 'Z'+1: ...
if (x in 'A' .. 'Z'+1) {...}
map(fun, 'A' .. 'Z'+1);
foreach (i; 'A' ..# 'Z') {...}
case 'A' ..# 'Z': ...
if (x in 'A' ..# 'Z') {...}
map(fun, 'A' ..# 'Z');
foreach (i; 'A' ..> 'Z') {...}
case 'A' ..> 'Z': ...
if (x in 'A' ..> 'Z') {...}
map(fun, 'A' ..> 'Z');
foreach (i; 'A' ... 'Z') {...}
case 'A' ... 'Z': ...
if (x in 'A' ... 'Z') {...}
map(fun, 'A' ... 'Z');
foreach (i; interval('A', 'Z')) {...}
case interval('A', 'Z'): ...
if (x in interval('A', 'Z')) {...}
map(fun, interval('A', 'Z'));
foreach (i; ['A' .. 'Z']) {...}
case ['A' .. 'Z']: ...
if (x in ['A' .. 'Z']) {...}
map(fun, ['A' .. 'Z']);
The a..b+1 syntax can't be used inside map() in a simple way.
The [a .. b] syntax is acceptable, but then it doesn't offer a good way to define those if() and map() for the noninclusive situation:
// inclusive cases?
foreach (i; ['A' .. 'Z']) {...}
case ['A' .. 'Z']: ...
if (x in ['A' .. 'Z']) {...}
map(fun, ['A' .. 'Z']);
// noninclusive cases?
foreach (i; 'A' .. 'Z') {...}
case 'A' .. 'Z': ...
if (x in 'A' .. 'Z') {...}
map(fun, 'A' .. 'Z');
Well... That's not perfect, but it looks better than the syntax suggested by Andrei. Do you have better ideas?
Bye,
bearophile
More information about the Digitalmars-d
mailing list