I have some code that I think used to work but doesn’t now. The issue I am having is comparing a class (apmfloat) object with nil.
The following code works as expected:
dim x as apmfloat // new apmfloat object = nil
if x = nil then // does not call compare method of class apmfloat
break // does break here
end if
But the following code does not work as expected:
[code]
dim x as apmfloat
x = 2. // x object <> nil
if x = nil then // calls the compare method of class apmfloat (causing comparison with apmfloat and nil object)
break
end if
[/code]
Has comparisons with nil changed, a new bug, or do I not understand how comparisons with class objects and nil should work? I don’t know how to workaround this either because if I compare the object passed to the compare method with nil it will just call itself recursively.
What does your compare code look like?
Also
If myclass is nil then
...
Kem, the compare method works as it should. Thanks for the suggestion of using the is operator. It is definitely what I needed and fixes my problem.
With respect, if the compare code worked as it should, this wouldn’t have been a problem. I’m guessing you wrote compare against a variant or something, but in any case, I think you would benefit from posting it.
The compare method is below.
#pragma DisableBoundsChecking
#pragma disablebackgroundtasks
#pragma StackOverflowChecking false
// determines if one apmfloat is less than, greater than, or equal to the other
// returns int64 = -1 for less than, 0 for equal, and +1 for greater than
Dim compare_floats As Int64
Dim smaller_significant_digits, j, jj As Int64
Dim mePtr as Ptr = me.digits.data
Dim numPtr as Ptr = number.digits.data
// compare the two floats by comparing sign, number of digits, exponent, and if necessary the digits themselves
While True
If Me.sign = 0 Then
If number.sign = 0 Then // 0 = 0
compare_floats = 0
Exit While
Elseif number.sign = -1 Then // 0 > -
compare_floats = 1
Exit While
Else
compare_floats = -1 // 0 < +
Exit While
End If
End If
If (Me.sign = 1) And ((number.sign = 0) Or (number.sign = -1)) Then // + > (0 or -)
compare_floats = 1
Exit While
End If
If (Me.sign = -1) And ((number.sign = 0) Or (number.sign = 1)) Then // - < (0 or +)
compare_floats = -1
Exit While
End If
// both signs are now the same
If (Me.sign = 1) And (number.sign = 1) Then // both are positive
If Me.exponent > number.exponent Then // larger exponent is more positive
compare_floats = 1
Exit While
End If
If Me.exponent < number.exponent Then
compare_floats = -1
Exit While
End If
// both are positive and exponents are equal, now compare digits
// start by determining the shorter length
If Me.significant_digits < number.significant_digits Then
smaller_significant_digits = Me.significant_digits
Else
smaller_significant_digits = number.significant_digits
End If
jj = smaller_significant_digits - 1
For j=0 To jj Step 1
If mePtr.int8(j) > numPtr.int8(j) Then //larger digits are more positive
compare_floats = 1
Exit While
End If
If mePtr.int8(j) < numPtr.int8(j) Then
compare_floats = -1
Exit While
End If
Next
// both numbers equal up to shorter length
If Me.significant_digits = number.significant_digits Then // numbers are the same
compare_floats = 0
Exit While
End If
If Me.significant_digits > number.significant_digits Then // more digits is more positive
compare_floats = 1
Exit While
End If
compare_floats = -1
Exit While
End If
// both numbers are negative
If Me.exponent > number.exponent Then // larger exponent is more negative
compare_floats = -1
Exit While
End If
If Me.exponent < number.exponent Then
compare_floats = 1
Exit While
End If
// exponents equal, must now test digits
// start by determining the shorter length
If (Me.significant_digits < number.significant_digits) Then
smaller_significant_digits = Me.significant_digits
Else
smaller_significant_digits = number.significant_digits
End If
jj = smaller_significant_digits - 1
For j=0 To jj Step 1
If mePtr.int8(j) > numPtr.int8(j) Then // larger digits are more negative
compare_floats = -1
Exit While
End If
If mePtr.int8(j) < numPtr.int8(j) Then
compare_floats = 1
Exit While
End If
Next
// all digits up to shorter number are equal
If (Me.significant_digits = number.significant_digits) Then // numbers are the same
compare_floats = 0
Exit While
End If
If Me.significant_digits > number.significant_digits Then // more digits is more negative
compare_floats = -1
Exit While
Else
compare_floats = 1
Exit While
End If
Wend
Return compare_floats
I assume “number” is the param here? How is it declared? As your class or something else?
If as your class, do you have another Operator_Compare or an Operator_Convert? Have you traced the code at the point where you do if myobject = nil then
to see how and where it’s doing the comparison?
Also, consider replacing all the code that does the sign comparison with this:
if me.sign > number.sign then
compare_floats = 1
exit while
elseif me.sign < number.sign then
compare_floats = -1
exit while
elseif me.sign = 0 and number.sign = 0 then
compare_floats = 0
exit while
end if
// The signs are the same
...
Kem, I have Operator_Compare methods for types Apmfloat, single, double, int32, int64, and text. Stepping through with the debugger a
if apmfloat_object = nil then
instruction directly calls the Apmfloat Operator_Compare method which has a declaration of
operator_compare(num as apmfloat_module.apmfloat) as int64
and the method consists of one line
Return Self.compare(num)
which calls the method that I posted above.
When the .compare method executes if either of the arguments ‘me’ or ‘num’ (both apmfloat objects) are nil the method will throw a nilobjectexception when it hits the lines:
Dim mePtr as Ptr = me.digits.data
Dim numPtr as Ptr = number.digits.dat
which is to be expected since one of the arguments is not instantiated and the .digits property does not exist yet.
Throwing the nilobjectexception is perfectly satisfactory since this case should not happen. You correctly directed me to use the ‘is’ operator which avoids the comparison with ‘nil’ which I now know should be avoided.
I get it now. Thanks for clarifying.