Jump to content
Henry Olive

Function with 2 return values ?

Recommended Posts

Good Day,
 

MyQuery Result is like below

TotalCost...TotalCostWıthExp

100              110

 

Is it possible something like below function

function.GetBomCosts (ItemCode:String): Value1,Value2 : Double

Thank You

 

 

 

Share this post


Link to post

Hi, only a single result but you can change to

 

function GetBomCosts(const ItemCode : String; var value1, value2 : Double) : boolean
begin
with TFDQuery.Create do
begin
 Value1:=0;
 value2:=0;
 Connection:= FDConnection1;
 SQL.Text:='SELECT itemcode,value1,value2 from table where code='+quotedstr(itemcode);
 active:=true;
 if fieldbyname('Itemcode').isNull then result:=false 
 else begin
        value1:=FieldByName('value1').asFloat;
        value2:=FieldByName('value2').asFloat;
        result:=true;
      end;
 active:=false;     
end;

end;

 

  • Like 2

Share this post


Link to post

You can return a record:

TTotalCostResult = record
  TotalCost: Double;
  TotalCostWıthExp: Double;
end;
function GetBomCosts(ItemCode:String): TTotalCostResult;

 

  • Like 1

Share this post


Link to post

You can return a TArray<Double>:

function GetBomCosts(const ItemCode : String) : TArray<Double>;
begin
  { Retrieve values }
  ...
  
  { Return values as array }
  SetLength(Result, 2);
  Result[0] := value1;
  Reuslt[1] := value2;
end;

 

Share this post


Link to post
9 minutes ago, Uwe Raabe said:

You can return a TArray<Double>:


function GetBomCosts(const ItemCode : String) : TArray<Double>;
begin
  { Retrieve values }
  ...
  
  { Return values as array }
  SetLength(Result, 2);
  Result[0] := value1;
  Reuslt[1] := value2;
end;

 

Whilst you can, this doesn't feel like a great idea. It's one thing returning a tuple in a language like Python with support for unpacking. But a Delphi dynamic array should be used for arrays, things where each item is a different value of the same thing. That's not the case here. They are two distinct things. 

 

Use a record, or two out params. 

  • Like 1

Share this post


Link to post
9 hours ago, David Heffernan said:

Whilst you can, this doesn't feel like a great idea. It's one thing returning a tuple in a language like Python with support for unpacking. But a Delphi dynamic array should be used for arrays, things where each item is a different value of the same thing. That's not the case here. They are two distinct things. 

 

Use a record, or two out params. 

I do not necessarily agree with this. I agree on the fact that a record would work better for several reasons and that a generic list has a number of disadvantages; however, if the function is eventually going to have multiple values, then a typed list (i.e. a generic but with a concrete type) would probably work better. However, if changes are infrequent and/or the values must be easy to identify then a record is absolutely the way to go.

I would never use a dynamic array because it's too easy to mis-identify things. 

Share this post


Link to post
1 hour ago, Stefan Glienke said:

A pair is a tuple where n is 2 - so yes it is a tuple

OK. What name would you give this type

 

array [0..2] of Double 

Share this post


Link to post
5 hours ago, David Heffernan said:

OK. What name would you give this type

 

array [0..2] of Double 

A static array of Double with the size 3 - exact type name would be context-specific and since you are not giving any context I cannot name it.

Share this post


Link to post
3 hours ago, Stefan Glienke said:

A static array of Double with the size 3 - exact type name would be context-specific and since you are not giving any context I cannot name it.

We don't need any context to know that a fixed length array shouldn't be named a tuple. 

Share this post


Link to post

You can return a TPointF:

procedure Test;
var
  A, B: Currency; // <-- ?
  P: TPointF;

  function GetResult(const s: string): TPointF;
  begin
    result.X := 99.98;
    result.Y := -1.01;
  end;

begin
  { get going fast }
  P := GetResult('ABC');
  { in order to be able to play with some data types }
  A := P.X;
  B := P.Y;
end;


 

Edited by Gustav Schubert
Use of Double should be questioned before optimization.

Share this post


Link to post
1 hour ago, Gustav Schubert said:

You can return a TPointF:


function GetBomCosts(ItemCode: string): TPointF;

procedure Test;
var
  BC: TPointF; // cointains X and Y of type single
  TotalCost: double;
  TotalConstWithExp: double;
begin  
  BC := GetBomCosts('ABC');
  TotalCost := BC.X; // conversion to double will be implicit
  TotalCostWithExp := BC.Y;
end;


 

It goes from bad to worse!! 

Share this post


Link to post
12 hours ago, Uwe Raabe said:

that would be better named TDouble

TDoubleDouble - we really need to mark what's inside 🙂

  • Like 1

Share this post


Link to post
38 minutes ago, David Heffernan said:

It goes from bad to worse!! 

But it started with two good answers at the top, which I liked, to make it clear. 🙂 

Share this post


Link to post

function sincronizarGrupos(out strDescMensagemOk: string; out strDescMensagem: string): Boolean;

 

or 

 

resp = json;

Share this post


Link to post
On 8/9/2022 at 12:47 AM, Stefan Glienke said:

array [0..2] of Double 

Trouble? 😉

 

I use a record for returning multiple values.  Clarity and type safety is of importance to me.

  • Like 4
  • Haha 1

Share this post


Link to post
2 hours ago, Lars Fosdal said:

Clarity and type safety is of importance to me.

no extra type safety is gained by using a record over an array

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

×