Jump to content

Georgge Bakh

Members
  • Content Count

    59
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Georgge Bakh


  1. You can use unit scopes for this as partially done in RTL.

    Place things which need different implementation for different platforms in separate units per implementation.

    E.g. Windows.Utils, Linux.Utils etc.

    Or even not bound to a platform but API:

    OpenGL.Render, DirectX11.Render etc.

     

    In uses clause of other units just write Utils or Render.

    And setup needed unit scope names in project settings - Windows;OpenGL.

    This approach with some architectural effort will minimize number of IFDEFs in code.


  2. I've checked. As Stefan said if TTest2 is sealed or its method Test() is final the call is non-virtual.

    If type parameter of TTest is constrained by an interface the correct method is called but despite non-virtual declaration of Test() method the call looks like virtual (FPC inlined the call).

    GetTypeName(TypeInfo(T)) is 'TTest2' in both cases.

    Overall the current behaviour of generics in Delphi seems to be too restrictive without any gain.

    May be in C# it's acceptable because it does have many other capabilities and aggressively optimizing JIT compiler. But for Delphi it's not suitable.


  3. @Kryvich

    Just curious - what else could output this code?

     

    I'm aware of FPC approach to generics and it's much better IMHO. Although not complete too.

     

    As of virtual calls - when writing a low-level library code there is not known where exactly it will be used. So trying to avoid virtual calls it normal especially when those are absolutely unnecessary.

     

    Thanks for help. Later will check and bench with sealed/final.

    And will decide on a choice to use ugly IFDEFS or drop Delphi support. :classic_sad:

     


  4. OK, C# is an authority here and my approach is totally wrong.

    But how it can be achieved in compile time?

    The task is simple: I have a class, let's call it TDataHandler which use another class as data provider - TDataProvider.

    TDataProvider can be a simple wrapper over a memory buffer or more complicated stream-based implementation or something else.

    In TDataHandler I call TDataProvider to get some data and several other data-related things.

    I could declare methods of TDataProvider as virtual and override them in actual implementation but I don't want to have virtual method calls (non-virtual is acceptable) instead of simply referencing a pointer (as generated by FPC).

    How it can be done?

    Please note that in Java (and probably C#) virtual calls is not a problem as JIT compiler will inline even virtual calls if needed and the resulting machine code will be similar to one generated by FPC.


  5. David, if I got you right, your advice is to use the technique with virtual methods because it works. It's a good advice thank you.

    But I wanted to use generics as it's a powerful technique which I successfully use in other languages and it seems it should work for my case. And a broad range of other cases which can be identified as parametrization by code.

    If it can't be done in Delphi it's sad but I'd want to know why. Is it a bug?

    Let's get on with it:

    I have TTest<TTest2> specialization of the above generic class TTest. May I expect that field FTest will have static type TTest2? If no why?


  6. If I'd wanted virtual methods I wouldn't use generics. Just field of some base class is enough.

    But it's not a compile time parametrization. It's runtime technique.

    5 hours ago, Eugine Savin said:

    This shouldn't work. Make method Test virtual and override it in Test2

     

    Why? My logic is: TTest<T> has field FTest of type T. Therefore specialized TTest<TTest2> will have field FTest of type TTest2. How the field can be of type TTest1? TTest1 is just a type parameter constraint after all. It's needed only to allow the use of Test() method in code.


  7. Tried to use generics to parametrize a class with some code.

    type
      TTest1 = class
        procedure Test();
      end;
    
      TTest2 = class(TTest1)
        procedure Test();
      end;
      
      TTest<T: TTest1, constructor> = class(TObject)
        FTest: T;
        procedure TestIt();
      end;

    When calling FTest.Test() I expect a method of actual type parameter to be called.

    procedure TTest<T>.TestIt();
    begin
      FTest := T.Create();
      FTest.Test();
      readln;
    end;

    But actually a method of type constraint (!) is being called.

    I.e. static type of FTest not depend on actual type parameter. It's always TTest1!

    Is there a workaround for this? How do you parametrize generic classes with code?

    Comparators, hash calculators and other useful things which give generics a purpose.

    It's an essential part of generics which simply not work! How this bug can not even be reported till now?

    The code works as expected with Free Pascal Compiler.

    https://quality.embarcadero.com/browse/RSP-27840


  8. If I got it right, you protecting with a critical section (the same one I hope) read access to fields as well as field modifications with change event call.

    This may be or may be not enough depending on what your program do and what invariants you must ensure.

    Additionally, with some logic in change event handler there is a risk of deadlock.


  9. On 2/11/2019 at 7:46 PM, Bob Devine said:

    Thanks, but pax has some unique features that aren't available in the various Delphi scripting engines, including the ability to create Delphi-compatible interface-based DLLs (so you can create plug-ins from within your app) and cross-language programming (Object Pascal/Object Basic/Javascript). 

    Look like Free Pascal has these features. Besides Basic support. Did you considered it?

     

    Compiler development is very interesting area. I think you will find people if you decide to go that way.


  10. Self signed certificates can be validated as usual. If lets say a server certificate is self-signed than a root CA certificate which was used for signing (may be self-signed as well) should be trusted by client. If both server and client data are under control it's possible to make the CA certificate trusted. That's how browsers work after all.

    Diffie-Hellman key exchange by itself doesn't protect from MitM attacks.


  11. 6 hours ago, Alexander Elagin said:

    Deja vu :classic_rolleyes:

    When an open source project doesn't have a precise release date it's not good but still ok. Especially considering the fact that the project is not backed by IBM, Google or other big entity and people working on the project on spare time.

     


  12. I-Pascal reports unused units on the fly and the ones which can be moved to implementation as well. And can apply the changes automatically as well as mark some unit in uses useful to not report it anymore.

    As of class helper case - interesting case, need to think about it.

    9 hours ago, Fr0sT.Brutal said:

    AFAIU, the only truly reliable way of detecting excess uses is removing each used unit one by one and try compiling.

    Even this is not absolutely reliable as you mentioned. But working with AST can give acceptable result.

    • Like 1

  13. 20 hours ago, David Schwartz said:

    So how do you bail out of the procedure if a check fails? Does this throw an exception? Or is another test needed?

    When a check fails the result of the chain call is an object of a special class (TFailedValidator?). Which let say hasFailed() method returns True. 🙂

    Depending on actual code of Validator and TFailedValidator you can check what happened and decide what to do.

    On 8/6/2019 at 11:24 PM, David Heffernan said:

    Why even bother writing those checks? An exception will be raised as soon as you attempt to use the nil instances. 

    In addition to other answers, explicit checks can act as contracts which can be easily read and also used by IDE and/or external static code analysis tools.


  14. On 8/5/2019 at 11:14 PM, David Schwartz said:

    What's the easiest way you know of to test predicate conditions of input parameters on methods and display a meaningful error message when one fails and skipping the rest, without using exceptions?

     

    Common situations include:

     

    * an input value is NIL or not

    * an input string is empty or not

    * an input numeric is < 0, = 0, or > 0

    * an input object has a property like the above that includes that the object's reference pointer is valid

     

    I'm curious if there's a way to have a list of one-liners that are easy to read and aren't part of a huge nested if..then statement filled with and's or or's and terminated with a  begin ShowMessage(...); Exit; end;

    With these requirements the solution may be something like:

        Validator
        .Check(value <> nil,  'Value is nil!')
        .Check(str <> '',     'String is empty!')
        .Check(Value.Num > 0, 'Value.Number <= 0!');

    Check() receives a boolean to check and string message to complain.

    If boolean is true returns Self. If false - other instance whose Check() method just returns Self on any input.


  15. 10 hours ago, David Heffernan said:

    You need to be able to create development environments in a robust way. These environments need to be identical. And you need to be able to build with different versions of your codebase, including different versions of your components. That isn't something that you get with naive package manager use.

    This is the primary goal of a good package manager. But I agree - GetIt obviously can't achieve it by design.


  16. On 7/26/2019 at 3:32 PM, Mike Torrettinni said:

    So, it comes down to: organized unit cycling vs 'spread the code around' non-unit cycling solution.

     

    Any thoughts on this? (if my explanation makes sense)

     

     

     

    To avoid unit cycles your form units should not depend on a unit which actually translates anything. Them should depend on some interface ITranslator which have methods TranslateProject and TranslateControl.

    Each unit create the implementation on demand with some kind of factory. E.g. Translator := TFactory.CreateTranslator();

    The factory may be implemented as a simple container for implementations. E.g. actual implementation class (which depends on all forms) at some point during initialization registers itself as implementation of ITranslator interface.

    With this design you don't have unit dependency cycles. In real life case it's better to use some DI container for this instead of creating it by yourself.

    Quote

    This is not working if I need to use any methods from TranslatorUnit in Unit1 or Unit2. MMX Unit dependency analyzer shows cycle: Unit1 -> TranslatorUnit -> Unit1, even if all uses are in Implementation section.

    This is because there is a cycle indeed. You cannot declare mutual units dependency in interface sections. At least one unit should use the other from implementation section. Otherwise the code will not compile.

    • Like 1
    • Thanks 1

  17. On 7/26/2019 at 7:08 PM, Clément said:

    USE_FEATURE might be defined as a project conditional define or in an included unit.( that really depends on the project)
    Anyway, I would like to know if there is an extension that would use syntax highlight in the {$IFDEF} block when USE_FEATURE is defined, fade the {$ELSE} block, and of course if USE_FEATURE is not defined, the $ELSE block would be colorful and $IFDEF block grayed out.

    I'm not aware of any extensions with such effect. May be mighty LSP will bring this feature (no).:classic_rolleyes:

    I-Pascal (Pascal support plugin for Intellij IDEA which I develop) does this.

    Also I think I saw Lazarus does this too but can't find it in 2.0.2.

    And I agree with @David Hoyle - it's not an easy to implement feature.

    • Like 1
×