针对常量整数集的案例陈述?
Case statement against constant set of integers?
精简版
给定:
const
Whitespace = [[=10=]09, [=10=]0A, [=10=]0C, [=10=]20];
- 作品:
if ch in Whitespace then...
- 失败:
case ch of Whitespace: ...
长版
通常,如果您要有一个 case
语句,您可以为每种情况包含不同的值,例如:
var
ch: UCS4Char; // unsigned 32-bit
case ch of
48..57: {asciiDigit}; //i.e. '0'..'9'
65..70: {asciiUpperHexDigit}; //i.e. 'A'..'F'
97..102: {asciiLowerHexDigit}; //i.e. 'a'..'f'
end;
可行,但我希望这些值是常量:
const
//https://infra.spec.whatwg.org/#code-points
asciiDigit = [Ord('0')..Ord('9')]; //https://infra.spec.whatwg.org/#ascii-digit
asciiUpperHexDigit = [Ord('A')..Ord('F')]; //https://infra.spec.whatwg.org/#ascii-upper-hex-digit
asciiLowerHexDigit = [Ord('a')..Ord('f')]; //https://infra.spec.whatwg.org/#ascii-lower-hex-digit
asciiHexDigit = asciiUpperHexDigit + asciiLowerHexDigit; //https://infra.spec.whatwg.org/#ascii-hex-digit
asciiUpperAlpha = [Ord('A')..Ord('Z')]; //https://infra.spec.whatwg.org/#ascii-upper-alpha
asciiLowerAlpha = [Ord('a')..Ord('z')]; //https://infra.spec.whatwg.org/#ascii-lower-alpha
asciiAlpha = asciiUpperAlpha + asciiLowerAlpha; //https://infra.spec.whatwg.org/#ascii-alpha
asciiAlphaNumeric = asciiDigit + asciiAlpha; //https://infra.spec.whatwg.org/#ascii-alphanumeric
是否有 any 排列的 any 语法允许:
case
正在 Cardinal
- 针对 "一组
Cardinal
s"?
或者我是否永远坚持以下内容?
var
ch: UCS4Char; //unsigned 32-bit
case ch of
Ord('!'): FState := MarkupDeclarationOpenState;
Ord('/'): FState := EndTagOpenState;
Ord('?'): AddParseError('unexpected-question-mark-instead-of-tag-name');
UEOF: AddParseError('eof-before-tag-name parse error');
Whitespace: FState := SharkTankContosoGrobber;
else
if ch in asciiDigit then
begin
FReconsume := True;
FState := tsTagNameState;
end
else
AddParseError('invalid-first-character-of-tag-name parse error');
end;
显然,使用概念 case
与正在执行的逻辑匹配;必须做的 if-elseif
是......较少。
注意:我不需要它实际上成为Delphi "set
",即具有特定含义的特定术语。我只想:
case ch of Whitespace: ...
以同样的方式工作:
if ch in Whitespace then...
已经有效了。
而且我们知道编译器已经可以将 Cardinal 与“集合”进行比较,因为以下已经有效:
case ch of
[=16=]0A, [=16=]0D, [=16=]09, [=16=]32: ...
end;
它将 Cardinal 与“一组数字”进行比较。
红利阅读
- Delphi case statement for integer ranges
- any way to compare an integer variable to a list of integers in if statement
不,不支持。
根据官方documentation:
A case statement has the form:
case selectorExpression of
caseList1: statement1;
...
caseListn: statementn;
end
where [...] each caseList
is one of the following:
- A numeral, declared constant, or other expression that the compiler can evaluate without executing your program. It must be of an ordinal type compatible with
selectorExpression
. [...]
- A subrange having the form
First..Last
, where First
and Last
both satisfy the criterion above and First
is less than or equal to Last
.
- A list having the form
item1, ..., itemn
, where each item satisfies one of the criteria above.
因此,作为 case
语法的一部分,这仅允许单个值、显式范围和此类值的列表。
尽管 Delphi 文档很好,但它并不完美,您不能 100% 依赖它。但是,我相信所有有经验的 Delphi 开发人员都会同意 caseList
不能是预先声明的 single-identifier 与 selectorExpression
.[=29= 兼容的序数值的“集合” ]
您可以在 Embarcadero's Jira 提交功能请求。
但是您可以使用范围语法和先前声明的子范围类型(不是设置常量)来实现部分类似的东西:
type
TAsciiDigit = '0'..'9';
TAsciiLatinCapitalLetter = 'A'..'Z';
TAsciiLatinSmallLetter = 'a'..'z';
procedure TForm1.FormCreate(Sender: TObject);
begin
var c := 'R';
case c of
Low(TAsciiDigit) .. High(TAsciiDigit):
ShowMessage('Digit!');
Low(TAsciiLatinCapitalLetter) .. High(TAsciiLatinCapitalLetter):
ShowMessage('Capital!');
Low(TAsciiLatinSmallLetter) .. High(TAsciiLatinSmallLetter):
ShowMessage('Small letter!');
else
ShowMessage('Something else.');
end;
end;
加分项: 事实上,文档的非 100% 准确性可以在上面引用的部分中看到:
selectorExpression
is any expression of an ordinal type smaller than 32 bits
那是胡说八道。 selectorExpression
当然可以是32位整数。
精简版
给定:
const
Whitespace = [[=10=]09, [=10=]0A, [=10=]0C, [=10=]20];
- 作品:
if ch in Whitespace then...
- 失败:
case ch of Whitespace: ...
长版
通常,如果您要有一个 case
语句,您可以为每种情况包含不同的值,例如:
var
ch: UCS4Char; // unsigned 32-bit
case ch of
48..57: {asciiDigit}; //i.e. '0'..'9'
65..70: {asciiUpperHexDigit}; //i.e. 'A'..'F'
97..102: {asciiLowerHexDigit}; //i.e. 'a'..'f'
end;
可行,但我希望这些值是常量:
const
//https://infra.spec.whatwg.org/#code-points
asciiDigit = [Ord('0')..Ord('9')]; //https://infra.spec.whatwg.org/#ascii-digit
asciiUpperHexDigit = [Ord('A')..Ord('F')]; //https://infra.spec.whatwg.org/#ascii-upper-hex-digit
asciiLowerHexDigit = [Ord('a')..Ord('f')]; //https://infra.spec.whatwg.org/#ascii-lower-hex-digit
asciiHexDigit = asciiUpperHexDigit + asciiLowerHexDigit; //https://infra.spec.whatwg.org/#ascii-hex-digit
asciiUpperAlpha = [Ord('A')..Ord('Z')]; //https://infra.spec.whatwg.org/#ascii-upper-alpha
asciiLowerAlpha = [Ord('a')..Ord('z')]; //https://infra.spec.whatwg.org/#ascii-lower-alpha
asciiAlpha = asciiUpperAlpha + asciiLowerAlpha; //https://infra.spec.whatwg.org/#ascii-alpha
asciiAlphaNumeric = asciiDigit + asciiAlpha; //https://infra.spec.whatwg.org/#ascii-alphanumeric
是否有 any 排列的 any 语法允许:
case
正在Cardinal
- 针对 "一组
Cardinal
s"?
或者我是否永远坚持以下内容?
var
ch: UCS4Char; //unsigned 32-bit
case ch of
Ord('!'): FState := MarkupDeclarationOpenState;
Ord('/'): FState := EndTagOpenState;
Ord('?'): AddParseError('unexpected-question-mark-instead-of-tag-name');
UEOF: AddParseError('eof-before-tag-name parse error');
Whitespace: FState := SharkTankContosoGrobber;
else
if ch in asciiDigit then
begin
FReconsume := True;
FState := tsTagNameState;
end
else
AddParseError('invalid-first-character-of-tag-name parse error');
end;
显然,使用概念 case
与正在执行的逻辑匹配;必须做的 if-elseif
是......较少。
注意:我不需要它实际上成为Delphi "set
",即具有特定含义的特定术语。我只想:
case ch of Whitespace: ...
以同样的方式工作:
if ch in Whitespace then...
已经有效了。
而且我们知道编译器已经可以将 Cardinal 与“集合”进行比较,因为以下已经有效:
case ch of
[=16=]0A, [=16=]0D, [=16=]09, [=16=]32: ...
end;
它将 Cardinal 与“一组数字”进行比较。
红利阅读
- Delphi case statement for integer ranges
- any way to compare an integer variable to a list of integers in if statement
不,不支持。
根据官方documentation:
A case statement has the form:
case selectorExpression of caseList1: statement1; ... caseListn: statementn; end
where [...] each
caseList
is one of the following:
- A numeral, declared constant, or other expression that the compiler can evaluate without executing your program. It must be of an ordinal type compatible with
selectorExpression
. [...]- A subrange having the form
First..Last
, whereFirst
andLast
both satisfy the criterion above andFirst
is less than or equal toLast
.- A list having the form
item1, ..., itemn
, where each item satisfies one of the criteria above.
因此,作为 case
语法的一部分,这仅允许单个值、显式范围和此类值的列表。
尽管 Delphi 文档很好,但它并不完美,您不能 100% 依赖它。但是,我相信所有有经验的 Delphi 开发人员都会同意 caseList
不能是预先声明的 single-identifier 与 selectorExpression
.[=29= 兼容的序数值的“集合” ]
您可以在 Embarcadero's Jira 提交功能请求。
但是您可以使用范围语法和先前声明的子范围类型(不是设置常量)来实现部分类似的东西:
type
TAsciiDigit = '0'..'9';
TAsciiLatinCapitalLetter = 'A'..'Z';
TAsciiLatinSmallLetter = 'a'..'z';
procedure TForm1.FormCreate(Sender: TObject);
begin
var c := 'R';
case c of
Low(TAsciiDigit) .. High(TAsciiDigit):
ShowMessage('Digit!');
Low(TAsciiLatinCapitalLetter) .. High(TAsciiLatinCapitalLetter):
ShowMessage('Capital!');
Low(TAsciiLatinSmallLetter) .. High(TAsciiLatinSmallLetter):
ShowMessage('Small letter!');
else
ShowMessage('Something else.');
end;
end;
加分项: 事实上,文档的非 100% 准确性可以在上面引用的部分中看到:
selectorExpression
is any expression of an ordinal type smaller than 32 bits
那是胡说八道。 selectorExpression
当然可以是32位整数。