omdl  v0.9.5
OpenSCAD Mechanical Design Library
iterable_operate.scad
Go to the documentation of this file.
1 //! Iterable data type operations.
2 /***************************************************************************//**
3  \file
4  \author Roy Allen Sutton
5  \date 2015-2023
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28  \details
29 
30  \amu_define group_name (Iterable Operations)
31  \amu_define group_brief (Operations for iterable data types.)
32 
33  \amu_include (include/amu/pgid_path_pstem_pg.amu)
34 *******************************************************************************/
35 
36 //----------------------------------------------------------------------------//
37 // validation.
38 //----------------------------------------------------------------------------//
39 
40 /***************************************************************************//**
41  \amu_include (include/amu/validate_log_th.amu)
42  \amu_include (include/amu/validate_log_td.amu)
43  \amu_include (include/amu/validate_results.amu)
44 *******************************************************************************/
45 
46 //----------------------------------------------------------------------------//
47 // group.
48 //----------------------------------------------------------------------------//
49 
50 /***************************************************************************//**
51  \amu_include (include/amu/group_in_parent_start.amu)
52  \amu_include (include/amu/includes_required.amu)
53 
54  \details
55 
56  \amu_define group_references
57  (
58  [search]: https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#search
59  )
60 
61  \amu_include (include/amu/validate_summary.amu)
62 *******************************************************************************/
63 
64 //----------------------------------------------------------------------------//
65 
66 //! Return an element of an iterable when it exists or a default value otherwise.
67 /***************************************************************************//**
68  \param v <iterable> An iterable value.
69  \param i <integer> An element index.
70  \param d <value> A default value.
71 
72  \returns (1) <value> <tt>v[i]</tt> when it is defined or \p d
73  otherwise.
74 *******************************************************************************/
75 function defined_e_or
76 (
77  v,
78  i,
79  d
80 ) = !is_iterable(v) ? d
81  : !is_undef( v[i] ) ? v[i]
82  : d;
83 
84 
85 //! Find the occurrences of a match value in an iterable value.
86 /***************************************************************************//**
87  \param mv <value> A match value.
88  \param v <iterable> An iterable value.
89  \param c <integer> A match count.
90  For <tt>(c>=1)</tt>, return the first \p c matches.
91  For <tt>(c<=0)</tt>, return all matches.
92  \param i <integer> The secondary element index to match for when
93  the elements of \p v are themselves iterable elements.
94 
95  \param i1 <integer> The element index of \p v where the search begins.
96  \param i2 <integer> The element index of \p v where the search ends.
97 
98  \returns (1) <list> A list of indexes where elements match \p mv.
99  (2) Returns \b empty_lst when no element of \p v matches
100  \p mv or when \p v is not iterable.
101 
102  \details
103 
104  The use-cases for find() and [search]\‍() are summarized in the
105  following tables.
106 
107  \b Find:
108 
109  | mv / v | string | list of scalars | list of iterables |
110  |---------------------|:------:|:-----------------:|:-------------------:|
111  | scalar | | (a) | (b) see note 1 |
112  | string | (c) | | (b) see note 1 |
113  | list of scalars | | | (b) see note 1 |
114  | list of iterables | | | (b) see note 1 |
115 
116  \b Search:
117 
118  | mv / v | string | list of scalars | list of iterables |
119  |---------------------|:------:|:-----------------:|:-------------------:|
120  | scalar | | (a) | (b) |
121  | string | (d) | invalid | (e) see note 2 |
122  | list of scalars | | (f) | (g) |
123  | list of iterables | | | (g) |
124 
125  \b Key:
126 
127  \li (a) Identify each element of \p v that equals \p mv.
128  \li (b) Identify each element of \p v where \p mv equals the element at
129  the specified column index, \p i, of each iterable value in \p v.
130  \li (c) If, and only if, \p mv is a single character, identify each
131  character in \p v that equals \p mv.
132  \li (d) For each character of \p mv, identify where it exists in \p v.
133  \b empty_lst is returned for each character of \p mv absent from \p v.
134  \li (e) For each character of \p mv, identify where it exists in \p v
135  either as a numeric value or as a character at the specified column
136  index, \p i.
137  \b empty_lst is returned for each character of \p mv absent from \p v.
138  \li (f) For each scalar of \p mv, identify where it exists in \p v.
139  \b empty_lst is returned for each scalar of \p mv absent from \p v.
140  \li (g) For each element of \p mv, identify where it equals the element
141  at the specified column index, \p i, of each iterable value in \p v.
142  \b empty_lst is returned for each element of \p mv absent from \p v
143  in the specified column index.
144 
145  \note \b 1: When \p i is specified, that element column is compared.
146  Otherwise, the entire element is compared. Functions find()
147  and [search]\‍() behave differently in this regard.
148  \note \b 2: Invalid use combination when any element of \p v is a
149  string. However, an element that is a list of one or more
150  strings is valid. In which case, only the first character of
151  each string element is considered.
152 
153  \amu_eval (${group_references})
154 *******************************************************************************/
155 function find
156 (
157  mv,
158  v,
159  c = 1,
160  i,
161  i1 = 0,
162  i2
163 ) = !is_iterable(v) ? empty_lst // not iterable
164  : (!is_undef(i2) && (i1 > i2)) ? empty_lst // at upper index
165  : (i1 > len(v)-1) ? empty_lst // at end of list
166  : ((is_undef(i) && (v[i1] == mv)) || (v[i1][i] == mv)) ? // match method
167  (
168  (c == 1) ? [i1] // one or all
169  : concat(i1, find(mv, v, c-1, i, i1+1, i2)) // add to list
170  )
171  : find(mv, v, c, i, i1+1, i2); // no match, cont.
172 
173 //! Count all occurrences of a match value in an iterable value.
174 /***************************************************************************//**
175  \param mv <value> A match value.
176  \param v <iterable> An iterable value.
177  \param s <boolean> Element matching search method.
178  \param i <integer> The secondary element index to match for when
179  the elements of \p v are themselves iterable elements.
180 
181  \returns (1) <integer> The number of times \p mv occurs in the list.
182 
183  \details
184 
185  When \p s == \b true, [search]\‍() is used to match elements. When
186  \p s == false, find() is used.
187 
188  \amu_eval (${group_references})
189 *******************************************************************************/
190 function count
191 (
192  mv,
193  v,
194  s = true,
195  i
196 ) = (s == false) ? len(find(mv, v, 0, i))
197  : len(merge_s(search(mv, v, 0, i)));
198 
199 //! Check for the existence of a match value in an iterable value.
200 /***************************************************************************//**
201  \param mv <value> A match value.
202  \param v <iterable> An iterable value.
203  \param s <boolean> Element matching search method.
204  \param i <integer> The secondary element index to match for when
205  the elements of \p v are themselves iterable elements.
206 
207  \returns (1) <boolean> \b true when \p mv exists in the list and
208  \b false otherwise.
209 
210  \details
211 
212  When \p s == \b true, [search]\‍() is used to match elements. When
213  \p s == false, find() is used.
214 
215  \amu_eval (${group_references})
216 *******************************************************************************/
217 function exists
218 (
219  mv,
220  v,
221  s = true,
222  i
223 ) = (s == false) ? (find(mv, v, 1, i) != empty_lst)
224  : (strip(search(mv, v, 1, i)) != empty_lst);
225 
226 //! Test if an element exists at a specified index of an iterable value.
227 /***************************************************************************//**
228  \param i <integer> An element index.
229  \param v <iterable> An iterable value.
230 
231  \returns (1) <boolean> \b true when the element \p v[i], exists and
232  \b false otherwise.
233  (2) Returns \b undef when \p i is not an number.
234 
235  \note This functions does not consider the value of the element
236  at the index position, but rather if an element exists at
237  the index position \p i.
238 *******************************************************************************/
239 function exists_e
240 (
241  i,
242  v
243 ) = !is_number( i ) ? undef
244  : (i < 0) ? false
245  : !is_iterable( v ) ? false
246  : (len(v) > i);
247 
248 //! Return the first element of an iterable value.
249 /***************************************************************************//**
250  \param v <iterable> An iterable value.
251 
252  \returns (1) <value> The first element of \p v.
253  (2) Returns \b undef when \p v is not defined, is not
254  iterable, or is empty.
255 
256  \details
257 
258  \note Value may also be a range to obtain its \em start value.
259 *******************************************************************************/
260 function first( v ) = v[0];
261 
262 //! Return the second element of an iterable value.
263 /***************************************************************************//**
264  \param v <iterable> An iterable value.
265 
266  \returns (1) <value> The second element of \p v.
267  (2) Returns \b undef when \p v is not defined, is not
268  iterable, or is empty.
269 
270  \details
271 
272  \note Value may also be a range to obtain its \em step value.
273 *******************************************************************************/
274 function second( v ) = v[1];
275 
276 //! Return the third element of an iterable value.
277 /***************************************************************************//**
278  \param v <iterable> An iterable value.
279 
280  \returns (1) <value> The second element of \p v.
281  (2) Returns \b undef when \p v is not defined, is not
282  iterable, or is empty.
283 
284  \details
285 
286  \note Value may also be a range to obtain its \em end value.
287 *******************************************************************************/
288 function third( v ) = v[2];
289 
290 //! Return the last element of an iterable value.
291 /***************************************************************************//**
292  \param v <iterable> An iterable value.
293 
294  \returns (1) <value> The last element of \p v.
295  (2) Returns \b undef when \p v is not defined, is not
296  iterable, or is empty.
297 *******************************************************************************/
298 function last
299 (
300  v
301 ) = !is_iterable(v) ? undef
302  : v[len(v)-1];
303 
304 //! Return the middle element of an iterable value.
305 /***************************************************************************//**
306  \param v <iterable> An iterable value.
307 
308  \returns (1) <value> The middle element of \p v.
309  (2) Returns \b undef when \p v is not defined, is not
310  iterable, or is empty.
311 *******************************************************************************/
312 function middle
313 (
314  v
315 ) = !is_iterable(v) ? undef
316  : v[len(v)/2];
317 
318 //! Return a list containing the first two elements of an iterable value.
319 /***************************************************************************//**
320  \param v <iterable> An iterable value.
321 
322  \returns (1) <list> A list containing the first two elements of \p v.
323  (2) Returns \b undef when \p v is not defined, is not
324  iterable, is empty or has less than two elements
325 
326  \details
327 
328  \note Value may also be a range.
329 *******************************************************************************/
330 function first2
331 (
332  v
333 ) = !is_iterable(v) ? undef
334  : (len(v) < 2) ? undef
335  : [v[0], v[1]];
336 
337 //! Return a list containing the first three elements of an iterable value.
338 /***************************************************************************//**
339  \param v <iterable> An iterable value.
340 
341  \returns (1) <list> A list containing the first three elements of \p v.
342  (2) Returns \b undef when \p v is not defined, is not
343  iterable, is empty, or has less than three elements.
344 
345  \details
346 
347  \note Value may also be a range.
348 *******************************************************************************/
349 function first3
350 (
351  v
352 ) = !is_iterable(v) ? undef
353  : (len(v) < 3) ? undef
354  : [v[0], v[1], v[2]];
355 
356 //! Return a list containing the last two elements of an iterable value.
357 /***************************************************************************//**
358  \param v <iterable> An iterable value.
359 
360  \returns (1) <list> A list containing the last two elements of \p v.
361  (2) Returns \b undef when \p v is not defined, is not
362  iterable, is empty, or has less than two elements.
363 *******************************************************************************/
364 function last2
365 (
366  v
367 ) = !is_iterable(v) ? undef
368  : let( l = len(v) )
369  (l < 2) ? undef
370  : [v[l-2], v[l-1]];
371 
372 //! Return a list containing the last three elements of an iterable value.
373 /***************************************************************************//**
374  \param v <iterable> An iterable value.
375 
376  \returns (1) <list> A list containing the last three elements of \p v.
377  (2) Returns \b undef when \p v is not defined, is not
378  iterable, is empty, or has less than three elements.
379 *******************************************************************************/
380 function last3
381 (
382  v
383 ) = !is_iterable(v) ? undef
384  : let( l = len(v) )
385  (l < 3) ? undef
386  : [v[l-3], v[l-2], v[l-1]];
387 
388 //! Return a list containing the first \p n elements of an iterable value.
389 /***************************************************************************//**
390  \param v <iterable> An iterable value.
391  \param n <integer> The element count.
392 
393  \returns (1) <list> A list containing the first \p n elements of \p v.
394  (2) Returns \b undef when \p v is not defined, is not
395  iterable, or is empty.
396 
397  \details
398 
399  When \p n is greater than the length of the iterable \p v, the list
400  will stop at the last element of \p v.
401 *******************************************************************************/
402 function firstn
403 (
404  v,
405  n = 1
406 ) = !is_iterable(v) ? undef
407  : is_empty(v) ? undef
408  : n < 1 ? empty_lst
409  : let ( s = min(n-1, len(v)-1) )
410  [for (i = [0 : s]) v[i]];
411 
412 //! Return a list containing the last \p n elements of an iterable value.
413 /***************************************************************************//**
414  \param v <iterable> An iterable value.
415  \param n <integer> The element count.
416 
417  \returns (1) <list> A list containing the last \p n elements of \p v.
418  (2) Returns \b undef when \p v is not defined, is not
419  iterable, or is empty.
420 
421  \details
422 
423  When \p n is greater than the length of the iterable \p v, the list
424  will start at the first element of \p v.
425 *******************************************************************************/
426 function lastn
427 (
428  v,
429  n = 1
430 ) = !is_iterable(v) ? undef
431  : is_empty(v) ? undef
432  : n < 1 ? empty_lst
433  : let ( s = max(0, len(v)-n) )
434  [for (i = [s : len(v)-1]) v[i]];
435 
436 //! Return a list containing all but the last \p n elements of an iterable value.
437 /***************************************************************************//**
438  \param v <iterable> An iterable value.
439  \param n <integer> The element count.
440 
441  \returns (1) <list> A list containing all but the last \p n
442  elements of \p v.
443  (2) Returns \b empty_lst when \p v contains fewer than \p n
444  elements.
445  (3) Returns \b undef when \p v is not defined, is not
446  iterable, or is empty.
447 *******************************************************************************/
448 function headn
449 (
450  v,
451  n = 1
452 ) = !is_iterable(v) ? undef
453  : is_empty(v) ? undef
454  : (n >= len(v)) ? empty_lst
455  : let ( s = min(len(v)-1, len(v)-1-n) )
456  [for (i = [0 : s]) v[i]];
457 
458 //! Return a list containing all but the first \p n elements of an iterable value.
459 /***************************************************************************//**
460  \param v <iterable> An iterable value.
461  \param n <integer> The element count.
462 
463  \returns (1) <list> A list containing all but the first \p n
464  elements of \p v.
465  (2) Returns \b empty_lst when \p v contains fewer than \p n
466  elements.
467  (3) Returns \b undef when \p v is not defined, is not
468  iterable, or is empty.
469 *******************************************************************************/
470 function tailn
471 (
472  v,
473  n = 1
474 ) = !is_iterable(v) ? undef
475  : is_empty(v) ? undef
476  : (n >= len(v)) ? empty_lst
477  : [for (i = [max(0, n) : len(v)-1]) v[i]];
478 
479 //! Reverse the elements of an iterable value.
480 /***************************************************************************//**
481  \param v <iterable> An iterable value.
482 
483  \returns (1) <list> A list containing the elements of \p v in
484  reversed order.
485  (2) Returns \b empty_lst when \p v is empty.
486  (3) Returns \b undef when \p v is not defined or is not iterable.
487 *******************************************************************************/
488 function reverse
489 (
490  v
491 ) = !is_iterable(v) ? undef
492  : is_empty(v) ? empty_lst
493  : [for (i = [len(v)-1 : -1 : 0]) v[i]];
494 
495 //! Shift the elements of an iterable value.
496 /***************************************************************************//**
497  \param v <iterable> An iterable value.
498  \param n <integer> The element shift count.
499  \param r <boolean> Shift the elements to the right (or left).
500  \param c <boolean> Perform circular shift (or drop).
501 
502  \returns (1) <list> A list containing the elements of \p v shifted
503  by \p n elements.
504  (2) Returns \b undef when \p v is not defined or is not iterable.
505 
506  \details
507 
508  The shift count \p n may be positive or negative.
509 *******************************************************************************/
510 function shift
511 (
512  v,
513  n = 0,
514  r = true,
515  c = true
516 ) = !is_iterable(v) ? undef
517  : let
518  (
519  l = len(v),
520  s = abs(n), // absolute magnitude
521  m = s % l, // circular magnitude
522  d = (n > 0) ? r : !r // shift direction
523  )
524  // non-circular and shift greater than elements
525  (c == false && s > l-1) ? empty_lst
526  // shift direction
527  : (d == true) ?
528  // shift right
529  [ if (m && c) for (i = [l-m : l-1]) v[i], for (i = [0 : l-1-m]) v[i] ]
530  // shift left
531  : [ for (i = [m : l-1]) v[i], if (m && c) for (i = [0 : m-1]) v[i] ];
532 
533 //! Select a range of elements from an iterable value.
534 /***************************************************************************//**
535  \param v <iterable> An iterable value.
536  \param i <range|list|integer> The index selection.
537 
538  \returns (1) <list> A list containing the selected elements.
539  (2) Returns \b undef when \p v is not defined, is not
540  iterable, or when \p i does not map to an element of \p v.
541  (3) Returns \b empty_lst when \p v is empty.
542 *******************************************************************************/
543 function select_r
544 (
545  v,
546  i
547 ) = (!is_iterable(v) || !all_defined(i)) ? undef
548  : is_empty(v) ? empty_lst
549  : ( !is_number(i) && !is_list(i) && !is_range(i) ) ? undef
550  : is_number(i) && !is_between(i, 0, len(v)-1) ? undef
551  : is_list(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
552  : is_range(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
553  : let ( s = is_number(i) ? [i] : i )
554  [for (j = [for (k=s) k]) v[j]];
555 
556 //! Return a list of all n-element sequential-subsets of an iterable value.
557 /***************************************************************************//**
558  \param v <iterable> An iterable value.
559  \param n <integer> The number of elements for each subset.
560  \param s <integer> The iteration step size.
561  \param w <boolean> Use wrap-at-end circular subset selection.
562 
563  \returns (1) <list-list> A list of all n-element sequential subsets
564  of \p v skipping \p s elements of \p v between each
565  subset selection.
566  (2) Returns \b empty_lst when \p v is empty, is not defined
567  or is not iterable.
568 
569  \details
570 
571  \b Example
572  \code{.C}
573  v = [1, 2, 3, 4];
574 
575  sequence_ns( v, 3, 1, false ); // [ [1,2,3], [2,3,4] ]
576  sequence_ns( v, 3, 1, true ); // [ [1,2,3], [2,3,4], [3,4,1], [4,1,2] ]
577  \endcode
578 *******************************************************************************/
579 function sequence_ns
580 (
581  v,
582  n = 1,
583  s = 1,
584  w = false
585 ) = is_empty(v) ? empty_lst
586  : [
587  for (i=[0 : s : (len(v)-((w == true) ? 1 : n)) ])
588  [
589  for (j=[i : (i+n-1)])
590  v[j % len(v)]
591  ]
592  ];
593 
594 //! Append a value to each element of an iterable value.
595 /***************************************************************************//**
596  \param nv <value> A new value to append.
597  \param v <iterable> An iterable value.
598 
599  \param r <boolean> Reduce list element before appending.
600  \param j <boolean> Join each appendage as a separate list.
601 
602  \param l <boolean> Append new value to last element.
603 
604  \returns (1) <list> A list with \p nv appended to each element of \p v.
605  (2) Returns \b undef when \p v is not defined or is not iterable.
606 
607  \details
608 
609  Appending with \p r == \b true causes each element of \p nv to be
610  appended to the elements of each iterable value. When \p r == \b
611  false, each element of \p nv is appended to the iterable value
612  itself. To append a list of elements together as a list to \p v,
613  enclose the elements of \p nv with a second set of brackets.
614 
615  \b Example
616  \code{.C}
617  v1=[["a"], ["b"], ["c"], ["d"]];
618  v2=[1, 2, 3];
619 
620  echo( append_e( v2, v1 ) );
621  echo( append_e( v2, v1, r=false ) );
622  echo( append_e( v2, v1, j=false, l=false ) );
623  \endcode
624 
625  \b Result
626  \code{.C}
627  ECHO: [["a", 1, 2, 3], ["b", 1, 2, 3], ["c", 1, 2, 3], ["d", 1, 2, 3]]
628  ECHO: [[["a"], 1, 2, 3], [["b"], 1, 2, 3], [["c"], 1, 2, 3], [["d"], 1, 2, 3]]
629  ECHO: ["a", 1, 2, 3, "b", 1, 2, 3, "c", 1, 2, 3, "d"]
630  \endcode
631 
632 *******************************************************************************/
633 function append_e
634 (
635  nv,
636  v,
637  r = true,
638  j = true,
639  l = true
640 ) = !is_iterable(v) ? undef
641  // when 'v' is empty
642  : is_empty(v) ? ((j == true) ? [concat(nv)] : concat(nv))
643  // 'v' not empty
644  : let
645  ( // current element 'ce'
646  ce = (r == true) ? first(v) : [first(v)]
647  )
648  // last element of 'v'
649  (len(v) == 1) ?
650  (
651  (j == true && l == true ) ? [concat(ce, nv)]
652  : (j == true && l == false) ? [ce]
653  : (j == false && l == true ) ? concat(ce, nv)
654  : ce
655  )
656  : (j == true) ? concat( [concat(ce, nv)], append_e(nv, tailn(v), r, j, l) )
657  : concat( concat(ce, nv) , append_e(nv, tailn(v), r, j, l) );
658 
659 //! Insert a new value into an iterable value.
660 /***************************************************************************//**
661  \param nv <value> A new value to insert.
662  \param v <iterable> An iterable value.
663 
664  \param i <integer> The index insert position.
665 
666  \param mv <list|string|value> Matched value candidates.
667  \param mi <integer> The matched selection index.
668 
669  \param s <boolean> Element matching search method.
670  \param si <integer> The search element index when matching.
671 
672  \returns (1) <list> A list with \p nv inserted into \p v at the
673  specified position.
674  (2) Returns \b undef when no value of \p mv exists in
675  \p v, when <tt>(mi + 1)</tt> exceeds the matched
676  element count, when \p i does not map to an element of
677  \p v, or when \p v is not defined or is not iterable.
678 
679  \details
680 
681  When \p s == \b true, [search]\‍() is used to match elements. When
682  \p s == false, find() is used.
683 
684  The insert position can be specified by an index, an element match
685  value, or list of potential match values. When multiple matches
686  exists, \p mi indicates the insert position. When more than one
687  insert position criteria is specified, the order of precedence is:
688  (1) \p mv then (2) \p i. To insert a list of elements together as a
689  list to \p v, enclose the elements of \p nv with a second set of
690  brackets.
691 
692  \amu_eval (${group_references})
693 *******************************************************************************/
694 function insert
695 (
696  nv,
697  v,
698  i = 0,
699  mv,
700  mi = 0,
701  s = true,
702  si
703 ) = !is_iterable(v) ? undef
704  // when 'v' is empty and 'i' or 'mv' specified
705  : (is_empty(v) && ( (i != 0) || !is_undef(mv)) ) ? undef
706  // when 'v' is empty, simply return 'nv'
707  : is_empty(v) ? concat(nv)
708  : let
709  ( // identify specified insert position 'p' or return undef
710  p = is_defined(mv) ?
711  // search for 'mv' in 'v' selecting 'mi'
712  ( s == false ) ? find(mv, v, 0, si)[mi]
713  : merge_s(search(mv, v, 0, si), false)[mi]
714  // using 'i'; element position 'i' must exists in 'v' or is undef
715  : !is_between(i, 0, len(v)) ? undef
716  : i,
717  // generate result list head 'h'
718  h = ( !is_undef(p) && (p>0) ) ? [for (j = [0 : p-1]) v[j]] : empty_lst,
719  // generate result list tail 't'
720  t = ( is_undef(p) || (p>len(v)-1) ) ? empty_lst : [for (j = [p : len(v)-1]) v[j]]
721  )
722  // result valid iff a valid insert position was specified
723  is_undef(p) ? undef : concat(h, nv, t);
724 
725 //! Delete elements from an iterable value.
726 /***************************************************************************//**
727  \param v <iterable> An iterable value.
728 
729  \param i <range|list|integer> Deletion Indexes.
730 
731  \param mv <list|string|value> Matched value candidates.
732  \param mc <integer> A match count.
733  For <tt>(mc>=1)</tt>, remove the first \p mc matches.
734  For <tt>(mc<=0)</tt>, remove all matches.
735 
736  \param s <boolean> Element matching search method.
737  \param si <integer> The element column index when matching.
738 
739  \returns (1) <list> A list with all specified elements removed.
740  (2) Returns \b undef when \p i does not map to an element
741  of \p v, when \p v is not defined, or is not iterable.
742 
743 
744  \details
745 
746  When \p s == \b true, [search]\‍() is used to match elements. When
747  \p s == false, find() is used.
748 
749  The elements to delete can be specified by an index position, a
750  list of index positions, an index range, an element match value, or
751  a list of element match values (when using [search]\‍()). When \p mv
752  is a list of match values, all values of \p mv that exists in \p v
753  are candidates for deletion. For each matching candidate, \p mc
754  indicates the quantity to remove. When more than one deletion
755  criteria is specified, the order of precedence is: (1) \p mv then
756  (2) \p i.
757 
758  \amu_eval (${group_references})
759 *******************************************************************************/
760 function delete
761 (
762  v,
763  i,
764  mv,
765  mc = 1,
766  s = true,
767  si
768 ) = !is_iterable(v) ? undef
769  // nothing to delete
770  : is_empty(v) ? empty_lst
771  // for 'i' a number, list or range; each indexed position must exists in 'v'
772  : is_number(i) && !is_between(i, 0, len(v)-1) ? undef
773  : is_list(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
774  : is_range(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
775  : let
776  ( // identify specified deletion position(s) 'p' or return undef
777  p = is_defined(mv) ?
778  // search for 'mv' in 'v' selecting 'mi'
779  ( s == false ) ? find(mv, v, mc, si)
780  : merge_s(search(mv, v, mc, si), false)
781  // using 'i'; for single number, format as list
782  : is_number(i) ? [i]
783  // using 'i'; pass list as specified
784  : is_list(i) ? i
785  // using 'i'; enumerate range to list
786  : is_range(i) ? [for (y=i) y]
787  : undef
788  )
789  [ // output only elements of 'v' that do not exists in 'p'
790  for (j = [0 : len(v)-1])
791  if (is_empty(find(j, p))) v[j]
792  ];
793 
794 //! Strip all matching values from an iterable value.
795 /***************************************************************************//**
796  \param v <iterable> An iterable value.
797  \param mv <value> A match value.
798 
799  \returns (1) <list> The list 'v' with all elements equal \p mv removed.
800  (2) Returns \b undef when \p v is not defined or is not iterable.
801 *******************************************************************************/
802 function strip
803 (
804  v,
805  mv = empty_lst
806 ) = !is_iterable(v) ? undef
807  : is_empty(v) ? empty_lst
808  : (first(v) == mv) ? concat(strip(tailn(v), mv))
809  : concat(firstn(v), strip(tailn(v), mv));
810 
811 //! Apply a binary mask to an interable value.
812 /***************************************************************************//**
813  \param v <iterable> An iterable value.
814  \param m <iterable> A binary mask.
815  \param r <boolean> Right align the mask to \p v value.
816  \param o <integer> A positive or negative mask offset.
817  \param u <value> The value assigned to elements of the mask that
818  does not exists or are undefined in \p v.
819  \param z <value> The value assigned to masked elements.
820 
821  \returns (1) <value> A list containing the masked values of \p v.
822  (2) Returns \b v as a list when \p m is not defined.
823  (3) Returns \p undef when \p m is not iterable or contains
824  values other than zero or one.
825 
826  \details
827 
828  This mask may be specified as a list or string and is composed of
829  ones and zeros. One indicates that an element value of \p v is
830  passed and a zero indicates that a value of \p v is to be replaced
831  with \p z.
832 *******************************************************************************/
833 function mask
834 (
835  v,
836  m,
837  r = false,
838  o = 0,
839  u = undef,
840  z = 0
841 ) = is_undef(m) ? headn(v, 0)
842  // if defined, 'm' must be iterable
843  : !is_iterable(m) ? undef
844  // string mask may only include "01"
845  : is_string(m) && !is_empty(delete(m, mv="01", mc=0)) ? undef
846  // list mask may only include [0, 1]
847  : is_list(m) && !is_empty(delete(m, mv=[0,1], mc=0)) ? undef
848  : let
849  ( // calculate the mask base offset
850  l = is_iterable(v) ? len(v) : 0,
851  j = ((r == true) ? l - len(m) : 0) + o
852  )
853  [
854  for (i = [0 : len(m)-1])
855  (m[i] == 1 || m[i] == "1") ? defined_e_or(v, i+j, u)
856  : exists_e(i+j, v) ? z : u
857  ];
858 
859 //! Return a list of the unique elements of an iterable value.
860 /***************************************************************************//**
861  \param v <iterable> An iterable value.
862 
863  \returns (1) <list> A list of unique elements with order preserved.
864  (2) Returns \b undef when \p v is not defined or is not
865  iterable.
866 
867  \warning Any and all list elements of \p v that have the value of \b
868  undef are ignored and is not considered to be a unique.
869 *******************************************************************************/
870 function unique
871 (
872  v
873 ) = is_undef(v) ? empty_lst
874  : !is_iterable(v) ? [v]
875  // handled empty list or empty string
876  : (len(v) == 0) ? empty_lst
877  // last element. filter case where first element of list is [undef]
878  : (len(v) == 1) ? (v == [undef]) ? empty_lst : headn(v, 0)
879  // set s=false to use find() for single element matching
880  : exists(last(v), headn(v), s=false) ? unique(headn(v))
881  : concat(unique(headn(v)), lastn(v));
882 
883 
884 //! @}
885 //! @}
886 
887 //----------------------------------------------------------------------------//
888 // openscad-amu auxiliary scripts
889 //----------------------------------------------------------------------------//
890 
891 /*
892 BEGIN_SCOPE validate;
893  BEGIN_OPENSCAD;
894  include <omdl-base.scad>;
895  include <common/validation.scad>;
896 
897  function fmt( id, td, v1, v2, v3 ) = table_validate_fmt(id, td, v1, v2, v3);
898  function v1(db, id) = table_validate_get_v1(db, id);
899  t = true; f = false; u = undef; s = validation_skip;
900 
901  tbl_test_values =
902  [
903  fmt("t01", "The undefined value", undef),
904  fmt("t02", "The empty list", empty_lst),
905  fmt("t03", "A long range", [0:0.5:9]),
906  fmt("t04", "string = (A string)", "A string"),
907  fmt("t05", "List-4 fruit", ["orange","apple","grape","banana"]),
908  fmt("t06", "List-7 characters", ["b","a","n","a","n","a","s"]),
909  fmt("t07", "List-1 undefined", [undef]),
910  fmt("t08", "List-2 integers-2", [[1,2],[2,3]]),
911  fmt("t09", "List-4 iterable-2", ["ab",[1,2],[2,3],[4,5]]),
912  fmt("t10", "List-4 iterable-3", [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]]),
913  fmt("t11", "List-15 of integers", [for (i=[0:15]) i])
914  ];
915 
916  tbl_test_answers =
917  [
918  ["defined_e_or_DE3",
919  "default", // t01
920  "default", // t02
921  "default", // t03
922  "t", // t04
923  "banana", // t05
924  "a", // t06
925  "default", // t07
926  "default", // t08
927  [4,5], // t09
928  ["a","b","c"], // t10
929  3 // t11
930  ],
931  ["find_12",
932  empty_lst, // t01
933  empty_lst, // t02
934  empty_lst, // t03
935  empty_lst, // t04
936  empty_lst, // t05
937  empty_lst, // t06
938  empty_lst, // t07
939  [0], // t08
940  [1], // t09
941  empty_lst, // t10
942  empty_lst // t11
943  ],
944  ["count_S1",
945  0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1
946  ],
947  ["exists_S1",
948  f, f, f, f, f, f, f, t, t, t, t
949  ],
950  ["exists_e_5",
951  f, f, f, t, f, t, f, f, f, f, t
952  ],
953  ["first",
954  undef, // t01
955  undef, // t02
956  0, // t03
957  "A", // t04
958  "orange", // t05
959  "b", // t06
960  undef, // t07
961  [1,2], // t08
962  "ab", // t09
963  [1,2,3], // t10
964  0 // t11
965  ],
966  ["second",
967  undef, // t01
968  undef, // t02
969  0.5, // t03
970  " ", // t04
971  "apple", // t05
972  "a", // t06
973  undef, // t07
974  [2,3], // t08
975  [1,2], // t09
976  [4,5,6], // t10
977  1 // t11
978  ],
979  ["third",
980  undef, // t01
981  undef, // t02
982  9, // t03
983  "s", // t04
984  "grape", // t05
985  "n", // t06
986  undef, // t07
987  undef, // t08
988  [2,3], // t09
989  [7,8,9], // t10
990  2 // t11
991  ],
992  ["last",
993  undef, // t01
994  undef, // t02
995  undef, // t03
996  "g", // t04
997  "banana", // t05
998  "s", // t06
999  undef, // t07
1000  [2,3], // t08
1001  [4,5], // t09
1002  ["a","b","c"], // t10
1003  15 // t11
1004  ],
1005  ["middle",
1006  undef, // t01
1007  undef, // t02
1008  undef, // t03
1009  "r", // t04
1010  "grape", // t05
1011  "a", // t06
1012  undef, // t07
1013  [2,3], // t08
1014  [2,3], // t09
1015  [7,8,9], // t10
1016  8 // t11
1017  ],
1018  ["first2",
1019  undef, // t01
1020  undef, // t02
1021  undef, // t03
1022  ["A"," "], // t04
1023  ["orange","apple"], // t05
1024  ["b","a"], // t06
1025  undef, // t07
1026  [[1,2],[2,3]], // t08
1027  ["ab", [1,2]], // t09
1028  [[1,2,3],[4,5,6]], // t10
1029  [0,1] // t11
1030  ],
1031  ["first3",
1032  undef, // t01
1033  undef, // t02
1034  undef, // t03
1035  ["A"," ","s"], // t04
1036  ["orange","apple","grape"], // t05
1037  ["b","a","n"], // t06
1038  undef, // t07
1039  undef, // t08
1040  ["ab", [1,2],[2,3]], // t09
1041  [[1,2,3],[4,5,6],[7,8,9]], // t10
1042  [0,1,2] // t11
1043  ],
1044  ["last2",
1045  undef, // t01
1046  undef, // t02
1047  undef, // t03
1048  ["n","g"], // t04
1049  ["grape","banana"], // t05
1050  ["a","s"], // t06
1051  undef, // t07
1052  [[1,2],[2,3]], // t08
1053  [[2,3], [4,5]], // t09
1054  [[7,8,9],["a","b","c"]], // t10
1055  [14,15] // t11
1056  ],
1057  ["last3",
1058  undef, // t01
1059  undef, // t02
1060  undef, // t03
1061  ["i","n","g"], // t04
1062  ["apple","grape","banana"], // t05
1063  ["n","a","s"], // t06
1064  undef, // t07
1065  undef, // t08
1066  [[1,2],[2,3],[4,5]], // t09
1067  [[4,5,6],[7,8,9],["a","b","c"]], // t10
1068  [13,14,15] // t11
1069  ],
1070  ["firstn_1",
1071  undef, // t01
1072  undef, // t02
1073  undef, // t03
1074  ["A"], // t04
1075  ["orange"], // t05
1076  ["b"], // t06
1077  [undef], // t07
1078  [[1,2]], // t08
1079  ["ab"], // t09
1080  [[1,2,3]], // t10
1081  [0] // t11
1082  ],
1083  ["lastn_1",
1084  undef, // t01
1085  undef, // t02
1086  undef, // t03
1087  ["g"], // t04
1088  ["banana"], // t05
1089  ["s"], // t06
1090  [undef], // t07
1091  [[2,3]], // t08
1092  [[4,5]], // t09
1093  [["a","b","c"]], // t10
1094  [15] // t11
1095  ],
1096  ["headn_1",
1097  undef, // t01
1098  undef, // t02
1099  undef, // t03
1100  ["A"," ","s","t","r","i","n"], // t04
1101  ["orange","apple","grape"], // t05
1102  ["b","a","n","a","n","a"], // t06
1103  empty_lst, // t07
1104  [[1,2]], // t08
1105  ["ab",[1,2],[2,3]], // t09
1106  [[1,2,3],[4,5,6],[7,8,9]], // t10
1107  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] // t11
1108  ],
1109  ["tailn_1",
1110  undef, // t01
1111  undef, // t02
1112  undef, // t03
1113  [" ","s","t","r","i","n","g"], // t04
1114  ["apple","grape","banana"], // t05
1115  ["a","n","a","n","a","s"], // t06
1116  empty_lst, // t07
1117  [[2,3]], // t08
1118  [[1,2],[2,3],[4,5]], // t09
1119  [[4,5,6],[7,8,9],["a","b","c"]], // t10
1120  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
1121  ],
1122  ["reverse",
1123  undef, // t01
1124  empty_lst, // t02
1125  undef, // t03
1126  ["g","n","i","r","t","s"," ","A"], // t04
1127  ["banana","grape","apple","orange"], // t05
1128  ["s","a","n","a","n","a","b"], // t06
1129  [undef], // t07
1130  [[2,3],[1,2]], // t08
1131  [[4,5],[2,3],[1,2],"ab"], // t09
1132  [["a","b","c"],[7,8,9],[4,5,6],[1,2,3]], // t10
1133  [15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0] // t11
1134  ],
1135  ["shift_r1",
1136  undef, // t01
1137  empty_lst, // t02
1138  undef, // t03
1139  ["g","A"," ","s","t","r","i","n"], // t04
1140  ["banana","orange","apple","grape"], // t05
1141  ["s","b","a","n","a","n","a"], // t06
1142  [undef], // t07
1143  [[2,3],[1,2]], // t08
1144  [[4,5],"ab",[1,2],[2,3]], // t09
1145  [["a","b","c"],[1,2,3],[4,5,6],[7,8,9]], // t10
1146  [15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] // t11
1147  ],
1148  ["shift_l1",
1149  undef, // t01
1150  empty_lst, // t02
1151  undef, // t03
1152  [" ","s","t","r","i","n","g","A"], // t04
1153  ["apple","grape","banana","orange"], // t05
1154  ["a","n","a","n","a","s","b"], // t06
1155  [undef], // t07
1156  [[2,3],[1,2]], // t08
1157  [[1,2],[2,3],[4,5],"ab"], // t09
1158  [[4,5,6],[7,8,9],["a","b","c"],[1,2,3]], // t10
1159  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0] // t11
1160  ],
1161  ["select_r_02",
1162  undef, // t01
1163  empty_lst, // t02
1164  undef, // t03
1165  ["A"," ","s"], // t04
1166  ["orange","apple","grape"], // t05
1167  ["b","a","n"], // t06
1168  undef, // t07
1169  undef, // t08
1170  ["ab",[1,2],[2,3]], // t09
1171  [[1,2,3],[4,5,6],[7,8,9]], // t10
1172  [0,1,2] // t11
1173  ],
1174  ["sequence_ns_31",
1175  empty_lst, // t01
1176  empty_lst, // t02
1177  empty_lst, // t03
1178  [
1179  ["A"," ","s"],[" ","s","t"],["s","t","r"],
1180  ["t","r","i"],["r","i","n"],["i","n","g"]
1181  ], // t04
1182  [
1183  ["orange","apple","grape"],
1184  ["apple","grape","banana"]
1185  ], // t05
1186  [
1187  ["b","a","n"],["a","n","a"],["n","a","n"],
1188  ["a","n","a"],["n","a","s"]
1189  ], // t06
1190  empty_lst, // t07
1191  empty_lst, // t08
1192  [["ab",[1,2],[2,3]],[[1,2],[2,3],[4,5]]], // t09
1193  [
1194  [[1,2,3],[4,5,6],[7,8,9]],
1195  [[4,5,6],[7,8,9],["a","b","c"]]
1196  ], // t10
1197  [
1198  [0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],
1199  [6,7,8],[7,8,9],[8,9,10],[9,10,11],[10,11,12],
1200  [11,12,13],[12,13,14],[13,14,15]
1201  ] // t11
1202  ],
1203  ["append_e_T0",
1204  undef, // t01
1205  [[0]], // t02
1206  undef, // t03
1207  [
1208  ["A",0],[" ",0],["s",0],["t",0],
1209  ["r",0],["i",0],["n",0],["g",0]
1210  ], // t04
1211  [
1212  ["orange",0],["apple",0],
1213  ["grape",0],["banana",0]
1214  ], // t05
1215  [
1216  ["b",0],["a",0],["n",0],["a",0],
1217  ["n",0],["a",0],["s",0]
1218  ], // t06
1219  [[undef,0]], // t07
1220  [[1,2,0],[2,3,0]], // t08
1221  [["ab",0],[1,2,0],[2,3,0],[4,5,0]], // t09
1222  [[1,2,3,0],[4,5,6,0],[7,8,9,0],["a","b","c",0]], // t10
1223  [
1224  [0,0],[1,0],[2,0],[3,0],[4,0],[5,0],
1225  [6,0],[7,0],[8,0],[9,0],[10,0],[11,0],
1226  [12,0],[13,0],[14,0],[15,0]
1227  ] // t11
1228  ],
1229  ["insert_T0",
1230  undef, // t01
1231  undef, // t02
1232  undef, // t03
1233  undef, // t04
1234  ["orange",0,"apple","grape","banana"], // t05
1235  ["b","a","n","a","n","a",0,"s"], // t06
1236  undef, // t07
1237  [[1,2],0,[2,3]], // t08
1238  ["ab",[1,2],0,[2,3],[4,5]], // t09
1239  undef, // t10
1240  [0,1,2,3,4,0,5,6,7,8,9,10,11,12,13,14,15] // t11
1241  ],
1242  ["delete_T0",
1243  undef, // t01
1244  empty_lst, // t02
1245  undef, // t03
1246  ["A"," ","s","t","r","i","n","g"], // t04
1247  ["orange","grape","banana"], // t05
1248  ["b","a","n","a","n","a"], // t06
1249  [undef], // t07
1250  [[1,2]], // t08
1251  ["ab",[1,2],[4,5]], // t09
1252  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
1253  [0,1,2,3,4,6,7,8,9,10,11,12,13,14,15] // t11
1254  ],
1255  ["strip",
1256  undef, // t01
1257  empty_lst, // t02
1258  undef, // t03
1259  ["A"," ","s","t","r","i","n","g"], // t04
1260  ["orange","apple","grape","banana"], // t05
1261  ["b","a","n","a","n","a","s"], // t06
1262  [undef], // t07
1263  [[1,2],[2,3]], // t08
1264  ["ab",[1,2],[2,3],[4,5]], // t09
1265  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
1266  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
1267  ],
1268  ["mask_01R",
1269  [undef,undef], // t01
1270  [undef,undef], // t02
1271  [undef,undef], // t03
1272  [0,"g"], // t04
1273  [0,"banana"], // t05
1274  [0,"s"], // t06
1275  [undef,undef], // t07
1276  [0,[2,3]], // t08
1277  [0,[4,5]], // t09
1278  [0,["a","b","c"]], // t10
1279  [0,15] // t11
1280  ],
1281  ["unique",
1282  empty_lst, // t01
1283  empty_lst, // t02
1284  [[0:0.5:9]], // t03
1285  ["A"," ","s","t","r","i","n","g"], // t04
1286  ["orange","apple","grape","banana"], // t05
1287  ["b","a","n","s"], // t06
1288  empty_lst, // t07
1289  [[1,2],[2,3]], // t08
1290  ["ab",[1,2],[2,3],[4,5]], // t09
1291  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
1292  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
1293  ]
1294  ];
1295 
1296  db = table_validate_init( tbl_test_values, tbl_test_answers );
1297 
1298  table_validate_start( db );
1299  test_ids = table_validate_get_ids( db );
1300 
1301  for (id=test_ids) table_validate( db, id, "defined_e_or_DE3", 1, defined_e_or( v1(db,id), 3, "default" ) );
1302  for (id=test_ids) table_validate( db, id, "find_12", 1, find( [1,2], v1(db,id) ) );
1303  for (id=test_ids) table_validate( db, id, "count_S1", 1, count( 1, v1(db,id), true ) );
1304  for (id=test_ids) table_validate( db, id, "exists_S1", 1, exists( 1, v1(db,id), true ) );
1305  for (id=test_ids) table_validate( db, id, "exists_e_5", 1, exists_e( 5, v1(db,id )) );
1306  for (id=test_ids) table_validate( db, id, "first", 1, first( v1(db,id) ) );
1307  for (id=test_ids) table_validate( db, id, "second", 1, second( v1(db,id) ) );
1308  for (id=test_ids) table_validate( db, id, "third", 1, third( v1(db,id) ) );
1309  for (id=test_ids) table_validate( db, id, "last", 1, last( v1(db,id) ) );
1310  for (id=test_ids) table_validate( db, id, "middle", 1, middle( v1(db,id) ) );
1311  for (id=test_ids) table_validate( db, id, "first2", 1, first2( v1(db,id) ) );
1312  for (id=test_ids) table_validate( db, id, "first3", 1, first3( v1(db,id) ) );
1313  for (id=test_ids) table_validate( db, id, "last2", 1, last2( v1(db,id) ) );
1314  for (id=test_ids) table_validate( db, id, "last3", 1, last3( v1(db,id) ) );
1315  for (id=test_ids) table_validate( db, id, "firstn_1", 1, firstn( v1(db,id), n=1 ) );
1316  for (id=test_ids) table_validate( db, id, "lastn_1", 1, lastn( v1(db,id), n=1 ) );
1317  for (id=test_ids) table_validate( db, id, "headn_1", 1, headn( v1(db,id), n=1 ) );
1318  for (id=test_ids) table_validate( db, id, "tailn_1", 1, tailn( v1(db,id), n=1 ) );
1319  for (id=test_ids) table_validate( db, id, "reverse", 1, reverse( v1(db,id) ) );
1320  for (id=test_ids) table_validate( db, id, "shift_r1", 1, shift( v1(db,id), n=1, r=true ) );
1321  for (id=test_ids) table_validate( db, id, "shift_l1", 1, shift( v1(db,id), n=1, r=false ) );
1322  for (id=test_ids) table_validate( db, id, "select_r_02", 1, select_r( v1(db,id), i=[0:2] ) );
1323  for (id=test_ids) table_validate( db, id, "sequence_ns_31", 1, sequence_ns( v1(db,id), n=3, s=1 ) );
1324  for (id=test_ids) table_validate( db, id, "append_e_T0", 1, append_e( 0, v1(db,id) ) );
1325  for (id=test_ids) table_validate( db, id, "insert_T0", 1, insert( 0, v1(db,id), mv=["x","r","apple","s",[2,3],5] ) );
1326  for (id=test_ids) table_validate( db, id, "delete_T0", 1, delete( v1(db,id), mv=["x","r","apple","s",[2,3],5] ) );
1327  for (id=test_ids) table_validate( db, id, "strip", 1, strip( v1(db,id) ) );
1328  for (id=test_ids) table_validate( db, id, "mask_01R", 1, mask( v1(db,id), [0,1], r=true ) );
1329  for (id=test_ids) table_validate( db, id, "unique", 1, unique( v1(db,id) ) );
1330 
1331  // end_include
1332  END_OPENSCAD;
1333 
1334  BEGIN_MFSCRIPT;
1335  include --path "${INCLUDE_PATH}" {var_init,var_gen_term}.mfs;
1336  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
1337  END_MFSCRIPT;
1338 END_SCOPE;
1339 */
1340 
1341 //----------------------------------------------------------------------------//
1342 // end of file
1343 //----------------------------------------------------------------------------//
empty_lst
<list> A list with no values (the empty list).
Definition: constants.scad:304
function headn(v, n=1)
Return a list containing all but the last n elements of an iterable value.
function firstn(v, n=1)
Return a list containing the first n elements of an iterable value.
function unique(v)
Return a list of the unique elements of an iterable value.
function select_r(v, i)
Select a range of elements from an iterable value.
function append_e(nv, v, r=true, j=true, l=true)
Append a value to each element of an iterable value.
function find(mv, v, c=1, i, i1=0, i2)
Find the occurrences of a match value in an iterable value.
function first3(v)
Return a list containing the first three elements of an iterable value.
function first2(v)
Return a list containing the first two elements of an iterable value.
function defined_e_or(v, i, d)
Return an element of an iterable when it exists or a default value otherwise.
function last3(v)
Return a list containing the last three elements of an iterable value.
function third(v)
Return the third element of an iterable value.
function last(v)
Return the last element of an iterable value.
function exists(mv, v, s=true, i)
Check for the existence of a match value in an iterable value.
function count(mv, v, s=true, i)
Count all occurrences of a match value in an iterable value.
function insert(nv, v, i=0, mv, mi=0, s=true, si)
Insert a new value into an iterable value.
function shift(v, n=0, r=true, c=true)
Shift the elements of an iterable value.
function exists_e(i, v)
Test if an element exists at a specified index of an iterable value.
function mask(v, m, r=false, o=0, u=undef, z=0)
Apply a binary mask to an interable value.
function strip(v, mv=empty_lst)
Strip all matching values from an iterable value.
function second(v)
Return the second element of an iterable value.
function lastn(v, n=1)
Return a list containing the last n elements of an iterable value.
function middle(v)
Return the middle element of an iterable value.
function delete(v, i, mv, mc=1, s=true, si)
Delete elements from an iterable value.
function first(v)
Return the first element of an iterable value.
function sequence_ns(v, n=1, s=1, w=false)
Return a list of all n-element sequential-subsets of an iterable value.
function last2(v)
Return a list containing the last two elements of an iterable value.
function tailn(v, n=1)
Return a list containing all but the first n elements of an iterable value.
function reverse(v)
Reverse the elements of an iterable value.
function all_defined(v)
Test if no element of an iterable value has an undefined value.
function is_iterable(v)
Test if a value has multiple parts and is iterable.
function is_empty(v)
Test if an iterable value is empty.
function merge_s(v, r=false)
Serially merge the elements of a list.
function is_between(v, l, u)
Test if a numerical value is between an upper and lower bounds.
function is_defined(v)
Test if a value is defined.
function is_number(v)
Test if a value is a number.
function is_range(v)
Test if a value is a range definition.