- Introduction
- str->Object Formation Using 'props{}'
- str->Object Formation Using 'props: args'
- 'props' Usage with PropObj
- PropObj.is(..):bool and args.is(..):bool
Introduction
We've entered into an era where dynamic is implied -- where behaviors change with context and operations require modularity. Every core object has transitioned to a PropObj paradigm, where dynamic capability is welcomed. Out of this transition, there has been growing demand for more flexibility within parameters and more streamlined behavior for objects utilizing these dynamic capabilities.
The 'props' concept is at its root, quite canonical -- it represents str->Object maps; their formation, translation, and re-location. It is used most often with respect to PropObj, but can be used with any function or str->Object map that is required. Below is the overview of how the syntax is used and the general ideology behind how it could be helpful.
str->Object Formation Using 'props{}'
General Usage
{ // Empty map -- props{..} always results in a str->Object map, no matter the contents. str->Object args = props{}; // Mixed type initialization. args = props{a="a", b=1, c=false, d=12., e=Vessel("e")}; // Output. pln(args.get("a")); pln(args.get("b")); pln(args.get("c")); pln(args.get("d")); pln(args.get("e")); }
Output:
a
1
false
12
Vessel(90)
Why?
A lot of objects and functions offer str->Object args=null
in various places. This is often used to add refined contextual information to an individual operation or construction. This is a nice way to not have to re-define operations when context between objects is altered (usually additional optional parameters within sub-classes). With respect to PropObj, it can also be used to initialize propData
(shown below).
str->Object Formation Using 'props: args'
General Usage
/** * Test for props: args. */ public void testA(props: args) { pln("testA"); for (k, v in args) pln(k); } /** * Test for props: args. * 'a' must be given before args can be populated. */ public void testB(str a="a", props: args) { pln("testB"); for (k, v in args) pln(k); } { // TestA testA(); // empty -- args=null testA(a="a", b=1, c=false); // TestB testB(); // empty -- args=null testB(a="a"); // just 'a' //testB(b="b"); // error, 'a' must be given first testB("a", b="b", c=1); testB(a="a", hello=Vessel("hello")); }
Output:
testA testA c a b testB testB testB c b testB hello
Why?
For objects and functions that will not be taking an already formed str->Object map, this props: args
syntax will forgo the need for the props{}
syntax. It behaves much like the rest
syntax -- creating a str->Object map that can be used for an undetermined number of keyed arguments.
'props' Usage with PropObj
PropObj is the real playground when it comes to the 'props' syntax and its capabilities. A lot of objects now fully utilize their propData. Whether it be anonymous data for local temporary retention or a formal PropDef with instructions as a quick property or animation property, these objects thrive in the dynamic CET medium.
Initialization
In the constructors for many PropObjs, there exists the str->Object args=null
or the props: args
. Although the first is more responsive to changing environments due to the added flexibility of passing an already created str->Object map, they behave much the same with respect to initializing a PropObj. These maps should directly translate to propData initialization via:
for (k, v in args) put(k, v);
In conjunction with PropDefs, this paradigm can be used to initialize fields and properties. If the object allows anonymous data (which is true by default), any passed pair will be accepted for continued utilization.
Vessel Example
In cm/core/vesselGenerics.cm, there exists the VesselAroundPos
debug Vessel. Below are code examples of how to manipulate this Vessels behavior depending on the debug context. Since all fields have CoreFieldPropDefs
, there is no need to create different constructors for different initializations or different behaviors for extended classes.
For documentation on Vessel arguments and behavioral arguments, see Vessels. For documentation on PropDefs within PropObj, see PropObjs.
/** * Init vessels. * this = RemoverAnimationG2. */ public void initVessels() { // Non-debug vessels LightRedSnapperOutline("highlight", owner=this, active=true, tags={#candidate, #highlight}); LightRedSpaceVesselOutline("vesselHighlight", owner=this, active=true, tags={#candidate, #spaceVessel}); RedCross("cross", owner=this, tags={#noCandidate, #cross}); // Debug examples -- normally only one would be used // Place one within the RemoverAnimationG2.initVessels() to test example // Blue sphere always around owner.pos VesselAroundPos("debug", owner=this, tags={#debug}, args=props{ownerPos=true, invalidAlways=true}); // Purple sphere around owner.pos VesselAroundPos("debug", owner=this, tags={#debug}, args=props{ownerPos=true, c=purple}); // No sphere but axis with text at owner.pos VesselAroundPos("debug", owner=this, tags={#debug}, args=props{ownerPos=true, axis=true, noSphere=true}); // Small red sphere at origin with axis at owner.pos with no text and larger axis radius, // with the Z axis color as black VesselAroundPos("debug", owner=this, tags={#debug}, args=props{ownerPos=true, axis=true, noSphere=true, sphereAtOrigin=true, radius3D=3inch, radius2D=2inch, c=brightRed, hideText=true, axisRadius=80inch, zc=black}); }
PropObj.is(..):bool and args.is(..):bool
Given all of this str->Object capability, there needs to be some way to easily test for what is contained within the data. This is where the is(..)
functions come into the 'props' world. This comes in extremely handy when checking for additional arguments or when testing against a value housed in propData (pretty cool for animation properties and quick properties also). For an example use case, look at the Vessel behavioral arguments (Vessel.update():bool
).
// Initialization of map str->Object myArgs = props{a=true, b=false, c="c", d=1.}; // Initialization of PropObj with args Vessel myVessel("testVessel", args=myArgs); // PropObj.is(..) -- propData // "a" myVessel.is("a") => true; myVessel.is("a", false) => false; myVessel.is("a", true) => true; myVessel.is("a", 2) => false; // "b" myVessel.is("b") => false; // Can only be false if b does not exist or the value is false myVessel.is("b", false) => true; // Can only be true if b does not exist or the value is false myVessel.is("b", true) => false; myVessel.is("b", 2.) => false; // "c" myVessel.is("c") => true; myVessel.is("c", "c") => true; myVessel.is("c", "a") => false; // "e" myVessel.is("e") => false; myVessel.is("e", false) => true; // str->Object.is(..) -- any str->Object map // "a" myArgs.is("a") => true; myArgs.is("a", false) => false; // "b" myArgs.is("b") => false; myArgs.is("b", false) => true; myArgs.is("b", true) => false; // "c" myArgs.is("c") => true; myArgs.is("c", "c") => true; myArgs.is("c", 34) => false; // "d" myArgs.is("d") => true; myArgs.is("d", 1) => false; myArgs.is("d", 1.) => true; // "g" myArgs.is("g") => false; myArgs.is("g", false) => true;
Comments
0 comments
Please sign in to leave a comment.