2015-09-18 55 views
0

我只知道從Delphi XE7有Parallel.For這很酷。所以我嘗試一小塊的代碼轉換,如:德爾福TParallel.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; 

UPDATE

是,以上代碼編譯,下面不(如果地圖數組作爲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' 

那麼,如何使這項工作儘可能簡單?

回答

4

此代碼,相同的是,在問題,在編譯既dcc32和dcc64,Delphi的XE7更新1.

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. 

局部變量iTestParallel是未使用的,因爲編譯器觀察到的,和應被刪除。不是說它有什麼區別。

我無法解釋爲什麼你無法編譯此代碼。要麼你正在使用我不同的編譯器,要麼使用不同的代碼。


更新

事實上,從你的問題的更新,事實證明,你有沒有貼不編譯代碼。

這裏的重大教訓是永遠不會發布僞代碼。始終發佈實際的代碼,儘可能最小化完整的代碼。

至於你真正的代碼,你剛纔發佈的,看起來像這樣:

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

匿名方法的一個關鍵特性是它們可以引用變量,這些變量對於定義它們的位置是可見的。

你需要沿着這些線路使用的東西:

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參數。那麼,我們可以在循環開始之前進行同樣的分配,但對我而言,這在語義上感覺很奇怪。

+0

謝謝。我發現如果map作爲var參數傳遞給過程,那麼它將不會編譯... –

+0

問題中的代碼不會將該數組作爲var參數傳遞。你可能想知道爲什麼我總是要求[mcve]。我希望你現在能理解我爲什麼這麼做。 –

+0

謝謝。現在我明白你的意思了......重新編輯了這個問題。 –