Ferreteria/v0.6/clade/Data/Mem/QVar: Difference between revisions

From Woozle Writes Code
< Ferreteria‎ | v0.6‎ | clade‎ | Data‎ | Mem
Jump to navigation Jump to search
No edit summary
No edit summary
Line 23: Line 23:
==About==
==About==
* '''Purpose''': queryable var-wrapper objects
* '''Purpose''': queryable var-wrapper objects
The idea here is that I wanted to be able to indicate whether a value {exists, has been set, etc.} without relying on a coding convention (the most obvious/common being the use of NULL to indicate that a value is unavailable). While "NULL=unavailable" is not a ''bad'' convention (and I still use it occasionally), it feels klugey to rely on it too much -- while providing an object to wrap the results is both semantic: <code>$qx->{{l/ver/fx|HasIt}}()</code> is much less ambiguous in intent than <code>![https://www.php.net/manual/en/function.is-null.php is_null]($x)</code>.
==History==
==History==
* '''{{fmt/date|2024|07|18}}''' starting this from scratch to replace the awkward double-wrapper Wrap and Core class-family.
* '''{{fmt/date|2024|07|18}}''' starting this from scratch to replace the awkward double-wrapper Wrap and Core class-family.
* '''{{fmt/date|2025|01|14}}''' Decided `SetIt_from[O]Array()` should specifically *not* save a reference, because that can cause problems if the value is set elsewhere, or if we're trying to let go of the array to save memory.
* '''{{fmt/date|2025|01|14}}''' Decided <code>SetIt_from[O]Array()</code> should specifically ''not'' save a reference, because that can cause problems if the value is set elsewhere, or if we're trying to let go of the array to save memory.
* '''{{fmt/date|2025|04|20}}''' Renamed `RefFromOArrElem()` -> `WithOAElement()`, for consistency with `FromOAElement()`
* '''{{fmt/date|2025|04|20}}''' Renamed <code>RefFromOArrElem()</code> -> <code>{{l/ver/fx|WithOAElement}}()</code>, for consistency with <code>{{l/ver/fx|FromOAElement}}()</code> (see <code>{{l/ver/fx|From*}}()</code>)
* '''{{fmt/date|2025|04|24}}''' Restored `FromValue()` from code removed on 04/14.
* '''{{fmt/date|2025|04|24}}''' Restored <code>{{l/ver/fx|FromValue}}()</code> from code removed on 04/14.
* '''{{fmt/date|2025|05|11}}''' Changed some terminology:
* '''{{fmt/date|2025|05|11}}''' Changed some terminology:
** <code>[From/With]AElement()</code> -> <code>[From/With]AValue()</code>
** <code>[From/With]AElement()</code> -> <code>[From/With]AValue()</code>

Revision as of 14:14, 26 November 2025

clade: Data\Mem\QVar
Clade Family
StandardBase QVar
Clade Aliases
Alias Clade
Base* [c,i] Aux\StandardBase
StaticTypes Data\Mem\Val\Types
ArrayOptsEnum Data\Mem\QVar\opts\Array
ArrayIface Sys\Data\Things\Array
Subpages

About

  • Purpose: queryable var-wrapper objects

The idea here is that I wanted to be able to indicate whether a value {exists, has been set, etc.} without relying on a coding convention (the most obvious/common being the use of NULL to indicate that a value is unavailable). While "NULL=unavailable" is not a bad convention (and I still use it occasionally), it feels klugey to rely on it too much -- while providing an object to wrap the results is both semantic: $qx->HasIt() is much less ambiguous in intent than !is_null($x).

History

  • 2024-07-18 starting this from scratch to replace the awkward double-wrapper Wrap and Core class-family.
  • 2025-01-14 Decided SetIt_from[O]Array() should specifically not save a reference, because that can cause problems if the value is set elsewhere, or if we're trying to let go of the array to save memory.
  • 2025-04-20 Renamed RefFromOArrElem() -> WithOAElement(), for consistency with FromOAElement() (see From*())
  • 2025-04-24 Restored FromValue() from code removed on 04/14.
  • 2025-05-11 Changed some terminology:
    • [From/With]AElement() -> [From/With]AValue()
    • [From/With]OAElement() -> [From/With]OAValue()
    ...and added [From/With]AIndex()

Code

interface iQVar extends BaseIface {

    // SETUP
    static function AsNew() : self;
    static function FromVarRef(&$v) : self;
    static function FromAValue(array $ar, int|string $vKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : self;
    static function FromOAValue(ArrayIface $oa, int|string $vKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : self;

    // ACCESS: typeless
    function HasIt() : bool;
    function ZapIt();
    function TypeOk(mixed $v) : bool;

    function WithOAValue(ArrayIface $oa, int|string $key, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : void;

    // ++ ACCESS: basic types ++ //

    //// - int

    function HasInt() : bool;
    function SetInt(int $n);
    function SetIntNz(?int $n);
    function &GetInt() : int;
    function GetIntNz(int $nDefault=0) : int;
    function RefInt(int &$n) : void;

    //// - string

    function HasStr() : bool;
    function SetStr(string $s);
    function SetStrNz(?string $s);
    function &GetStr() : string;
    function GetStrNz(string $sDefault='', string $sPfx='', string $sSfx='') : string;
    function RefStr(string &$s) : void;

    //// - object

    function HasObj() : bool;
    function SetObj(object $o);
    function SetObjNz(?object $o);
    function GetObj() : object;
    function GetObjNz(object $oDefault=NULL) : ?object;

    /*
    // ACCESS: undeclarable
    // These can't be declared because their types change in each podling. "mixed" is replaced by the corresponding type.

    function SetIt(mixed $n);
    function SetItNz(?mixed $v);
    function &GetIt() : mixed;
    function GetItNz(mixed $vDefault=0) : mixed;
    function RefIt(mixed &$v) : void;

    function SetDefault(mixed $n);
    */
}

/**
 * NOTE:
 *  2024-07-19 There is an implied SetIt(variant) method, but we can't declare it here
 *    because that would prevent $v from having a required type.
 */
trait tQVar {

    // ++ SETUP ++ //

    public static function AsNew() : iQVar { return new static; }
    public static function FromVarRef(&$v) : iQVar {
        $oThis = new static;
        $oThis->RefIt($v);
        return $oThis;
    }
    public static function FromValue(mixed $v) : iQVar {
        $oThis = new static;
        $oThis->SetIt($v);
        return $oThis;
    }
    public static function FromAIndex(array $ar, int|string $vKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : iQVar {
        $oThis = new static;
        $oThis->WithAIndex($ar,$key,$eOpt);
        return $oThis;
    }
    public static function FromAValue(array $ar, int|string $vKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : iQVar {
        $oThis = new static;
        $oThis->WithAValue($ar,$key,$eOpt);
        return $oThis;
    }
    public static function FromOAValue(ArrayIface $oa, int|string $key, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : iQVar {
        $oThis = new static;
        $oThis->WithOAValue($oa,$key,$eOpt);
        return $oThis;
    }

    // -- SETUP -- //
    // ++ ACCESS: typeless ++ //

    protected $v = NULL;
    public function ZapIt()          { $this->v = NULL; }

    protected function WithAIndex(array $ar, int|string $snKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : void {
        $isFnd = FALSE;
        if (array_key_exists($snKey,$ar)) {
            $this->SetIt($snKey);
        }
    }

    public function WithAValue(array $ar, int|string $snKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : void {
        $isFnd = FALSE;
        if (array_key_exists($snKey,$ar)) {
            $vDup =& $ar[$snKey];
            $isFnd = $this->TypeOk($vDup);
        }
        if (!$isFnd) {
            $isFnd = $this->HandleAbsent($snKey,$eOpt);
        }
        if ($isFnd) {
            $this->RefIt($vDup);
        }
    }
    public function WithOAValue(ArrayIface $oa, int|string $snKey, ArrayOptsEnum $eOpt=ArrayOptsEnum::Nothing) : void {
        $isFnd = FALSE;
        if ($oa->HasIt($snKey)) {
            $vDup =& $oa->GetRef($snKey);
            $isFnd = $this->TypeOk($vDup);
        }
        if (!$isFnd) {
            $isFnd = $this->HandleAbsent($snKey,$eOpt);
        }
        if ($isFnd) {
            $this->RefIt($vDup);
        }
    }
    protected function HandleAbsent(int|string $snKey, ArrayOptsEnum $eOpt) : bool {
        $isFnd = FALSE;
        switch($eOpt) {
          case ArrayOptsEnum::MakeElem:
            $vDup = $oa->MakeIt($snKey);  // create an entry for the key so we can RefIt
            $isFnd = TRUE;
            echo " - used MakeIt($snKey)".CRLF;
            break;
          case ArrayOptsEnum::ZapLocal:
            $this->ZapIt();
            echo " - used ZapIt()".CRLF;
            break;
        }
        return $isFnd;
    }

    // ++ ACCESS: basic types ++ //

    //// - int

    public function HasInt() : bool           { return is_int($this->v); }
    public function SetInt(int $n)            { $this->v = $n; }
    public function SetIntNz(?int $n)         { if (is_int($n)) { $this->SetInt($n); } else { $this->ZapIt(); } }
    public function &GetInt() : int           { return $this->v; }
    public function GetIntNz(int $nDefault=0) : int { return $this->HasInt() ? $this->v : $nDefault; }
    public function RefInt(int &$n) : void { $this->v =& $n; }

    //// - string

    public function HasStr() : bool      { return is_string($this->v); }
    public function SetStr(string $s)    { $this->v = $s; }
    public function SetStrNz(?string $s) { if (is_string($s)) { $this->SetStr($s); } else { $this->ZapIt(); } }
    public function &GetStr() : string   { return $this->v; }
    public function GetStrNz(
      string $sDefault='',
      string $sPfx='',
      string $sSfx=''
      ) : string { return ($this->HasStr() ? ($sPfx.$this->v.$sSfx) : $sDefault); }
    public function GetStrNzN(
      string $sDefault=NULL,
      string $sPfx='',
      string $sSfx=''
      ) : ?string { return ($this->HasStr() ? ($sPfx.$this->v.$sSfx) : $sDefault); }
    public function RefStr(string &$s) : void { $this->v =& $s; }

    //// - object

    public function HasObj() : bool                             { return is_object($this->v); }
    public function SetObj(object $o)                           { $this->v = $o; }
    public function SetObjNz(?object $o)                        { if (is_object($o)) { $this->SetObj($o); } else { $this->ZapIt(); } }
    public function GetObj() : object                           { return $this->v; }
    public function GetObjNz(object $oDefault=NULL) : ?object   { return $this->HasObj() ? $this->v : $oDefault; }

    // -- ACCESS -- //
}
abstract class caQVar extends BaseClass implements iQVar {
    use tQVar;
}