Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 11/02/22 in all areas

  1. DxDublin

    Looking for a localization tool

    I did a more thorough test with these four localization tools. Our application is huge. It contains hundreds of forms and thousands of units. Most of those units have resource strings. We also use visual form inheritance in every form. We use frames and inherited frames, too. Our forms have been designed such a way that there is plenty of room for string expansion. So, we do not need a form editor to change the layout. However, translators need a form preview to see the context of the strings. We use several freelance translators that need to work simultaneously with the developers. We use CI/CD and new content appears almost every week. Finally, we have both 32-bit and 64-bit version of our application. We target to 6 languages. Before we start, I would like to point it out that Delphi has a specific pattern how the localization should be done. It is to use forms, resource strings and resource DLLs. ITE uses this approach. Unfortunately, the implementation of ITE is just so bad that it is barely useable. Therefore, there is room for other tools. Let’s start write TsiLang. It is a component-based solution. It does not follow the standard VCL localization method but forces you to do major refactoring to your code. This means adding components to every form and replacing resource strings with TsiLang’s own implementation. The product works, and it is very cheap. I am sure TsiLang has its own fans. In a large project like ours, the price of the localization tool is not the prime factor. The features are. This is where TsiLang gets short. No form preview, propriety implementation, limited team work features, limited translation aids (TM, MT, terminology). This was the first to go. Korzh Localizer is a step forward. It allows you to use resource strings. It does not refactor your source code hardly at all. However, it is not based on resource DLL but uses its own language files. Like TsiLang it does not have form preview and has very limited translation aids. This was the second to go. Remaining two tools, BTM and Soluling, both works on the right principle: the standard VCL localization method. They are also totally decoupled from Delphi IDE that is very important. I like them both. BTM is a free tool and a very good one. It does the localization so much better than the TsiLang and Localizer. BTM is free and Anders has maintained it for three years. Huge respect for him. However, BTM lacks some very important features. First the form preview. Second is that if you have both 32-bit and 64-bit applications, you need to create two separate projects and somehow copy paste the translations. In addition, it scans all strings properties and you have to exclude them manually. There are no rules to configure what properties to localize and what to ignore. BTM has some translations aids but lots of features are missing, such as translation validation and interactive TM/MT/terms. My test sample contains TTreeView and TListView components. TsiLang, Localizer and BTM did not scan the nodes of those components. They were just ignored. What am I supposed to do in a case like that? Remove the design time data and populate the nodes on runtime using resource strings. No thanks. In most case you do not need (and should not) localize images but sometimes you have to. These tree tools cannot handle them either. This brings me to the last tool, Soluling. Soluling is more expensive than the above three tools. However, with that price, you get a tool that has all the features you need to localize a large VCL application. Soluling has a brilliant form editor. It is not only a preview, but you can change the layout. I would suggest not to go on that path but to pay some extra attention to your original UI design. However, if you need to do layout change, you can. Soluling localizes TTreeView, TListView and images. Soluling also has a concept of platform files. It means that you can add many variants of the same EXE file (e.g. 32-bit, 64-bit, debug, trial, etc.). No need to have a duplicate project file. No need to translate the same strings twice. Soluling’s translation aids are top level. Soluling’s features even exceed the features of the mainstream CAT tools like Passolo, MemoQ and Catalyst! Finally, in most cases you have also some other files but Delphi application to localize. For example, you might have some documentation files and web pages. Soluling can do those too. I quickly tested HTML, React and Markdown. All worked nicely. Both BTM and Soluling have a command-line tool to be used in the build pipeline. The both tools require zero changes to your source code and you are not forever bound to the tool you selected, such in the case you selected TsiLang or Localizer. Ultimately, this is a “battle“ between two Nordic guys: Anders and Jaakko. They both did it right. If you have a small Delphi-only project and small budget, go for Better Translation Manager. If you have a larger project or budget, or you also have other files but Delphi EXEs, go for Soluling. I have attached screnshots from each tool.
  2. Anders Melander

    Looking for a localization tool

    Thanks for the kind words. Much appreciated. Yes, I made a conscious choice not to include any kind of form editor or preview, even though I have these features implemented locally, simply because they never work reliably. The main problem is that in case your forms contains 3rd party controls, then the viewer/editor will need to be able to load the runtime packages containing these controls, and the packages have to be the correct version, for the correct version of Delphi. etc. etc. It's a nightmare. For in-house translation, I think I came up with a better solution to providing context. With a few lines of code one can have BTM follow the focus of the target application. Start the target application, open a form in the application and BTM will automatically select the corresponding module. Click a control in the application and BTM will select the properties of that control. Of course with external translators providing the application, and all the dependencies it might have, might not be feasible (it isn't in our case). In that case a simple screenshot should do it. No need for that. The language modules, as @aehimself said, are just empty resource DLLs with no code. The same DLL stub is used for 32- and 64-bit. Sure there is; It's called a Stop List. You can configure properties or modules to ignore based on a plethora of different rules - or regex if everything else fails. Validation is performed live. In addition, you can validate the whole project via the ribbon: BTM validates a host of different properties such as leading and trailing space/colons/whatnot, delimiters, shortcuts, case (and type of casing), etc. etc. Many validation violations can be resolved automatically. Some are too risky to try and do automatically. I don't know what you mean by "interactive TM/MT/terms". If you mean automatic translation lookup and prompt, then BTM does that too. The UI sucks a bit though. Yes, these are Windows common controls and unfortunately, the VCL developers chose to persist them using their internal binary (and undocumented) stream format. If you look at the DFM file of a form containing one of these controls you will see what I mean. I guess I could write adapters specifically for these controls but so far I haven't had any requests for them.
  3. RDP1974

    location based

    well, calculate the distance between two points is needed
  4. Linuxuser1234

    How can i add a custom font to a windows fmx application

    @vfbbi got it working thanks
  5. Anders Melander

    Looking for a localization tool

    It's unavoidable. For instance if a resourcestring is deleted then the whole range of IDs above it must change their ID. With regard to Windows resources I don't think ordinal resource IDs (not just string IDs) were ever meant to be stable. Instead we were supposed to use .rc and .h files and symbolic names - which is basically what the drc file is.
  6. Jaska

    Looking for a localization tool

    Resource only DLLs are platform independent so the same DLL can be loaded in both 32 and 64-bit environment. However this doesn't solve the problem. It only works if the resource string IDs in both 32-bit and 64-bit EXE are exactly the same. This is not the case on most Delphi application. If you compile the same source to 32 and 64 bit you will see that 1) The amount resource strings differ 2) The Ids of the resource strings differ So you have to build two sets of resource DLLs. One for 32 bit and another for 64-bit
  7. I'd say your numbers are ridiculously small for any modern DB. 1M records per day is nothing. Just post events to separate DB writer thread, use transactions to pack inserts into batches and don't bother with any other optimizations. F.ex., I have ~250 inserts to Firebird DB per second (21.5M per day)
  8. vfbb

    How can i add a custom font to a windows fmx application

    Another option that works in XE7+ and cross-platform is use the Skia4delphi as your app render. Then you only need to add the follow code in the app initialization: initialization TSkTypefaceManager.RegisterTypeface('Material Design Icons Desktop.ttf');
  9. Brian Evans

    if i changed the P4D DLLPath how to reload DLLs ?

    PyScripter is opensource so you can read the code. A quick look seems to suggest it doesn't - it unloads a bunch of common .pyd that might be loaded. I could be missing something however. In file cInternalPython.pas the procedure TInternalPython.DestroyPythonComponents; from https://github.com/pyscripter/pyscripter.
  10. pyscripter

    First Python + DelphiVCL Program

    It is cross-platform. It supports all targets Delphi supports.
  11. David Heffernan

    generics

    Stop trolling, that's my job!
  12. Stefan Glienke

    generics

    Doesn't that make it a container? 😜
  13. David Heffernan

    generics

    From my code base I find this: TThreadsafe<T> = class private FLock: TCriticalSection; FValue: T; function GetValue: T; procedure SetValue(const NewValue: T); public constructor Create; destructor Destroy; override; property Value: T read GetValue write SetValue; end; And this: Enum<T: record> = class strict private class function TypeInfo: PTypeInfo; static; class function TypeData: PTypeData; static; public class function IsEnum: Boolean; static; class function Count: Integer; static; class function ToOrdinal(Value: T): Integer; static; class function FromOrdinal(Value: Integer): T; static; class function TryFromOrdinal(Value: Integer; out Enum: T): Boolean; static; class function ToString(Value: T): string; static; class function FromString(const Value: string): T; static; class function MinValue: Integer; static; class function MaxValue: Integer; static; class function InRange(Value: Integer): Boolean; static; class function EnsureRange(Value: Integer): Integer; static; class function FromName(const Name: string): T; static; class function TryFromName(const Name: string; out Enum: T): Boolean; static; class function ToName(Item: T): string; static; class function ToNewSentenceName(Item: T): string; static; class function ToMidSentenceName(Item: T): string; static; class function ToUpperCaseName(Item: T): string; static; class function ToPascalCaseName(Item: T): string; static; end; And this: TArray = class public type TWriteItem<T> = reference to procedure(const TaggedFile: ITaggedFile; const Item: T); TReadItem<T> = reference to procedure(const TaggedFile: ITaggedFile; out Item: T); strict private const SortOrderFactor: array [TSortOrder] of Integer = (1, -1); public class procedure Swap<T>(var Left, Right: T); static; class procedure Reverse<T>(var Values: array of T; Index, Count: Integer); overload; static; class procedure Reverse<T>(var Values: array of T); overload; static; class function Reversed<T>(const Values: array of T): TArray<T>; static; class procedure Shuffle<T>(var Values: array of T; const Random: TFunc<Integer, Integer>; Index, Count: Integer); overload; static; class procedure Shuffle<T>(var Values: array of T; const Random: TFunc<Integer, Integer>); overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; Index, Count: Integer; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; Index, Count: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; Index, Count: Integer; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; Index, Count: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicate<T>; out ItemIndex: Integer): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicate<T>): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicateOfObj<T>; out ItemIndex: Integer): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicateOfObj<T>): Boolean; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T): Integer; overload; static; class function Equal<T>(const lhs, rhs: array of T; const Comparer: IEqualityComparer<T>): Boolean; overload; static; class function Equal<T>(const lhs, rhs: array of T; EqualOp: TEqualOp<T>): Boolean; overload; static; class function Equal<T>(const lhs, rhs: array of T): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparer: IComparer<T>): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static; class function Ordered<T>(const Values: array of T; Index, Count: Integer): Boolean; overload; static; class function Ordered<T>(const Values: array of T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IEqualityComparer<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IEqualityComparer<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; EqualOp: TEqualOp<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; EqualOp: TEqualOp<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IComparer<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IComparer<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparison: TComparison<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparison: TComparison<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IEqualityComparer<T>; Index, Count: Integer; const Dispose: TProcOfObj<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; EqualOp: TEqualOp<T>; Index, Count: Integer; const Dispose: TProcOfObj<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; EqualOp: TEqualOp<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; EqualOp: TEqualOp<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer; const Dispose: TProcOfObj<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IComparer<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparison: TComparison<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T): Integer; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static; class function Sorted<T>(const Values: array of T; Order: TSortOrder; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; Order: TSortOrder): Boolean; overload; static; class function Sorted<T>(const Values: array of T): Boolean; overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder); overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>); overload; static; class procedure Sort<T>(var Values: array of T; Order: TSortOrder; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; Order: TSortOrder); overload; static; class procedure Sort<T>(var Values: array of T); overload; static; class function Copy<T>(const Source: array of T; Index, Count: Integer): TArray<T>; overload; static; class function Copy<T>(const Source: array of T): TArray<T>; overload; static; class procedure Move<T>(const Source: array of T; var Dest: array of T; Index, Count: Integer); overload; static; class procedure Move<T>(const Source: array of T; var Dest: array of T); overload; static; class function Concatenated<T>(const Source1, Source2: array of T): TArray<T>; overload; static; class function Concatenated<T>(const Source: array of TArray<T>): TArray<T>; overload; static; class procedure Initialise<T>(var Values: array of T; const Value: T); static; class function New<T>(Count: Integer; const Value: T): TArray<T>; static; class function Zero<T>(Count: Integer): TArray<T>; static; class procedure Zeroise<T>(var Values: array of T); static; class procedure Free<T: class>(const Values: array of T); static; class procedure FreeAndNil<T: class>(var Values: array of T); static; class function GetHashCode<T>(const Values: array of T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function GetHashCode<T>(const Values: array of T): Integer; overload; static; class function GetHashCode<T>(Values: Pointer; Count: Integer; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function GetHashCode<T>(Values: Pointer; Count: Integer): Integer; overload; static; class procedure Write<T>(const TaggedFile: ITaggedFile; const WriteItem: TWriteItem<T>; const Values: TArray<T>); overload; static; class procedure Write<T>(const TaggedFile: ITaggedFile; const Values: TArray<T>); overload; static; class procedure Read<T>(const TaggedFile: ITaggedFile; const ReadItem: TReadItem<T>; out Values: TArray<T>); overload; static; class procedure Read<T>(const TaggedFile: ITaggedFile; out Values: TArray<T>); overload; static; class procedure Skip(const TaggedFile: ITaggedFile); static; end; And this: NDArray<T> = record public type {$POINTERMATH ON} P = ^T; {$POINTERMATH OFF} private type TEnumerator = record private FOwner: ^NDArray<T>; FCurrentIndices: TArray<Integer>; function GetCurrent: T; public class function New(const Owner: NDArray<T>): TEnumerator; static; property Current: T read GetCurrent; function MoveNext: Boolean; end; private FBase: P; FValues: TArray<T>; FRank: Integer; FShape: TArray<Integer>; FStride: TArray<NativeInt>; function LinearIndex(const Indices: array of Integer): NativeInt; function GetCount: NativeInt; function GetItem(const Indices: array of Integer): T; procedure SetItem(const Indices: array of Integer; const Value: T); function GetSlice(const Indices: array of Integer): NDArray<T>; procedure SetSlice(const Indices: array of Integer; const Value: NDArray<T>); function GetIsEmpty: Boolean; function GetHasZeroDimension: Boolean; public class function New(const Shape: array of Integer): NDArray<T>; overload; static; class function New(const Shape: array of Integer; const Values: TArray<T>): NDArray<T>; overload; static; class function New(const Shape: array of Integer; const Value: T): NDArray<T>; overload; static; class function Zero(const Shape: array of Integer): NDArray<T>; static; class function Diagonal(const Values: array of T): NDArray<T>; overload; static; class function Diagonal(Size: Integer; const Value: T): NDArray<T>; overload; static; class function Empty: NDArray<T>; static; class operator Explicit(const arr: TArray<T>): NDArray<T>; property IsEmpty: Boolean read GetIsEmpty; property HasZeroDimension: Boolean read GetHasZeroDimension; property Rank: Integer read FRank; property Shape: TArray<Integer> read FShape; property Stride: TArray<NativeInt> read FStride; property Count: NativeInt read GetCount; property DataPtr: P read FBase; property Items[const Indices: array of Integer]: T read GetItem write SetItem; default; function ItemPtr(const Indices: array of Integer): P; property Slice[const Indices: array of Integer]: NDArray<T> read GetSlice write SetSlice; procedure CopyTo(Dest: P; Count: NativeInt); function Clone: NDArray<T>; function ToFlattenedArray: TArray<T>; class procedure Write(const TaggedFile: ITaggedFile; const WriteItem: TArray.TWriteItem<T>; const Value: NDArray<T>); overload; static; class procedure Write(const TaggedFile: ITaggedFile; const Value: NDArray<T>); overload; static; class procedure Read(const TaggedFile: ITaggedFile; const ReadItem: TArray.TReadItem<T>; out Value: NDArray<T>); overload; static; class procedure Read(const TaggedFile: ITaggedFile; out Value: NDArray<T>); overload; static; public function GetEnumerator: TEnumerator; end; And this: TIterativeSolver<T> = class public type P = ^T; protected class procedure AGSIterate(A, b, x, work: P; N: Integer; Storage: TMatrixStorage); static; class procedure AGSCalcResidual(A, b, x, r: P; N: Integer; Storage: TMatrixStorage); static; class function AGSIsZero(b: P; N: Integer): Boolean; static; class function AGSSqrMag(x: P; N: Integer): Double; static; class function AGSAccel(r, x: P; work: Pointer; iter, N: Integer): Boolean; static; public class function SolveAGS(const A: NDArray<T>; var b: NDArray<T>; maxiter: Integer; tol: Double; out iter: Integer): Boolean; static; end; And this: type TLUSolver<T> = class public type P = ^T; TWorkspace = record public ipiv: TArray<Integer>; public procedure Update(N: Integer); end; protected //protected to avoid spurious compiler warning class procedure DecomposeDense(A: P; ipiv: PInteger; N: Integer); overload; static; class procedure SubstituteDense(A: P; ipiv: PInteger; N: Integer; b: P; Storage: TMatrixStorage); static; class procedure DecomposeBanded(A: P; ipiv: PInteger; N, Bandwidth, ldab: Integer); overload; static; class procedure SubstituteBanded(A: P; ipiv: PInteger; N, Bandwidth, ldab: Integer; b: P; Storage: TMatrixStorage); static; class procedure DecomposeDense(A: P; N: Integer; var Workspace: TWorkspace); overload; static; class procedure DecomposeBanded(A: P; N, Bandwidth, ldab: Integer; var Workspace: TWorkspace); overload; static; public class procedure Decompose(var A: NDArray<T>; var Workspace: TWorkspace); static; class procedure Substitute(var A, b: NDArray<T>; const Workspace: TWorkspace); static; class procedure Solve(var A, b: NDArray<T>); static; end; And this: TData<T> = record x: T; xPrime: TArray<T>; xPrimePrime: TArray<TArray<T>>; xPrimePrimePrime: TArray<TArray<TArray<T>>>; end; And this: TTableItem<T: TModelObject> = record public ModelObject: T; ObjectIndex: Integer; ItemIndex: Integer; public class function New(ModelObject: T; ObjectIndex, ItemIndex: Integer): TTableItem<T>; static; class function DisplayName(ModelObject: TModelObject; const ItemName: string; ItemIndex: Integer): string; overload; static; function DisplayName(const ItemName: string): string; overload; procedure RedirectDataAccess(var Handler: TDataObject; var Index: Integer); end; I could go on, but it's pretty boring. And these are just some examples from one particular code base. Other code bases will have different use cases. As Stefan said, generics are used for generic programming. So yeah, a myriad.
  14. Vincent Parrett

    generics

    I use generics a lot in non container/collection scenarios - for example Delphi Mocks fluent api uses the generic type to allow a type safe definition of the mock. Without generics we would be using strings - which is not typesafe and would not survive refactoring. Another example - I have lexer/parser library (used in FinalBuilder) //NOTE : T MUST be an Enumerated Type (need better constraints!) TTokenRec<T> = record private ..... end; ILexer<T> = interface function Next : TTokenRec<T>; ... TBaseLexer<T> = class(TInterfacedObject,ILexer<T>) //concrete usages TDSLLexer = class(TBaseLexer<TDSLTokenKind>,IDSLLexer) TVariableSenseLexer = class(TBaseLexer<TTokenKind>) //parsers built on top of the lexers IParser<TAstNodeType,TParseErrorType> = interface TBaseParser<TTokenType,TAstNodeType,TParseErrorType> = class(TInterfacedObject,IParser<TAstNodeType,TParseErrorType>) TDSLParser = class(TBaseParser<TDSLTokenKind,TDSLASTNodeType,TDSLParserErrorType>) TVariableSenseParser = class (TBaseParser<TTokenKind, TVariableSenseASTNodeType, TVariableSenseParserErrorType>) Generics allows you to avoid copying and pasting tons of boilerplate code, changing types etc, or doing having to do tons of nasty type casting. If Delphi's generics were better there would be many more uses for them, but when you attempt anything complex you run into limitations. If you really want to know what else can be done with generics, you would have to look at other languages that have better generics implementations (like c#).
  15. Remy Lebeau

    generics

    Have you read the official documentation yet? https://docwiki.embarcadero.com/RADStudio/en/Generics_Index
  16. Stefan Glienke

    generics

    As a reaction to one of his answers during Q&A I wrote a blog post. Having said that and personally loving generics for various use cases (as shown in the blog post) there are also things that are solved sub optimal - which I also wrote about. Also if you have used generics in C# then you will likely miss co- and contravariance - oh, look, I also wrote about that. If you are going really fancy with generics and code that uses RTTI you have to be aware about some percularities - guess what: wrote about it. Now because in generics you basically have the lowest common denominator and we are lacking quite some ways to specify some traits of the supported types via constraints there are several things that you cannot do or have to fall back to indirections: most common example is using comparer interfaces for generic sorting algorithm or hashtables. That is mostly where a naively implemented generic algorithm might be slower than some handcrafted code for the specific type unless you heavily optimize for various cases (as I have done in Spring).
  17. No, it is a forward declaration. The class itself is declared after TDrawingObject. That declaration is enough for the compiler to know it has to reserve space for the class field (Actually a pointer). The code accessing the property DrawingObjectList is in the implementation section and after both classes have been completely defined.
  18. emileverh

    Formatting inline var

    Hi! For D11; Can anybody tell me what setting(s) I needin Tools-Options-Language-Formatter ( or may be it's not possible at all ) the format an inline var. I want to have the keyword in front of the variable, now a line break is added. By the way the line break is not added in a 'regular' declaration This is what I want: TfrmMain.SomeStuff; var x : integer; begin ... lots of code var settings := dtmSettings.ReadRecord; end; And Delphi 11 does this: TfrmMain.SomeStuff; var x : integer; begin ... lots of code var settings := dtmSettings.ReadRecord; end; Any help is welcome 😉
×