Jump to content

David Heffernan

Members
  • Content Count

    3499
  • Joined

  • Last visited

  • Days Won

    174

Posts posted by David Heffernan


  1. 36 minutes ago, Rudy Velthuis said:

     

    I generally resort to assembler (if possible, i.e. on Windows, 32 bit or 64 bit target), although I always try to have a PUREPASCAL backup and I optimize that as much as I can.

    Practical for small amounts of code that is seldom modified. Of course good compilers typically produce better code than humans can manage. 


  2. 51 minutes ago, Rudy Velthuis said:

    I doubt that optimizations often make a difference in the runtime of a program, unless you are really running very processor-intensive code. But even then, the algorithms used are far more important than an optimized runtime.

    I'm not talking about the runtime. I'm talking about the code emitted by the compiler when it compiles my code. 

     

    Performance is critical for my program. Some of the critical sections of code I translated to C in order to reap significant performance benefits of having a good optimising compiler. 

     

    So yes, this is a real issue. 


  3. The complexity is linear with the number of digits. In this case it's probably much easier to write the code if you convert each number to text. 

     

    You then need an array of counts for each digit. Count the digits. Finally check that each digit has the same number of occurrences. 

     

    In practical terms, complexity arguments aren't actually going to be relevant here. It's the constant of proportionality that will matter most in performance. 

    • Like 1

  4. 1 hour ago, Rudy Velthuis said:

    I don't remember where, but I have seen some improvements in code generation, especially in the 64 bit compiler

    I see pretty much the same code in 10.3 as produced by XE7 in my real world app, using the Windows x64 Delphi compiler.  Performance is identical.  Still significantly worse than could be achieved by the mainstream C++ compilers. Probably worse than what could be achieved in C#!

    • Like 1

  5. 13 hours ago, Rudy Velthuis said:

     

    I don't expect a big speed difference due to that (but there may have been speed differences due to better optimization in the compilers and especially in the runtime).

    Runtime optimisation only helps if your code relies heavily on the runtime functions that have been improved. And where are these improvements in the code emitted by the compilers? I've not seen anything. What has changed? 


  6. 3 hours ago, Ruslan said:

    I guess if a pointer is declared in a method that is used to fill a Dictionary, List or ObjectList than it is not needed to set it to nil at the end

    You never need to set a pointer to nil. 

    • Thanks 1

  7. You said that the objects were instantiated by calling the constructor. You later say that they are loop variables used when iterating over a collection. So that's a total contradiction. 

     

    So, with this new information the simple answer is that you never need to set the loop variable to nil. 

     

    We read the question just fine. Please don't tell us to read it again. It's you that should read it again. 


  8. 4 hours ago, David Schwartz said:

    I think what DH is saying is that there's nothing that prevents the author of the GetABC function from returning fxyz or FloatToStr(sin(2*pi*r*r)) or just a random string. That's true.

     

    Reminds me of a time way back when color monitors were $4,000 and I was advocating for the use of colors to help highlight errors in red, success in green, and stuff like that. A contrarian guy on the team argued, "How do you know that someone won't display errors in green and successful results in red?"

     

    Indeed, I'm working on a project now where we're porting an app from Oracle to PostgreSQL, and there are functions that are not returning what we're expecting. It's a major headache to track this stuff down.

     

    Assuming there are some reasonable conventions being followed (which you should always verify if at all possible), then a function purporting to return a string version of a certain variable can be counted on to do that, while a function that returns an integer version will do that instead -- regardless of how that variable is implemented.

     

    So if it's defined as a string, then the version of GetABC : string just returns fabc while the integer version returns StrToInt(fabc) -- and you need to ensure that fabc is supposed to be an integer and not a float.

     

    The point is, the function acts as an adapter to convert whatever the implementation type is into whatever type the function returns. And if you change the implementation type, then code that accesses it directly will either fail to compile or fail at run-time, while the code that uses the adapter function will continue to work (assuming you update the function properly).

     

    The function hides the implementation. 

     

    Properties are just sugar coating that make accessors & mutators easier to use.

     

    That's the not true part of what I am saying.

     

    There's also the not helpful part of what you stated. I found your comment to be entirely unhelpful.


  9. 2 hours ago, David Schwartz said:

    No matter HOW fabc is defined within the class, you can be sure that a method like

     

    function GetABC : string;

     

    will ALWAYS return the contents of fabc as a string, regardless of how fabc is actually declared. And regardless of whether fabc is private, protected, public, or published.

    That's not true, and not helpful. The function can return anyrhing it likes. No reason where there has to be a field anywhere whose value is returned. 


  10. When facing terminology that you don't recognise I cannot recommend the use of websearch highly enough. 

     

    https://enterprisecraftsmanship.com/2016/07/27/what-is-an-implementation-detail/

     

    https://stackoverflow.com/questions/1777719/what-is-the-definition-of-an-implementation-detail

     

    And no, it's the second excerpt that relies on leaking implementation details, which is why it should not be used. 

    • Like 2
    • Thanks 1

  11. 8 hours ago, Rudy Velthuis said:

    I know what a vector is, in several meanings of the word, thanks, and I know how to use them, or calculate with them or what kind of operations on them make sense.

     

    Not sure what that has to do with the fact that I think it is silly and stupid to declare open array parameters on overloaded operators. If you want to pass open array parameters to something, make that something a function, not an operator.

     

    And note that I think there is nothing wrong with declaring static array types (including Euclidian vectors or transformation matrices) or dynamic array types as parameters for operators. It makes sense to add two vectors (Euclidian kind) or concatenate the C++ kind of vectors using a + operator. It also makes sense to multiply a vector (any kind, actually) with a scalar using a * operator. But operators and open array parameters are a bad match.

     

    Again: this is fine:

    
    class operator Multiply(Left: Double; const Right: TVector3): TVector3; // scales a plain static 3D vector
    // or:
    class operator Multiply(Left: Double; const Right: TArray<Double>): TArray<Double> // numpy-style "broadcast": each element of Right is multiplied by Left.

    But this doesn't make any sense IMO:

    
    class operator Multiply(const Left, Right: array of Double): TArray<Double>; // Convolution: Left[i] is multiplied with Right[i]

    If you want that, then code it as:

    
    class function Multiply(const Left, Right: array of Double): TArray<Double>; static;

    And then you can call it like

    
    Result := Multiply([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);

    But this is (syntactical) nonsense, IMO:

    
    Result := [1.0, 2.0, 3.0] * [4.0, 5.0, 6.0];

    Because you can't or at least shouldn't be able to use open array constructors like that, outside a parameter list. And they could be confused with dynamic array constants and perhaps even with sets anyway. Pure nonsense to try that, IMO.

    So if it compiles but doesn't work as expected, I am not surprised.

    That's not nonsensical from the programmer's perspective. Only from the constraints of the language design. 

     

    I'm coming at this with an open mind as to what a programmer would like to be able to do. You are tied down by the historical precedent of syntax.

     

    The fact that [1,2] can be an open array constructor, a dynamic array, or a set, depending on context is the root of the problem. It is that poor design of the language that is at the root of this question. 

     

    So I object to your defence of the language and assertions that what the programmer wants to do is nonsensical. 

     

    I struggle to understand these two claims of yours:

     

    1. A plain function is a better way to implement an equality test than an operator. In my view that is an indefensible claim. You have to use a plain function because the language syntax doesn't support an operator. But that doesn't make the operator undesirable. Just unachievable. 

    2. An operand that is an array implies more than two operands. I can't work that out. That's why I though you don't know what a vector is. But you seem to have got past that in your last post where you happily use arrays as operands. 


  12. 2 hours ago, Rudy Velthuis said:

    Sure, arrays/vectors/matrices/lists/tuples/etc. can be thought of as single entities and I fully agree that one can use operators to combine them too, or to map single operations to such structures (e.g. like numpy's "broadcasts":  myNewArray := myArray + 3;). But not open array parameters. They are parameters. Parameters belong in a parameter list, and operators do not have parameter lists. Well yes, they can have formal parameter lists when you declare their overloads, but not when they are used in infix or prefix notation. And that use is their sole raison d'être. After all, everything an operator does can be done with a plain function call too, like they do in Java; it just doesn't look so "natural".

     

    So if I had designed operator overloading, I would not have allowed open array parameters or arrays of const for them, for (to me) obvious reasons. I would of course have allowed predefined array types, dynamic and static, and TArray<x>, and what not.

     

    It's almost as if you don't know what a vector is. 


  13. 4 minutes ago, Rudy Velthuis said:

    Duuude, an open array parameter is not one single thing, IMO. And the operators defined in Delphi only have one or two operands. Anything else makes no sense for those operators.

    An array can be thought of as a single entity. Consider vector arithmetic. Take two vectors of length N and sum them. That's one operator, two operands, each operand a vector with N scalar components. 

     

    My entire livelihood is based on such a form of mathematics. Are you saying I've been doing it wrong? 

    • Like 2

  14. There are only two functions, the A and the W version. The A version converts the input text arguments to Unicode and calls the W version. That's always the case with Windows. The A function is just a time and memory consuming wrapper around the W function. 

     

    Note that this implies it makes no difference to the output of the created process since the W version is always going the work in the end. 

     

    Basic rule is always call the W version. It's more efficient, the system is Unicode natively, and the W version means your code can be used by non English users. 

    • Like 2

  15. 1 hour ago, Rudy Velthuis said:

    Nothing wrong with arrays and operator, but everything with open array parameters on operators. Operators should have one or two parameters, depending on the type of operator, and not ranges of operands.

    Dude, an array doesn't have to mean a range of operands. An array can be viewed as a single thing.

     

    Also, it's entirely possible to imagine useful operators with more than two operands. 

×