OpenFlexure Microscope OpenSCAD docs
libs/libdict.scad
function _is_in_str(value, list)
[Source]
function _is_in_str(value, list) = search([value], list) != [[]];
function _is_in_num(value, list)
[Source]
function _is_in_num(value, list) = search(value, list) != [];
function is_in(value, list)
[Source]
function is_in(value, list) = assert(is_num(value) || is_string(value) , "is_in: value must be a number or string") assert(is_list(list), "is_in: list must be a list") is_num(value) ? _is_in_num(value, list) : _is_in_str(value, list);
function _libdict_sum_list(list, starting_element=0, running_total=0)
[Source]
function _libdict_sum_list(list, starting_element=0, running_total=0) = starting_element >= len(list) ? running_total : _libdict_sum_list(list, starting_element + 1, running_total + list[starting_element]);
* * Sum a list * This recursive function sums a list. It should be called with one * argument (the list); the other two arguments simply allow it to be * "tail-recursive" which lets OpenSCAD optimise it better. This is * very close to the example given in the OpenSCAD docs.
function _check_errant_match(list, match)
[Source]
function _check_errant_match(list, match) = let( non_list = [for (m = match) is_list(list[m])? 0 : 1], number_of_non_lists = _libdict_sum_list(non_list) ) number_of_non_lists == 1 ? 0 : 1;
*
* When checking a list for uniqueness, we can get "errant matches".
* An errant match is when a non-list matches with the first element in a list.
* i.e. it would consider [1, [1,0]] to be non-unique. We cannot know which
* element is the non-list but we do know that it is errant if exactly one
* of them is not a list.
* If two elements are non-lists, they must be identical in order to have matched.
* Similarly, if all elements are lists, they must be identical because search
* will have matched them as whole lists.
* The argument "list" is the list we are checking for uniqueness, and "match" is
* a vector of indices that have been returned by search.
function is_unique(list)
[Source]
function is_unique(list) = assert(is_list(list), "is_unique: list must be a list") let( matches = search(list, list, 0), // Assign 1 or 0 depending on is the match length for each element // return wether any matches are greater than one (mathcing more than // itself) // note cannot search for true or false so using 1 and zero bool_list = [for (match = matches) if (len(match)==1) 0 // should put a 1 here to show they matched but in the case of // [1, [1]] it will match both, so need to check if they are // both lists or both not list else _check_errant_match(list, match)] ) !is_in(1, bool_list);
function _is_pairs(list)
[Source]
function _is_pairs(list) = !is_list(list) ? false : len(list)==0 ? false : !is_in(0, [for (pair = list) is_list(pair) && len(pair)==2 ? 1: 0]);
function _is_list_of_strings(list)
[Source]
function _is_list_of_strings(list) = !is_in(0, [for (item = list) is_string(item) && len(item)>0 ? 1: 0]);
function _keylist(dict)
[Source]
function _keylist(dict) = [for (pair=dict) pair[0]];
function valid_dict(dict)
[Source]
function valid_dict(dict) = //if the input are not pairs return instantly !_is_pairs(dict) ? false : let ( //if they are pairs get all keys keys = _keylist(dict), all_strings = _is_list_of_strings(keys), unique = is_unique(keys) ) (all_strings && unique) ? true : false;
function key_lookup(key, dict)
[Source]
function key_lookup(key, dict) = assert(is_string(key), "`key` must be a string") assert(valid_dict(dict), "`dict` must be a valid 'dictionary'") let( // key is in [] because otherwise openscad will search for each letter rather than the string. index = search([key], dict, 1, 0)[0] ) assert (index!=[], "Key lookup failed, key not found!") dict[index][1];
function replace_value(key, value, dict)
[Source]
function replace_value(key, value, dict) = assert(is_string(key), "`key` must be a string") assert(valid_dict(dict), "`dict` must be a valid 'dictionary'") assert(is_in(key, _keylist(dict)), "`key` not found in dictionary!") [for (kv_pair = dict) key!=kv_pair[0] ? kv_pair : [key, value]];
function replace_multiple_values(rep_dict, dict)
[Source]
function replace_multiple_values(rep_dict, dict) = assert(valid_dict(rep_dict), "`rep dict` must be a valid 'dictionary'") assert(valid_dict(dict), "`dict` must be a valid 'dictionary'") let( // loop over all keys in replacement dict checking they are in the original rep_keys = [for (key = _keylist(rep_dict)) assert(is_in(key, _keylist(dict)), "`key` not found in dictionary!") key ] ) //Finally return the updated dictionary using this long list comprehension. [ for (kv_pair = dict) let( key = kv_pair[0], // check if this key is in the replacement dictionary and if so return index // key is in [] because otherwise openscad will search for each letter rather // than the string. index = search([key], rep_dict, 1, 0)[0] // if index is empty return original key value pair, else return the key with // the replaced value ) index == [] ? kv_pair : [key, rep_dict[index][1]] ];