- 浏览: 220983 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
dysking:
SWT 和 JFace -
wangyuhfut:
东西不少啊。学习中。。。
一个比较好、中文说明的emacs配置文件 1 -
pacocai:
呵呵!学习,学习~~~不过要说编辑器的话个人更喜欢用VIM,比 ...
一个比较好、中文说明的emacs配置文件 1 -
zhf1zhf2:
这两百多个记起来也不容易啊
英国人是这样背的! -
regex:
试了两次,都是乱码,版本是23.1.1,看来不适合
汉化 Emacs 菜单
7 If 语句
If 语句提供了按条件执行语句的方法。
If语句:
if ( If条件 ) Then语句
if ( If条件 ) Then语句 else Else语句
If条件:
表达式
auto 标识符 = 表达式
单个声明符 = 表达式
Then语句:
作用域语句
Else语句:
作用域语句
表达式 将被计算,计算的结果必须可以被转换为布尔型。如果它为 true,则转换到 Then
语句,否则就转换到 Else语句。
“虚悬的(dangling) else”问题可以通过使用最近的那个 if 语句关联到该 else 来解决。
如果提供有一个 auto 标识符,那么它就会被 声明并被初始化 成该表达式的 值和类型。它的作用范围 从被初始化开始一直到 Then语句 的结尾。
如果提供有一个 声明符,那么它就会被声明并被初始化成该表达式的值。它的作用范围从
被初始化开始一直到 Then语句 的结尾。
import std.regexp;
...
if (auto m = std.regexp.search("abcdef", "b(c)d"))
{
writefln("[%s]", m.pre); // 输出 [a]
writefln("[%s]", m.post); // 输出 [ef]
writefln("[%s]", m.match(0)); // 输出 [bcd]
writefln("[%s]", m.match(1)); // 输出 [c]
writefln("[%s]", m.match(2)); // 输出 []
}
else
{
writefln(m.post); // 错误,m 未定义
}
writefln(m.pre); // 错误,m 未定义
8 While 语句
While语句:
while ( 表达式 ) 作用域语句
While 语句实现了简单的循环。 表达式 将被计算,计算的结果必须可以被转换为布尔型。
如果它的结果为 true,执行作用域语句。在执行该 作用域语句 后,此 表达式 会被再次计
算,并且如果为 true 的话,该 作用域语句 会被再次执行。这个过程会持续下去,直到 表
达式 的计算出的结果为 false。
int i = 0;
while (i < 10)
{
foo(i);
i++;
}
Break语句 将退出循环。Continue语句 将直接转去再次计算 表达式。
9 Do 语句
Do语句:
do 作用域语句 while ( 表达式 )
do-While 语句实现了简单的循环。 先执行 作用域语句。然后 表达式 会被计算,同时要求计算的结果必须可以被转换为 布尔型。如果结果为 true ,则此循环会被重复一次。这个过程会持续下去,直到 表达式 的计算出的 结果为 false。
int i = 0;
do
{
foo(i);
} while (++i < 10);
Break语句 将退出循环。Continue语句 将直接转去再次计算 表达式。
9.10 For 语句
For 语句实现了带有初始化、测试和递增的 循环结构。
For语句:
for (初始化 测试; 递增) 作用域语句
初始化:
;
无范围非空语句
测试:
空
表达式
递增:
空
表达式
先执行 初始化。然后计算 测试 ,结果必须可以被转换为布尔型。如果结果为 true ,执行
语句。在执行语句后,将执行 递增。然后再次计算 测试,如果结果为 true 再次执行语
句 。持续这个过程直到 测试 的计算结果为 false 。
Break语句 将退出循环。Continue语句 将直接跳转到 递增。
A ForStatement creates a new scope.如果 初始值 声明了一个变量,变量的作用域持续到语句结束。
例如:
for (int i = 0; i < 10; i++)
foo(i);
等同于:
{ int i;
for (i = 0; i < 10; i++)
foo(i);
}
函数体不能为空:
for (int i = 0; i < 10; i++)
; // 非法
正确的写法是:
for (int i = 0; i < 10; i++)
{}
初始值 可以忽略。测试 也可以被忽略;如果忽略,就假定为 true 。
11 Foreach 语句
foreach 语句遍历一个 聚集 的全部内容。
Foreach语句:
Foreach (Foreach类型列表; 聚集) 作用域语句
Foreach:
foreach
foreach_reverse
Foreach类型列表:
Foreach类型
Foreach类型 , Foreach类型列表
Foreach类型:
ref 类型 标识符
类型 标识符
ref 标识符
标识符
聚集:
表达式
元组
聚集 会被计算。它的结果必须为 静态数组、动态数组、关联数组、结构或类类型的聚集表
达式。对于聚集表达式的每个元素执行一次 无作用域非空语句。在每次遍历开始
时,Foreach类型列表 声明的变量 默认为聚集的内容的 拷贝(即采用传值方式)。如果变量是 ref,这些变量就是聚集内容的 引用(即采用传引用方式)。
聚集必须是循环不变量,即在 无作用域非空语句 里将聚集的元素不能被添加或移除。
如果聚集表达式是静态或动态数组,可以声明一个或者两个变量。如果声明了一个变量,那
么这个变量就被赋予 数组元素的 值,依着次序地进行。除了下面提到的特殊情况以外,变
量的类型必须同数组内容的类型相 匹配,。
如果声明了两个变量,第一个变量则对应该数组的 索引,而第二个对应该数组的 值。注意该 索引 必须是 int 或 uint 类型,而不能是ref,并且它的值就是数组元素的 索引值。
char[] a;
...
foreach (int i, char c; a)
{
writefln("a[%d] = '%c'", i, c);
}
对于 foreach,数组的元素会从索引 0 开始被迭代,一直到该数组的最大值。对于
foreach_reverse,则会以相反的顺序访问数组元素。
如果聚集表达式是 char、wchar 或者 dchar 的静态或动态数组,则 值 的 类型 可以是
char、wchar 或者 dchar 中的任何一个。采用这种方式,所有的 UTF 数组都可以被解码为任意的 UTF 类型:
char[] a = "\xE2\x89\xA0"; // \u2260 encoded as 3 UTF-8 bytes
foreach (dchar c; a)
{
writefln("a[] = %x", c); // 输出 'a[] = 2260'
}
dchar[] b = "\u2260";
foreach (char c; b)
{
writef("%x, ", c); // prints 'e2, 89, a0, '
}
聚集可以是字符串文字,这样它们就可以被看作 char、wchar 或 dchar 数组来进行访问:
void test()
{
foreach (char c; "ab")
{
writefln("'%s'", c);
}
foreach (wchar w; "xy")
{
writefln("'%s'", w);
}
}
输出结果:
'a'
'b'
'x'
'y'
如果聚集表达式是关联数组,可以声明一个或者两个变量。如果声明了一个变量,那么这个
变量就被赋予数组元素的 值,依着次序地进行。变量的类型必须同数组内容的类型匹配。
如果声明了两个变量,第一个变量则对应该数组的 索引,而第二个对应该数组的 值。索引
必须同关联数组的索引具有相同的类型。它不能是 ref,它的值是数组元素的索引。对于
foreach,数组元素的顺序是不明确的。而将 foreach_reverse 用于关联数组是非法的。
double[char[]] a; // 索引 类型是 char[],值 类型是 double
...
foreach (char[] s, double d; a)
{
writefln("a['%s'] = %g", s, d);
}
如果它是一个结构或类对象,则 foreach 会通过特有的 opApply 成员函数会定
义。foreach_reverse 的动作则由特有的 opApplyReverse 成员函数进行定义。为了使用相应的 foreach 语句,这些特有函数必须被该类型定义。这些函数拥有的类型:
int opApply(int delegate(ref Type [, ...]) dg);
int opApplyReverse(int delegate(ref Type [, ...]) dg);
这里的 类型 跟在 标识符 里的 Foreach类型 声明所使用的 类型 相匹配。多重 Foreach
类型 跟在传递给 opApply 或 opApplyReverse 的委托类型里的多重 类型 相一致。也可以有多重 opApply 和 opApplyReverse 函数,通过将 dg 的类型跟 Foreach语句 的 Foreach类型 相匹配来进行一个一个的选择。应用函数体会迭代它所聚集的全部元素,并把它们每一个都传递给 dg 函数。如果 dg 返回 0,那么应用就继续下一个元素。如果 dg 返回一个非零值,apply 必须停止迭代并返回该值。否则,在迭代完所有的元素之后,apply 会返回0。
例如,假设有一个类,它是一个窗口,拥有两个元素:
class Foo
{
uint array[2];
int opApply(int delegate(ref uint) dg)
{ int result = 0;
for (int i = 0; i < array.length; i++)
{
result = dg(array[i]);
if (result)
break;
}
return result;
}
}
使用这个的实例可能像这样:
void test()
{
Foo a = new Foo();
a.array[0] = 73;
a.array[1] = 82;
foreach (uint u; a)
{
writefln("%d", u);
}
}
输出结果:
73
82
如果 聚集 是一个委托,那么此委托的类型署名就跟用于 opApply 的一样。这使得许多不
同命名的循环策略可以在相同的类或结构里共存。
ref 可以被用来更新原有的元素:
void test()
{
static uint[2] a = [7, 8];
foreach (ref uint u; a)
{
u++;
}
foreach (uint u; a)
{
writefln("%d", u);
}
}
输出结果:
89
ref 不能被应用到该索引值。
如果没有指定,在 Foreach类型 里的 类型 可以从 聚集 的类型进行推断。
在 foreach 迭代所有元素时,聚集本身不需要被重新调整大小、重新分配、释放、重新赋值
或重新析构。
int[] a;
int[] b;
foreach (int i; a)
{
a = null; // 错误
a.length = a.length + 10; // 错误
a = b; // 错误
}
a = null; // 正确
如果聚集是一个 tuple,那么就可能会声明一到两个变量。如果声明了一个变量,那么这个
变量就被赋予该 Tupe 元素的 值,一个接一个地。如果给定了该变量的类型,则它必须跟
Tuple 内容里的类型相匹配。如果没有给定,则该变量的类型会被设置成该 Tuple 元素的类型,它可能从一个迭代变化到另一个迭代。如果声明了两个变量,第一个变量则对应该数组
的 索引,而第二个对应该数组的 值。索引 必须是 int 或 uint 类型,它不能是 ref,并且它的值是该 Tuple 元素的索引。
如果该 Tuple 是一个类型列表,那么该 foreach 语句对于每一个类型都会被执行一次,并且该值会成该类型的别名。
import std.stdio;
import std.typetuple; // 用于类型元组
void main()
{
alias TypeTuple!(int, long, double) TL;
foreach (T; TL)
{
writefln(typeid(T));
}
}
输出
int
long
double
如果在 foreach 体内有 Break语句,则会退出 foreach ,而 Continue语句 将立即开始下一轮遍历。
12 Switch 语句
switch 语句依照 switch 表达式的值来选择一条 case 语句执行。
Switch语句:
switch ( 表达式 ) 作用域语句
Case语句:
case 表达式列表 :语句
Default语句:
default: 语句
表达式 会被计算。结果的类型 T 必须是 整数类型 或者 char[]、 wchar[] 或者 dchar[]。所得结果同各个 case 表达式进行比较。如果存在匹配,就转而执行相应的 case 语句。
case 表达式,也就是 表达式列表,是由 逗号分隔 的表达式的列表。
如果没有 case 表达式能够匹配,并且存在 default 语句,就转去执行 default 语句。
如果没有 case 表达式能够匹配,并且不存在 default 语句,就会抛出 SwitchError 异常。之所以这么做,是为了捕获一些常见的错误,如为枚举添加了新值却忘记了为这个值提供对应的 case 语句。这同 C 和 C++ 不太一样。
case 表达式必须都是常量值或数组,
并且必须能隐式地转换为 switch 表达式 的类型 T。
case 表达式的值必须互不相同。
而且不能有两个或者更多的 default 语句。
与 switch 相关联的 case 语句和 default 语句可以在语句块中嵌套;它们不必非要位于最外层的块中。例如,下面是合法的:
switch (i)
{
case 1:
{
case 2:
}
break;
}
同在 C 和 C++ 中一样,case 语句会顺序执行后面的 case 子句。break 语句将退出 switch块语句。
例如:
switch (i)
{
case 1:
x = 3;
case 2:
x = 4;
break;
case 3,4,5:
x = 5;
break;
}
如果 i 等于 1,x 将等于 4 。
注意: 同 C 和 C++ 不同的是,可以在 switch 表达式中使用字符串。例如:
char[] name;
...
switch (name)
{
case "fred":
case "sally":
...
}
对于如命令行选项处理这样的应用来说,采用这种语法的代码更直接,更清晰并且不易出
错。ascii 和 wchar 都可以使用。
实现注意: 编译器的代码生成程序可以认为 case 语句已经按照使用的频率排序,频率高的
排在最前面,频率低的排在最后。尽管这不会影响程序的正确性,但对于提高性能来说是有
益的。
13 Continue 语句
Continue语句:
continue;
continue 标识符 ;
continue 会中当前断其封闭循环语句的迭代,然后开始下一次迭代。 continue 执行它所在最内层的 while、for 或者do 语句的下次迭代。执行递增子句。
如果 continue 后跟有 标识符,则该 标识符 必须是它所在的 while、for 或者 do 语句外的标号,continue 会执行所在循环的下次迭代。如果不存在那样的语句,就是错误。
所有被跳过的 finally 子句都会执行,同时会释放所有被跳过的 synchronization 对象。
注意: 如果 finally 子句中有 return、throw 或者 goto 到 finally 子句之外的这样的动作,continue 的目标永远也无法达到。
for (i = 0; i < 10; i++)
{
if (foo(i))
continue;
bar();
}
14 Break 语句
Break语句:
break;
break 标识符 ;
break 退出它所在的语句。 break 退出它所在最内层的 while、for、do 或者 switch 语句,并在该语句之后恢复执行。
如果 break 后跟有 标识符,则该 标识符 是它所在的 while、for、do 或者 switch 语句外的标号,break 会退出那条语句。如果不存在那样的语句,就是错误。
所有被跳过的 finally 子句都会执行,同时会释放所有被跳过的 synchronization 对象。
注意: 如果 finally 子句中有 return、throw 或者 goto 到 finally 子句之外的这样的动作,break 的目标永远也无法达到。
for (i = 0; i < 10; i++)
{
if (foo(i))
break;
}
15 Return 语句
Return语句:
return;
return 表达式 ;
return 语句的作用是推出当前的函数并提供一个返回值。 如果函数指定了非 void 的返回类型,就必须给出 表达式。表达式 会被隐式地转换为函数的返回类型。
如果函数指定了一个不为 void 的返回类型,则至少需要一个 return 语句、throw 语句 或assert(0) 表达式。
就算函数的返回类形是 void,也可以有 表达式 存在。表达式 会被计算,但是什么也不会
返回。
在函数实际返回之前,任何带有 auto 存储特性的对象都会被破坏掉,所有的封闭 finally 子句会被执行,所有的 scope(exit) 语句会被执行,所有的 scope(success) 语句会被执行,并且所有的封闭 synchronization 对象会被释放。
如果外围的 finally 子句中有 return、goto 或者 throw 的话,函数就不会正常的返回。
如果存在后验条件(参见契约式编程),则在计算 表达式 之后执行该后验条件,然后函数
返回。
int foo(int x)
{
return x + 3;
}
16 goto 语句
Goto语句:
goto 标识符 ;
goto default ;
goto case ;
goto case 表达式 ;
一个 goto 会跳转到以 标识符 为标号的语句处。
if (foo)
goto L1;
x = 3;
L1:
x++;
第二种形式:goto default;,即跳转到最内层 Switch语句 中的 Default语句 处。
第三种形式:goto case;,即跳转到最内层 Switch语句 中的下一个 Case语句 处。
第四种形式:goto case 表式;,即跳转到跟封闭在 Switch语句 里面的匹配该
Expression 的 Case语句 处。
switch (x)
{
case 3:
goto case;
case 4:
goto default;
case 5:
goto case 4;
default:
x = 4;
break;
}
所有的被跳过的 finally 子句都会执行,同时会释放所有的被跳过的同步互斥体。
使用 Goto语句 来跳过初始化是非法的。
17 With 语句
with 语句用来简化对同一个对象的重复引用。
With语句:
with ( 表达式 ) 作用域语句
with ( 符号 ) 作用域语句
with ( 模板实例 ) 作用域语句
表达式 的结果是对类实例或者结构的引用。在 with 的过程体内,所有的标志符符号都将在
那个类引用的名字空间内查找。With语句
with (expression)
{
...
ident;
}
在语义上等价于:
{
Object tmp;
tmp = expression;
...
tmp.ident;
}
注意 表式 只会计算一次。with 语句不会改变 this 或 super 引用的对象。
对于是一个作用域或者 模板实例 的符号,在查找符号时相应的作用域会被搜索。
例如:
struct Foo
{
typedef int Y;
}
...
Y y; // 错误,Y 未定义
with (Foo)
{
Y y; // 等同于 Foo.Y y
}
。。。
If 语句提供了按条件执行语句的方法。
If语句:
if ( If条件 ) Then语句
if ( If条件 ) Then语句 else Else语句
If条件:
表达式
auto 标识符 = 表达式
单个声明符 = 表达式
Then语句:
作用域语句
Else语句:
作用域语句
表达式 将被计算,计算的结果必须可以被转换为布尔型。如果它为 true,则转换到 Then
语句,否则就转换到 Else语句。
“虚悬的(dangling) else”问题可以通过使用最近的那个 if 语句关联到该 else 来解决。
如果提供有一个 auto 标识符,那么它就会被 声明并被初始化 成该表达式的 值和类型。它的作用范围 从被初始化开始一直到 Then语句 的结尾。
如果提供有一个 声明符,那么它就会被声明并被初始化成该表达式的值。它的作用范围从
被初始化开始一直到 Then语句 的结尾。
import std.regexp;
...
if (auto m = std.regexp.search("abcdef", "b(c)d"))
{
writefln("[%s]", m.pre); // 输出 [a]
writefln("[%s]", m.post); // 输出 [ef]
writefln("[%s]", m.match(0)); // 输出 [bcd]
writefln("[%s]", m.match(1)); // 输出 [c]
writefln("[%s]", m.match(2)); // 输出 []
}
else
{
writefln(m.post); // 错误,m 未定义
}
writefln(m.pre); // 错误,m 未定义
8 While 语句
While语句:
while ( 表达式 ) 作用域语句
While 语句实现了简单的循环。 表达式 将被计算,计算的结果必须可以被转换为布尔型。
如果它的结果为 true,执行作用域语句。在执行该 作用域语句 后,此 表达式 会被再次计
算,并且如果为 true 的话,该 作用域语句 会被再次执行。这个过程会持续下去,直到 表
达式 的计算出的结果为 false。
int i = 0;
while (i < 10)
{
foo(i);
i++;
}
Break语句 将退出循环。Continue语句 将直接转去再次计算 表达式。
9 Do 语句
Do语句:
do 作用域语句 while ( 表达式 )
do-While 语句实现了简单的循环。 先执行 作用域语句。然后 表达式 会被计算,同时要求计算的结果必须可以被转换为 布尔型。如果结果为 true ,则此循环会被重复一次。这个过程会持续下去,直到 表达式 的计算出的 结果为 false。
int i = 0;
do
{
foo(i);
} while (++i < 10);
Break语句 将退出循环。Continue语句 将直接转去再次计算 表达式。
9.10 For 语句
For 语句实现了带有初始化、测试和递增的 循环结构。
For语句:
for (初始化 测试; 递增) 作用域语句
初始化:
;
无范围非空语句
测试:
空
表达式
递增:
空
表达式
先执行 初始化。然后计算 测试 ,结果必须可以被转换为布尔型。如果结果为 true ,执行
语句。在执行语句后,将执行 递增。然后再次计算 测试,如果结果为 true 再次执行语
句 。持续这个过程直到 测试 的计算结果为 false 。
Break语句 将退出循环。Continue语句 将直接跳转到 递增。
A ForStatement creates a new scope.如果 初始值 声明了一个变量,变量的作用域持续到语句结束。
例如:
for (int i = 0; i < 10; i++)
foo(i);
等同于:
{ int i;
for (i = 0; i < 10; i++)
foo(i);
}
函数体不能为空:
for (int i = 0; i < 10; i++)
; // 非法
正确的写法是:
for (int i = 0; i < 10; i++)
{}
初始值 可以忽略。测试 也可以被忽略;如果忽略,就假定为 true 。
11 Foreach 语句
foreach 语句遍历一个 聚集 的全部内容。
Foreach语句:
Foreach (Foreach类型列表; 聚集) 作用域语句
Foreach:
foreach
foreach_reverse
Foreach类型列表:
Foreach类型
Foreach类型 , Foreach类型列表
Foreach类型:
ref 类型 标识符
类型 标识符
ref 标识符
标识符
聚集:
表达式
元组
聚集 会被计算。它的结果必须为 静态数组、动态数组、关联数组、结构或类类型的聚集表
达式。对于聚集表达式的每个元素执行一次 无作用域非空语句。在每次遍历开始
时,Foreach类型列表 声明的变量 默认为聚集的内容的 拷贝(即采用传值方式)。如果变量是 ref,这些变量就是聚集内容的 引用(即采用传引用方式)。
聚集必须是循环不变量,即在 无作用域非空语句 里将聚集的元素不能被添加或移除。
如果聚集表达式是静态或动态数组,可以声明一个或者两个变量。如果声明了一个变量,那
么这个变量就被赋予 数组元素的 值,依着次序地进行。除了下面提到的特殊情况以外,变
量的类型必须同数组内容的类型相 匹配,。
如果声明了两个变量,第一个变量则对应该数组的 索引,而第二个对应该数组的 值。注意该 索引 必须是 int 或 uint 类型,而不能是ref,并且它的值就是数组元素的 索引值。
char[] a;
...
foreach (int i, char c; a)
{
writefln("a[%d] = '%c'", i, c);
}
对于 foreach,数组的元素会从索引 0 开始被迭代,一直到该数组的最大值。对于
foreach_reverse,则会以相反的顺序访问数组元素。
如果聚集表达式是 char、wchar 或者 dchar 的静态或动态数组,则 值 的 类型 可以是
char、wchar 或者 dchar 中的任何一个。采用这种方式,所有的 UTF 数组都可以被解码为任意的 UTF 类型:
char[] a = "\xE2\x89\xA0"; // \u2260 encoded as 3 UTF-8 bytes
foreach (dchar c; a)
{
writefln("a[] = %x", c); // 输出 'a[] = 2260'
}
dchar[] b = "\u2260";
foreach (char c; b)
{
writef("%x, ", c); // prints 'e2, 89, a0, '
}
聚集可以是字符串文字,这样它们就可以被看作 char、wchar 或 dchar 数组来进行访问:
void test()
{
foreach (char c; "ab")
{
writefln("'%s'", c);
}
foreach (wchar w; "xy")
{
writefln("'%s'", w);
}
}
输出结果:
'a'
'b'
'x'
'y'
如果聚集表达式是关联数组,可以声明一个或者两个变量。如果声明了一个变量,那么这个
变量就被赋予数组元素的 值,依着次序地进行。变量的类型必须同数组内容的类型匹配。
如果声明了两个变量,第一个变量则对应该数组的 索引,而第二个对应该数组的 值。索引
必须同关联数组的索引具有相同的类型。它不能是 ref,它的值是数组元素的索引。对于
foreach,数组元素的顺序是不明确的。而将 foreach_reverse 用于关联数组是非法的。
double[char[]] a; // 索引 类型是 char[],值 类型是 double
...
foreach (char[] s, double d; a)
{
writefln("a['%s'] = %g", s, d);
}
如果它是一个结构或类对象,则 foreach 会通过特有的 opApply 成员函数会定
义。foreach_reverse 的动作则由特有的 opApplyReverse 成员函数进行定义。为了使用相应的 foreach 语句,这些特有函数必须被该类型定义。这些函数拥有的类型:
int opApply(int delegate(ref Type [, ...]) dg);
int opApplyReverse(int delegate(ref Type [, ...]) dg);
这里的 类型 跟在 标识符 里的 Foreach类型 声明所使用的 类型 相匹配。多重 Foreach
类型 跟在传递给 opApply 或 opApplyReverse 的委托类型里的多重 类型 相一致。也可以有多重 opApply 和 opApplyReverse 函数,通过将 dg 的类型跟 Foreach语句 的 Foreach类型 相匹配来进行一个一个的选择。应用函数体会迭代它所聚集的全部元素,并把它们每一个都传递给 dg 函数。如果 dg 返回 0,那么应用就继续下一个元素。如果 dg 返回一个非零值,apply 必须停止迭代并返回该值。否则,在迭代完所有的元素之后,apply 会返回0。
例如,假设有一个类,它是一个窗口,拥有两个元素:
class Foo
{
uint array[2];
int opApply(int delegate(ref uint) dg)
{ int result = 0;
for (int i = 0; i < array.length; i++)
{
result = dg(array[i]);
if (result)
break;
}
return result;
}
}
使用这个的实例可能像这样:
void test()
{
Foo a = new Foo();
a.array[0] = 73;
a.array[1] = 82;
foreach (uint u; a)
{
writefln("%d", u);
}
}
输出结果:
73
82
如果 聚集 是一个委托,那么此委托的类型署名就跟用于 opApply 的一样。这使得许多不
同命名的循环策略可以在相同的类或结构里共存。
ref 可以被用来更新原有的元素:
void test()
{
static uint[2] a = [7, 8];
foreach (ref uint u; a)
{
u++;
}
foreach (uint u; a)
{
writefln("%d", u);
}
}
输出结果:
89
ref 不能被应用到该索引值。
如果没有指定,在 Foreach类型 里的 类型 可以从 聚集 的类型进行推断。
在 foreach 迭代所有元素时,聚集本身不需要被重新调整大小、重新分配、释放、重新赋值
或重新析构。
int[] a;
int[] b;
foreach (int i; a)
{
a = null; // 错误
a.length = a.length + 10; // 错误
a = b; // 错误
}
a = null; // 正确
如果聚集是一个 tuple,那么就可能会声明一到两个变量。如果声明了一个变量,那么这个
变量就被赋予该 Tupe 元素的 值,一个接一个地。如果给定了该变量的类型,则它必须跟
Tuple 内容里的类型相匹配。如果没有给定,则该变量的类型会被设置成该 Tuple 元素的类型,它可能从一个迭代变化到另一个迭代。如果声明了两个变量,第一个变量则对应该数组
的 索引,而第二个对应该数组的 值。索引 必须是 int 或 uint 类型,它不能是 ref,并且它的值是该 Tuple 元素的索引。
如果该 Tuple 是一个类型列表,那么该 foreach 语句对于每一个类型都会被执行一次,并且该值会成该类型的别名。
import std.stdio;
import std.typetuple; // 用于类型元组
void main()
{
alias TypeTuple!(int, long, double) TL;
foreach (T; TL)
{
writefln(typeid(T));
}
}
输出
int
long
double
如果在 foreach 体内有 Break语句,则会退出 foreach ,而 Continue语句 将立即开始下一轮遍历。
12 Switch 语句
switch 语句依照 switch 表达式的值来选择一条 case 语句执行。
Switch语句:
switch ( 表达式 ) 作用域语句
Case语句:
case 表达式列表 :语句
Default语句:
default: 语句
表达式 会被计算。结果的类型 T 必须是 整数类型 或者 char[]、 wchar[] 或者 dchar[]。所得结果同各个 case 表达式进行比较。如果存在匹配,就转而执行相应的 case 语句。
case 表达式,也就是 表达式列表,是由 逗号分隔 的表达式的列表。
如果没有 case 表达式能够匹配,并且存在 default 语句,就转去执行 default 语句。
如果没有 case 表达式能够匹配,并且不存在 default 语句,就会抛出 SwitchError 异常。之所以这么做,是为了捕获一些常见的错误,如为枚举添加了新值却忘记了为这个值提供对应的 case 语句。这同 C 和 C++ 不太一样。
case 表达式必须都是常量值或数组,
2.014 or a runtime initialized const or invariant variable of integral type.
并且必须能隐式地转换为 switch 表达式 的类型 T。
case 表达式的值必须互不相同。
2.014 Const or invariant variables must all have different names. If they share a value, the first case statement with that value gets control.
而且不能有两个或者更多的 default 语句。
与 switch 相关联的 case 语句和 default 语句可以在语句块中嵌套;它们不必非要位于最外层的块中。例如,下面是合法的:
switch (i)
{
case 1:
{
case 2:
}
break;
}
同在 C 和 C++ 中一样,case 语句会顺序执行后面的 case 子句。break 语句将退出 switch块语句。
例如:
switch (i)
{
case 1:
x = 3;
case 2:
x = 4;
break;
case 3,4,5:
x = 5;
break;
}
如果 i 等于 1,x 将等于 4 。
注意: 同 C 和 C++ 不同的是,可以在 switch 表达式中使用字符串。例如:
char[] name;
...
switch (name)
{
case "fred":
case "sally":
...
}
对于如命令行选项处理这样的应用来说,采用这种语法的代码更直接,更清晰并且不易出
错。ascii 和 wchar 都可以使用。
实现注意: 编译器的代码生成程序可以认为 case 语句已经按照使用的频率排序,频率高的
排在最前面,频率低的排在最后。尽管这不会影响程序的正确性,但对于提高性能来说是有
益的。
13 Continue 语句
Continue语句:
continue;
continue 标识符 ;
continue 会中当前断其封闭循环语句的迭代,然后开始下一次迭代。 continue 执行它所在最内层的 while、for 或者do 语句的下次迭代。执行递增子句。
如果 continue 后跟有 标识符,则该 标识符 必须是它所在的 while、for 或者 do 语句外的标号,continue 会执行所在循环的下次迭代。如果不存在那样的语句,就是错误。
所有被跳过的 finally 子句都会执行,同时会释放所有被跳过的 synchronization 对象。
注意: 如果 finally 子句中有 return、throw 或者 goto 到 finally 子句之外的这样的动作,continue 的目标永远也无法达到。
for (i = 0; i < 10; i++)
{
if (foo(i))
continue;
bar();
}
14 Break 语句
Break语句:
break;
break 标识符 ;
break 退出它所在的语句。 break 退出它所在最内层的 while、for、do 或者 switch 语句,并在该语句之后恢复执行。
如果 break 后跟有 标识符,则该 标识符 是它所在的 while、for、do 或者 switch 语句外的标号,break 会退出那条语句。如果不存在那样的语句,就是错误。
所有被跳过的 finally 子句都会执行,同时会释放所有被跳过的 synchronization 对象。
注意: 如果 finally 子句中有 return、throw 或者 goto 到 finally 子句之外的这样的动作,break 的目标永远也无法达到。
for (i = 0; i < 10; i++)
{
if (foo(i))
break;
}
15 Return 语句
Return语句:
return;
return 表达式 ;
return 语句的作用是推出当前的函数并提供一个返回值。 如果函数指定了非 void 的返回类型,就必须给出 表达式。表达式 会被隐式地转换为函数的返回类型。
如果函数指定了一个不为 void 的返回类型,则至少需要一个 return 语句、throw 语句 或assert(0) 表达式。
就算函数的返回类形是 void,也可以有 表达式 存在。表达式 会被计算,但是什么也不会
返回。
在函数实际返回之前,任何带有 auto 存储特性的对象都会被破坏掉,所有的封闭 finally 子句会被执行,所有的 scope(exit) 语句会被执行,所有的 scope(success) 语句会被执行,并且所有的封闭 synchronization 对象会被释放。
如果外围的 finally 子句中有 return、goto 或者 throw 的话,函数就不会正常的返回。
如果存在后验条件(参见契约式编程),则在计算 表达式 之后执行该后验条件,然后函数
返回。
int foo(int x)
{
return x + 3;
}
16 goto 语句
Goto语句:
goto 标识符 ;
goto default ;
goto case ;
goto case 表达式 ;
一个 goto 会跳转到以 标识符 为标号的语句处。
if (foo)
goto L1;
x = 3;
L1:
x++;
第二种形式:goto default;,即跳转到最内层 Switch语句 中的 Default语句 处。
第三种形式:goto case;,即跳转到最内层 Switch语句 中的下一个 Case语句 处。
第四种形式:goto case 表式;,即跳转到跟封闭在 Switch语句 里面的匹配该
Expression 的 Case语句 处。
switch (x)
{
case 3:
goto case;
case 4:
goto default;
case 5:
goto case 4;
default:
x = 4;
break;
}
所有的被跳过的 finally 子句都会执行,同时会释放所有的被跳过的同步互斥体。
使用 Goto语句 来跳过初始化是非法的。
17 With 语句
with 语句用来简化对同一个对象的重复引用。
With语句:
with ( 表达式 ) 作用域语句
with ( 符号 ) 作用域语句
with ( 模板实例 ) 作用域语句
表达式 的结果是对类实例或者结构的引用。在 with 的过程体内,所有的标志符符号都将在
那个类引用的名字空间内查找。With语句
with (expression)
{
...
ident;
}
在语义上等价于:
{
Object tmp;
tmp = expression;
...
tmp.ident;
}
注意 表式 只会计算一次。with 语句不会改变 this 或 super 引用的对象。
对于是一个作用域或者 模板实例 的符号,在查找符号时相应的作用域会被搜索。
例如:
struct Foo
{
typedef int Y;
}
...
Y y; // 错误,Y 未定义
with (Foo)
{
Y y; // 等同于 Foo.Y y
}
。。。
发表评论
-
土耳其文《d编程》range 翻译 一
2011-11-15 02:01 1507Ranges 范围 Ranges are an abstra ... -
土耳其文《d编程》range 翻译 二
2011-11-15 01:59 1006As you can see, that output doe ... -
d2 range 和 标准C++中的Iterator(迭代器)简介
2011-05-07 12:59 2117原文: http://hi.baidu.com/c ... -
三访安德烈Alexandrescu(第2部)
2010-08-20 12:53 1422Google翻译哦 面试------> 应翻成 访谈 ... -
三访安德烈Alexandrescu(第一部分)
2010-08-20 12:43 1349google翻译哦 Interview with Andre ... -
Garden Editor project 日记 之二 10.16 ---
2009-10-16 02:39 02009.10.16 T[new] misgivings ... -
Garden Editor project 日记 之一 09.09.25 --- 10.15
2009-09-24 22:56 0kill two birds with one stone, ... -
template metaprogramming 9
2009-09-09 16:08 1169原文:https://docs.google.co ... -
Floating Point in D (2.030 新)
2009-05-12 23:27 20485.17 23:50 更新 5.16 20:30 翻译更 ... -
Migrating to Shared (2.030 新)
2009-05-12 23:03 11545.19 0:10 更新(完成) ... -
D 2.0 的gc
2008-12-04 19:53 1251http://lucifer1982.wordpress.co ... -
垃圾回收 2.014
2008-06-10 07:20 983无版本差异 D 是一种全面采用垃圾回收(Garbage Co ... -
类 class 2.014
2008-06-09 22:51 1085D 的面向对象的特性都来源于类。类层次里的顶层是 Object ... -
接 口 2.014
2008-06-09 22:51 843接口声明: interface 标 ... -
C 语言接口 2.014
2008-06-09 22:50 1029D 的设计就是要在目标系统上能够很好地符合于 C 编译器。D ... -
Traits 特征 2.014
2008-06-07 11:25 12466.14 翻译 (d语言的反 ... -
常量和不变量 Const and Invariant 2.014
2008-06-07 11:22 1312请参考: D 2.0 Const/Final/Invarian ... -
词法 2.014
2008-06-07 10:22 1501在 D 中,词法分析独立于语法分析和语义分析。词法分析器是将源 ... -
枚 举 2.014
2008-06-07 08:41 1155枚举声明: enum 枚举标记 枚举体 enum 枚举体 en ... -
函 数 2 (2.014)
2008-06-07 08:22 10327 嵌套函数 函数可以被 ...
相关推荐
Oracle.DataAccess.dll 2.112.3.0
binutils-2.15.92.0.2-13.0.0.0.2.x86_64.rpm
TouchWin编辑工具V2.C.6序列号
libxml2-2.6.32是该库的一个特定版本,提供了稳定的性能和丰富的API,使得开发者能够高效地处理XML文档,无论是读取、解析还是生成XML内容。 PHP的GD库则是一个用于创建和处理图像的库,常用于网页动态图像生成,...
arm 开发库文件 嵌入式开发 libmpc.so.2
FTDIUN2K.INI 驱动
vuforia 官网下载速度慢,上传下下载链接............................................................................................................................................................
内部版本 STM32 ST-LINK utility V4.2.0.0,STLinkUSBDriver.dll v5.0.3.0, ST-LINK_CLI.exe v3.2.0.0,Firmware Version v2.J29.S7。亲测OK
jquery.table2excel.js,一款挺好用的javascript导出插件,需要jquery-1.7.1.min.js的支持。使用方法: $(document).ready(function() { //导出excel $("#output").click(function(){ var myDate = new Date(); ...
Win7 ws2_32.dll
PDF转换成图片的项目实例,用VS2008可以直接运行。如需了解更多PDF转成图片的信息,请参考:http://blog.csdn.net/shi0090/article/details/7262199
外贸用语2.docx 当代日本语会话(高级下册).pdf 敬语 日本の歴史1.doc 日本史概说电子版.pdf 日本年代表.doc 日汉翻译改错(式辞挨拶).doc 日语N2(二级)单词表_很方便记忆.xls 日语N2文法190句.doc 日语N2核心词汇....
HttpWatch是一款强大的网页数据分析工具.集成在Internet Explorer工具栏.包括网页摘要.Cookies管理.缓存管理.消息头发送/接受.字符查询.POST 数据和目录管理功能.报告输出
libaio-0.3.105-2.x86_64.rpm libaio-devel-0.3.105-2.i386.rpm libaio-devel-0.3.105-2.x86_64.rpm libaio-devel-0.3.106-5.x86_64.rpm pdksh-5.2.14-36.el5.x86_64.rpm unixODBC-2.2.11-7.1.x86_64.rpm unixODBC-...
ser2pl64.sys是电脑重要系统文件,字面意思就是64位的串口Pl驱动系统配置文件,如果你的电脑安装PL2303等问题弹出”非旺玖原装的PL2303,请联系您的供货商“或者出现提示信息”ser2pl64.sys丢失“或者“ser2pl64.sys...
2. **灵活性**:re2c支持正则表达式语法,允许开发者定义复杂的规则来匹配输入字符串。它可以根据需要自定义处理逻辑,适应多种语言和模式。 3. **无缝集成**:re2c可以直接嵌入到现有的C项目中,无需额外的工具链...
DevComponents.DotNetBar2.dll DevComponents.DotNetBar.Design.dll DevComponents.Instrumentation.Design.dll DevComponents.Instrumentation.dll DevComponents.TreeGX.dll DevComponents DotNetBar2 DotNetBar ...
Swftools是一个功能丰富的套件,包含了多个处理SWF文件的小程序,如jpeg2swf.exe、png2swf.exe和gif2swf.exe,它们分别用于将JPEG、PNG和GIF图像转换为SWF。 描述中提到,安装这个压缩包后,用户可以获得一系列的...
安装samba服务时,经常提示缺少依赖包。这里是libldap.so.2
2 业务系统分析 ................................................................................................................................. 6 2.1 业务系统职能 ......................................