aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cppawk-cons.1163
-rw-r--r--cppawk-include/cons-priv.h6
-rw-r--r--testcases-cons30
3 files changed, 196 insertions, 3 deletions
diff --git a/cppawk-cons.1 b/cppawk-cons.1
index c1cb640..a4d766d 100644
--- a/cppawk-cons.1
+++ b/cppawk-cons.1
@@ -1437,6 +1437,169 @@ returns nil and
returns
.BR x .
+.SS Functions \fIldiff\fP, \fIlast\fP and \fIbutlast\fP
+.bk
+Syntax:
+
+.ft B
+ ldiff(\fIx\fP, \fIy\fP)
+ last(\fIx\fP, [\fIn\fP])
+ butlast(\fIx\fP, [\fIn\fP])
+.ft R
+
+The
+.B ldiff
+function calculates the prefix of the list
+.I x
+which excludes the suffix
+.IR y .
+If
+.I y
+isn't a suffix of
+.IR x ,
+then
+.B ldiff
+returns
+.IR x .
+
+If
+.I y
+is an atom, then it is a suffix of
+.I x
+if
+.I x
+is terminated by the same atom.
+In that case, what is returned is a proper list of the elements of
+.IR x :
+that is, one terminated by
+.BR nil .
+Effectively, the
+.I y
+atom suffix is "removed" by way of being replaced by
+.BR nil .
+
+If
+.I y
+is a list, then to be a suffix of
+.I x
+it must match a tail portion of
+.I x
+exactly. The terminating atom of
+.I y
+must be the same as that of
+.I x
+and all the elements must match exactly.
+The return value is a list of all the elements of
+.I x
+which precede that portion of
+.I x
+which matches the
+.I y
+suffix.
+
+.B ldiff
+uses the
+.B ==
+operator for determining sameness of suffixes and terminating atoms.
+
+The
+.B last
+function returns an
+.IR n -element-long
+suffix of list
+.IR x ,
+where
+.I n
+must be a nonnegative integer. If omitted,
+.I n
+defaults to 1.
+
+The suffix of
+.I x
+returned by
+.B last
+always includes the original terminating atom taken from
+.IR x .
+
+If
+.I n
+is zero, then the return value of
+.B last
+is that terminating atom itself.
+
+.B Note: in the "algebra" of Lisp lists,
+an atom may be regarded as a list of length zero terminated by that atom.
+For instance, if the cons cell (1 . 42) is an improper list of length 1
+terminated by 42, then 42 is the rest of that list, which for some
+purposes may be regarded as a list of length zero terminated by 42.
+Thus the zero-length suffix of (1 . 42) is 42, and this is what
+.B "last(cons(1, 42), 0)"
+calculates.
+
+If
+.I n
+equals or exceeds the length of
+.IR x ,
+then
+.B last
+returns
+.IR x .
+
+The
+.B butlast
+function is complementary to
+.BR last :
+it returns that portion of
+.B x
+that is not returned by
+.BR last :
+the prefix of
+.B x
+omitting the last
+.I n
+elements. The meaning of the
+.I n
+parameter is the same, and it defaults to the same value of 1.
+
+If
+.I n
+equals or exceeds the length of
+.IR x ,
+then
+.B butlast
+returns
+.BR nil .
+
+For any given list
+.I x
+and nonnegative
+.IR n ,
+the expression
+.hy 0
+.BI append(butlast( x ", " n ),
+.BI last( x ", " n ))
+.hi 1
+returns a list similar to
+.IR x .
+
+.B Examples:
+
+.ft B
+ ldiff(list(1, 2, 3, 4), list(3, 4)) -> (1 2)
+ ldiff(list(1, 2, 3, 4), list(1, 2, 3, 4)) -> nil
+ ldiff(list(1, 2, 3, 4), list(4)) -> (1 2 3)
+ ldiff(list(1, 2, 3, 4), list(5, 6)) -> (1 2 3 4)
+ ldiff(list(1, 2, 3, 4), "abc") -> (1 2 3 4)
+ ldiff(cons(1, cons(2, 3)), 3) -> (1 2)
+
+ last(list(1, 2, 3)) -> (3)
+ last(list(1, 2, 3), 2) -> (2 3)
+ last(cons(1, cons(2, 3)), 0) -> 3
+
+ butlast(list(1, 2, 3), 2) -> (1)
+ butlast(list(1, 2, 3), 15) -> nil
+.ft R
+
.SH "SEE ALSO"
cppawk(1)
diff --git a/cppawk-include/cons-priv.h b/cppawk-include/cons-priv.h
index 2f5bdce..55790d1 100644
--- a/cppawk-include/cons-priv.h
+++ b/cppawk-include/cons-priv.h
@@ -706,10 +706,10 @@ function __nthcdr(__pos, __lst)
function __ldiff(__main, __tail,
__out, __iter)
{
- if (__null(main))
- return nil
+ if (__null(__main))
+ return __nil
- if (__null(tail))
+ if (__null(__tail))
return __main
__out = __list_begin()
diff --git a/testcases-cons b/testcases-cons
index 6211be6..6b7751d 100644
--- a/testcases-cons
+++ b/testcases-cons
@@ -619,3 +619,33 @@ nil
(1 2 3)
(3)
(1 2 3)
+--
+34:
+$cppawk '
+#include <cons.h>
+
+BEGIN {
+ print sexp(ldiff(list(1, 2, 3, 4), list(3, 4)))
+ print sexp(ldiff(list(1, 2, 3, 4), list(1, 2, 3, 4)))
+ print sexp(ldiff(list(1, 2, 3, 4), list(4)))
+ print sexp(ldiff(list(1, 2, 3, 4), list(5, 6)))
+ print sexp(ldiff(list(1, 2, 3, 4), "abc"))
+ print sexp(ldiff(cons(1, cons(2, 3)), 3))
+ print sexp(last(list(1, 2, 3)))
+ print sexp(last(list(1, 2, 3), 2))
+ print sexp(last(cons(1, cons(2, 3)), 0))
+ print sexp(butlast(list(1, 2, 3), 2))
+ print sexp(butlast(list(1, 2, 3), 15))
+}'
+:
+(1 2)
+nil
+(1 2 3)
+(1 2 3 4)
+(1 2 3 4)
+(1 2)
+(3)
+(2 3)
+3
+(1)
+nil