! form.ax - utility predicates based on the form of expressions ! == - identity relation (== % %). ! id - identity function (id % %). ! -- Same as == but we think of id as the identity function from argument to ! a result, while == is an equivalence relation for 2 identical expressions. ! concat - concatenation function ! (concat ) (concat (\$1) (\$2) (\$1 \$2)). !>>> This is called 'append' in traditional LP, ! but we use 'concat' to avoid confusion with 'append1': ! generalization of concat to >2 input arguments (concat %arg1 %arg2 \$args (\$) (\$res \$))< ! adding an argument (concat %arg1 %arg2 \$args (\$res)). ! concatenation of a sequence of sequences (1-argument case) (concat () ()). (concat ((\$) \$seqs) (\$ \$concat))< (concat (\$seqs) (\$concat)). ! Generalize other binary operators in this manner? (plus, and, etc.) ! from ho.ax: (generalize concat ()). ! append1 - append one value to a sequence (append1 (\$) % (\$ %)). ! front_append - append expression to front of a sequence (fappend % (\$) (% \$)). ! last - last element in a sequence (last (\$ %) %). ! head - first element in a sequence (head (% \$) %). ! tail - rest of a sequence after its head (tail (% \$) (\$)). ! in - expression is in a sequence (in % (\$1 % \$2)). !>>> This is called 'member' in traditional LP. ! insert - insert an expression at some (any) point in a sequence (insert %x (\$1 \$2) (\$1 %x \$2)). ! reverse - reverse a sequence (reverse () ()). (reverse (% \$) (\$rev %))< (reverse (\$) (\$rev)). ! zero_or_more - sequence is zero or more occurrences of an expression (zero_or_more % ()). (zero_or_more % (% \$))< (zero_or_more % (\$)). ! -- better name needed! closure? ! ldistr - distribute an element over the front of multiple sequences (ldistr % () ()). (ldistr % ((\$) \$seqs) ((% \$) \$seqs'))< (ldistr % (\$seqs) (\$seqs')). ! -- or could use higher-order definition: (ldistr \$args)< ((1* fappend) \$args). ! distr - distribute a sequence of elements over the fronts of sequences ! (Note that this is same as fappend*, once we define the * mapping ! (which needs distr in its definition!).) (distr () () ()). (distr (%el \$els) ((\$seq) \$seqs) ((%el \$seq) \$seqs'))< (distr (\$els) (\$seqs) (\$seqs')). ! turn relation into * that applies to sequences of arguments ((` (\$rel '*')) \$nulls)< (zero_or_more () (\$nulls)). ! empty arg sequences ((` (\$rel '*')) \$argseqsx)< ! non-empty arg sequences ((` (\$rel '*')) \$argseqs), ((` (\$rel)) \$args), ! relation to be mapped (distr (\$args) (\$argseqs) (\$argseqsx)). ! all_subsets - set of all subsets of a set (sequence) ! (all_subsets ( ... )) ! -- note that element order is preserved ! -- note that we don't eliminate duplicate subsets (in case some original ! set elements are the same) ! -- Better name needed to reflect that these are all subsets of elements ! from the original sequence given in their original order. (all_subsets () (())). (all_subsets (% \$) (\$w% \$w/o%))< (all_subsets (\$) (\$w/o%)), (ldistr % (\$w/o%) (\$w%)). !/ examples: (all_subsets () (())) -- just the empty sequence itself (all_subsets (a) ((a) ())) (all_subsets (a b) ((a b) (a) (b) ())) (all_subsets (a b c) ((a b c) (a b) (a c) (a) (b c) (b) (c) ())) ... !\ ! insert_between - insert an expression between each element of a sequence ! (We do not insert before first element or after last.) (insert_between %x () ()). ! no insertion here (insert_between %x (%) (%)). ! or here (insert_between %x (%' % \$) (%' %x \$'))< ! here's where we insert (insert_between %x (% \$) (\$')). ! =length - two sequences are equal length (=length () ()). (=length (%1 \$1) (%2 \$2))< (=length (\$1) (\$2)). ! `' - "constant" or "quote" function ((`' %) %ignored %). ! result comes from the function, argument is ignored