generic functions in VO dialect

This forum is meant for questions and discussions about the X# language and tools
Post Reply
User avatar
wriedmann
Posts: 4018
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

generic functions in VO dialect

Post by wriedmann »

Hi Robert,
in my VO applications, I have many calls like this:

Code: Select all

method ReceiveBroadcastMessage( symServer ) class AnAuftragEdit
do case
case symServer == #MAuftrag .and. oDCTabControl:IsCreated( #AnAuftragSubEdit1 )
    oDCTabControl:GetPage( #AnAuftragSubEdit1 ):CheckMontageAuftrag()
endcase
	
return nil
When migrating to X#, I have to change that code to

Code: Select all

method ReceiveBroadcastMessage( symServer ) class AnAuftragEdit
do case
case symServer == #MAuftrag .and. oDCTabControl:IsCreated( #AnAuftragSubEdit1 )
#ifdef __XSHARP__
  ( ( AnAuftragSubEdit1 ) oDCTabControl:GetPage( #AnAuftragSubEdit1 ) ):CheckMontageAuftrag()
#else
  oDCTabControl:GetPage( #AnAuftragSubEdit1 ):CheckMontageAuftrag()
#endif
endcase
	
return nil
My idea would now to create a method in my TabControl class like this

Code: Select all

method GetPageNative<T>( uPage as usual ) as T
local oReturn			as T

oReturn				:= ( T ) self:GetPage( uPage )

return oReturn
but here the compiler says

Code: Select all

error XS0030: Cannot convert type 'VO.Window' to 'T'
because currently GetPage returns a VO.Window.
My question now is, if it is a good idea to build a generic function for such code pieces, and it that is possible.
I have to admit that I'm inspired by the PCallNative() function.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 5472
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: generic functions in VO dialect

Post by Chris »

Hi Wolfgang,

In general, I think its a very good idea to use generic methods for strongly typing stuff, but I'm not sure if it's helpful in this particular case.

First of all, to make it compile, you can first cast to object:

Code: Select all

oReturn := ( T )(OBJECT) GetPage( uPage )
or you can use the ASTYPE operator and provide a constraint for your generic method, specifying what the T type can be:

Code: Select all

method GetPageNative<T>( uPage as usual ) as T where T is Window
LOCAL oReturn AS T
oReturn := GetPage( uPage ) ASTYPE T
RETURN oReturn
This will also further help the compiler to prevent you from using this method with types that do not make sense in this context. Actually the constraint version I think should also work with the simple

Code: Select all

( T ) GetPage( uPage )
syntax, but it doesn't, looks like a bug.

Anyway, the above will work, but I'm not sure what you will gain from this? You will need to call the method with specifying as a generic parameter the type that will be returned (like

Code: Select all

GetPageNative<MyTabPageClass>(3)
), so you need to know this from the code that calls this method. Then again, maybe that's exactly what you want to achieve, in which case I think your method is perfect (also from readability POV)!
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
wriedmann
Posts: 4018
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Re: generic functions in VO dialect

Post by wriedmann »

Hi Chris,
without casting the return value of the GetPage() method, the compiler complains that the class VO.Window (that is the return type) does not has a method CheckMontageAuftrag().
And personally I see a generic method as a cleaner way of typing, so

Code: Select all

( ( AnAuftragSubEdit1 ) oDCTabControl:GetPage( #AnAuftragSubEdit1 ) ):CheckMontageAuftrag()
becomes

Code: Select all

oDCTabControl:GetPageNative<AnAuftragSubEdit1>( #AnAuftragSubEdit1 ):CheckMontageAuftrag()
and first saves a few brackets, and second makes the compiler check if the method exists and if the parameter list is true.
But in theory it should be possible to write a generics method without parameter where the generic method can take the parameter from the type:

Code: Select all

oDCTabControl:GetPageNative<AnAuftragSubEdit1>():CheckMontageAuftrag()
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 5472
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: generic functions in VO dialect

Post by Chris »

Hi Wolfgang,

Ah right, you need to make the constraint a DataWindow:

Code: Select all

FUNCTION GetPageNative<T>( ) AS T WHERE T IS DataWindow
For omitting the parameter, maybe you can use something like this inside the GetPageNative() method:

Code: Select all

FOREACH oPage AS DataWindow IN <pages list>
	IF oPage:GetType() == TypeOf(T)
		RETURN (T)oPage
	END IF
NEXT
Didn't test it, but I think it should work.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
wriedmann
Posts: 4018
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Re: generic functions in VO dialect

Post by wriedmann »

Hi Chris,
thank you very much!
I think I prefer the version without the parameter - non because it saves some typing, but because it eliminates to specify the same (or nearly same) thing two times, making it easier to avoid errors.
I have to test that, but I think this is the way to go.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
wriedmann
Posts: 4018
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Re: generic functions in VO dialect

Post by wriedmann »

Hi Chris,
it is strange: the method code

Code: Select all

method GetPageNative<T>() as T where T is VO.DataWindow
	local oReturn			as T
	local cPageName			as string

	cPageName			:= T:GetType():Name
	oReturn				:= self:GetPage( cPageName ) astype T

	return oReturn
seems to be seen as Clipper method.

Code: Select all

error XS9126: Type 'DynamicTabControl' cannot have an overloaded method 'GetPageNative' because one of the overloads has the CLIPPER calling convention.
Adding a pascal or strict keyword does not work either

Code: Select all

method GetPageNative<T>() as T where T is VO.DataWindow pascal
nor

Code: Select all

method GetPageNative<T>() as T pascal where T is VO.DataWindow
works, returning different errors.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 5472
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: generic functions in VO dialect

Post by Chris »

Hi Wolfgang,

This happens because I assume you have enabled /vo5. The STRICT clause needs to be put at the end of the definition (after the WHERE clause), what errors are you getting when you do that?

Also do you need to indeed define multiple methods with the same name?
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Post Reply