Archived

This forum has been archived. Please start a new discussion on GitHub.

3.5b: Python optional value mapping questions

First question: Regarding Ice.Unset, one checks if a data member is unset using ==. My question goes to PEP-8 which states that:
Comparisons to singletons like None should always be done with is or is not, never the equality operators.

Is Ice.Unset a singleton? Is it safe to compare against Ice.Unset with 'is' instead of '=='? Should we be using 'is' instead of '=='? From a code style point of view, that seems to be preferred and could be a little faster.

Second question: Why wasn't None used instead of introducing Ice.Unset?

Thanks,
Blair

Comments

  • mes
    mes California
    Hi,

    Unset is a singleton, so you should use is for comparisons.

    We cannot use None as the "marker" value for optional values because None is already a legal value for non-optional types, such as strings, sequences, dictionaries, and classes, and that leads to ambiguities. For example, if you pass None as the value of an optional class argument, did you mean that Ice should pass the optional set to a nil value, or did you mean that the optional is unset?

    We use Unset to avoid such ambiguities.

    Regards,
    Mark
  • I have been porting my project to Ice 3.5, adopting the new optional values in place of the old technique of using a sequence, and have found a hopefully unintended aspect of Ice.Unset lead to a common coding mistake.

    Before Ice 3.5:
    sequence<string> OptionalString;
    
    struct Foo {
      OptionalString bar;
    };
    
    # Python Usage
    if foo.bar:
      print foo.bar[0]
    

    Ice 3.5:
    struct Foo {
      optional(0) string bar;
    };
    
    # Python Usage (wrong)
    if foo.bar:
      print foo.bar
    
    # Python Usage (right)
    if foo.bar is not Ice.Unset:
      print foo.bar
    

    The "wrong" case is the naive porting of the old code, where the old code follows the PEP8-recommended technique of using a list in boolean context to test if it is empty. My expectation in Ice 3.5 is that Ice.Unset would also evaluate to false in boolean context. But because of an implementation detail, Ice.Unset is an instance of 'object' and evaluates true in boolean context.

    I understand that using the 'is' operator is the only foolproof way of checking if a value is unset, and that many "set" values would evaluate to false in a boolean context. However, I still feel it would be highly convenient if Ice.Unset behaved more like None and evaluated false in boolean context.

    In our organization we are considering modifying Ice to change this behavior. We are wondering if you are interested in sharing your opinion on this, if you have any plans to change this behavior, or if you would be interested in a patch from us.

    The proposed change is to change Ice.Unset to be an instance of a new custom type that implements __nonzero__ to return False.