Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-02

Primitive Record Wrappers

39 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mazola Winstrol

Hello list,

In some situations, would be very interesting to determine whether the value of a primitive variable is initialized or not. For example, fields in database records can contain null values. By implementing an ORM, it would be interesting to represent these null values in the properties of objects.

Java has the so called Primitives Class Wrappers, where each primitive type (int, boolean ...) has a corresponding wrapper class (Integer, Boolean ...). By using class wrappers you can represent null values in primitive types through null class instances references.

Using class wrappers in FPC is not feasible due to memory management issues (the programmer needs to worry about the lifetime of the instances and free the instances manually).

Perhaps, a solution in FPC would be using primitive record wrappers with custom records operators.

What do you think about it? Is there any other solution?

Regards

Reply by email

Mazola Winstrol
to leledumbo

2016-02-18 8:00 GMT-02:00 leledumbo :

Show quoted text 7 lines
> What do you think about it? Is there any other solution? There's a reason why http://www.freepascal.org/docs-html/3.0.0/fcl/db/tfield.isnull.html is invented

You didnt understand my point. Design classes coupled with DB framework is not a solution.

In the following class

type
   TPerson = class(TObject)
   private
      FId: Integer;
      FName: String;
      FBirthDate: TDateTime;
   public
      property Id: Integer read FId write FId;
      property Name: String read FName write FName;
      property BirthDate: TDateTime read FBirthDate write FBirthDate;
   end;

Suppose that this class represent data of the Person table in a sql database. Suppose that there is records where the column "BirthDate" is null. How do i represent a null "BirthDate" in my object?

Regards

Reply by email

Marco van de Voort
to Mazola Winstrol

In our previous episode, Mazola Winstrol said:

Show quoted text 6 lines
end; Suppose that this class represent data of the Person table in a sql database. Suppose that there is records where the column "BirthDate" is null. How do i represent a null "BirthDate" in my object?

Keep using variants instead of typed data.

Reply by email

Mazola Winstrol
to Mazola Winstrol: 2016-02-18 8:00 GMT-02:00 leledumbo : You didnt understand my point. Design classes…
"Marco van de Voort" wrote 11 lines
In our previous episode, Mazola Winstrol said: > end; > > > Suppose that this class represent data of the Person table in a sql > database. Suppose that there is records where the column "BirthDate" is > null. How do i represent a null "BirthDate" in my object? Keep using variants instead of typed data.

I think this is not a good alternative. As the variant are untyped, should the consumers of the person class assume that BirthDate are filled as a formated date string '01/01/1980' or as a native tdatetime?

I think it would be better using record wrappers to primitive types. See http://blogs.embarcadero.com/abauer/2008/09/18/38869.

What do you think about that?

Reply by email

Michalis Kamburelis
to Mazola Winstrol

2016-02-18 15:43 GMT+01:00 Mazola Winstrol :

Show quoted text 21 lines
Em 18/02/2016 10:12, "Marco van de Voort" escreveu: > > In our previous episode, Mazola Winstrol said: > > end; > > > > > > Suppose that this class represent data of the Person table in a sql > > database. Suppose that there is records where the column "BirthDate" is > > null. How do i represent a null "BirthDate" in my object? > > Keep using variants instead of typed data. > I think this is not a good alternative. As the variant are untyped, should the consumers of the person class assume that BirthDate are filled as a formated date string '01/01/1980' or as a native tdatetime? I think it would be better using record wrappers to primitive types. See http://blogs.embarcadero.com/abauer/2008/09/18/38869. What do you think about that?

Personally, I like the Nullable<T> idea from C#, which is basically a generic record adding a "HasValue: boolean" to "Value: T". The type-safety is nice, and it's sometimes very useful (when you cannot "cheat" and say that "empty string" or "zero value" always means "uninitialized"). Looking at your link
http://blogs.embarcadero.com/abauer/2008/09/18/38869 , this is exactly trying to implement Nullable<T> in Object Pascal.

The major problem there is that it's difficult to force it to be always initialized with zeroes. Currently, a non-global variable of unmanaged type can always be filled with memory garbage, as explained in other thread. The trick in
http://blogs.embarcadero.com/abauer/2008/09/18/38869 to use interfaces feels ugly, it's an over-use of the "interface" specifics in Object Pascal.

I remember a thread on fpc-devel "Pascal Smart Pointers Idea + ARC implementation" where the original author (Maciej Izak) was already working to overcome this:

. His reasons was similar (force the contents to be initialized with zero) and his solution felt cleaner -- introduce "class operator Initialize" where you can initialize your record.

Any chance that this would be added/merged to FPC one day?:)

Regards,
Michalis

Reply by email

Sven Barth
to Michalis Kamburelis

Am 20.02.2016 06:25 schrieb "Michalis Kamburelis" <

Show quoted text 10 lines
: I remember a thread on fpc-devel "Pascal Smart Pointers Idea + ARC implementation" where the original author (Maciej Izak) was already working to overcome this: . His reasons was similar (force the contents to be initialized with zero) and his solution felt cleaner -- introduce "class operator Initialize" where you can initialize your record. Any chance that this would be added/merged to FPC one day?:)

I'm indeed inclined to implement this one day, though I don't know yet how exactly I want it to look.

Regards,
Sven

Reply by email

Mazola Winstrol
to Michalis Kamburelis: 2016-02-18 15:43 GMT+01:00 Mazola Winstrol : Personally, I like the Nullable<T> idea from…

2016-02-20 3:24 GMT-02:00 Michalis Kamburelis :

Show quoted text 9 lines
The major problem there is that it's difficult to force it to be always initialized with zeroes. Currently, a non-global variable of unmanaged type can always be filled with memory garbage, as explained in other thread. The trick in http://blogs.embarcadero.com/abauer/2008/09/18/38869 to use interfaces feels ugly, it's an over-use of the "interface" specifics in Object Pascal.

A less "ugly" code could be to store the pointer value in an array of bytes (TBytes). As the TBytes type is a managed type, it will always be initialized.

Reply by email

Sven Barth
to Mazola Winstrol
"Mazola Winstrol" wrote 13 lines
2016-02-20 3:24 GMT-02:00 Michalis Kamburelis : > > The major problem there is that it's difficult to force it to be > always initialized with zeroes. Currently, a non-global variable of > unmanaged type can always be filled with memory garbage, as explained > in other thread. The trick in > http://blogs.embarcadero.com/abauer/2008/09/18/38869 to use interfaces > feels ugly, it's an over-use of the "interface" specifics in Object > Pascal. > A less "ugly" code could be to store the pointer value in an array of

bytes (TBytes). As the TBytes type is a managed type, it will always be initialized.

The managed type isn't needed for the data (that should be stored as a plain field to let the compiler take care of finalization), but instead it's needed to store whether the field contains a valid value (not Null) or not (null). For this potentially any managed type (array, string, interface) can be used, but it might indeed be that the manual interface approach is the fastest, because there one can avoid unnecessary locking (it's done by the implementations of AddRef and Release) which is not the case with arrays and strings as the reference counting routines always do locking.

Regards,
Sven

Reply by email

Maciej Izak
to Sven Barth: Am 20.02.2016 06:25 schrieb "Michalis Kamburelis" < I'm indeed inclined to implement this…

2016-02-20 9:23 GMT+01:00 Sven Barth :

Show quoted text 16 lines
Am 20.02.2016 06:25 schrieb "Michalis Kamburelis" < >: > I remember a thread on fpc-devel "Pascal Smart Pointers Idea + ARC > implementation" where the original author (Maciej Izak) was already > working to overcome this: > > . His reasons was similar (force the contents to be initialized with > zero) and his solution felt cleaner -- introduce "class operator > Initialize" where you can initialize your record. > > Any chance that this would be added/merged to FPC one day?:) I'm indeed inclined to implement this one day, though I don't know yet how exactly I want it to look.

Finally I have some time to continue my work on this. I need to take break from Sparta/Lazarus :P. Hopefully all will be available soon on smart_pointers branch.

Best regards, Maciej Izak

Reply by email

Mazola Winstrol
to Maciej Izak

Hello,

In the code bellow, the generic type TNullableTyple is implemented (and incomplete for now).

Is there any possibility of "nullable types" be added to RTL or anyother fpc provided package?

unit NullableTypes;
{$mode delphi}{$H+}
interface
type
  { TNullable }
  TNullable<T> = record
  strict private
    FValue: T;
    FHasValue: IInterface;
    function GetValue: T;
    function GetHasValue: Boolean;
    procedure SetValue(const AValue: T);
    procedure SetFlatInterface(var Intf: IInterface);
  public
    constructor Create(const AValue: T);
    function GetValueOrDefault: T; overload;
    function GetValueOrDefault(Default: T): T; overload;
    property HasValue: Boolean read GetHasValue;
    property Value: T read GetValue;
    class operator Implicit(AValue: TNullable<T>): T;
    class operator Implicit(const AValue: T): TNullable<T>;
    class operator Explicit(AValue: TNullable<T>): T;
  end;
  TInteger = TNullable<Integer>;
function NopAddref(inst: Pointer): Integer; stdcall;
function NopRelease(inst: Pointer): Integer; stdcall;
function NopQueryInterface(inst: Pointer; const IID: TGUID; out Obj):
HResult;

const
FlagInterfaceVTable: array[0..2] of Pointer =
(
@NopQueryInterface,
@NopAddref,
@NopRelease

  );
  FlagInterfaceInstance: Pointer = @FlagInterfaceVTable;
implementation
uses
  SysUtils;
function NopAddref(inst: Pointer): Integer; stdcall;
begin
  Result := -1;
end;
function NopRelease(inst: Pointer): Integer; stdcall;
begin
  Result := -1;
end;
function NopQueryInterface(inst: Pointer; const IID: TGUID; out Obj):
HResult;
stdcall;
begin
  Result := E_NOINTERFACE;
end;

{ TNullable }

procedure TNullable<T>.SetFlatInterface(var Intf: IInterface);
begin
  Intf := IInterface(@FlagInterfaceInstance);
end;
class operator TNullable<T>.Explicit(AValue: TNullable<T>): T;
begin
  Result := AValue.Value;
end;
function TNullable<T>.GetHasValue: Boolean;
begin
  Result := FHasValue  nil;
end;
function TNullable<T>.GetValue: T;
begin
  if not HasValue then
    raise Exception.Create('Invalid operation, Nullable type has no value');
  Result := FValue;
end;
function TNullable<T>.GetValueOrDefault: T;
begin
  if HasValue then
    Result := FValue
  else
   Result := Default(T);
end;
function TNullable<T>.GetValueOrDefault(Default: T): T;
begin
  if not HasValue then
    Result := Default
  else
    Result := FValue;
end;
class operator TNullable<T>.Implicit(AValue: TNullable<T>): T;
begin
  Result := AValue.Value;
end;
class operator TNullable<T>.Implicit(const AValue: T): TNullable<T>;
begin
  Result := TNullable<T>.Create(AValue);
end;
procedure TNullable<T>.SetValue(const AValue: T);
begin
  FValue := AValue;
  SetFlatInterface(FHasValue);
end;
constructor TNullable<T>.Create(const AValue: T);
begin
  FValue := AValue;
  SetFlatInterface(FHasValue);
end;
end.

Reply by email

Dmitry Boyarintsev
to Mazola Winstrol
Mazola Winstrol wrote
In the code bellow, the generic type TNullableTyple is implemented (and incomplete for now).

How to reset TNullableType to Null value? HasValue seems to be read-only.

Is there any possibility of "nullable types" be added to RTL or anyother fpc provided package?

You could start your own package separate from RTL. It's not about where the package is hosted, it's about letting others know that the package exists.

thanks,
Dmitry

Reply by email

Sven Barth
to Maciej Izak
"Maciej Izak" wrote
2016-02-27 4:38 GMT+01:00 Mazola Winstrol : > > In the code bellow, the generic type TNullableTyple is implemented (and

incomplete for now).

> It can be done more optimal with incoming operators Initialize and

Finalize. I have working implementation but I need to adjust the code to the FPC compiler code standard :P

Sidenote for this (don't know whether you have already ensured that): these operators must not be useable as global operators as after all they must he known in the RTTI and that can't work if they're declared in another unit that might not even be included... (That's in contrast to how operators normally behave in FPC, but there's not really a way around it :/ )

Regards,
Sven

Reply by email

Mazola Winstrol
to Sven Barth

I've implemented a new version. For this version i created a mock class to use with FHasValue (the previous implementation uses a hack to the interface internal layout).

unit NullableTypes;
{$mode delphi}{$H+}
interface
type
  { TMockInterfacedObject }
  TMockInterfacedObject = class(TObject, IUnknown)
  strict private
    class var FInstance: TMockInterfacedObject;
  public
    class constructor Create;
    class destructor Destroy;
    class property Instance: TMockInterfacedObject read FInstance;
    function QueryInterface({$IFDEF
FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) :
longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
    function _AddRef: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
    function _Release: longint; {$IFNDEF
WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  end;
  { TNullable }
  TNullable<T> = record
  strict private
    FValue: T;
    FHasValue: IInterface;
    function GetValue: T;
    function GetHasValue: Boolean;
    procedure SetValue(const AValue: T);
    procedure SetFlatInterface(var Intf: IInterface);
  public
    constructor Create(const AValue: T);
    procedure Clear;
    function GetValueOrDefault: T; overload;
    function GetValueOrDefault(Default: T): T; overload;
    property HasValue: Boolean read GetHasValue;
    property Value: T read GetValue;
    class operator Implicit(const AValue: Pointer): TNullable<T>;
    class operator Implicit(AValue: TNullable<T>): T;
    class operator Implicit(const AValue: T): TNullable<T>;
    class operator Explicit(AValue: TNullable<T>): T;
  end;
  TInteger = TNullable<Integer>;
implementation
uses
  SysUtils;

{ TNullable }

procedure TNullable<T>.SetFlatInterface(var Intf: IInterface);
begin
  Intf := TMockInterfacedObject.Instance;
end;
class operator TNullable<T>.Explicit(AValue: TNullable<T>): T;
begin
  Result := AValue.Value;
end;
function TNullable<T>.GetHasValue: Boolean;
begin
  Result := FHasValue  nil;
end;
function TNullable<T>.GetValue: T;
begin
  if not HasValue then
    raise Exception.Create('Invalid operation, Nullable type has no value');
  Result := FValue;
end;
function TNullable<T>.GetValueOrDefault: T;
begin
  if HasValue then
    Result := FValue
  else
   Result := Default(T);
end;
function TNullable<T>.GetValueOrDefault(Default: T): T;
begin
  if not HasValue then
    Result := Default
  else
    Result := FValue;
end;
class operator TNullable<T>.Implicit(const AValue: Pointer): TNullable<T>;
begin
  if AValue = nil then
    Result.Clear
  else
    raise Exception.Create('Invalid operation, incompatible values.');
end;
class operator TNullable<T>.Implicit(AValue: TNullable<T>): T;
begin
  Result := AValue.Value;
end;
class operator TNullable<T>.Implicit(const AValue: T): TNullable<T>;
begin
  Result := TNullable<T>.Create(AValue);
end;
procedure TNullable<T>.SetValue(const AValue: T);
begin
  FValue := AValue;
  SetFlatInterface(FHasValue);
end;
constructor TNullable<T>.Create(const AValue: T);
begin
  FValue := AValue;
  SetFlatInterface(FHasValue);
end;
procedure TNullable<T>.Clear;
begin
  FHasValue := nil;
end;

{ TMockInterfacedObject }

class constructor TMockInterfacedObject.Create;
begin
  FInstance := TMockInterfacedObject.Create;
end;
class destructor TMockInterfacedObject.Destroy;
begin
  FInstance.Free;
end;
function TMockInterfacedObject.QueryInterface({$IFDEF
FPC_HAS_CONSTREF}constref
  {$ELSE}const{$ENDIF} iid : tguid;out obj): longint;
begin
  Result := E_NOINTERFACE;
end;
function TMockInterfacedObject._AddRef: longint;
begin
  Result := -1;
end;
function TMockInterfacedObject._Release: longint;
begin
  Result := -1;
end;
end.

Reply by email

Mazola Winstrol
to Dmitry Boyarintsev: On Fri, Feb 26, 2016 at 10:38 PM, Mazola Winstrol How to reset TNullableType to Null…

2016-02-27 0:49 GMT-03:00 Dmitry Boyarintsev :

Show quoted text 8 lines
On Fri, Feb 26, 2016 at 10:38 PM, Mazola Winstrol wrote: > In the code bellow, the generic type TNullableTyple is implemented (and > incomplete for now). > How to reset TNullableType to Null value? HasValue seems to be read-only.

In the last version, there is two ways:

var
   NullInt: TNullable<Integer>;
begin
   NullInt.Clear; // Method 1
   NullInt := nil; // Method 2
end;

Reply by email

silvioprog
to Mazola Winstrol: I've implemented a new version. For this version i created a mock class to use with…
Mazola Winstrol wrote
I've implemented a new version. For this version i created a mock class to use with FHasValue (the previous implementation uses a hack to the interface internal layout).

Thanks for share that. It seems a very useful unit.

unit NullableTypes;
{$mode delphi}{$H+}

$MODE DELPHI implies {$H ON}
<http://www.freepascal.org/docs-html/prog/progsu105.html>, so so you should remove the {$H+}.

Silvio Clécio

Reply by email

Maciej Izak
to Sven Barth: incomplete for now). Finalize. I have working implementation but I need to adjust the…

2016-02-27 9:44 GMT+01:00 Sven Barth :

Show quoted text 7 lines
Sidenote for this (don't know whether you have already ensured that): these operators must not be useable as global operators as after all they must he known in the RTTI and that can't work if they're declared in another unit that might not even be included... (That's in contrast to how operators normally behave in FPC, but there's not really a way around it :/ )

Yes that is true :). Maybe in next week (or in 2 weeks) my implementation will be ready to commit. Current implementation on my machine, works fine even for code with

-New
-GetMem + Initialize/InitializeArray

it is important base for SmartPtr / SmartObj.

Best regards, Maciej Izak

Reply by email

Mazola Winstrol
to Mazola Winstrol

I have noticed that, by using generics, we can't overload arithmetic operators.

E.g.:

...
class operator Negative(A: TNullableType<T>): T;
...

class operator TNullableType<T>.Negative(A: TNullableType<T>): T;
begin
    Result := -1 * A;
end;
....

wouldn't compile with the error "Operator not applicable to this operand type".

Is there any workaround to overcome this?

Reply by email

Sven Barth
to Mazola Winstrol
"Mazola Winstrol" wrote
I have noticed that, by using generics, we can't overload arithmetic

operators.

Show quoted text 14 lines
E.g.: ... class operator Negative(A: TNullableType<T>): T; ... class operator TNullableType<T>.Negative(A: TNullableType<T>): T; begin Result := -1 * A; end; .... wouldn't compile with the error "Operator not applicable to this operand

type".

Is there any workaround to overcome this?

As far as I am concerned that *should* work. If it does not, then it's a bug. Please file a bug report with a simple example program.

Regards,
Sven

Reply by email

Mazola Winstrol
to Sven Barth

2016-02-29 13:16 GMT-03:00 Sven Barth :

Show quoted text 28 lines
Am 29.02.2016 16:13 schrieb "Mazola Winstrol" : > > I have noticed that, by using generics, we can't overload arithmetic operators. > > E.g.: > > ... > class operator Negative(A: TNullableType<T>): T; > ... > > class operator TNullableType<T>.Negative(A: TNullableType<T>): T; > begin > Result := -1 * A; > end; > .... > > wouldn't compile with the error "Operator not applicable to this operand type". > > Is there any workaround to overcome this? As far as I am concerned that *should* work. If it does not, then it's a bug. Please file a bug report with a simple example program. Regards, Sven

I apologize, it works.

There is a problem in my design. The code won't compile if i try to specialize with a type which doesn'y supports arithmetic operators e.g String types.

==== code ====

{$mode delphi}
  TNullableType<T> = record
  private
    FValue: T;
  public
    class operator Negative(A: TNullableType<T>): T;
  end;
  TString = TNullableType<String>;

.....

class operator TNullableType<T>.Negative(A: TNullableType<T>): T;
begin
  Result := -1 * A.FValue;
end;

=== code ====

Compilation error: "Operator is not overloaded: "ShortInt" * "AnsiString" ";

Is there any way to overcome this? Is there any way to tell the compiler to ignore some operators depending on the specialization type?

Regards

Reply by email

Unknown author
to Mazola Winstrol
Mazola Winstrol wrote
There is a problem in my design. The code won't compile if i try to specialize with a type which doesn'y supports arithmetic operators e.g String types.

apparently i'm missing something... why should arithmetic operators be recognized for strings? that doesn't make sense? arithmetic operators are for numerics not strings...

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list* unless private contact is specifically requested and granted.

Reply by email

Rainer Stratmann
to Mazola Winstrol: In some situations, would be very interesting to determine whether the value of a…
you wrote 22 lines
Hello list, In some situations, would be very interesting to determine whether the value of a primitive variable is initialized or not. For example, fields in database records can contain null values. By implementing an ORM, it would be interesting to represent these null values in the properties of objects. Java has the so called Primitives Class Wrappers, where each primitive type (int, boolean ...) has a corresponding wrapper class (Integer, Boolean ...). By using class wrappers you can represent null values in primitive types through null class instances references. Using class wrappers in FPC is not feasible due to memory management issues (the programmer needs to worry about the lifetime of the instances and free the instances manually). Perhaps, a solution in FPC would be using primitive record wrappers with custom records operators. What do you think about it? Is there any other solution? Regards

I did not read everything. But it seems, that you want to have a function you also can program by yourself.

Reply by email

Sven Barth
to Mazola Winstrol: 2016-02-29 13:16 GMT-03:00 Sven Barth : I apologize, it works. There is a problem in my…
"Mazola Winstrol" wrote
Is there any way to overcome this? Is there any way to tell the compiler

to ignore some operators depending on the specialization type?

No, there is not. Better not use operators other than the assignment ones or provide different Nullable types for different purposes (that maybe can be assigned to each other).

Regards,
Sven

Reply by email

Mazola Winstrol
to Sven Barth

2016-03-01 9:13 GMT-03:00 Sven Barth :

Show quoted text 8 lines
Am 01.03.2016 04:08 schrieb "Mazola Winstrol" : > Is there any way to overcome this? Is there any way to tell the compiler to ignore some operators depending on the specialization type? No, there is not. Better not use operators other than the assignment ones or provide different Nullable types for different purposes (that maybe can be assigned to each other).

The problem is type the same structures for the various nullable types. Perhaps, a "ugly" solution would be:

===== code =========

{$mode delphi}
{$DEFINE typename:=TSimpleNullableType<T>}
typename = record
strict private
   {$INCLUDE commonprivatedefinition.inc}
public
   {$INCLUDE commonprivatedefinition.inc}
end;
{$DEFINE typename:=TArithmeticNullableType<T>}
typename = record
strict private
   {$INCLUDE commonprivatedefinition.inc}
public
   {$INCLUDE commonprivatedefinition.inc}
   class operator Negative(A: TArithmeticNullableType<T>): T;
end;

==== code ======

Regards

Reply by email

Mazola Winstrol
to Unknown author: apparently i'm missing something... why should arithmetic operators be recognized for…

2016-03-01 1:48 GMT-03:00 :

Show quoted text 13 lines
On 02/29/2016 10:08 PM, Mazola Winstrol wrote: > There is a problem in my design. The code won't compile if i try to > specialize with a type which doesn'y supports arithmetic operators e.g > String > types. > apparently i'm missing something... why should arithmetic operators be recognized for strings? that doesn't make sense? arithmetic operators are for numerics not strings...

The operator shouldn't be recognized for strings. The problem is that we are using a generic record for defining a nullable type. So, we can't make a subclass to define operators applicable only for numeric types.

Reply by email

Constantine Yannakopoulos
to Mazola Winstrol: I have noticed that, by using generics, we can't overload arithmetic operators. E.g.: ...…
Mazola Winstrol wrote 20 lines
I have noticed that, by using generics, we can't overload arithmetic operators. E.g.: ... class operator Negative(A: TNullableType<T>): T; ... class operator TNullableType<T>.Negative(A: TNullableType<T>): T; begin Result := -1 * A; end; .... wouldn't compile with the error "Operator not applicable to this operand type". Is there any workaround to overcome this?

The only solution I have found is to implement ALL operators for TNullableType<T> by defining a generic interface INullableOperatiors<T> that contains methods for all operators, then implement for each type by means of manual interface implementation and then delegate each class operator implementation to the corresponding implementation using RTTI of the generic parameter T like in Delphi's Generics.Defaults and IComparer<T>/IEqualityComparer<T>. This way the implementation of an operator not supported for a specific type (e.g. negation for strings) will raise an exception.

It's a rather tedious task though and I abandoned it half way and I'm sure Sven would object to such an implementation as it involves manual interfaces. I can send you the unfinished Delphi unit via private email if you want.

Reply by email

Mazola Winstrol
to Constantine Yannakopoulos

2016-03-01 10:07 GMT-03:00 Constantine Yannakopoulos :

Show quoted text 17 lines
The only solution I have found is to implement ALL operators for TNullableType<T> by defining a generic interface INullableOperatiors<T> that contains methods for all operators, then implement for each type by means of manual interface implementation and then delegate each class operator implementation to the corresponding implementation using RTTI of the generic parameter T like in Delphi's Generics.Defaults and IComparer<T>/IEqualityComparer<T>. This way the implementation of an operator not supported for a specific type (e.g. negation for strings) will raise an exception. It's a rather tedious task though and I abandoned it half way and I'm sure Sven would object to such an implementation as it involves manual interfaces. I can send you the unfinished Delphi unit via private email if you want.

Can you send me?

Regards

Reply by email

Mazola Winstrol
to silvioprog

2016-03-02 23:12 GMT-03:00 silvioprog :

Show quoted text 11 lines
On Tue, Mar 1, 2016 at 12:08 AM, Mazola Winstrol wrote: [...] > > I apologize, it works. > Do you have plan to share it in some place like Github, Lazarus-CCR or as Lazarus generics demo? Just a idea, because this implementation sounds good.

Yes, sure! I dont know where to place yet. What you suggests?

I will send to list the final version in the next days for discussion.

Reply by email

silvioprog
to Mazola Winstrol
Mazola Winstrol wrote 17 lines
2016-03-02 23:12 GMT-03:00 silvioprog : > On Tue, Mar 1, 2016 at 12:08 AM, Mazola Winstrol > wrote: > [...] >> >> I apologize, it works. >> > > Do you have plan to share it in some place like Github, Lazarus-CCR or as > Lazarus generics demo? Just a idea, because this implementation sounds good. > > Yes, sure! I dont know where to place yet. What you suggests? I will send to list the final version in the next days for discussion.

I can ask FPC/Lazarus team to distribute it as a FPC, Lazarus or Lazarus-CCR generics demo, otherwise you can send it to Github, something like "github.com/mazofeifer/fpc-prw". :-)

Silvio Clécio

Reply by email

Mazola Winstrol
to silvioprog
Show quoted text 9 lines
On Thu, Mar 3, 2016 at 10:16 AM, Mazola Winstrol wrote: > > I will send to list the final version in the next days for discussion. >

Hello list,

I am sending you the nullable types implementation. The approach i choose is to separate comon parts in include files. This way, i can implement almost all operators a primitive type supports and so we can use the Nullable Types almost the same way we use native types. E.g. NullableInteger supports arithmetic operators while the NullableBoolean supports only the logical ones.

Please see the code in attachments and send your suggestions / remarks.

Best regards

Reply by email

silvioprog
to Mazola Winstrol

On Sun, Mar 6, 2016 at 7:21 PM, Mazola Winstrol
wrote:
[...]

Please see the code in attachments and send your suggestions / remarks.

Thanks for share.

How do I use the the NullableTypes.String unit?

Tried:

program project1;
{$mode objfpc}{$H+}
uses NullableTypes.String;
begin
end.

Got:

Fatal: Syntax error, "identifier" expected but "STRING" found

Silvio Clécio

Reply by email

Sven Barth
to silvioprog
"silvioprog" wrote
On Sun, Mar 6, 2016 at 7:21 PM, Mazola Winstrol
Show quoted text 23 lines
[...] > > Please see the code in attachments and send your suggestions / remarks. Thanks for share. How do I use the the NullableTypes.String unit? Tried: program project1; {$mode objfpc}{$H+} uses NullableTypes.String; begin end. Got: Fatal: Syntax error, "identifier" expected but "STRING" found

That is indeed not the best name around, but use "&String", that should work...

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 30 lines
Am 11.03.2016 04:16 schrieb "silvioprog" : > > On Sun, Mar 6, 2016 at 7:21 PM, Mazola Winstrol wrote: > [...] >> >> Please see the code in attachments and send your suggestions / remarks. > > > Thanks for share. > > How do I use the the NullableTypes.String unit? > > Tried: > > program project1; > > {$mode objfpc}{$H+} > > uses NullableTypes.String; > > begin > end. > > Got: > > Fatal: Syntax error, "identifier" expected but "STRING" found That is indeed not the best name around, but use "&String", that should work...

Maybe rename this to NullableTypes.Strings ?

Using keywords as identifiers is a really bad idea.

I can understand it if you need to import data/routines from another language, but really not for native pascal routines.

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt
"Michael Van Canneyt" wrote 49 lines
On Fri, 11 Mar 2016, Sven Barth wrote: > Am 11.03.2016 04:16 schrieb "silvioprog" : >> >> >> On Sun, Mar 6, 2016 at 7:21 PM, Mazola Winstrol > > wrote: >> >> [...] >>> >>> >>> Please see the code in attachments and send your suggestions / remarks. >> >> >> >> Thanks for share. >> >> How do I use the the NullableTypes.String unit? >> >> Tried: >> >> program project1; >> >> {$mode objfpc}{$H+} >> >> uses NullableTypes.String; >> >> begin >> end. >> >> Got: >> >> Fatal: Syntax error, "identifier" expected but "STRING" found > > > That is indeed not the best name around, but use "&String", that should > work... Maybe rename this to NullableTypes.Strings ? Using keywords as identifiers is a really bad idea. I can understand it if you need to import data/routines from another language, but really not for native pascal routines.

I agree.

Regards,
Sven

Reply by email

Mazola Winstrol
to silvioprog: On Sun, Mar 6, 2016 at 7:21 PM, Mazola Winstrol [...] Thanks for share. How do I use the…

2016-03-11 0:15 GMT-03:00 silvioprog :

Show quoted text 27 lines
On Sun, Mar 6, 2016 at 7:21 PM, Mazola Winstrol wrote: [...] > Please see the code in attachments and send your suggestions / remarks. > Thanks for share. How do I use the the NullableTypes.String unit? Tried: program project1; {$mode objfpc}{$H+} uses NullableTypes.String; begin end. Got: Fatal: Syntax error, "identifier" expected but "STRING" found

I will fix the unit names, as suggested by Sven and Michael.

The approach i used doesn't work with the current fpc 3.0 release due to some bugs in the compiler (#0029859
<http://bugs.freepascal.org/view.php?id=29859> and #0029792 <http://bugs.freepascal.org/view.php?id=29792>).

Please wait for the fixes. I will send a new version here.

Reply by email