Operator_Convert and WebPictures

Given this class:

Class cFoo
Constructor cFoo(p as picture = nil) as cFoo

And this code:

  dim p as Picture = nil
  dim wp as WebPicture = nil
  
  
  dim f as new cFoo()   // works
  dim f as new cFoo(nil)  // works 
  dim g as new cFoo(p)  // works
  dim h as new cFoo(wp)   // Gives a NOE at runtime

What do you think should happen?

What actually happens is that on the last line, you get a NilObjectException.

What appears to be happening is that the automatic conversion between WebPicture and Picture fails, triggering the exception.

This is not what I would have expected - somehow it seems more logical to me that if an object is Nil, it would automatically convert to a Nil object of another class? Or, I’d expect that passing Nil to a

Hmm, I just discovered something else weird. It seems that in some cases, a WebPicture will automatically be created from a Nil picture object? The created WebPicture has these characteristics:

FileName: picture.png
mData : a 98 byte PNG data file

Is this a bug or feature? I don’t remember seeing this before…

dim wp as WebPicture = nil
dim p as picture = nil

wp = p  // what should the value of wp be now?  It should be Nil, right?

[quote=71203:@Michael Diehr]
This is not what I would have expected - somehow it seems more logical to me that if an object is Nil, it would automatically convert to a Nil object of another class?[/quote]

Not surprised in the least
wp is nil
But you’re expect the method “operator_convert() as picture” to be called

try it in your own code like

    dim p as picture = wp.Operator_Convert()

when wp is nil

It will give you the exact same NOE for the exact same reason

That’s not what I’m seeing - I have a situation where a nil Picture object is being auto-converted to a non-nil (but small and blank) webPicture object. This is inside a class constructor that uses default parameters - so maybe it doesn’t happen in the trivial example?

I’ll try to isolate a test and report back. Hang on.

Try this code in a webApp:

 dim p as picture = Nil
 dim wp as WebPicture = p  // wp is not nil !
 break

This compiles, and runs, and what happens is that WP is not nil, but rather gets created as an empty WebPicture object. This seems illogical to me - is there any other situation in the Xojo framework where Nil gets operator_convert()d into a non-nil object?

It doesn’t with variants, for example:

 dim p as picture = Nil
 dim v as variant = p  // v is nil
 break

Also, Norman - to be clear - you have it backwards from what I’m saying. I’m talking about the Picture to WebPicture conversion. You are talking about the WebPicture to Picture conversion. This matters … in fact

  dim p as picture
  dim wp as webpicture
  p = wp.Operator_Convert  //  compiles
  wp = p.Operator_Convert  // won't compile

Submitted as <https://xojo.com/issue/32724> with demo project

Also: I changed the title of this thread to reflect the actual issue.

[quote=71431:@Michael Diehr]Also, Norman - to be clear - you have it backwards from what I’m saying. I’m talking about the Picture to WebPicture conversion. You are talking about the WebPicture to Picture conversion. This matters … in fact

  dim p as picture
  dim wp as webpicture
  p = wp.Operator_Convert  //  compiles
  wp = p.Operator_Convert  // won't compile
[/code][/quote]

Yeah this makes sense as well

WebPicture has something like Operator_Convert( fromValue as Picture )
This behaves like a constructor and the WP takes a NIL (p in your case) and makes a new web picture that has no content because P is nil

Not a bug in fact

[code]dim p as picture = Nil
dim wp as new WebPicture( p )

break[/code]

WP better not be nil but what it wraps might be

Suppose you have a class - myThing
It has one public property - p as picture

[code]dim m as new MyThing
m.p = nil[/code]

OK so now lets make this an Operator_Convert
[code]Class MyThing
   property thePic as picture
   sub Operator_Convert ( p as picture )
           // self exists & is not nil
           self.p = p
   end sub[/code]

So by the time you get to calling the Operator the object EXISTS - its not nil (it can't be nil)

And FWIW your example code
 [code] dim p as picture
  dim wp as webpicture
  p = wp.Operator_Convert  //  compiles
  wp = p.Operator_Convert  // won't compile

is incorrect which is why it does not compile
P has no “convert TO” operator_convert i.e. it does not have Operator_Convert() as WebPicture
WP has a “convert_from” operator_convert - it DOES have Operator_Convert(p as picture)

And there’s good reason for this set up as the firs would cause a dependency on Picture so EVERY project would have to include WebPicture (not what we want)
The second ONLY causes a dependency when you use WebPicture in a Web project

I still think it’s weird and confusing, and somewhat unprecedented.

Is there any other situation in the framework where this happens (a nil object is operator_converted to a non nil object?) I’ve been using REALbasic/Xojo for years, and it seems unusual to me, and it makes for unexpected behavior in code, which I think violates the “principle of least surprise”

Example:

  dim p as picture = Nil
  dim wp as WebPicture = p  // I expect WP to be nil here, but it's not nil.   
  dim v as variant = p
  wp = v  // at this point, I have no idea.   It should be nil, but since p is a picture, maybe it's not?   Who knows.  

Ideas:

  • remove WebPicture’s operator_convert that converts from a picture
  • add an explicit “.fromPicture” call
  • (if one doesn’t exist) add a Constructor so you can say new WebPicture(p as Picture)

I think this would make code more readable and less surprising. The nil to not-nil object happening automatically is a real “gotcha”. I had code that was using nil object checking in logic, and this conversion already got me! :slight_smile:

[quote=71467:@Michael Diehr]I still think it’s weird and confusing, and somewhat unprecedented.
Is there any other situation in the framework where this happens (a nil object is operator_converted to a non nil object?) [/quote]
Possibly but if we didn’t do unprecedented things we’d never have introduced operator_convert as there were ways to do this yourself before it came to being (although that was so long ago they just seem to have always been there)
Or the operator_index or ……
The language & frameworks would be stagnant - which is not useful

This is not limited to the framework - but it’s certainly not widely used in the framework

You can do this yourself & create the EXACT SAME situation
And have been able to do so since operator_convert came to be
Mars and I discussed this at some length way back when - Operator_Convert is more like an initializer than a constructor.
The object is created and THEN the operator_convert is called to do whatever initialization you want with the passed parameters (the FROM values) - and thats VERY important in this case.
The conversion is the web picture initializing FROM a picture and NOT a picture converting itself TO a web picture.

Am I aware of any other place where this can / does occur in the framework ?
I suspect Json Item might do this with the dictionary conversion

It’s not widely done

As for changing it I’m not sure

  1. It runs the risk of breaking a lot of projects - although pretty publicly since the assignment of picture to web picture would just fail & not compile any more
  2. I have no idea what side effect this might have on the framework itself & therefore all web apps

Thanks, Norman - I understand the issues here. I can probably work around this by making my class constructor have two variations (one which takes WebPictures and one which takes Pictures) and in that way, I can pass nil objects and have them stay nil.

well if you try to do

dim wp as new webpicture ( nil )

and expect to get a nil object you won’t be able to since the constructor can’t return anything

However a factory method could return a nil like

dim wp as MyClass.FromData(nil)

and MyClass.FromData could return a nil object