diff options
-rw-r--r-- | cppawk-cons.1 | 163 | ||||
-rw-r--r-- | cppawk-include/cons-priv.h | 6 | ||||
-rw-r--r-- | testcases-cons | 30 |
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 |