Comparing an object with nil

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.