DeHL 0.8.3

DeHL

I will be brief as usual — version 0.8.3 of DeHL is out. The downloads can be found on this page and changelog on this page. This release “fixes” some of the things I wanted fixed for a long time, so it seemed this is the perfect moment for this to happen. A new unit is introduced — DeHL.Tuples — which brings seven generic Tuple<…> types. I have also finished moving away from Integer and Cardinal to NativeInt and NativeUInt through all DeHL.

Breaking changes are:

  1. DeHL.Converter was renamed to DeHL.Conversion. This name change was done mostly to reflect the nature of the unit. It does not contain one simple class anymore. Now there is a fully featured conversion system.
  2. TBinaryTree<T> (in DeHL.Collections.BinaryTree) is no more. It was written way in the beginnings of the project and was buggy, incomplete and utterly useless.
  3. And the most visible and breaking of all changes is the removal of TKeyValuePair<TKey, TValue> (in DeHL.KeyValuePair). It was replaced with KVPair<TKey, TValue> (in DeHL.Tuples). The easiet way to get over this change is to find and replace all TKeyValuePair instances with KVPair and all DeHL.KeyValuePair uses with DeHL.Tuples.

Now, obviously an example using Tuples:

uses
  SysUtils, DeHL.Tuples;

{ If you are lazy and do not wish to declare a new record type
  to be used as result. Use Tuple<..> do to that. }
function GiveMeSomeData(): Tuple<String, Integer, Integer>;
begin
  { ... Do some processing ... }
  Result := Tuple.Create('Some data', 100, -99);
end;

var
  LResult: Tuple<String, Integer, Integer>;
begin
  { Obtain the result }
  LResult := GiveMeSomeData();

  { And write the results to the console }
  with LResult do
    WriteLn('Something was done with result: ', Value1, ', ', 
      Value2, ', ', Value3, '!');
end.

The new conversion engine handles most of the possible conversions and also allows registering custom ones:

uses
  SysUtils,
  DeHL.Conversion,
  DeHL.Collections.List;

type
  { Declare some type that cannot be converted into integer directly.
    We're making up an "int". }
  TRecordInt = packed record
    FValueAsString: string;
    FSign: Boolean;

    constructor Create(const AInt: Integer);
  end;

{ TRecordInt }

constructor TRecordInt.Create(const AInt: Integer);
begin
  { Decompose an int }
  FValueAsString := IntToStr(Abs(AInt));
  FSign := (AInt < 0);
end;

var
  LInputList: TList<TRecordInt>;
  S: String;
  I: Integer;
begin
  { Create a list of TRecordInt }
  LInputList := TList<TRecordInt>.Create();

  { Fill it with some random values (positive and negative) }
  for I := 0 to 10 do
    LInputList.Add(TRecordInt.Create(Random(MaxInt) - (MaxInt div 2)));

  { Now comes the interesting part ... register a custom converter
    from TRecordInt to Integer }
  TConverter<TRecordInt, Integer>.Method :=
    function(const AIn: TRecordInt; out AOut: Integer): Boolean
    begin
      { Convert the TRecordInt back to an integer }
      Result := TryStrToInt(AIn.FValueAsString, AOut);
      if Result and AIn.FSign then
        AOut := -AOut;
    end;

  { Now print the values to the console. Convert them from TRecordInt to
    Integer then to String }
  for S in LInputList.Op.Cast<Integer>.Op.Cast<String> do
    WriteLn(S);
end.

TConverter is also smart enough to figure out that “type MyInt = type Integer” is actually equivalent to Integer. If there is no explicit custom conversion method registered for it the converter for the standard type will be selected is possible. In the worst case, when TConverter cannot convert directly between the given types, it falls back to Variant conversion (using TType.TryConvertToVariant and TType.TryConvertFromVariant) which all types registered with DeHL’s type system, if possible, should implement.

Well, that’s all for today,
Have Fun!

20 Responses to 'DeHL 0.8.3'

  1. Vic says:

    I’ve decided to try out your library. In the past I’ve made use of Delphi’s built-in TObjectDictionary, like this: TMyObjectList = class(TObjectDictionary)…etc.

    When I try to compile using your implementation of TObjectDictionary, I get “[DCC Error] myunit.pas(##): E2511 Type parameter ‘TKey’ must be a class type”

    I see in your source that you’ve declared TObjectDictionary like this: TObjectDictionary… (with the class specifier).

    How can I continue to use strings as Keys in my object lists?

    Thanks, Vic.

  2. Vic says:

    Sorry, it looks like WordPress is eating my angle brackets. Anyway, what I’m trying to do is use a string for the TKey parameter. Hope that helps.

  3. alex says:

    Yes, indeed. TObjectDictionary in DeHL is limited to two classes only. You can make your own with only values being objects. See how TObjectDictionary is implemented. It’s really simple and in fact it just wraps some basic functionality.

  4. Feature request…

    DeHL.Math.Money

    Class would be nice, with proper handing of $1.00 / 3 = 0.33 + 0.33 + 0.34 or rounding errors. Similarly.. In countries which don’t have 1c or 2c and minimum coin is 5c.

    Anyway.. Just a thought

  5. alex says:

    You probably mean the Decimal data type (as in .NET Decimal). It’s on my todo list.

  6. Yes.. Decimal is what I was after..

    Thanks.. Looks like its progressing well in SVN.

  7. alex says:

    @Andrew Tierney
    I’m basing it’s interface on Java’s BigDecimal — it looks much better than the others I’ve seen.
    Hope to make it more “Delphi-sh”.

    Also note that it is BigDecimal and not Decimal.

  8. Vic says:

    Hello,

    I’m having an issue with your library (0.8.3). The Delphi IDE stops responding at times when Code Completion is invoked. At first I thought it was something else, like an addin or installed package or bad library path. But it seems to be something in your library. The following code same reproduces the problem on my machine (Win 7 Ult x64, D2010 Ent):

    { CODE START }
    unit Unit2;

    interface

    uses
    //Use one or the other, not both. See note towards the end of code.
    DeHL.Collections.List; // When this line is uncommented, code completion fails
    //Generics.Collections; // When this line is uncommented, code completion works

    type
    TMyEnum = (meAAA, meBBB, meCCC);

    TMyObject = class(TObject)
    strict private
    FName: string;
    FMyEnum: TMyEnum;
    public
    property Firstname: string read FName write FName;
    property MyEnum: TMyEnum read FMyEnum write FMyEnum;
    constructor Create;
    end;

    TMyContainer = class(TList)
    end;

    implementation

    { TMyObject }

    constructor TMyObject.Create;
    begin
    FName := ”;
    FMyEnum := m // <– invoking code completion (Ctrl+Space) here hangs the IDE
    end;

    end.
    { CODE END }

    Invoking code completion in the constructor, on the enumeration causes the IDE to stop responding. In process explorer, the bds.exe process runs at 50%CPU, while the Private bytes/Working Set continues to climb and climb. After about 8-9 minutes, it stops and the IDE becomes responsive again, but the process repeats itself if code completion is invoked again.

    Can you or anyone else verify this problem, and perhaps a solution?? I would like to use your library, but this issue prevents that.

    Vic

  9. alex says:

    It’s a known issue with Delphi 2010’s code completion. I will see what I can do.

  10. Vic says:

    I see in Quality Central report #85788 is very similar. I added a comment showing this way of reproducing the issue. Hopefully a workaround or fix will be available soon.

  11. Have you tried DeHL with Freepascal ?

    It would be nice to deploy to linux/osx on freepascal, while the Delphi roadmap progresses to cross platform in 2011.

  12. alex says:

    @Andrew Tierney
    Unfortunately DeHL is not going to work on FPC. There are severe differences between the generics model of the two compilers.

  13. André says:

    @alex
    Already found something about the hanging Code Completion? Because it is not usable for me!
    (and I hate that because I am really enthusiast about DeHL!)

  14. alex says:

    I am sorry but I cannot recommend anything for D2009 or D2010. You can try to include DeHL not as a package but as source files directly. That might help.

  15. Any thoughts on expanding the LINQ style queries for the framework/Collections ?

  16. Are you still updating DeHl ? or do you recommend people move to the Collections 1.1 library ?

    Are the collectiosn in DeHl and Collections 1.1 similar with DeHL having String Extensions etc ?

    Thanks

  17. alex says:

    I’m trying to get Collections 1.2 out which will be the first truly “stable” release. Then I will consider going back to DeHL and update it.

    Being one man doesn’t really help …

  18. Understand.. I’m impressed with what you have already released.

    Just wasn’t sure if Collections was a replacement for DeHL…

    Regards
    Andrew

  19. Rainier Dennis says:

    Will the current DeHL work with XE2?

Leave a Reply

Your email address will not be published.