Jump to content
Mike Torrettinni

Manage overloaded IfThen functions

Recommended Posts

I use IfThen a lot. Delphi already has some of it's own IfThen defined: in System.Math are defined for numbers, in System.StrUtils there is one defined for string parameters:

System.Math: function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer = 0): Integer; overload; inline;
 //... and other number types of parameters
System.StrUtils: function IfThen(AValue: Boolean; const ATrue: string; AFalse: string = ''): string; overload; inline;

I have a few of my own, with XML types, TVirtualStringTree parameters... all overloaded of course, in my Utils.pas unit.

 

I would like to have them all defined in my Utils, so I only need to put Utils in uses. The problem is when if I still need to use System.StrUtils or System.Math for other functions, I get error:

E2251 Ambiguous overloaded call to 'IfThen' System.StrUtils.pas(499)...

It makes sense, because same Ifthen signatures are not in System.StrUtils and my Utils.

 

Is there anyway to avoid this error and force it to use IfThen from my Utils and not get this error?

 

Share this post


Link to post

You can and should point the compiler to the right unit file specially if you are reusing functions names,

System.Math.IfThen(....    instead of just IfThen

or just 

StrUtils.Ifthen

for your library

Utils.IfThen(...  

 

One more thing: did you named a file in your library "Utils.pas" ?

I suggest to pick some naming pattern for your own library, also stick to a pattern for each project you are writing, this on the long run will simplify your life.

example mtUtils.pas instead of just Utils.pas, this will prevent rare and time wasting situation, when you there is a file has the same popular name in either a 3rdparty library or a project.

  • Thanks 1

Share this post


Link to post
1 hour ago, David Heffernan said:

What types are the parameters for the functions that are ambiguous? 

Integer and String, copied from Math and StrUtils.

Share this post


Link to post
1 hour ago, Kas Ob. said:

You can and should point the compiler to the right unit file specially if you are reusing functions names,

System.Math.IfThen(....    instead of just IfThen

or just 

StrUtils.Ifthen

for your library

Utils.IfThen(...  

 

One more thing: did you named a file in your library "Utils.pas" ?

I suggest to pick some naming pattern for your own library, also stick to a pattern for each project you are writing, this on the long run will simplify your life.

example mtUtils.pas instead of just Utils.pas, this will prevent rare and time wasting situation, when you there is a file has the same popular name in either a 3rdparty library or a project.

 

Oh, I didn't think about this... I'm not used to using unit identifiers, except in some cases. Before I started using namespaces for unit names, it would be easier, but now it's getting annoying to have to name the full unit name. Like:

ProjectName.Utilities.IfThen() instead of just IfThen()

 

If there is no other way, then I can start using unit prefix. But it will take time to adjust.

 

No, Utils.pas name is just for this example purpose.

Share this post


Link to post
1 hour ago, Mike Torrettinni said:

Integer and String, copied from Math and StrUtils.

This seems odd. Why would you need another implementation of IfThen for Integer and string? Why would you need more than one? 

Share this post


Link to post
Just now, David Heffernan said:

This seems odd. Why would you need another implementation of IfThen for Integer and string? Why would you need more than one? 

I have many units where I need access to integer, string and one of custom IfThen implementations. So, I want to just use my Utils.pas, without StrUtils and Math in these units.

Share this post


Link to post
1 hour ago, David Heffernan said:

That's a poor idea in my view. 

Just trying to clean up the uses clause. And these are simple functions, nothing I need to worry about Delphi changing in the future.

Share this post


Link to post
5 minutes ago, David Heffernan said:

Well, now you've got to fully qualify function calls left right and centre, so it's hard to see this as a clean up. 

You are right, it doesn't seem like there is a perfect solution. A trade off in all cases. Will see how it goes with this, perhaps I will realize it was not a good decision, or it will be really neat solution to my problem.

Share this post


Link to post

isn't this "IfThen" is the one that nobody uses because it evaluates both branches?

Edited by Attila Kovacs
  • Like 2

Share this post


Link to post
13 minutes ago, Attila Kovacs said:

isn't this "IfThen" is the one that nobody uses because it evaluates both branches?

It works very good on simple types, I use it a lot. For example:

IntegerValue := IfThen(condition, IntVal1, IntVal2); 
StringValue := IfThen(Condition, String1, String2);

For expressions, you need to be aware they will be evaluated, so it can cause problems if not used correctly, like:

vStr1 := '1';
vStr2 := '';
vInt := IfThen(condition, vStr1.ToInteger, vStr2.ToInteger); // will fail at runtime  

The runtime error will occur here: EConvertError with message ''' is not a valid integer value for Integer type'

 

It's like with everything else in Delphi: if you don't use it is expected, you get unexpected behavior. Use it as is it designed, you get correct behavior.

Share this post


Link to post
32 minutes ago, Mike Torrettinni said:

if you don't use it is expected, you get unexpected behavior. Use it as is it designed, you get correct behavior

The point is not that it doesn't behave as designed. It's that the design is poor. What is needed is a conditional operator built into the language, like in almost all other languages. 

Share this post


Link to post
2 minutes ago, David Heffernan said:

The point is not that it doesn't behave as designed. It's that the design is poor. What is needed is a conditional operator built into the language, like in almost all other languages. 

I assume you are right - I'm the last one to judge the core of Delphi functionality... was just explaining what he was asking about with example. That is how I remember IfThen issues, but my experience is limited to simple type examples.

 

 

Share this post


Link to post

I also use IfThen a lot - but only for string constants.
A ternary operator - or lambdas without the verbosity would have been so nice.

 

Share this post


Link to post
15 minutes ago, Lars Fosdal said:

so nice

for sure

H := (C = 0 ? 0 :
    V = r ? (g - b) / C :
    V = g ? (b - r) / C + 2 :
            (r - g) / C + 4
    );

 

  • Haha 4

Share this post


Link to post

Hi,

 

I'm using another construction for simple types:

 

iif<T>( aCond : boolean; aTrue : T; aFalse : T ) : T;

 

function iif<T>( aCond : boolean; aTrue : T; aFalse : T ) : T;

begin

     if aCond then Result := aTrue else Result := aFalse;
end;

 

No overloads, very easy to ready....

 

 

procedure SomeProcedure;

begin

     a := iif<string>( aCond, 'Hello', 'World');
     b := iif<integer>( aCond, 12, 0 );
end;

 

 

As for ternary operators, it would be a nice addition. Couldn't it be written in ASM?

Edited by Clément

Share this post


Link to post
20 hours ago, Kas Ob. said:

You can and should point the compiler to the right unit file specially if you are reusing functions names,

System.Math.IfThen(....    instead of just IfThen

or just 

StrUtils.Ifthen

for your library

Utils.IfThen(...   

 

..

 

I suggest to pick some naming pattern for your own library,

This "naming pattern" is not limited to the uses alone.

I know, most people dislike that decorating of function names, but I do that in some similar cases too,

like that:

MtIfThen(...  

 

Share this post


Link to post
3 minutes ago, Clément said:

function iif<T>( aCond : boolean; aTrue : T; aFalse : T ) : T;

begin

     if aCond then Result := aTrue else Result := aFalse;
end;

 
 


Not in Delphi, for sure.

Share this post


Link to post
22 minutes ago, Clément said:

Couldn't it be written in ASM?

What's the point? The arguments would still be evaluated up front. You need the cooperation of the compiler to avoid that.

  • Like 1

Share this post


Link to post
26 minutes ago, Lars Fosdal said:


Not in Delphi, for sure.

In a delphi class, record, or form I mean.

 

Share this post


Link to post
4 minutes ago, Anders Melander said:

What's the point? The arguments would still be evaluated up front. You need the cooperation of the compiler to avoid that.

 

One can always hope. :classic_blush:
 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×