The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,854 other subscribers

Archive for the ‘Delphi’ Category

Delphi: workaround doing math with generic types preventing “E2015 Operator not applicable to this operand type” with TValue (as there is no way to constraint the generic type to be floating point or ordinal)

Posted by jpluimers on 2021/12/14

A while ago on Facebook (it’s a private group, so you cannot see the posts unless you both have a Facebook account and are member of the group), [Archive.is] Niels Tjørnhøj-Thomsen (coming from a C++ templates background) asked why the below method would throw a E2015 Operator not applicable to this operand type in the complex expression:

function TAxis<t>.Calc(const AScalar: T): single;
begin
  Result := fStart + ( ( ( AScalar - fMin ) / fRange ) * fExtent );
end;

The type itself was very simple:

TAxis<T> = record
  fMin, fMax, fRange: T;
  fStart, fEnd, fExtent: single;
  function Calc( const AScalar: T ): single;
end;

He used these small example specialisations that put me on the wrong foot, as the order was TDateTime followed by single:

var
  rXAxis: TAxis<TDateTime>;
  rYAxis: TAxis<single>;

So at first I thought this might be caused by TDateTime to be defined in the System unit as a typed type:

type
  TDateTime = type Double;

It wasn’t.

Splitting the code in 4 lines with assignments of single expression operations would make the error appear in all expressions.

Casting parts of the expression to simple would not help either.

A small test program [Archive.is] might put you, like me, on the wrong foot because the specialisation is in the same source file as the generic type:

program DelphiMathAndGenerics;

type
  TAxis<T> = record
    fMin, fMax, fRange: T;
    fStart, fEnd, fExtent: single;
    function CalcCasted( const AScalar: T ): single;
    function CalcPlain( const AScalar: T ): single;
  end;

function TAxis<T>.CalcCasted(const AScalar: T): single;
var
  Offset: single;
  NormalisedOffset: single;
  ScaledOffset: single;
begin
  // First 2 lines give the same error: E2089 Invalid typecast
  Offset := single(AScalar) - fMin;
  NormalisedOffset := Offset / single(fRange);
  ScaledOffset := NormalisedOffset * fExtent;
  Result := fStart + ScaledOffset;
end;

function TAxis<T>.CalcPlain(const AScalar: T): single;
var
  Offset: T;
  NormalisedOffset: T;
  ScaledOffset: T;
begin
  // All 4 lines give the same error: E2015 Operator not applicable to this operand type
  Offset := AScalar - fMin;
  NormalisedOffset := Offset / fRange;
  ScaledOffset := NormalisedOffset * fExtent;
  Result := fStart + ScaledOffset;
end;

var
  rXAxis: TAxis<TDateTime>;
  rYAxis: TAxis<single>;

begin
end.

Splitting this in two files [Archive.is], a AxisUnit unit having only the TAxis<T> type, and a main program (even without having the specialisations) shows that even the unit itself would not compile.

This shows a major difference between Delphi (and similar C#) generics and C++ templates:

  • generics are compiled and fully verified at the generic stage
  • templates are pre-processed, then finally verified at specialisation stage

A solution would be that Delphi could constraint the generic type T into something like float or ordinal so the compiler would know that more operators are allowed in the code. But alas, Delphi – like C# – has a very limited number of constraints (C# only would allow a constraint for enumerations in version 7.3): Delphi Constraints in Generics – RAD Studio XE documentation wiki.

This StackOverflow question is very similar, and has the same answer (generics in Delphi work differently than templates in C++): [Source] templates – Arithmetic operations with generic types in Delphi – Stack Overflow

I’m new in Delphi. For a project required by my company, I need to translate some code from our existing C++ classes to Delphi. Some of these classes are templates, such …

Workaround: use the TValue.From<T>() function

There is a workaround though, but it is slow, as you need to convert from the generic T type to the actual (in this case floating point) type you can apply the operators on.

This is possible with the (Delphi 2010 introduced) TValue.From<T>() method which returns a TValue record. That TValue record has instance methods like AsExtended to extract or convert the embedded value as a specific type.

Initially, [Wayback] Delphi 2010 Rtti.TValue documentation had the From method signature wrong, maybe because of many wiki and blog HTML editors kill angle bracket pairs < and > in code blocks:

function From(const Value: T): TValue; static;

Since the [Wayback] Delphi XE System.Rtti.TValue documentation, the From method signature is fixed (see the bold parts):

class function From<T>(const Value: T): TValue; static;

With the [Wayback] Delphi XE2 Rtti.TValue documentation, the unit got renamed from Rtti into System.Rtti and has not changed further.

When using TValue.From<T>(), the AxisUnit becomes this:

unit AxisUnit;

interface

type
  TAxis<T> = record
    fMin, fMax, fRange: T;
    fStart, fEnd, fExtent: single;
    function Calc( const AScalar: T ): single;
  strict private
    function AsSingle(const Value: T): single;
  end;

implementation

uses
  System.Rtti;

function TAxis<T>.AsSingle(const Value: T): single;
begin
  Result := TValue.From<T>(Value).AsExtended
end;

function TAxis<T>.Calc(const AScalar: T): single;
var
  Offset: single;
  NormalisedOffset: single;
  ScaledOffset: single;
begin
  Offset := AsSingle(AScalar) - AsSingle(fMin);
  NormalisedOffset := Offset / AsSingle(fRange);
  ScaledOffset := NormalisedOffset * fExtent;
  Result := fStart + ScaledOffset;
end;

end.

–jeroen

Read the rest of this entry »

Posted in .NET, C#, Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

On TStrings (and TStringList) sorting: what the default Sort behaviour is and how to change sorting order

Posted by jpluimers on 2021/12/07

Because I need this eventually, here the full quote of my answer in [Wayback] sorting – How can I get TStringList to sort differently in Delphi – Stack Overflow (The default Sort behaviour is to accommodate i18n sorting in natural order):

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development, Undocumented Delphi | Leave a Comment »

parsing – delphi – strip out all non standard text characers from string – Stack Overflow

Posted by jpluimers on 2021/12/02

From a while back a totally non-optimised code example by me (intentionally limiting to AnsiStr as it was about filtering ASCII, and UniCode has way many code points for the Latin script).

// For those who need a disclaimer: 
// This code is meant as a sample to show you how the basic check for non-ASCII characters goes
// It will give low performance with long strings that are called often.
// Use a TStringBuilder, or SetLength & Integer loop index to optimize.
// If you need really optimized code, pass this on to the FastCode people.
function StripNonAsciiExceptCRLF(const Value: AnsiString): AnsiString;
var
  AnsiCh: AnsiChar;
begin
  for AnsiCh in Value do
    if (AnsiCh >= #32) and (AnsiCh <= #127) and (AnsiCh <> #13) and (AnsiCh <> #10) then
      Result := Result + AnsiCh;
end;

and an optimised one by [WayBack] David Heffernan

function StrippedOfNonAscii(const s: string): string;
var
  i, Count: Integer;
begin
  SetLength(Result, Length(s));
  Count := 0;
  for i := 1 to Length(s) do begin
    if ((s[i] >= #32) and (s[i] <= #127)) or (s[i] in [#10, #13]) then begin
      inc(Count);
      Result[Count] := s[i];
    end;
  end;
  SetLength(Result, Count);
end;

Even when “trivial”, I usually do not prematurely optimise as optimised code is almost always less readable than non-optimised code.

Source: [Wayback] parsing – delphi – strip out all non standard text characers from string – Stack Overflow

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Interesting situation now UWP isn’t panacea any more: for Windows development, native is back to center stage

Posted by jpluimers on 2021/11/17

Summary: UWP (Universal Windows Platform) is dying, long live native Windows development.

Source: [Wayback/Archive] Native Windows is Back to Center Stage

With the downplay of UWP, native development is again the primary Windows development model, after 20 years (given we had .NET in between). Native is what Delphi does at its best, so this is great news

Via:

–jeroen

Posted in Delphi, Development, Software Development, Windows Development | Leave a Comment »

Infusion pump and PCA (patient-controlled analgesia) calculation

Posted by jpluimers on 2021/11/09

This is a great PCA calculator: [Archive.is] CADD calculator 0.5BETA END USER Google Docs – Google Sheets

Via:

Related:

–jeroen

Read the rest of this entry »

Posted in Development, Excel, Google, GoogleDocs, GoogleSheets, Office, Office Automation, Office VBA, Power User, Scripting, Software Development | Leave a Comment »

Some links on Delphi compiler potential speed improvements…

Posted by jpluimers on 2021/11/04

A long time ago, there was an interesting blog post referenced from [WayBack] See how you can use Delphi’s upcoming new language feature to improve performance of your code. – Erik van Bilsen – Google+ referred to [WayBack] Inline Variables can increase performance – grijjy blog which made me comment [WayBack] “given the potential performance improvements the compiler already could do, and how long they could have been done, I would not bet on these new improvements becoming reality anytime soon.” that I later backed up with these links:

One of the observations there is that since Delphi 2005, no major compiler speed improvements have been done, and that even between Delphi 5 and 2005 mot much has been done either.

From my point of view, the – not so big – Delphi compiler team is very busy keeping balls up in the air supporting the many compiler targets and architecture changes that have been introduced over the past decade or so, that they do not have resources to improve code generation other than rely on the LLVM tool chain (which is not used for Windows x86 and x64 development that covers like 90+% of the Delphi users).

In my book, when you need an “inline var”, you usually want to refactor that bit of code into a separate method anyway.

Refactoring out parts of code that have implicit try/finally blocks for managed variables or records is a strategy that can improve execution speed in many Delphi applications anyway, especially if that piece of code is outside of the happy flow: it moves unneeded overhead out of that flow.

This is actually a strategy used for instance in the Spring4D library: Stefan Glienke has a very good insight in how the compiler works and did magic to some performance critical code paths there.

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Word for Mac 2011: create macro or shortcut to ‘Insert Picture – Microsoft Community

Posted by jpluimers on 2021/11/02

As it combines VBA and AppleScript, I might need the script from this in the future [WayBack] Word for Mac 2011: create macro or shortcut to ‘Insert Picture – Microsoft Community.

–jeroen

Posted in Development, Office, Office 2011 for Mac, Office Automation, Office VBA, Scripting, Software Development | Leave a Comment »

EProgrammerNotFound exception in Delphi? – Stack Overflow

Posted by jpluimers on 2021/10/19

From a long while my answer to [WayBack] EProgrammerNotFound exception in Delphi? – Stack Overflow (I added the WayBack links)

It was introduced in Delphi 2009, still present in Delphi 2010, and [WayBack] recently got some [WayBackmore attention on the [WayBackinternet.

I think it is an easter egg, similar to [WayBack] “EBCAK” (Error Between Chair and Keyboard), and the [WayBack] skipping of Delphi version number 13.

[WayBack] EProgrammerNotFound

  • is declared in the Win32 branch of the SysUtils unit, but not used anywhere in the RTL or VCL
  • is not present in Delphi Prism
  • was introduced in Delphi 2009, so not present in VCL.NET
  • has currently (version 3.5) nothing similar in the .NET framework (not sure why, these guys [WayBack] do have humour)

I don’t think EProgrammerNotFound is actually meant to be used at all, but since it is there, people will jokingly use it (similar like putting a stray “const False = True; True = not False;” in someone elses sourcecode).

On green bits and red bits (which I highly associate with the “green wobbly bit”:

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

The Charlie Calvert “Here’s to Good Friends and New Adventures” article

Posted by jpluimers on 2021/10/14

Since this contains a list of contains from back then (20+ years ago!), I save it for future reference: [WayBack] Here’s to Good Friends and New Adventures

I would like to make a very short list of the other people at Borland who I have had the privilage of working with very closely. These people are Jason Sprenger, Xavier Pacheco, Steve Teixeira, John Kaster, Lar Mader and Rich Jones. Each of these people I worked with every day over a period of years, and they never showed me anything but the very best and most admirable human traits. I hope I am so lucky as to work with such fine people again in my life.

As for all the others, there is no way even to begin to thank them. A few of these people are Karen Giles, Lino Tadros, Steve Trefethen, Christine Ellis, Paolo Ciccone, Yolanda Davis, Blake Stone, Bruneau Babet, Dave Marancik, Anders Ohlsson, Dave Powell, Claudio Briceno, Joe Manzone, Terri Bartos, Dave Wilhelm, Andrea Ginsberg, Jason Vokes, Ludo Neveu, Martin Pamdeth, Martin Raim, Ernesto Franchini, Edwin Desouza, Zack Urlocker, Rosemary Abell, Robert Warren, Scott Bussinger, Richard Morris, Paul Beach, Jeremy McGee, Nimish Vora, Michael Swindell, Lorie Hull, Kendyll Upstrom, Kari Gallant, Allen Bauer, Josh Dahlby, Jose Rubens, John Thomas, John Williams, J.D. Hildebrand, Hizo Jozsef, Goran Kallmark, Ben Riga, George Cross, Gary Benner, Fred Felman, Erik Jakowitz, Danny Thorpe, Craig Farrell, Claudia Currie, Bill Weber, Lance Devon, Robert West, Amber Hein, Richard Kubat, Jeff Peters, Ellie Peters, Krystyna Niedzwiedzka, Kathy Berkland, Kelly Welty, Tom Lam, Nester Miranda (and Carlos!), Dana Kaufman, Pawal Ksiezyk, Jim Wright, Lori and Ellen from travel, Sergey Orlik and many others who I just don’t happen to recall right now, or who I liked very much but only met a few times.

I’m also indebted to Ray Kanopka, Mark Miller, Dick Malley, Dan Horn, Taco Oosterkamp, Bob Swart, Ann Lynnworth, Marco Cantu, Jeroen Pluimers, and many more who worked in the Borland community and brought me great joy. It’s amazing to consider how many talented and remarkable people have been drawn to this company.

jeroenhttps://www.facebook.com/groups/137012246341854/permalink/2895795467130171/

Posted in Borland C++, C++, C++ Builder, Delphi, Development, Pascal, Software Development, Turbo Pascal | Leave a Comment »

www.fmxrtl.com – BiDi support for Firemonkey

Posted by jpluimers on 2021/10/12

www.fmxrtl.com – BiDi support for Firemonkey

[WayBack] Wayback Machine

Arabic, Hebrew in FireMonkey!

Don’t you wanted to use the fastest development environment, to make an for middle east?

Now it is possible to create an app in Arabic, Hebrew, or Farsi) with Delphi FireMonkey for all environments.

–jeroen

Posted in Delphi, Development, FireMonkey, Software Development | Leave a Comment »