Recent

Author Topic: how to check type of value  (Read 1222 times)

Gebo

  • New Member
  • *
  • Posts: 42
    • chahpander for lingeries
how to check type of value
« on: October 12, 2024, 10:42:09 am »
I want to check a value does it float or no , how can I do It?

Thanks
I like programming I begun by vb,vb.net,c# and finally free pascal and lazarus .I like martial arts sports and I am a kickboxer and made our team sport club called black eagle school I have a website for modern clothes..

Thaddy

  • Hero Member
  • *****
  • Posts: 16178
  • Censorship about opinions does not belong here.
Re: how to check type of value
« Reply #1 on: October 12, 2024, 10:56:15 am »
GetTypeKind(value) e.g.:
Code: Pascal  [Select][+][-]
  1. // complete program
  2. var
  3.   a:integer;
  4.   b:double;
  5. begin
  6.   writeln(GetTypeKind(a));
  7.   writeln(GetTypeKind(b));
  8.   readln;
  9. end.
Works in all modes.
If I smell bad code it usually is bad code and that includes my own code.

Gebo

  • New Member
  • *
  • Posts: 42
    • chahpander for lingeries
Re: how to check type of value
« Reply #2 on: October 12, 2024, 12:07:32 pm »
Thanks, I will try It.
I like programming I begun by vb,vb.net,c# and finally free pascal and lazarus .I like martial arts sports and I am a kickboxer and made our team sport club called black eagle school I have a website for modern clothes..

VisualLab

  • Hero Member
  • *****
  • Posts: 573
Re: how to check type of value
« Reply #3 on: October 12, 2024, 12:36:54 pm »
I want to check a value does it float or no , how can I do It?

Is it possible to know why you are checking the type? I'm asking out of pure curiosity (because in Pascal, variables must be assigned a type). Do you need to handle some special case in your code?

jamie

  • Hero Member
  • *****
  • Posts: 6735
Re: how to check type of value
« Reply #4 on: October 12, 2024, 03:16:38 pm »
This reminds me of a request I had but sure it will never be fulfilled.

Currently I have do that does this

Code: Pascal  [Select][+][-]
  1.  
  2. Procedure ReadBin(Var TheBin; TheBinSize:Integer);
  3. Begin
  4.   // read from memory the TheBin at the amount of TheBinSize);
  5. End;
  6.  

Whet would be nice is this.

Code: Pascal  [Select][+][-]
  1. Procedure ReadBin(Var thenbin; TheBinSizeInteger = Sizeof(theBin));
  2. Begin
  3.  ...
  4. end;
  5.  

With that, You can elect to not provide the SizeoF(Type) coming in and have the compiler do it for me.

There for a simple Readbin(Var SomeDataItemSomeWhere);

this could words, Bytes, Dwords, Records etc.

I don't think type info would help much here because you still need to laboring pain for entering it for the second parameter.

The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 16178
  • Censorship about opinions does not belong here.
Re: how to check type of value
« Reply #5 on: October 12, 2024, 04:46:11 pm »
The type info can be of great help with e.g. generics. I find it a normal question.
It works around the rather limited type restrictions, like <T:class>
What I am missing most, almost daily, is a type restriction to ordinals <T:ordinal>, which I solve using GetTypeKind.
E.g. Q&D:
Code: Pascal  [Select][+][-]
  1. function TestOrdinal<T>:Boolean;
  2. begin
  3.  result := gettypekind(T) in [tkinteger,tkChar,tkBool,tkInt64, tkQword];
  4. end;
Of course I raise an exception if the generic class does not satisfy the ordinal restriction.
(The above is Delphi mode, btw)
« Last Edit: October 12, 2024, 05:32:06 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

VisualLab

  • Hero Member
  • *****
  • Posts: 573
Re: how to check type of value
« Reply #6 on: October 13, 2024, 12:02:01 am »
What I am missing most, almost daily, is a type restriction to ordinals <T:ordinal>...

You're not the only one who misses this. I'd like something like this too. Preferably for a few categories of simple types:
  • ordinal (as you mentioned),
  • enumerated,
  • integer - from int8 to int64,
  • real - single, double, extended,
  • numerical (or numeral) - integer and real.
Not having to do type checking would not only simplify the source code, but the execution time would also be slightly shorter.

Thaddy

  • Hero Member
  • *****
  • Posts: 16178
  • Censorship about opinions does not belong here.
Re: how to check type of value
« Reply #7 on: October 13, 2024, 07:31:57 am »
Ordinal is a family, so integers already belong to ordinal, as do enumerations to some extend.(pred(), succ()).
The main reason for <T:ordinal> is that you can then only specialize to one of the family members, like byte or integer.
This family is comparable to the class or record family. My request is well received, but has alas no urgency.
I believe it was Sven who suggested there could be more families added, maybe a numerical family or a family of float types etc. Or sets since sets are also a family.
If I smell bad code it usually is bad code and that includes my own code.

Bart

  • Hero Member
  • *****
  • Posts: 5467
    • Bart en Mariska's Webstek
Re: how to check type of value
« Reply #8 on: October 13, 2024, 04:18:57 pm »
It would be nice if we could do:
Code: Pascal  [Select][+][-]
  1. procedure DoIt(var X);
  2. var
  3.   tk: TTypeKind;
  4. begin
  5.   tk := System.GetTypeKind(X);
  6.   case tk of
  7.     tkAString: writeln('X is an AnsiString');
  8.     tkInteger: writeln('X is an Integer');
  9.     tkDynArray: writeln('X is a dynamic array');
  10.   end;
  11. end;
   

But of course tk will always be tkUnknow.

Bart

Warfley

  • Hero Member
  • *****
  • Posts: 1758
Re: how to check type of value
« Reply #9 on: October 13, 2024, 04:41:56 pm »
You're not the only one who misses this. I'd like something like this too. Preferably for a few categories of simple types:
  • ordinal (as you mentioned),
  • enumerated,
  • integer - from int8 to int64,
  • real - single, double, extended,
  • numerical (or numeral) - integer and real.
Not having to do type checking would not only simplify the source code, but the execution time would also be slightly shorter.
To extend this list also object and record. The reason for this is, if you have some structure that takes ownership of the thing it gets handed over, you might need to initialize finalize it.
If it's a record it needs to call finalize, if it's an object it needs to call done and if its a class it needs to call destroy/free. My dream would be to just use implicitspecialization with it:
Code: Pascal  [Select][+][-]
  1. generic procedure finalize<T:record>(var arec:T);
  2. begin
  3.   finalize(arec);
  4. end;
  5. generic procedure finalize<T:object>(var aobj:T);
  6. begin
  7.   aobj.done;
  8. end;
  9. generic procedure finalize<T:TObject>(var aclass:T);
  10. begin
  11.   aclass.free;
  12. end;
And let implicitspecialization and overloads do the dispatching at compiletime.

Right now you always have to do RTTI which is a runtime mechanism, even tho this should be known at compiletime.

Thaddy

  • Hero Member
  • *****
  • Posts: 16178
  • Censorship about opinions does not belong here.
Re: how to check type of value
« Reply #10 on: October 13, 2024, 05:00:48 pm »
This is my current pattern:
Code: Pascal  [Select][+][-]
  1. program restricttypes;
  2. {$mode delphi}
  3. {.$define useAsserts}
  4. {$ifdef UseAsserts}
  5. {$C+}
  6. {$endif}
  7. uses
  8.   sysutils, typinfo;
  9.  
  10. type
  11. {$ifndef UseAsserts}
  12.   ESpecializeException = class(Exception);
  13. {$endif}
  14.  
  15.   TmyClass<T> = class
  16.   strict private
  17.     class constructor create;
  18.   end;
  19.  
  20.   Ta = TMyClass<integer>;
  21.   Tb = TMyClass<single>; // generates runtime exception, yes, on the type declaration!
  22.  
  23.   class constructor TMyClass<T>.create;
  24.   var
  25.     info:PTypeInfo;
  26.   begin
  27.     info := typeinfo(T);
  28.     { This will be raised at runtime. I can't find a way
  29.       to catch the error at compile time }
  30.     writeln(info^.kind);
  31.     {$ifdef UseAsserts}
  32.     Assert( info^.kind in [tkinteger,tkChar,tkBool,tkInt64, tkQword],'specialization is not an ordinal type:');
  33.     {$else UseExceptions}
  34.     if not (info^.kind in [tkinteger,tkChar,tkBool,tkInt64, tkQword]) then
  35.        raise ESpecializeException.Create('This specialization is not an ordinal type');
  36.     {$endif}
  37.   end;
  38. procedure test;
  39.  var
  40.    a:Ta;
  41.  begin
  42.    a:=Ta.Create;
  43.    write(a.Classname);
  44.    a.free;
  45.  end;
  46.  begin
  47.    test;
  48.  end.
Which is sufficient, except that exceptios are caught at runtime. (note assert is of course also an exception).

But all this deviates a bit from the original question and GetTypeKind is perfectly suitable for beginners.
« Last Edit: October 13, 2024, 05:02:44 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5755
  • Compiler Developer
Re: how to check type of value
« Reply #11 on: October 14, 2024, 09:48:39 pm »
It would be nice if we could do:
Code: Pascal  [Select][+][-]
  1. procedure DoIt(var X);
  2. var
  3.   tk: TTypeKind;
  4. begin
  5.   tk := System.GetTypeKind(X);
  6.   case tk of
  7.     tkAString: writeln('X is an AnsiString');
  8.     tkInteger: writeln('X is an Integer');
  9.     tkDynArray: writeln('X is a dynamic array');
  10.   end;
  11. end;
   

But of course tk will always be tkUnknow.

You mean like this? ;) (requires main)

Code: Pascal  [Select][+][-]
  1. program timplfunc;
  2. {$mode objfpc}{$H+}
  3. {$ModeSwitch ImplicitFunctionSpecialization }
  4.  
  5. generic procedure DoIt<T>(const X: T);
  6. var
  7.   tk: TTypeKind;
  8. begin
  9.   tk := System.GetTypeKind(X);
  10.   case tk of
  11.     tkAString: writeln('X is an AnsiString');
  12.     tkInteger: writeln('X is an Integer');
  13.     tkDynArray: writeln('X is a dynamic array');
  14.   end;
  15. end;
  16.  
  17. var
  18.   s: AnsiString;
  19.   i: LongInt;
  20.   a: array of Byte;
  21. begin
  22.   DoIt(s);
  23.   DoIt(i);
  24.   DoIt(a);
  25. end.

Bart

  • Hero Member
  • *****
  • Posts: 5467
    • Bart en Mariska's Webstek
Re: how to check type of value
« Reply #12 on: October 14, 2024, 10:23:02 pm »
You mean like this? ;) (requires main)

I must admit it's not exactly what I was looking for, but nevertheless: a brilliant solution!

Bart

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10553
  • Debugger - SynEdit - and more
    • wiki
Re: how to check type of value
« Reply #13 on: October 14, 2024, 11:27:54 pm »
There may have once been the idea of something more to the expectation of this thread... About almost 2 decades ago.

https://gitlab.com/freepascal.org/fpc/source/-/issues/40562

Follow the link to the commit, and blame it and get
https://gitlab.com/freepascal.org/fpc/source/-/commit/9adb202a924e9c94e81d4c7becb76f7f169923d3?page=3#d1513415756091fc5a78f1a2270475230af6ffab_529_534

And the commit message of this contains
Code: Text  [Select][+][-]
  1. Some initial work on a formaldef which also carries the typinfo of a parameter.

Well, whatever it was, never went past an idea.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5755
  • Compiler Developer
Re: how to check type of value
« Reply #14 on: October 17, 2024, 10:26:58 pm »
Well, whatever it was, never went past an idea.

Turns out there isn't that much left inside the compiler to get it working. When it does you'll get this:

Code: Pascal  [Select][+][-]
  1. program tformal;
  2.  
  3. uses
  4.   TypInfo;
  5.  
  6. procedure Test(const aArg: type);
  7. var
  8.   ti: PTypeInfo;
  9.   td: PTypeData;
  10. begin
  11.   ti := PTypeInfo(TypeInfo(aArg));
  12.   Writeln(ti^.Name);
  13.   Write('Value: ');
  14.   td := GetTypeData(ti);
  15.   case ti^.Kind of
  16.     tkInteger: begin
  17.       case td^.OrdType of
  18.         otSLong:
  19.           Writeln(PLongInt(@aArg)^);
  20.       end;
  21.     end;
  22.     tkSString: begin
  23.       Writeln(PShortString(@aArg)^);
  24.     end;
  25.     tkAString: begin
  26.       Writeln(PAnsiString(@aArg)^);
  27.     end;
  28.   end;
  29. end;
  30.  
  31. var
  32.   l: LongInt;
  33.   s: String;
  34.   a: AnsiString;
  35. begin
  36.   l := 42;
  37.   Test(l);
  38.   s := 'Foobar';
  39.   Test(s);
  40.   a := 'Hello';
  41.   Test(a);
  42. end.

Output:

Code: [Select]
PS C:\fpc\git> .\testoutput\tformal.exe
LongInt
Value: 42
ShortString
Value: Foobar
AnsiString
Value: Hello

 

TinyPortal © 2005-2018