-
Notifications
You must be signed in to change notification settings - Fork 0
objects.scad
Functions for creating and accessing object-like lists.
Note: throughout this LibFile, we refer to things as Objects. I wish they were real, blessed, official capital-O Objects, and they're not. See this project's HOWTO wiki for a quick-start, minimum number of steps to get this into your OpenSCAD modules.
To use, add the following lines to the beginning of your file:
include <openscad_objects/objects.scad>
-
Section: Base Object Functions & Usage
-
Object()
– Create a generic Object -
obj_is_obj()
– Test to see if a given value could be an Object -
obj_is_valid()
– Deeply test an Object to ensure its data types are consistent -
obj_debug_obj()
– Given an Object, return a single string that describes the Object -
obj_has()
– Test to see if an Object has a particular attribute -
obj_has_value()
– Test to see if an Object has any data in it -
obj_get_names()
– Get a list of all the attribute names in the Object -
obj_get_values()
– Get a list of all the values in the Object -
obj_get_values_by_attrs()
– Get a list of values from the Object in arbitrary order -
obj_get_defaults()
– Get a list of all the attribute defaults in the Object
-
-
-
obj_accessor()
– Generic read/write attribute accessor -
obj_accessor_get()
– Generic read-only attribute accessor -
obj_accessor_set()
– Generic write-only attribute accessor -
obj_accessor_unset()
– Generic attribute deleter
-
-
Section: Managing Lists of Objects
-
obj_select()
– Select Objects from a list based on their position in that list -
obj_select_by_attr_defined()
– Select Objects from a list if they have a particular attribute defined -
obj_select_by_attr_value()
– Select Objects from a list based on the value of a specified attribute -
obj_sort_by_attribute()
– Sort a list of Objects based on a specified attribute -
obj_select_values_from_obj_list()
– Get a list of values for one attribute out of a list of Objects -
obj_regroup_list_by_attr()
– Group a list of Objects based on a specified attribute -
obj_select_by_attrs_values()
– Select Objects from a list based on one or more sets of attribute-value pairs -
obj_list_debug_obj()
– Runobj_debug_obj()
against a list of Objects
-
-
Section: Object Attribute Data Types
-
ATTRIBUTE_DATA_TYPES
– Known data types -
obj_data_type_is_valid()
– Test to see if the attribute of a given Object data type is valid -
data_type_is_valid()
– Test to see if a given data type is valid -
obj_type_check_value()
– Test if a specified Object attribute matches its data type -
test_value_type()
– Test if a data value matches its data type
-
These functions assist the creating and usage of object-like lists: "Objects".
Objects have two basic parts: a list of attributes, their types, and default values; and, a list of values for those attributes.
object = [
TOC,
value_1,
value_N
];
The list of attributes, their data types, and their default values are all stored in the first element in the Object list: this is the table-of-contents (or "TOC"). The TOC is itself a list, and each element in the TOC list is an attribute defintion. After the TOC, each element in the Object list is the value of the attributes listed in the definition.
The functions in this section deal with creating the Object, and with its validity.
Synopsis: Create a generic Object
See Also: obj_debug_obj(), ATTRIBUTE_DATA_TYPES
Usage:
- object = Object(name, attrs);
- object = Object(name, attrs, <vlist=vlist>, <mutate=object>);
Description:
Given an Object name as a string name
, a list of attributes attrs
,
optionally a list of variable-listed values vlist
, and optionally an existing
Object to model against mutate
, create and return an Object-like list object
.
This Object will be a list that is len(attrs) + 1
elements long: the first element
will be a table-of-contents element containing the names and data types of each attribute;
the remaining elements will be the values assigned to those attributes.
Defining what attributes the Object has with attrs
:
The attrs
argument is a list of attribute names, and optionally data types and defaults,
upon which the Object will be modeled. Each element in attrs
is either a string or a list.
In string form, the attribute's defining format is:
name[=data_type[=default]]
, where name
is the name of the attribute; and, data_type
is
one of the supported data types listed below in ATTRIBUTE_DATA_TYPES
; and, default
is
a default value for that attribute.
Object_Attributes = [
"a1=s", // defines "a1", a string attribute
"a2=i=10" // defines "a2", an integer attribute, with a default of 10
];
When using the list form to define attributes, the attribute's defining format is a three-element list:
[name, data_type, default]
. The three elements directly map to those in the string
format. Using a list format is required when the default
is not easily represented in a
simple string (such as when the default is a list itself, or an object, or a pre-defined
constant such as PI
or CENTER
).
Object_Attributes = [
["a1", "s"], // defines "a1", a string attribute
["a2", "i", 10], // defines "a2", an integer attribute, with a default of 10
["a3", "l", [1, 2, 3]], // defines "a3", a list attribute, with a default list
];
Pre-populating Objects with values with vlist
:
The vlist
listing argument to Object()
is a variable list of [attribute, value]
lists.
Attribute pairs given in vlist
can be in any order. Attribute pairs may not be repeated.
Unspecified attributes will be set to undef
.
Modelling Objects from other Objects with mutate
:
Optionally, an existing, similar Object can be provided via the mutate
argument: that
existing Object list will be used as the original set of Object attribute values, with any
new values provided in vlist
taking precedence.
Arguments:
By Position | What it does |
---|---|
name |
The "name" of the object (think "classname"). No default. |
attrs |
The list of known attributes, and optionally their type and default for this object. No default. |
By Name | What it does |
---|---|
vlist |
Variable list of attributes and values: [ ["a1", 10], ["a2", "none"] ] ; or, a list of running attribute value pairing: ["a1", 10, "a2", "none"] . Default: [] (which will produce an Object with no values). |
mutate |
An existing Object of a similar name type on which to pre-set values. Default: []
|
Object()
returns a list that should be treated as an opaque object: reading values directly
from the object
list, or modifying them manually into a new list, is not entirely safe.
Example 1: empty object creation: this is an empty object that has no values assigned to its attributes:
include <openscad_objects/objects.scad>
obj = Object("Obj", ["attr1=i", "attr2=s", "attr3=b=true"]);
echo(obj);
// emits: ECHO: [["Obj", ["attr1", "i", undef], ["attr2", "s", undef], ["attr3", "b", true]], undef, undef, undef]
Example 2: same empty object creation, but with the object shown with obj_debug_obj()
. Note that while attr3
has a default value set, all of the attributes are still undefined:
include <openscad_objects/objects.scad>
obj = Object("Obj", ["attr1=i", "attr2=s", "attr3=b=true"]);
echo(obj_debug_obj(obj));
// emits: ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): undef
// 2: attr2 (s: undef): undef
// 3: attr3 (b: true): undef"
Example 3: pre-populating object attributes at creation. Note the values set for attr2
and attr3
:
include <openscad_objects/objects.scad>
o = Object("Obj", ["attr1=i", "attr2=s", "attr3=b=true"], [["attr2", "hello"], ["attr3", false]]);
echo(obj_debug_obj(o));
// emits: ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): undef
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
Example 4: pre-populating just as above, with the same attributes and values, but with a simpler vlist
:
include <openscad_objects/objects.scad>
o = Object("Obj", ["attr1=i", "attr2=s", "attr3=b=true"], ["attr2", "hello", "attr3", false]);
echo(obj_debug_obj(o));
// emits: ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): undef
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
Example 5: using mutate
will carry values from a previous Object into a new one, with vlist
values taking precedence:
include <openscad_objects/objects.scad>
O_attrs = ["attr1=i", "attr2=s", "attr3=b=true"];
o = Object("Obj", O_attrs, [["attr2", "hello"], ["attr3", false]]);
echo(obj_debug_obj(o));
o2 = Object("Obj", O_attrs, vlist=["attr1", 12], mutate=o);
echo(obj_debug_obj(o2));
// emits:
// ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): undef
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
// ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): 12
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
Example 6: when using mutate
, you can specify an empty attrs
list: the attributes will be carried over from the mutated Object:
include <openscad_objects/objects.scad>
O_attrs = ["attr1=i", "attr2=s", "attr3=b=true"];
o = Object("Obj", O_attrs, [["attr2", "hello"], ["attr3", false]]);
echo(obj_debug_obj(o));
o2 = Object("Obj", [], vlist=["attr1", 12], mutate=o); // <-- an empty `attrs` list specified
echo(obj_debug_obj(o2));
// emits:
// ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): undef
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
// ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): 12
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
Synopsis: Test to see if a given value could be an Object
Usage:
- bool = obj_is_obj(obj);
Description:
Given a thing, possibly an Object, returns true if that thing can be considered an Object, of any type.
To be considered an Object, a thing must: be a list; have a zeroth element defined; have a length that is the same length as its zeroth element; and, whose sub-list elements under its zeroth element have the same depth and count.
If the thing matches those requirements, obj_is_obj()
returns true
; otherwise, it will return false
.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list (potentially). No default. |
It is not an error to test for an object and have it return false
.
Example 1: a positive test for an Object with obj_is_obj()
:
include <openscad_objects/objects.scad>
obj = Object("Obj", ["attr=i"]);
echo(obj_is_obj(obj));
// emits: ECHO: true
Example 2: a false test for an Object:
include <openscad_objects/objects.scad>
echo(obj_is_obj(1));
// emits: ECHO: false
Synopsis: Deeply test an Object to ensure its data types are consistent
Usage:
- bool = obj_is_valid(obj);
Description:
Given an object obj
, returns true
if the object is "valid", and false
otherwise. "Valid" in this
context means the object is an object (as per obj_is_obj()
); and, has at least one attribute element; whose
attributes all have a valid type assigned; and, whose attributes with values all match their specified types.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
It is not an error to test for an object and have it return false
.
Synopsis: Given an Object, return a single string that describes the Object
Usage:
- string = obj_debug_obj(obj);
- string = obj_debug_obj(obj, <show_defaults=true>, <sub_defaults=false>);
Description:
Given an object obj
, return a string string
of debug layout information
of the object. Nested objects within the object will also
be expanded with a visual indent.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
By Name | What it does |
---|---|
show_defaults |
If enabled, then TOC-provided defaults will be shown alongside the attribute data types. Default: true
|
sub_defaults |
If enabled, then TOC-provided defaults will be shown as the attribute's value, if the value is not set. Default: false
|
obj_debug_obj()
does not output this debugging information anywhere: it's up
to the caller to do this.
Example 1:
include <openscad_objects/objects.scad>
O_attrs = ["attr1=i", "attr2=s", "attr3=b=true"];
o = Object("Obj", O_attrs, [["attr2", "hello"], ["attr3", false]]);
echo(obj_debug_obj(o));
// emits:
// ECHO: "0: _toc_: Obj
// 1: attr1 (i: undef): undef
// 2: attr2 (s: undef): hello
// 3: attr3 (b: true): false"
Synopsis: Test to see if an Object has a particular attribute
Usage:
- bool = obj_has(obj, name);
Description:
Given an object obj
and an accessor name name
, return true
if the object "can" access
that name, or false
otherwise. An object need not have a specified value for the given name,
only the ability to access and refer to it; in other words, if the name
exists in the Object's
TOC, then obj_has()
will return true.
Essentially, this is a thinly wrapped obj_toc_get_attr_names()
.
This might seem similar way to perl5's can()
or python's callable()
, but this is inaccurate:
obj_has()
cannot test if the object is able to execute or call the given name
; it can only
tell if the object has the given name
as an attribute. The perl5 exists()
or python hasattr()
functions would be more analagous to obj_has()
.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
A string that may exist as an attribute for the Object. No default. |
Example 1:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i=10", "a2=i", "a3=i=13"], ["a1", 10, "a2", 12, "a3", 23]);
b = obj_has(obj, "a1");
// b == true
Example 2:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i=10", "a2=i", "a3=i=13"], ["a1", 10, "a2", 12, "a3", 23]);
b = obj_has(obj, "radius");
// b == false
Synopsis: Test to see if an Object has any data in it
Usage:
- bool = obj_has_value(obj);
Description:
Given an object obj
, return true
if any one of its attributes are defined. If no attributes
have a value defined, obj_has_value()
returns false
.
obj_has_value()
does not evaluate the values of an object using any accessors, there is no
conditional evaluation of the values done: objects that provide accessors with defaults
won't use those accessors here, and unset attribute values will be considered undefined.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
Example 1:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i=10", "a2=i", "a3=i=13"], ["a1", 10, "a2", 12, "a3", 23]);
retr = obj_has_value(obj);
// retr == `true`
Example 2:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i=10", "a2=i", "a3=i=13"]);
retr = obj_has_value(obj);
// retr == `false`
Synopsis: Get a list of all the attribute names in the Object
Usage:
- names = obj_get_names(obj);
Description:
Given an object obj
, return the names of the attributes listed in its TOC as a
list names
. Names are returned in the order in which they are stored in the Object.
obj_get_names()
does not return the Object's TOC.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
Example 1:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i", "a3=i"], ["a1", 10, "a2", 12, "a3", 23]);
names = obj_get_names(obj);
// names == ["a1", "a2", "a3"];
Synopsis: Get a list of all the values in the Object
Usage:
- values = obj_get_values(obj);
Description:
Given an object obj
, return the values of the attributes listed in its
TOC as a list values
. This is functionally the same as doing [for (i=[1:len(obj[0])-1]) obj[i]]
.
Values are returned in the order in which they are stored in the object.
obj_get_values()
does not return the object's TOC, so len(object) > len(obj_get_values(object))
.
obj_get_values()
does not return values via the built-in accessor obj_accessor()
, and no
value defaults or type checking is done on the values before they're returned.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
Example 1:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i", "a3=i"], ["a1", 10, "a2", 12, "a3", 23]);
values = obj_get_values(obj);
// values == [10, 12, 23];
Synopsis: Get a list of values from the Object in arbitrary order
Usage:
- values = obj_get_values_by_attrs(obj, names);
Description:
Given an object obj
and a list of attribute names names
, return the values for those
attributes as a list values
. Values are returned in the order in which they are
specified in names
.
If the attributes have no value set, and there is a list of optional defaults defaults
,
returns the value at the same position as the attribute appears in names
.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
names |
A list of attribute names. No default. |
By Name | What it does |
---|---|
defaults |
A list of default values that positionally map to the attributes in names . No default. |
It is not an error to specify an attribute name multiple times. A defaults
list that
isn't as long as a names
list will be padded to be the same length with undef
elements; however, a
defaults
list that is longer than a names
list will have its extraneous elements
ignored.
There is no type comparison for the defaults
list given to obj_get_values_by_attrs()
against the attributes in obj
.
Example 1: calling obj_get_values_by_attrs()
. Note the order of the names
differs from the Object's order:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["attr1=i", "attr2=i"], ["attr1", 5, "attr2", 10]);
values = obj_get_values_by_attrs(obj, ["attr2", "attr1"]);
// values == [10, 5]
Example 2: only one attribute is specified in names
, and only one value is returned in values
:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["attr1=i", "attr2=i"], ["attr1", 5, "attr2", 10]);
values = obj_get_values_by_attrs(obj, ["attr2"]);
// values == [10]
Example 3: with no values set in the object, undef
is returned for the attributes:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["attr1=i", "attr2=i"]);
values = obj_get_values_by_attrs(obj, ["attr1", "attr2"]);
// values == [undef, undef]
Example 4: with no value set in the object for "attr2" and no attribute defaults set in the Object, the value from defaults
is returned instead:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["attr1=i, "attr2=i"], ["attr1", 3]);
values = obj_get_values_by_attrs(obj, ["attr1", "attr2"], [4, 4]);
// values == [3, 4]
Synopsis: Get a list of all the attribute defaults in the Object
Usage:
- defaults = obj_get_defaults(obj);
Description:
Given an Object obj
, return the defaults values of the attributes listed in its
TOC as a list defaults
. Defaults are returned in the order in which they are
stored in the Object. If an attribute has no default set, its position in the
defaults
list will be undef
.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
Example 1:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i=10", "a2=i", "a3=i=13"], ["a1", 10, "a2", 12, "a3", 23]);
defaults = obj_get_names(obj);
// defaults == [10, undef, 13];
These are the Object attribute accessors; functions that "get" and "set" the attribute values in the Object.
"Getting" an attribute's value from Object is pretty easy: take the attribute name, look it up in the TOC to get its index, and use that index to get the entry from the Object. If there's no value within the Object and a default is available, return that instead. Works pretty much like every other OO model out there, easy-peasy.
axle = Object("Axle",
[["diameter", "i"], ["length", "i"]],
[["diameter", 10], ["length", undef]]
);
echo( obj_accessor_get(axle, "diameter") );
// ECHO: 10
"Setting" an attribute's value is a little more interesting, because OpenSCAD doesn't let you change a variable after it's been declared: in other languages, the data for a class or object may be altered and is liable to change, but in OpenSCAD you can't do that. So: instead of returning the new value, or a "you changed this value" success flag, setting an attribute's value returns an entirely new Object. The new Object has the newly-set attribute value, and the original Object is unmodified.
axle = Object("Axle",
[["diameter", "i"], ["length", "i"]],
[["diameter", 10], ["length", undef]]
);
echo( obj_accessor_get(axle, "length") );
// ECHO: undef
axle2 = obj_accessor_set(axle, "length", nv=30);
echo( obj_accessor_get(axle2, "length") );
// ECHO: 30
There's one mutable accessor, obj_accessor()
, that
can both get
and set
values by attribute name. There are also
two get- and set-specific accessors: obj_accessor_get()
returns attributes in a
read-only manner; and, obj_accessor_set()
returns a modifed object list after
setting the attribute to a new value. And, there is obj_accessor_unset()
, to
set a named attribute explicitly to undef
(essentially, a delete).
Synopsis: Generic read/write attribute accessor
Usage:
- obj_accessor(obj, name, <default=undef>, <nv=undef>);
Usage: to retrieve an attribute's value from an object:
- value = obj_accessor(obj, name);
- value = obj_accessor(obj, name, <default=undef>);
Usage: to set an attribute's value into an object:
- new_object = obj_accessor(obj, name, nv=new_value);
Description:
Basic accessor for object attributes. Given an object obj
and an attribute name name
, operates on that attribute.
The operation depends on what other options are passed. Calls to obj_accessor()
with an nv
(new-value) option
defined will create a new object based on obj
with the new value set for name
, and then will return that
modified object list as new_object
(a "set" operation).
Calls to obj_accessor()
without the nv
option will look the current value of name
up in the object and
return it (a "get" operation). "Get" operations can provide a default
option, for when values aren't set.
The precedence order for "gets" is: object-stored-value || default-option || object-toc-stored-default || undef
:
if the value of name
in the object is not defined, the value of the default
option passed to obj_accessor()
will be returned; if there is no default
option provided, the object's TOC default will be returned; if there is no TOC default
for the object, undef
will be returned.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
The attribute name to access. The name must be present in obj 's TOC. No default. |
By Name | What it does |
---|---|
default |
If provided, and if there is no existing value for name in the object obj , returns the value of default instead. |
nv |
If provided, obj_accessor() will update the value of the name attribute and return a new Object list. The existing Object list is unmodified.
|
_consider_toc_default_values |
If enabled, TOC-stored defaults will be returned according to the mechanics above. If disabled with false , the TOC default for a given attribute will not be considered as a viable return value. Default: true
|
It's not an error to provide both default
and nv
in the same request, but doing so will yield a warning
nonetheless. If they're both present, obj_accessor()
will act on the new value in nv
and return a new object
list, and will neither evaluate nor set the value from default
.
It's not an error to provide a nv
argument that is undef
; however, if you're unknowningly passing undef
with nv
expecting it to clear the attribute in that object, or because you thought it was set to a value, obj_accessor()
won't know what you meant to do and will act as if you wanted to "get" the value for that attribute. To explicitly
clear an object's attribute, use obj_accessor_unset()
. To explicitly set an attribute to a new value, use
obj_accessor_set()
(which will error out if nv
is not defined).
Todo:
- when getting an attribute without a value and a default is provided, do a type check on the default value before returning
Example 1: direct "get" call to obj_accessor()
:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 30]);
a1 = obj_accessor(obj, "a1");
// a1 == 30
a2 = obj_accessor(obj, "a2", default=10);
// a2 == undef
// (because `a2` is not set in `obj`, and there is no Object default, there is no value to return.)
a2_2 = obj_accessor(obj, "a2", default=10);
// a2_2 == 10
// (`a2` is still unset in the `obj` object, but `default` was provided to `obj_accessor()`, so that default of 10 is returned instead)
Example 2: direct "set" calls to obj_accessor()
:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 30]);
obj2 = obj_accessor(obj, "a1", nv=6);
// obj2 is a new object, of the same type as `obj`; its `a1` value is now 6.
// obj's `a1` value is still 30.
Example 3: gotcha when providing undef
as a new-value:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 10, "a2", 30]);
obj2 = obj_accessor(obj, "a1", nv=undef);
// obj2 == 10, because `obj_accessor()` didn't see a value for `nv`: instead of changing `a1`, the value of `a1` was returned.
Synopsis: Generic read-only attribute accessor
See Also: obj_accessor()
Usage:
- value = obj_accessor_get(obj, name, <default=undef>);
Description:
Basic "get" accessor for Objects. Given an object obj
and attribute name name
, obj_accessor_get()
will look the current
value of name
up in the object and return it as value
(a "get" operation).
obj_accessor_get()
is a simplified wrap around obj_accessor()
, and the mechanics on how values are returned
are the same. "Get" operations can provide a default
option, for when values aren't set.
The precedence order for "gets" is: object-stored-value || default-option || object-toc-stored-default || undef
:
if the value of name
in the object is not defined, the value of the default
option passed to obj_accessor_get()
will be returned; if there is no default
option provided, the object's TOC default will be returned; if there is no TOC default
for the object, undef
will be returned.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
The attribute name to access. The name must be present in obj 's TOC. No default. |
By Name | What it does |
---|---|
default |
If provided, and if there is no existing value for name in the object obj , returns the value of default instead. |
_consider_toc_default_values |
If enabled, TOC-stored defaults will be returned according to the mechanics above. If disabled with false , the TOC default for a given attribute will not be considered as a viable return value. Default: true
|
Note that obj_accessor_get()
will accept a nv
option, to make writing accessor glue easier, but
that nv
option won't be evaluated or used.
Example 1: direct calls to obj_accessor_get()
:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 30]);
value = obj_accessor_get(obj, "a1");
// value == 30
Example 2: passing nv
yields no change:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 30]);
value = obj_accessor_get(obj, "a1", nv=25);
// value == 30 (the `nv` option is ignored)
Synopsis: Generic write-only attribute accessor
See Also: obj_accessor()
Usage:
- new_object = obj_accessor_set(obj, name, nv);
Description:
Basic "set" accessor for Objects. Given an object obj
, an attribute name name
, and a new value nv
for that
attribute, obj_accessor_set()
will return a new Object list with the updated value for that attribute as new_object
.
The existing Object list is unmodified, and a wholly new Object with the new value is returned instead.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
The attribute name to access. The name must be present in obj 's TOC. No default. |
nv |
The new value to set as the new attribute. No default. |
Unlike obj_accessor()
, it is an error to call obj_accessor_set()
without a new value (nv
) passed.
If the value of the attribute name
needs to be removed, use obj_accessor_unset()
instead.
Note that obj_accessor_set()
will accept a default
option, to make writing accessor
glue easier, but it will be neither evaluated nor used.
Example 1: direct call to obj_accessor_set()
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 30]);
new_obj = obj_accessor_set(obj, "a1", nv=20);
// new_obj's `a1` attribute is now 20
Synopsis: Generic attribute deleter
Usage:
- new_obj = obj_accessor_unset(obj, name);
Description:
Basic "delete" accessor for Objects. Given an Object obj
and an attribute
name name
, a new Object will be returned
with the un-set attribute value. The existing Object list is unmodified, and a
wholly new Object list with the unset value is returned instead.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
The attribute name to access. The name must be present in obj 's TOC. No default. |
Example 1:
include <openscad_objects/objects.scad>
obj = Object("ExampleObj", ["a1=i", "a2=i"], ["a1", 30]);
new_obj = obj_accessor_unset(obj, "a1");
// new_obj's `a1` attribute is now unset
echo(obj_accessor_get(new_obj, "a1"));
// emits: ECHO: undef
These are functions to help manage lists or collections of Objects. In most cases, standard list manipulation functions work fine, but when you need to select or act on a subset of Objects based on their attribute values, turn here.
Synopsis: Select Objects from a list based on their position in that list
Usage:
- list = obj_select(obj_list, idxs);
Description:
Given a list of objects obj_list
and a list of element indexes idxs
, returns the
objects in obj_list
identified by their index position idx
as a new list list
.
The Objects need not be all of the same object type.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
idxs |
A list of positional index integers |
It's probably a really bad idea to give a list of idxs
that doesn't match the
length of obj_list
.
Todo:
- turns out this is just a very thinly wrapped select(). Is there a reason to keep this?
Synopsis: Select Objects from a list if they have a particular attribute defined
Usage:
- list = obj_select_by_attr_defined(obj_list, attr);
Description:
Given a list of Objects obj_list
and an attribute name attr
, return
all the Objects in obj_list
that have the attribute attr
defined as a list list
.
The Objects are returned in the order they appear in obj_list
.
The returned list
of Objects may not be the same length as obj_list
. The returned
list list
may have no elements in it.
The list of Objects given need not be all of the same type.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
attr |
An attribute name |
Synopsis: Select Objects from a list based on the value of a specified attribute
Usage:
- list = obj_select_by_attr_value(obj_list, attr, value);
Description:
Given an list of Objects obj_list
, an attribute name attr
, and a comparison value value
, return
all Objects in obj_list
whose value for attr
matches value
as a list list
.
The Objects are returned in the order they appear in obj_list
.
The Objects in obj_list
need not be all of the same type.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
attr |
An attribute name |
value |
A comparison value |
Synopsis: Sort a list of Objects based on a specified attribute
Usage:
- list = obj_sort_by_attribute(obj_list, attr);
Description:
Given a list of Objects obj_list
and an attribute name attr
, sort the list
of objects by the value of their attribute attr
and return that list.
Objects listed in obj_list
need not be all of the same type.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
attr |
An attribute name |
Synopsis: Get a list of values for one attribute out of a list of Objects
Usage:
- list = obj_select_values_from_obj_list(obj_list, attr);
- list = obj_select_values_from_obj_list(obj_list, attr, <default=undef>);
Description:
Given a list of Objects obj_list
and an attribute name attr
, return
a list of all the values of attr
in the Objects in obj_list
. The
values are returned in the order they appear in obj_list
.
The Objects in obj_list
need not be all the same type.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
attr |
An attribute name |
By Name | What it does |
---|---|
default |
A value to be used as a default for Objects that do not have their attribute attr set. Default: undef
|
Synopsis: Group a list of Objects based on a specified attribute
Usage:
- list = obj_regroup_list_by_attr(obj_list, attr);
Description:
Given a list of Objects obj_list
and an attribute name attr
,
return a list of groups of the Objects in obj_list
grouped
by defined and unique values of attr
.
The groupings of Objects are returned in no particular order.
Objects listed in obj_list
need not be all of the same type.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
attr |
An attribute name |
If an Object within obj_list
has the attribute attr
but
it is neither defined nor has a default value, it will not
be grouped. Grouping Objects with an undef
value for the
attribute is something that'd be nice; however, the
functions obj_regroup_list_by_attr()
depends on do not
today support selecting Objects on an undefined attribute.
Synopsis: Select Objects from a list based on one or more sets of attribute-value pairs
See Also: obj_select_by_attr_value()
Usage:
- list = obj_select_by_attrs_values(obj_list, arglist);
Description:
Given a list of Objects obj_list
and a list of selectors arglist
,
recursively examine obj_list
to select items that match each selector, and
return those elements as list
. The elements in list
are returned in
the order they appear in obj_list
.
For obj_select_by_attrs_values()
, the arglist
list of selectors is a collection of [attr, value]
lists that are used to exclude items from obj_list
. attr
is the object attribute
to examine, and value
is the value that it must match in order to be returned.
In brief, obj_select_by_attrs_values()
is calling obj_select_by_attr_value()
for each pairing in arglist
against the same obj_list
over and over, ideally
reducing the number of elements in obj_list
to get the desired set. (You could
probably achieve the same by getting the results of obj_select_by_attr_value()
for each selector, and then calculating the intersection of all those results;
however, obj_select_by_attrs_values()
is probably going to be faster, since
obj_list
is likely to be shortened for each recurively-examined selector.)
The Objects in obj_list
need not be all the same type, however they all
need to support the arglist
selectors.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
arglist |
A list of [attr, value] lists, where: attr is an attribute name; and, value is a comparison value |
Synopsis: Run obj_debug_obj()
against a list of Objects
Usage:
- list = obj_list_debug_obj(obj_list);
Description:
Given a list of Objects obj_list
, run obj_debug_obj()
on each
Object, and return their output as a list.
Arguments:
By Position | What it does |
---|---|
obj_list |
A list of Objects |
Synopsis: Known data types
Description:
A list of known attribute data types. "Types" in this context are single-character symbols that indicate what the attribute is meant to hold.
Type IDs: The following data type IDs are known:
Type ID | What It Represents |
---|---|
s |
literal strings. Example: "a string" . (Note: Strings are always assigned with quotes and we show that here, but as elsewhere in OpenSCAD the quotes are not part of the string.)
|
i |
integers. Example: 1
|
b |
booleans. Example: true
|
l |
lists. There is no restriction on list length or content. Example: [1, 2, "abc"]
|
u |
undefined. Example: undef
|
o |
objects. Objects in this context lists that are expected to have a valid TOC as their first element. Example: [["Object", ["attribute", "b"]], undef]
|
Synopsis: Test to see if the attribute of a given Object data type is valid
Usage:
- bool = obj_data_type_is_valid(obj, name);
Description:
Given an Object obj
and the name of an attribute within that Object name
,
return true
if the defined data type for that attribute is valid, or
false
otherwise.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
An attribute name that exists within obj . No default. |
Synopsis: Test to see if a given data type is valid
Usage:
- data_type_is_valid(type);
Description:
Given a type, returns true
if the type is found within ATTRIBUTE_DATA_TYPES, or false otherwise.
Arguments:
By Position | What it does |
---|---|
type |
the type of data to check. No default. |
Synopsis: Test if a specified Object attribute matches its data type
See Also: test_value_type()
Usage:
- bool = obj_type_check_value(obj, name);
- bool = obj_type_check_value(obj, name, <value=value>);
Description:
Given a valid Object obj
and the name of an attribute that exists in that Object name
,
return true
if the value stored in the Object's attribute matches the data type
set for that attribute, or false
otherwise.
A specific data value value
may be optionally provided, and obj_test_check_value()
will check that value against the attribute's data type, rather than whatever
is in the Object.
Arguments:
By Position | What it does |
---|---|
obj |
An Object list. No default. |
name |
An attribute name that exists within obj . No default. |
By Name | What it does |
---|---|
value |
A value to compare against name 's data type. Default: undef (meaning the Object's attribute value will be checked) |
Todo:
- figure out if we care about enforcing object types (eg,
["attr-name", "o:Axle"]
) - re-implement a proper range type
Synopsis: Test if a data value matches its data type
See Also: ATTRIBUTE_DATA_TYPES
Usage:
- bool = test_value_type(type_id, value);
Description:
Given a valid data type type_id
and a data value value
,
return true
if the value matches the data type, or false otherwise.
Arguments:
By Position | What it does |
---|---|
type_id |
A valid data type ID. No default. |
value |
A data value. No default. |
It is an error to specify a data type ID that does not exist within ATTRIBUTE_DATA_TYPES.