Len() can't be 'overloaded'

General FreeBASIC programming questions.
Post Reply
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Len() can't be 'overloaded'

Post by MrSwiss »

I've noticed at first, when trying a customized string-type, which was to contain
a overloaded Operator Len() (unary operator overload) as per description in doc.
It gave a Error, in which it was stated, that this is on the TODO list.

In the light of the recent discussion on WString (making it dynamic, e.t.c.), I find
it somewhat strange, that TODO's on the "base type" are not addressed first.

In order to prove my suspicions, I've simplified massively. First, doing a #undef of
Len, in order to use my own implementations (every one of the 3 is working fine,
if, and only if, the other 2 are 'commented out') a clear indication, that over-
loading in and of itself, is not possible with Len() ...
(IIRC, there was a similar issue with Sqr(), that was fixed, recently.)

testing code:

Code: Select all

' Len_Overload-test1.bas -- (c) 2019-05-18/23, MrSwiss
'
' compile: -s console
'

#Undef Len

' testing ...
'Function Len OverLoad( _                ' do it the C'ish way ...
'    ByVal psz   As ZString Ptr _        ' until we get a char = zero/NULL
'    ) As ULongInt
'    Dim As ULongInt le = 0
'    Dim As UByte    t
'
'    Do
'        t = psz[le] : le += 1
'    Loop Until t = 0
'    ? "psz"
'    Return (le - 1)
'End Function

'Function Len OverLoad( _                ' internal definition
'    ByRef s     As Const String _       ' signed integer
'    ) As Integer
'    ? "s LI"
'    Return CPtr(Integer Ptr, @s)[1]
'End Function

Function Len OverLoad( _                ' similar to internal definition
    ByRef s     As Const String _       ' just unsigned integer
    ) As UInteger
    ? "s ULI"
    Return CPtr(UInteger Ptr, @s)[1]
End Function

' demo code ...
Dim As String st = "test, test, blah, blah, blaaaaaaaaahhhhhhhhhh!"
Dim As ZString Ptr pszt = StrPtr("not so funny: can't overload Len()!")

Print Len(st), st
Print
Print Len(*pszt), *pszt
Print

Sleep
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Len() can't be 'overloaded'

Post by fxm »

It is not the problem of 'Len()', because if an other name is used ('_Len()' for example), there is the same behavior:
- the 2nd and 3th functions cannot be overloaded because they have the same parameter type (the return type of a function is not taken into account for overloading),
- for the other case, see the bug report #666 Cannot overload 'as string' with 'as zstring ptr'.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Len() can't be 'overloaded'

Post by MrSwiss »

As written: Operator Len() ... (first noticed).
fxm wrote:(the return type of a function is not taken into account for overloading)
does NOT apply there.
Operators can differentiate on return type only (Operator specific behaviour).

It's not really helpful, to concentrate on "heavily simplified code" (as clearly stated).
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Len() can't be 'overloaded'

Post by fxm »

1) It's not my fault if your text and your example are not full consistent. I made the choice to privilege the example (you can not blame me!).

2) The 'Len()' operator is not a member operator but an unary operator (not declared inside the Type). Therefore, the return value is not discriminant for overloading criterion (as for static functions).
Anyway:
Documentation wrote:The Cast Operator is the only operator (or function) that can be declared multiple times when only the return type differs.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Len() can't be 'overloaded'

Post by MrSwiss »

1) Current behaviour doesn't allow, a differing implementation of String.
2) Len() is a crucial part of that.
3) Unary / Binary / Ternary Operators in types, are in principle possible.
(e.g. + or & overloaded concatenation Operators (unary))
4) The received Error: 143, clearly states (TODO) ...
(this means to me, it's currently a exception to the rule)
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Len() can't be 'overloaded'

Post by fxm »

In documentation, I don't see any error message with "TODO".
Can you precise?
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Len() can't be 'overloaded'

Post by MrSwiss »

Sorry, the error # was too low (by 10) ...
FbTemp.bas(33) error 153: Operator cannot be a member function (TODO), before '(' in 'Declare Operator Len() As ULong'
FbTemp.bas(33) error 153: Operator cannot be a member function (TODO), before '(' in 'Declare Operator Len(ByRef As zstr_t) As ULong'
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: Len() can't be 'overloaded'

Post by srvaldez »

@MrSwiss, what's the expected output?
I have a 3 year old version of FB and it compiles your code with no problem

Code: Select all

s ULI
46            test, test, blah, blah, blaaaaaaaaahhhhhhhhhh!

s ULI
35            not so funny: can't overload Len()!
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Len() can't be 'overloaded'

Post by MrSwiss »

@srvaldez,

please, read it all, again ...

I'm not a fan, of repeating myself. ;-)
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Len() can't be 'overloaded'

Post by fxm »

Code: Select all

Type Vector
  Dim As Integer x, y
  Declare Operator Len () As Uinteger
End Type
  • FBIDETEMP.bas(3) error 153: Operator cannot be a member function (TODO), before '(' in 'Declare Operator Len () As Uinteger'
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Len() can't be 'overloaded'

Post by coderJeff »

Self-ops must be member functions (they are passed a hidden THIS parameter) and require an instance to invoke. Non-self-ops must be non-member functions.

Because, what would the invocation of operator len() member function look like when passed implicit THIS parameter? Maybe:

Code: Select all

type T
	__ as integer
	declare operator len() as uinteger
end type

operator T.len() as uinteger
	return 0
end operator

dim x as T
print x.len()
In which case, "len" is just like a normal member function, and this will compile fine:

Code: Select all

type T
	__ as integer
	declare function len() as uinteger
end type

function T.len() as uinteger
	return 0
end function

dim x as T
print x.len()

I'm fairly certain that the "TODO" in the error message refers only to static member function. Maybe it should be added to the global namespace, too? maybe not? Probably one the reasons it still is a TODO:

Code: Select all

type T
	__ as integer
	declare static operator len( byref arg as T ) as uinteger
end type

operator T.len( byref arg as T ) as uinteger
	return 0
end operator 

dim x as T
print T.len( x )
But again, this can already by done using a normal static member function, as in this compiles OK:

Code: Select all

type T
	__ as integer
	declare static function len( byref arg as T ) as uinteger
end type

function T.len( byref arg as T ) as uinteger
	return 0
end function

dim x as T
print T.len( x )
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Len() can't be 'overloaded'

Post by MrSwiss »

@coderJeff,

thanks for your clarifications. The static Operator, seems to be, what I'm looking for.
However, the expectation on the 'to be obtained result' is different than yours:

Code: Select all

...

Dim As T	x

Print Len( x )		' <---- no type prefix
This seems to mean, that your question:
coderJeff wrote: Maybe it should be added to the global namespace, too? maybe not?
whould be a: Yes (global namespace add)

Because only that, whould be convincing proof, that Len() can be 'overloaded'.
As soon, as a additional specifier comes into play, it's no longer a true 'overload'.
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Len() can't be 'overloaded'

Post by coderJeff »

As mentioned:
fxm wrote:2) The 'Len()' operator is not a member operator but an unary operator (not declared inside the Type).
Operator len() can be overloaded; a non-member unary operator declared/defined outside of the type in the global namespace.

Code: Select all

type T
	__ as integer
	declare const property length() as uinteger
end type 

const property T.length() as uinteger
	'' fake a length, just for example
	property = 42
end property

'' overload the LEN operator (in the global namespace)
operator len( byref arg as const T ) as uinteger
	operator = arg.length
end operator

dim s as string = "123"
dim f as string * 10 = "123"
dim z as zstring * 15 = "12345"
dim w as wstring * 20 = "1234567"
dim x as T

''    3       10      5       7       42
print len(s), len(f), len(z), len(w), len(x) 
CONST is optional. It indicates that passing the argument or calling the member proc doesn't modify the variable.
MrSwiss wrote:The static Operator, seems to be, what I'm looking for.
Yes, LEN can be overloaded, but with a static member operator, can be done better.

The advantage would be that a static operator have access to the private member/data of the type. What currently can't be done with the globally overloaded operator only. So as above, the workaround is to provide a public member (property length) that can be called from the global overload operator to achieve the same result.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Len() can't be 'overloaded'

Post by MrSwiss »

coderJeff wrote:Operator len() can be overloaded; a non-member unary operator declared/defined outside of the type in the global namespace.
Thanks, that clears the fog.
I think generally speaking, its better to state "what it is", instead of stating "what it isn't".
Seems far easier to understand, from a logic point of view.
coderJeff wrote:CONST is optional. It indicates that passing the argument or calling the member proc doesn't modify the variable.
Yes, I'm aware of that.

Any chance of allowing Static Operator Len(...) in future versions ?
(the current workaround seems to be clumsy)
coderJeff wrote:The advantage would be that a static operator have access to the private member/data of the type.
That's the idea, behind the whole madness ...
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Len() can't be 'overloaded'

Post by coderJeff »

MrSwiss wrote:Any chance of allowing Static Operator Len(...) in future versions ?
(the current workaround seems to be clumsy)
coderJeff wrote:The advantage would be that a static operator have access to the private member/data of the type.
That's the idea, behind the whole madness ...
I think there is 2 parts to this issue, which I put in bug reports:

1) #903 Operator cannot be a member function (TODO)
not too difficult, I will create a pull request soon. No tests written yet. I would be very grateful if anyone ever wanted to learn how to write tests for the fbc test-suite. It's not difficult, but after writing 1000's, it's tedious. Looking for anyone that wants to share my pain...

2) #902 Overloaded operators do not respect namespace
This one is harder. Internally, fbc only tracks a list of global operators. Operators that respect namespace does not exist yet, though fbc should. If the only purpose for allowing 1) above is accessing private UDT members; then should probably be achieved another way. Because, otherwise, usage of overloaded operators in a UDT (which is a kind of namespace) or a namespace, but not respecting that namespace is counter intuitive (clumsy).

MrSwiss, thanks for your investigation on the issue so far.
Post Reply