3

コードの書き方についての私の理解はまだ非常に限られていると思います。SEARCH GENERIC LISTS からソリューションを変更しようとしまし たが、検索パラメーターとして任意のキーワードを受け入れるようにコードを変更することはできません

unit Unit_TsearchableTList;

interface

uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons,
  contnrs, Generics.Collections;

type
  TSearchableObjectList<T: class> = class(TObjectList<T>)

  public type
    TPredicate = reference to function(aItem: T; asearchValue: String): boolean;
  public
    function search(aFound: TPredicate<T>; asearchValue: String): T;
  end;

implementation

function TSearchableObjectList<T>.search(aFound: TPredicate<T>;
  asearchValue: String): T;
var
  item: T;
begin
  for item in Self do
    * * * * * * * * COMPILE ERROR IS HERE * * * * * * * * * * * * * * * *
      * ! ! ! ! ! !
  if aFound(item, asearchValue) then
    Exit(item);
  Result := nil;
end;

end.

使用例:

type
  TReplaceElementNames = class
    FindName: String;
    ReplaceName: String;
    ReplacementCondition: TReplacementCondition; // not relevant code
  end;

var
  LookUpList: TList<TReplaceElementNames>;
  search    : TReplaceElementNames;

begin
  LookUpList := TSearchableObjectList<TReplaceElementNames>.Create;

  search := LookUpList.search(
    function(aItem: TReplaceElementNames; searchname: String): boolean
    begin
      Result := aItem.FindName = searchname;
    end);
4

2 に答える 2

2

コードで定義した型は ですTPredicate。しかし、あなたは でTPredicate<T>定義された型であるを使用し続けましたSysUtils。交換するだけ

TPredicate<T>

TPredicate

あなたのコードで、それはコンパイルされます。


そうは言っても、受け入れた回答でコードを使用すると、より簡単になります。検索文字列を提供するために変数キャプチャが使用されるため、2 つのパラメーター述語は必要ありません。

于 2013-07-19T12:08:26.527 に答える
1

定義上、述語は、 http: //docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.TPredicate のように 1 つのパラメーターのみを取るものです。

では、何と比較するかなど、より多くのパラメーターを渡すにはどうすればよいでしょうか? これは、ocntext をキャプチャし、そのコンテキストを固定して新しい一時関数を生成することによって行います。

あなたの例を次のように変更します(私は冗長にしようとしているので、手順を追跡できます):

Type CanCompareWithString<T> = function (const Value:T; const Target: string): boolean;
// overcoming Delphi limitation

Function CreatePredicateFunction<T>(Const Target: String; Const Matcher: CanCompareWithString<T>): TPredicate<T>;
begin
   Result := function // creating new function (more correct: new closure)
                (Arg1: T): Boolean // see top link to Delphi docs
                begin
                  Result := 
                     Matcher // capturing the passed function
                     ( Arg1, 
                       Target ) // capturing the target value
                end;    // finished creating closure
    end;


  TSearchableObjectList<T: class> = class(TObjectList<T>)
  public
    function search(aFound: TPredicate<T>): T; overload;
    function search( asearchValue: String; Matcher: CanCompareWithString<T>): T; overload;
  end;

function TSearchableObjectList<T>.search(aFound: TPredicate<T>): T;
var
  item: T;
begin
  for item in Self do
  if aFound(item) then
    Exit(item);
  Result := Default(T);
end;

function TSearchableObjectList<T>.search( asearchValue: String;  Matcher: CanCompareWithString<T>): T;
begin
  Result := 
    Search(
       CreatePredicateFunction(
           Matcher, aSearchValue)
    ); 
end;

どのように使用できますか?うまくいけば、そのようなもの:

function StringMatcher(const Value:string; const Target: string): boolean;
begin
   Result := Value = Target;
end;

var L_S : TSearchableObjectList<String>; S: String;

S := L_S.Search('abcde', StringMAtcher);

ここで、「なぜですか?なぜその StringMatcher なのか?」と尋ねるかもしれません。

そして問題は、Delphi では、型を持つ演算子に部分的な制約を追加できないことです (Scala では、実存型と呼ばれます)。コンパイルできないだけです

function Equal<T>(const value: String): boolean;
begin
  Result := T = Value;
end;

function Sum<U>(const value1, value2: U): U;
begin
  Result := value1 + value2;
end;

Delphi は現在、その型 T が何であるかを認識しておらず、文字列と比較できるかできないかを保証できないため、その「T = 値」をコンパイルすることはできません。

Delphi は現在、そのタイプ U が何であるかを認識しておらず、追加できるかどうかを確認できないため、その「値 1 + 値 2」をコンパイルすることはできません。

これは大きな制限ですが、それが現状です。

次の型の実装を見てください。

そして、似たようなタスクを実行するために必要なボイラープレートの種類を確認できます (ただし、T と T を比較するのではなく、T と T を比較するだけのタスクです)。

于 2013-07-19T14:01:58.673 に答える