Delphi TParallel.For - 无法捕获符号
Delphi TParallel.For - Cannot Capture Symbol
我只知道 Delphi XE7 有 Parallel.For 这很酷。所以我尝试转换一小段代码,比如:
procedure TestParallel;
var
i, j, u, v: integer;
map: array of array of integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
for i := 0 to u do
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end;
end;
至:
procedure TestParallel;
var
i, u, v: integer;
map: array of array of integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
更新
是的,上面的代码可以编译,下面的不是(如果map数组作为var参数传递)
type
data = array of array of integer;
procedure TestParallel(var map: data);
var
i, u, v: integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
但不幸的是,编译器说:
[dcc64 Error] Project2.dpr(70): E2555 Cannot capture symbol 'map'
那么,如何使这项工作尽可能简单?
此代码与问题中的代码相同,可在 Delphi XE7 更新 1 上在 dcc32 和 dcc64 中编译。
program Project1;
uses
System.Threading;
procedure TestParallel;
var
i, u, v: integer;
map: array of array of integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
begin
end.
TestParallel
中的局部变量 i
未使用,正如编译器观察到的那样,应将其删除。并不是说它有什么不同。
我无法解释为什么您无法编译此代码。您使用的编译器与我不同,或者代码与我不同。
更新
事实上,从您的问题更新来看,您没有 post编辑无法编译的代码。
这里的重要教训是永远不要 post 假代码。始终 post 真实代码,尽可能完整的代码,尽可能少。
至于你的真实代码,你刚刚 posted,看起来像这样:
procedure TestParallel(var map: data);
var
i, u, v: integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
编译失败,因为无法捕获 var 参数。在编译声明变量的函数时,编译器必须能够看到捕获是必要的。对于 var
参数,编译器不知道变量的声明位置。见 Anonymous Methods Variable Binding:
A key feature of anonymous methods is that they may reference variables that are visible to them where they were defined.
您需要按照以下方式使用:
procedure TestParallel(var map: TArray<TArray<Integer>>);
var
LocalMap: TArray<TArray<Integer>>;
u, v: integer;
begin
SetLength(LocalMap, 101, 101);
TParallel.&For(0, high(LocalMap), procedure(i: integer)
var
j: integer;
begin
for j := 0 to high(LocalMap[i]) do
begin
if (LocalMap[i][j] <> 0) then
begin
LocalMap[i][j] := 1;
end;
end;
end);
map := LocalMap;
end;
我们声明了一个本地,然后我们可以捕获它。然后我们可以在循环完成后分配给 var
参数。好吧,我们可以在循环开始之前平均分配,但我觉得这在语义上很奇怪。
我只知道 Delphi XE7 有 Parallel.For 这很酷。所以我尝试转换一小段代码,比如:
procedure TestParallel;
var
i, j, u, v: integer;
map: array of array of integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
for i := 0 to u do
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end;
end;
至:
procedure TestParallel;
var
i, u, v: integer;
map: array of array of integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
更新
是的,上面的代码可以编译,下面的不是(如果map数组作为var参数传递)
type
data = array of array of integer;
procedure TestParallel(var map: data);
var
i, u, v: integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
但不幸的是,编译器说:
[dcc64 Error] Project2.dpr(70): E2555 Cannot capture symbol 'map'
那么,如何使这项工作尽可能简单?
此代码与问题中的代码相同,可在 Delphi XE7 更新 1 上在 dcc32 和 dcc64 中编译。
program Project1;
uses
System.Threading;
procedure TestParallel;
var
i, u, v: integer;
map: array of array of integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
begin
end.
TestParallel
中的局部变量 i
未使用,正如编译器观察到的那样,应将其删除。并不是说它有什么不同。
我无法解释为什么您无法编译此代码。您使用的编译器与我不同,或者代码与我不同。
更新
事实上,从您的问题更新来看,您没有 post编辑无法编译的代码。
这里的重要教训是永远不要 post 假代码。始终 post 真实代码,尽可能完整的代码,尽可能少。
至于你的真实代码,你刚刚 posted,看起来像这样:
procedure TestParallel(var map: data);
var
i, u, v: integer;
begin
SetLength(map, 101, 101);
u := 100; v := 100;
TParallel.&For(0, u, procedure(i: integer)
var
j: integer;
begin
for j := 0 to v do
begin
if (map[i][j] <> 0) then
begin
map[i][j] := 1;
end;
end;
end);
end;
编译失败,因为无法捕获 var 参数。在编译声明变量的函数时,编译器必须能够看到捕获是必要的。对于 var
参数,编译器不知道变量的声明位置。见 Anonymous Methods Variable Binding:
A key feature of anonymous methods is that they may reference variables that are visible to them where they were defined.
您需要按照以下方式使用:
procedure TestParallel(var map: TArray<TArray<Integer>>);
var
LocalMap: TArray<TArray<Integer>>;
u, v: integer;
begin
SetLength(LocalMap, 101, 101);
TParallel.&For(0, high(LocalMap), procedure(i: integer)
var
j: integer;
begin
for j := 0 to high(LocalMap[i]) do
begin
if (LocalMap[i][j] <> 0) then
begin
LocalMap[i][j] := 1;
end;
end;
end);
map := LocalMap;
end;
我们声明了一个本地,然后我们可以捕获它。然后我们可以在循环完成后分配给 var
参数。好吧,我们可以在循环开始之前平均分配,但我觉得这在语义上很奇怪。