Jump to content
jesu

function: how to return nil

Recommended Posts

Hello. I'm trying to create a function that can return a float or nil:

 

function myfunc(const pa_value:string): double;
begin
  if pa_value = whatever then result := -1
  else result := nil;
end;

to replace many lines like this (simplified code):

if check then
parambyname('myparam').asfloat := -1
else
parambyname('myparam').clear;

What is the right way to do that?

Thanks.

Share this post


Link to post

Using variant?

function myfunc(const pa_value:string): variant;
begin
  if pa_value = whatever then result := -1
  else result := null;
end;

and then

parambyname('myparam').AsVariant := myfunc();

 

Share this post


Link to post

It depends on what your function does, but just like a function returning an integer returns a special value (often -1 or 0) in case of error, your function could return a special value as a double number.

Carefully select the value so that it doesn't collide with expected values in your application. I'm think about a value like 2.12345e-308. Just define a constant to give that value a nice name easy to use and remember.

 

 

 

Share this post


Link to post
30 minutes ago, FPiette said:

Carefully select the value so that it doesn't collide with expected values in your application. I'm think about a value like 2.12345e-308. Just define a constant to give that value a nice name easy to use and remember.

NaN

 

 

  • Like 1

Share this post


Link to post
1 hour ago, Anders Melander said:
2 hours ago, FPiette said:

Carefully select the value so that it doesn't collide with expected values in your application. I'm think about a value like 2.12345e-308. Just define a constant to give that value a nice name easy to use and remember.

NaN

Anders, I'm not sure that NaN is a good choice because this special value is generated in other cases. Something like 2.12345e-308is a better choice and collision risk is much lower.

Share this post


Link to post

I'm pretty sure that anyone asking for help with something as basic as this isn't handling, or even aware of, NaN.

 

Regardless, I personally wouldn't solve the problem with a magic value.

  • Like 1

Share this post


Link to post

It's impossible to suggest a good solution without knowing more about the context. If it's just a case of either setting or clearing a TParam value then just pass the TParam to the function and let the function operate directly on that.

Share this post


Link to post

You're better off doing something like

 

function myfunc(const InVal: String; out OutVal: Double): Boolean;

 

Return True if the value was set and false if not.

 

There are other ways to handle this but the worst way is a magic value in Double. There's no reason to do that when it is so easy to indicate explicitly whether or not the value is valid.

  • Like 4

Share this post


Link to post

I usually prefix functions like this with "Try", so instead of

function GetTheValue(parameters ...): SomeType;

it's

function TryGetTheValue(parameters ...; out Value: SomeType): Boolean;

  • Like 2

Share this post


Link to post
2 hours ago, dummzeuch said:

TryGetTheValue(

Very good suggestion by @dummzeuch Very few people give enough thought to naming of functions and variables. Developing a consistent approach can significantly help with long term program readability / long term support for large projects. Anything that hints at doing that gets my full support !

https://cigolblog.wordpress.com/2023/01/

https://cigolblog.wordpress.com/2019/10/

https://cigolblog.wordpress.com/2017/06/

Share this post


Link to post

Thanks for the suggestions.

Returning a dummy value would mean rewriting the stored procedures so that's a no-no.

I'm trying to avoid Variants because in the past I've had problems with variants <-> float. I've tried this instead


 

procedure ProcValorDeCombo(var pn_param: TFDParam; pt_Combo: TComboBox);
var
 vn_marca: double;
begin
  case pt_Combo.ItemIndex of
   -1: begin 
         // code ...
         pn_param.AsFloat := vn_marca;
       end;

   // code...
   else pn_param.Clear;    
  end;
end;

but when I try to call it

ProcValorDeCombo(ParamByName('myparam'), mycombo);

I get E2197 Constant object cannot be passed as var parameter

 

Edited by jesu

Share this post


Link to post

Because I'm modifying it inside the procedure

 

Share this post


Link to post

ok, I'm not modifying tparam, but tparam.value

Share this post


Link to post
26 minutes ago, jesu said:

Because I'm modifying it inside the procedure

...

ok, I'm not modifying tparam, but tparam.value

The TFDParam parameter is an object reference (i.e. a pointer). You are not modifying the object reference; You are modifying a property on the object. So drop the var.

 

I would also change the TComboBox parameter to an integer and pass TComboBox.ItemIndex instead; There's no reason to create a dependency on TCombobox when all you need is the ItemIndex.

Share this post


Link to post

Right, I've removed var and it works, but the combobox style is csDropDown so I check both itemindex and text. And there are lots of them, so if I have a problem I use the name to find which one is wrong.

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

×