Jump to content
Sign in to follow this  
Lars Fosdal

Type inference question

Recommended Posts

Consider

type
  Use = record
  public
    class function When<T>(const aBool: Boolean; const WhenTrue: T; const WhenFalse: T): T; static; inline;
  end;

{ Use }

class function Use.When<T>(const aBool: Boolean; const WhenTrue, WhenFalse: T): T;
begin
  if aBool
   then Result := WhenTrue
  else Result := WhenFalse
end;

procedure Test(Cond: Boolean);
type
  TObjectClass = class of TObject;
var
  i: Integer;
  b: Byte;
  c: Cardinal;
  w: Word;
  s: String;
  d: Double;
  o: TObjectClass;
begin
  s := Use.When(Cond,'True', 'False');
  s := Use.When(Cond, 1, 2).ToString;
  i := Use.When<Integer>(Cond, 1, -2);
  b := Use.When<Byte>(Cond, 1, 2);
  c := Use.When(Cond, 1, 2);
  w := Use.When(Cond, 1, 2);
  d := Use.When(Cond, 3.14, 42.0);
  o := Use<TObjectClass>.When(Cond, TObject, TStringList);
end;

This is valid code.

But

  i := Use.When<Integer>(Cond, 1, -2);

requires the type to be specified.

 

Also 

  w := Use.When(Cond, 1, 128);

stops working - actually for any signed or unsigned type - when the second parameter is changed to 128 or higher.

 

It then complains: 

image.thumb.png.9c4e28dd2f8399a87cc9a061640170e6.png

 

Why?  I though the left hand type would assist in the type inference and hence the parameter validation?

 

Edit: I just noticed that this only happens for Error Insight - not during compilation.

 

Share this post


Link to post
5 minutes ago, Lars Fosdal said:

This is valid code.

Apart from the last line which does not compile because Use is not generic.

 

6 minutes ago, Lars Fosdal said:

I though the left hand type would assist in the type inference and hence the parameter validation?

You are thinking wrong - Delphi never infers from the lhs but only from the passed parameter. And there is usually takes the type from the first one if you have multiple with the same generic type - that is why it needs help with the 1, -2 combination.

Share this post


Link to post

The code compiles without a warning - also for that last line, @Stefan Glienke.

 

In fact, even 

  b := Use.When<Byte>(Cond, 1, 300);

compiles.  That is a bit weird, I think.

Edit: Note to self - make sure you compile the project that contains the file you are fiddling with.

  • Haha 1

Share this post


Link to post
9 minutes ago, Lars Fosdal said:

The code compiles without a warning

It does not - check again your code - it says:

o := Use<TObjectClass>.When(Cond, TObject, TStringList);

but clearly, you meant:

  o := Use.When<TObjectClass>(Cond, TObject, TStringList);

 

9 minutes ago, Lars Fosdal said:

In fact, even 


  b := Use.When<Byte>(Cond, 1, 300);

compiles.  That is a bit weird, I think.

No, it does not (in 11.3). And even in older versions, assigning any literal to Byte that is not within 0..255 always gives an E1012

Edited by Stefan Glienke

Share this post


Link to post
  o := Use<TObjectClass>.When(Cond, TObject, TStringList);

I did indeed mean

  o := Use.When<TObjectClass>(Cond, TObject, TStringList);

but nevertheless, it compiles. Go figure.

 

image.thumb.png.9e4453d053fc6e955fffd3656609e600.png

Share this post


Link to post

Changed the w line to 

  w := Use<Word>.When(Cond, 1, 32000);

That works too!
 

Share this post


Link to post

FFS... I need to log off.  Scrolling further up in the source code, I found...

type
  Use<T> = record
  public
    class function When(const aBool: Boolean; const WhenTrue: T; const WhenFalse: T): T; static;
  end;

{ Use<T> }

class function Use<T>.When(const aBool: Boolean; const WhenTrue, WhenFalse: T): T;
begin
  if aBool
   then Result := WhenTrue
  else Result := WhenFalse
end;

 

200w[1].gif

  • Haha 1

Share this post


Link to post

I guess I was trying to find out which of the constructs that was more readable.

Share this post


Link to post
28 minutes ago, Stefan Glienke said:

You are thinking wrong - Delphi never infers from the lhs but only from the passed parameter. And there is usually takes the type from the first one if you have multiple with the same generic type - that is why it needs help with the 1, -2 combination.

Thank you, @Stefan Glienke - that clears up the fog.

It would have been nice, though - if the left side would be able to hint the type.

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
Sign in to follow this  

×