Jump to content

darnocian

Members
  • Content Count

    111
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by darnocian


  1.  

    14 minutes ago, David Heffernan said:

    It depends on what you are comparing, what algorithms are involved etc. 

    Ok. I was just hoping for some sort of example, as the SameValue/isZero is a generalised approach. 

     

    So back to the original post, I guess we can just take it that there are some issues with the new version of the compiler, and will need to log some issues with QP once it is back again.


  2. Sorry. A bit late to answer now...

     

    .a files is a normally a C static library. In C are essentially a container around compiled .o files. There is no point to distribute .a files, unless someone is going to link against it. Typically static libraries are only useful during dev for users of libraries, and not so much for applications as they would get linked in. 

     

    Your main deliverables from an app perspective would be the executable along with any shared libraries (dlls/so/dylib). Nothing stopping you from shipping anything you want of course.

     

    With shared library, the developer using the shared lib just needs to know the directory and filename, and then reference the library and functions appropriately as required. The main thing is that it is clear what platform is used and being able to distinguish 32/64bit. There is no universal convention from what I'm aware of. If you are using Delphi, use the Delphi convention... it is clear enough. <platform>/<configuration>. although, if you are only going to ship release builds, just do <platform>


  3. 7 hours ago, David Heffernan said:

    Using arbitrary epsilon values is not failsafe and relies on luck. 

    mainly on what solution thinks is acceptable.

     

    These are all tools. we can choose to use what we want, but just need to know the limitations.


  4. The rationale for it is when it comes to rounding due to the way the float is represented with limited bits... there will be to mismatches. You may be lucky, and comparison may work, but the epsilon comparison approach is a failsafe method to cater for rounding issues in the process of various calculations.

     

    Here is a simple example.

    procedure Test;
    var
      d: double;
      d2: double;
      diff: double;
      v, v2: double;
    begin
      d :=  1.0000002;
      d2 := 1.0000001;
      v  := 0.0000001;
      v2 := 0.0000001;
      diff := d - d2;  // 9.99999998363421e-08
    
      assert(v = v2); // values do match
      assert(diff <> v); // doesn't match because of rounding
      assert(SameValue(diff, v));
    end;

    above done on win32. 

     

    I aligned the numbers on purpose... if we do the math, we can see v should be d-d2. 

     

     v = v2 is true....

     

    then noddy calculation, we have diff = d-d2... and diff <> v,

     

    but SameValue with the epsilon shows with the given precision, we assume the numbers to be the same.

     

     


  5. Floating point is always fun.

     

    Math.IsZero has 3 overloads for different types - extended, double, single

     

    With a simple test app on Delphi 12:

     

    program Project1;
    
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      System.Math,
      System.SysUtils;
    
    procedure Test;
    var
      e: extended;
      d: double;
      s: single;
      te, td, ts: boolean;
    begin
      e := 3.5527136788055E-15;
      d := 3.5527136788055E-15;
      s := 3.5527136788055E-15;
      te := iszero(e);
      td := iszero(d);
      ts := iszero(s);
    end;
    
    begin
      try
        Test;
      except
        on e: Exception do
          Writeln(e.ClassName, ': ', e.Message);
      end;
    
    end.

    On Win32, I was surprised that 'te' is false. 

    On Win64, the values are as expected.

     

    Something to note for those that don't know. In Win64, 'extended' is 64bit like 'double', where on Win32 it is 80bit.

     

    I didn't check between versions, but is the resolution the same?

     

    Squirrelled away on line 5290 in System.Math, there is:

    const
      FuzzFactor = 1000;
      SingleResolution   = 1E-7 * FuzzFactor;
      DoubleResolution   = 1E-15 * FuzzFactor;
    {$IFDEF EXTENDEDHAS10BYTES}
      ExtendedResolution = 1E-19 * FuzzFactor;
    {$ELSE !EXTENDEDHAS10BYTES}
      ExtendedResolution = DoubleResolution;
    {$ENDIF !EXTENDEDHAS10BYTES}

    IMO I think those consts should probably be variables and in the interface section so they can be overridden if required.

     

    It does look like something buggy happening with the 'Extended' type on win32...

     

    I played with SameValue and Compare( which uses SameValue), which didn't look bad. SameValue/Compare take an Epsilon (the resolution).

     

    Stepping through IsZero, what I spotted in the debugger:

      if Epsilon = 0 then
        Epsilon := ExtendedResolution;

    After the assignment to Epsilon, Epsilon was 0 and not 1e-16. On 64bit, Epsilon becomes 1e-12.

     

    So something funky with the codegen? I recall some changes to FP operations in the new compiler, but I can't recall offhand.


  6. If you want to export for other languages, a DLL project is what you want. when you switch platform the project will generate a so, etc.  You just need to add the exports. Note that symbols may be exported differently on different platforms. E.g. there may be an _ in front of names when importing… best way to validate is to dump exports on the shared object once it is created.i haven’t tested android recently, but did Linux.


  7. Hi All,

     

    Just a quick announcement that a new version 1.7.5 of the Sempare Template Engine is now available. 

     

    Sempare Template Engine for Delphi allows for flexible dynamic text generation. It can be used for generating email, html, source code, xml, configuration, etc. 

     

    Integrations have been done with a number of web frameworks such as: Indy, WebBroker, Horse, DelphiMVCFramework, mORMot, ...

     

    Please check out the project, and 'star' it on github.

     

    https://github.com/sempare/sempare-delphi-template-engine

     

    From v1.7.5

    FIX: Improved JSON (System.JSON) support
    FIX: Refactor RTTI deref methods

     

    From v1.7.4 (released last week)

     

    NEW: Assignment can now be done using both Pascal (:=) and C (=) operators. This is a flexibility feature to support users.
    NEW: default(value, default) method. Default is returned when IsEmpty(value) is true.
    NEW: domid(record_or_class [, context:str] )
    NEW: pascal-like ternary: <% greet := true; print( 'hello' if greet else 'bye' ) %>
    FIX: refactor old C-like ternary <% print(greet? 'hello':'bye' ) %>
    FIX: some of the language constructs required open and close brackets. These are now optional. Close bracket will be forced when the open bracket is used.
    FIX: semi colons can be used more liberally within the script blocks, even with empty statements. <% print('hello'); ; ; ; print('world') ; %>

     

    Regards,

    Conrad

     

    • Like 2

  8. 10 hours ago, Vincent Parrett said:

    This sort of topic comes up just often

    That is also why I called it my 'wish list'. 😉

     

    I agree with stability. In my list, I'm not sure if 'improve' is actually a 'feature' or a 'fix'. Depends on interpretation, and I guess the underlying implementation complexity that we are not aware of.

     

    However, I'd like a major version number to actually include features, with minor versions including minor feature/improvements, and patches.

     

    Quote

    profit doesn't get re-invested.    

    It looks like they have started on the C++ side of things... that is promising.

     

    It is hard evolving a product, especially a language, with the being any knocks. Sometimes you get close, but we've seen, it can be a challenge.  

     

    How do we found out how to get the message about reinvestment to the powers that be? Unfortunately, there needs to be lobbying power, and that means numbers. strike strike strike 😉 

     

    Jokes aside.. It is still an amazing product... we all wish it were better, faster... and hope that we can get new generations of developers to be as enthused about it as we are.

     

     


  9. my wish list for Delphi 13 (although probably too long!)

     

    IDE

    - continued LSP enhancements (it is gradually getting better, but I'm still having issues...)

    - support for auto completion of anonymous methods ....

                         e.g. var func : TFunc<integer> := { Ctrl+Space here and the rest expands } function : integer begin end;

    - support that could 'suggest units to include' when you start using something that is not already referenced.

    - support to handle multiple monitors... when I place it on one monitor, between startup, edit and debug, I'd like it to stay in the same place, without resizing, or jumping about.

    - code formatter! please! 

     

    object pascal:

    - improved type inference on generics ... IMO there are scenarios where the compiler forces you to specify a type when I think it can be inferred from a parameter type, or even a return type. Delphi doesn't ever try to match return types generally at present. ;(

    - traits - essentially compile time generics/interfaces .... so you program to a trait, and anything that matches (interface, record, class) that matches the methods, fields, properties etc could work with it. This could remove a lot of repetition in very similar code (which is what generics is all about)

    - interface improvements (possibly an alternative away from COM compatibility which is what probably gives us the restrictions we currently have) ...

    - improved generics - e.g.

                       1. generic functions (already mentioned by Lars)

                       2. allowing for constants to be passed as generic parameters could be useful. Could allow for meta programming like in C++

                       3. when using methods in an implementation of a unit,  from within a generic method, the compiler forces you to declare the method again in the interface section. I hate exposing things that shouldn't have to be public.

    - compile time constants from expressions that may be the result of function calls.

                      e.g. const PI :double = calcPI();

    - constraints on attributes

                      e.g. so we can localise their usage to methods, parameters, types, etc... 

    - an improved case statement supporting match criteria

    - a short inline lambda (syntactic sugar - shorter form of anonymous method).

                     e,g, var add1 := lambda (y:integer): y+1;   

                            var two := add1(1);

    - improved helpers / partial classes - somehow supporting multiple with conflict resolution 

    - magic functions to identify filename, function, line no.  This could be useful for use with loggers, but could bloat code if not used cautiously. Some things can be done with map files and 3rd parties, but would be nicer to have stack traces, etc accessible as part of the normal RTL.

     

    my wishlist is possibly too big ;(

    • Like 1

  10. 2 hours ago, David Heffernan said:

    What would offsets be helpful for given that the data streamed in those fields is never used

    Say in serialisation, you construct offsets relative to a certain address (say the start of the first record), and in deserialisation in another process, you convert back to pointers again. The key to it being useful is the layout and relative addressing.


  11. I am pleased to announce that Daniele Teti's DelphiMVCFramework (https://github.com/danieleteti/delphimvcframework) now includes an adaptor to integrate with the Sempare Template Engine (https://github.com/sempare/sempare-delphi-template-engine). A sample project (https://github.com/danieleteti/delphimvcframework/tree/master/samples/serversideviews_sempare), modelled on the Mustache sample, illustrates the usage. The README.md provides an overview on the usage and the sample app.

     

    Daniele has also published a post on his latest release: https://www.danieleteti.it/post/delphimvcframework-3-4-1-sodium/

     

    The template engine is not included in the distribution. To include it, contrib/get-sempate-template-engine.bat will clone it into the lib folder. The Sempare Template Engine is also available via Embarcadero's GetIt (https://getitnow.embarcadero.com/sempare-template-engine-for-delphi). v1.7.3 and above is required.

     

    Note that the template engine is dual-licensed, under GPL for open source and the Sempare Commerical license for commercial projects.

     

    Here is an example of how the template engine is used in a project:

    1. You need a controller method mapping onto an HTTP endpoint (GET /people)

      1 [MVCPath('/people')]
      2 [MVCHTTPMethods([httpGET])]
      3 [MVCProduces(TMVCMediaType.TEXT_HTML)]
      4
      5 procedure TWebSiteController.PeopleList;
      6 var
      7  LDAL: IPeopleDAL;
      7  lPeople: TPeople;
      9 begin
     10   LDAL := TServicesFactory.GetPeopleDAL;
     11   lPeople := LDAL.GetPeople;
     12   try
     13     ViewData['people'] := lPeople;
     14     LoadView(['people_list']);
     15     RenderResponseStream;
     16   finally
     17     lPeople.Free;
     18   end;
     19 end;

     

    2. You need to assign some data to be rendered in the ViewData collection. This could be any data that can be inspected via RTTI.

    13 ViewData['people'] := lPeople;

    3. Identify the view to be used.
     

     14     LoadView(['people_list']);

     

    4. Define the template 'people_list.tpl' in the 'templates' directory.
     

    {{ for person of people }}
        {{ person.FirstName }}
    {{ end }}


    The actual example in the sample project is a bit more detailed. In DAL.pas,
     

    type
       TPerson = class
          // ...
          property FirstName: string read FFirstName write SetFirstName;
          property LastName: string read FLastName write SetLastName;
          // ...
       end;

     


    The template engine can dereference properties or fields on PODOs, or any type of structure dynamically and provides extensibility methods to support custom behaviour, as required.

     

    More detailed documentation is available on https://github.com/sempare/sempare-delphi-template-engine.

     

    Please contact us for consulting/support/training if required. info@sempare.ltd/conrad.vermeulen@gmail.com

     

    Have fun.

    • Thanks 2

  12. Hi all,

     

    I'm pleased to announce the new release (v1.7.3) of the Sempare Template Engine.

     

    Update includes:

    • NEW: initial compatibility with the DelphiMVCFramework (https://github.com/danieleteti/delphimvcframework/pull/711)
    • NEW: added some helper debug methods for probing the stack frames
    • NEW: add Context.VariableResolver allow for pulling variables (previously you had to publish variables explicitly or pass all data upfront)
    • NEW: map values can now contain expressions. You can use configuration like { "key": "value" } within the template. Useful when passing data to included templates dynamically to limit variable scope.
    • FIX: context missing on two of the TTemplateRegistry.Eval overloads which resulted in some of the config being missed.
    • FIX: general refactorings
    • FIX: VCL dependency removed. Introductory licensing text is now included in template output when run without the define. 
    • FIX: refactor SempareVersion() helper

     

    Older release notes can be viewed on the releases page.

     

    Have fun.


  13. I appreciate the conceptual difference between stackfull vs stackless coroutines. Fibers are stackful, where for stackless, we would need the compiler to weave in state management support for the yield/await type behaviour efficiently as done in many other languages that have the feature. Stackful has to save the stack when context switching, where the stackless has minimal state to save. I think without having language features, and trying to emulate the behaviour is probably only achievable with fiber like apis, be it less efficiently.

     

    The Gor article does provide good references / motivations as to why use is not encouraged. The scalability, performance and maintainability aspects ultimately dictate how useful something is in the long run. 

     

    Needless, I still find it an interesting space and something to play with.


  14. I have a few points:

    1. it may be easier to use the Appercept AWS SDK. You don't need to bring Python into the picture in order to use it. Understandably, the SDK is currently only available in Delphi Enterprise. 

    2. in the code above, as you are downloading binary, I'd say it would be easier just write to file from python, and then read it back in from Delphi. I have not checked the marshalling code in the Py4D layer, but I assume that is what you are after. It depends on how you intend to use it, if the file is really big, do you want the whole thing in memory?

    3. in python, I think you could also do

    Quote

    pbarray = io_stream.getvalue()

     and in delphi,

    Quote

    var barray = PyEngine.GetVarAsVariant('pbarray');

    I suspect this might mean there could be 2 copies of the byte array in memory temporary, which may not be ideal. 

     

    disclaimer: I havn't tested the above, but guessing it may get towards the right direction.


  15. @David Schwartz  The approach of placing some middleware in front of the database is definitely better. The benefit of the approach vs direct db access is that you are likely to have more options in terms of scalability and support, and ability to centralise business logic. If you define the service contract well, you can change the implementation of the backend, as long as you don't break the contract, and all your clients can continue working. From a scalability perspective, you can easily put a load balancer in place to front multiple servers. When it comes to the db, you could have multiple read replicas with the backend server spreading the load between them, if your system is more read heavy. Anyways, it all depends on the problem you have, but having a service offering does give you options. It can become a pain if you have multiple clients (say desktop, web, mobile) having to implement business logic - one could get out of date because of a bug and management forgot to replace the contractor that was last working on that client that everyone forgot about. 😉 Further, you also have away of measuring usage, as you can enable logging, whereas with direct access to a db, you would need to query db logs or something. Further, the art of the service contact is how much data is in a request/response, do you make lots of small calls, or do you make one big one, etc...  all depends on the problem.

     

    So with Google Firebase DB, I've seen mobile clients connect directly to it. Many companies have found this attractive in terms of simplicity, as an object store, it is easy to add / query items. However, I've seen issues where initially people get excited as it is so fast just accessing the db directly. then the pain creeps in there are different clients that have implemented the business logic internally. Anyways, you have to be careful about the use case and the problem being solved. Typically a cloud functions  (like an aws lambda) could also linked to an endpoint to wrap business logic. I havn't tried using Firebase from TMS, so can't comment, but google essentially exposes the nosql db like a rest api (https://firebase.google.com/docs/reference/rest/database) So all the scalability and separation between implementation is handled by google probably in ways I've described, and hidden to the end user / developer.  In my opinion, it is still a db store, so I'd still prefer to with front business layer or something vs going directly in.

     

    in my opinion, it is definitely useful to create the abstraction of having a service to front the db / storage ecosystem. don't expose the sql or whatever the underlying storage query language directly to the user, as you are then you are exposing internals and likely to have problems later where some friendly guy sends a 'drop table transactions' or something. 😉 

    • Like 1

  16.  

    Brian Long made a nice video on accessing Android APIs... 

    Jim McKeeth also wrote an article which referenced the above: http://delphi.org/2014/07/custom-classes-dex/

     

    On the various classes, you may note there are init() methods. these map onto the Java constructors (similar concept to Delphi constructors).

     

    from the app.java, I think you need to map over mSM62K2DriverApi and mMxFingerAlgAPI to Delphi fields on your form, something like:
     

    Quote

    FSM62K2DriverApi : JSM62K2DriverApi;

    FMxFingerAlgAPI : JMxFingerAlgAPI;

    and then initialize them :

    Quote

    FSM62K2DriverApi := TJSM62K2DriverApi.init();   

    FMxFingerAlgAPI :=TJMxFingerAlgAPI.init() ;

     

    then you should be able to reference the methods you are after.

    • Like 1

  17. I do find the mixed response in this thread really interesting. When I raised the RSP, Brian Long, an long time Delphi guy, asked if I had tested the routines and I said I'd provide an example test project. Most missed the intent to facilitate completeness as I did not labour that point too much. I thought providing the missing routines and tests is something that could be useful to to anyone else that was curious/explorers/prototypers, etc. I agree, 99.9% of coders will never need to go near this stuff.

     

    Open question - should there be a blanket ban on experiments or using stuff that nobody else does because it is deemed obsolete (g*d, how many times have I heard that about Delphi/Pascal). Just putting it out there.... 

     

    • Like 1
×