Jump to content

David Heffernan

Members
  • Content Count

    3710
  • Joined

  • Last visited

  • Days Won

    185

Posts posted by David Heffernan


  1. 1 hour ago, JonRobertson said:

    Should that matter? I started learning Pascal 35 years ago and C the following year. Not once have I written

    
    c := (a < b) ? a : b;

    or

    
    if (a == b) { doSomething(); }

    while writing Pascal code.

    This is a strange post. The issue with multiple languages is the mix of zero based and one based indexing. 


  2. 1 hour ago, dummzeuch said:

    Since Delphi is kind of a legacy programming language nowadays, backwards compatibility is very important. You don't want to throw away millions lines of proven code because they don't work any more, or even worse, because they are now buggy. So trying to change strings to be zero based was a bad idea, even if it was "just for mobile platforms".

    I don't disagree with that point. My point is that it was a bad idea in the first place to make strings 1 based.


  3. for var item in arr do

    This is generally to be preferred, but sometimes you want the index as well as the item. In Python we write

    for index, item in enumerate(arr):
    	print(f"arr[{index}] = {item}")

    The absence of such a feature, which also relies on tuple unpacking, makes such loops in Delphi less convenient. This is pretty much the only reason for still using classic for loops.


  4. 8 hours ago, Nigel Thomas said:

    Using Delphi D2007.

     

    I'm trying to do the following:

     

    
    type
      FileSig = record
        Offset: Integer;
        arrSig: array of byte;
      end;
    
    const
      sig1: FileSig =
        (Offset: 10;
         arrSig: array [0..2] of byte = ($00,$01,$02);
        )

    But I can't: E2029 ')' expected but ',' found

     

    In D10+ I can do:

    
    const
      sig1: FileSig =
        (Offset: 10;
         arrSig: [$00,$01,$02];
        )

    Is there a way I can do similar in D2007?

    No, this is not possible in Delphi 2007. You can declare typed constants for fixed length arrays, but not dynamic arrays.

    • Thanks 1

  5. 27 minutes ago, A.M. Hoornweg said:

    And many of these methods call each other, which complicates matters further because setfpcr/restorefpcr would have to support nesting.

    That's easy to fix. You just make sure that they call internal methods only.

     

    27 minutes ago, A.M. Hoornweg said:

    And multi-threading would make matters even more complicated.

    Not really. You can store the FPCR to a local variable in the exported method. 

     

     

    The thing is, the change in Delphi 12 isn't actually causing any new issues. These issues always existed. It's just a consequence of the "design" of DLLs not making FPCR part of the ABI.

    • Like 3

  6. 7 hours ago, msohn said:

    Now to get back to some real code, I'd love to hear your opinion on the following fragment (sorry, insert code popup again didn't work):

     

    function MyFloatingPointAPI: Double; cdecl;
    begin
      try
        Result:= ComplexCalculation;
      except
        on E: EInvalidOp do
          Result:= NAN;
        on E: EZeroDivide do
          Result:= INF;
        on E: Exception do
          ...log, handle, whatever
      end;
    end;

     

    If you properly document that NAN and INF are possible results of your API, this should work fine both with and without FP exceptions without introducing much of a performance hit, right?

    One very obvious problem is that you need to write code like this everywhere. Not just at the top level. I stand by my advice before. Either:

     

    1. Make FPCR part of the contract, or

    2. Take control on entry, and restore on exit.


  7. 6 hours ago, msohn said:

    In the end, you should make your code work both ways and check floating point calculation results with IsNAN and IsInfinity, e.g.

    
    try
      F:= <some floating point calculation>
    except
      on E: EInvalidOp do
        F:= NAN;
      on E: EZeroDivide do
        F:= INF;
    end;
    if IsNAN(F) then
      <handle InvalidOp>
    if IsInfinity(F) then
      <handle zero divide>

    This is the worst advice I've seen in quite some time!! 


  8. 3 hours ago, msd said:

    Google Gemini (please don't even give it a try).

    ChatGPT 3.5: Correct Translation

    ChatGPT 4.0: Pro Translation

    This is pretty epic, let's be honest. Take all the drudge out, and let us work on the brain stuff.


  9. 1 minute ago, David Schwartz said:

    So what DO you do in a case where, say, you might use an object to collect an accumulation of data that is provided by multiple sources? 

     

    It's often done for contextual state management over time...

     

    That's kind of a vague specification. For instance, is the data pushed or pulled? I would imagine that makes a difference. 


  10. 50 minutes ago, David Schwartz said:

    I encounter errors in (1) when the code is rather long and I declare an object but forget to add the Free to the Finally clause.

    I don't really understand this. I always write the try/finally immediately after the construction, and always bang the Free in immediately. Then I fill out the body. It's just a habit that you form so that you don't make such mistakes. And honestly, this is never one that is hard to debug because you just have a leak. And presumably you use leak detection tools so that you'd always find them immediately.

    52 minutes ago, David Schwartz said:

    For (2), I'd love to see what your approach is. I've not found an approach that is robust and works well everywhere, other than something that takes a lot of extra code to check things everywhere.

    I don't really understand this scenario either. If you have a reference to something that may or may not exist, you would test Assigned() before using it. And when you were finished, you'd set the reference back to nil once you'd destroyed it.

     

    The scenario that is tricky is when you have multiple references to an object.

    • Like 6

  11. 36 minutes ago, David Schwartz said:

    I'd like this because chasing down orphaned blocks and references to objects that got deleted early seem to take up more of my time than any other types of debugging issues.

    It's odd you say that, but I never have to debug issues like this. There are two simple patterns for lifetime and they are so ingrained, nobody ever makes a mistake in my team.

    • Like 4
×