rfc:boxingandunboxing

Request for Comments: Boxing and Unboxing

This RFC discusses a new feature for PHP called boxing and includes discussions of related RFCs that would complete the implementation of boxing and unboxing.

Introduction

Boxing and unboxing is a concept from the C# language. The basic idea of boxing in C# is that a value type is implicitly converted to an object type. Unboxing is the opposite and is done explicitly to convert the object back to a value type.

Boxing: Implicit Conversion To Objects

The most obvious use for boxing is function and method type hints. The object type hints could be used to do implicit boxing of variables. Either a new magic method (__box for example) or a new interface (Boxable for example) would need to be added to PHP. The boxing method would accept the scalar value and set its internal representation (similar to __wakeup). The method could either return false (and let PHP handle the failure) or throw an exception (BoxingException for example) when the supplied value is not valid for the boxing operation.

It would be best for PHP to include as many object versions of scalar types as possible. The boxing functionality could be added to the SPL Types 1) to provide for standard representations of the scalar types. The power to box variables would also be available in userland classes.

It could also be possible to try to perform implicit conversions from one object type to another, but the overhead of this feature may be too much. Consider it as an option only.

Unboxing: Or, Casting To Scalar

The unboxing of variables would need to occur on an explicit cast or on a call to an internal function. The unboxing could be implemented as the RFC for class casting to scalar 2). It already discusses some examples for a new magic method or interface. I propose some more to relate to the unboxing concept (__unbox for a magic method, and Unboxable for an interface).

Benefits

The benefits to boxing and unboxing include:

  • Only minor modifications required to the current type-hinting implementation (I am only assuming this part).
  • The boxing and unboxing ability can be used in userland classes to accomplish “cool things”.
  • Get SplTypes and scalar casting in PHP core.

Examples

Example of different int object classes:

 <?php
 class StrictInt //implements Boxable, Unboxable
 {
     protected int $value;
     public function __box($value)
     {
         if (!is_int($value)) {
             //throw new BoxingException('StrictInt does not except non-int values');
             return false;
         }
         $this->value = $value;
     }
     public function __unbox($type, $class = null)
     {
         switch ($type) {
             case (Unboxable::INT):
                 return $this->value;
                 break;
             case (Unboxable::FLOAT):
                 return (float)$this->value;
                 break;
             case (Unboxable::STRING):
                 return (string)$this->value;
                 break;
             default:
                 throw new UnboxingException('StrictInt cannot convert to type: ' . Unboxable::getTypeString($type));
                 break;
         }
     }
 }
 class FuzzyInt //implements Boxable, Unboxable
 {
     protected $value;
     public function __box($value)
     {
         $this->value = (int)$value;
     }
     public function __unbox($type, $class = null)
     {
         switch ($type) {
             case (Unboxable::INT):
                 return $this->value;
                 break;
             case (Unboxable::FLOAT):
                 return (float)$this->value;
                 break;
             case (Unboxable::STRING):
                 return (string)$this->value;
                 break;
             default:
                 throw new UnboxingException('FuzzyInt cannot convert to type: ' . Unboxable::getTypeString($type));
                 break;
         }
     }
 }
 function testStrict(StrictInt $value)
 {
     $test = (int)$value * 2;
     echo $test, ' ', $value;
 }
 function testFuzzy(FuzzyInt $value)
 {
     $test = (int)$value * 2;
     echo $test, ' ', $value;
 }
 testStrict(1); // '2 1'
 // testStrict(1.5); // error
 // testStrict('1'); // error
 // testStrict('one'); // error
 testFuzzy(1); // '2 1'
 testFuzzy(1.5); // '2 1'
 testFuzzy('1'); // '2 1'
 testFuzzy('one'); // '0 0'

Proposal and Patch

No patch exists for Boxing. The casting to scalar has some patches on its RFC page.

Rejected Features

None

Changelog

2009-07-06: Initial Draft

rfc/boxingandunboxing.txt · Last modified: 2017/09/22 13:28 (external edit)