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