diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | lib.c | 36 | ||||
-rw-r--r-- | txr.1 | 34 |
3 files changed, 75 insertions, 3 deletions
@@ -1,3 +1,11 @@ +2014-01-21 Kaz Kylheku <kaz@kylheku.com> + + * lib.c (car, cdr, ldiff): Extend to handle vectors and strings. + Thereby, numerous previously list-only operations in TXR Lisp + now magically handle strings and vectors. + + * txr.1: Documented. + 2014-01-20 Kaz Kylheku <kaz@kylheku.com> * lib.c (broken_down_time_list): New static function. @@ -203,6 +203,16 @@ val car(val cons) cons->lc.func = nil; return cons->lc.car; } + case VEC: + if (zerop(cons->v.vec[vec_length])) + return nil; + return cons->v.vec[0]; + case STR: + case LIT: + case LSTR: + if (zerop(length_str(cons))) + return nil; + return chr_str(cons, zero); default: type_mismatch(lit("~s is not a cons"), cons, nao); } @@ -223,6 +233,13 @@ val cdr(val cons) cons->lc.func = nil; return cons->lc.cdr; } + case VEC: + case STR: + case LIT: + case LSTR: + if (le(length(cons), one)) + return nil; + return sub(cons, one, t); default: type_mismatch(lit("~s is not a cons"), cons, nao); } @@ -611,9 +628,22 @@ val ldiff(val list1, val list2) { list_collect_decl (out, ptail); - while (list1 && list1 != list2) { - list_collect (ptail, car(list1)); - list1 = cdr(list1); + switch (type(list2)) { + case STR: + case LIT: + case LSTR: + case VEC: + while (list1 && !equal(list1, list2)) { + list_collect (ptail, car(list1)); + list1 = cdr(list1); + } + break; + default: + while (list1 && list1 != list2) { + list_collect (ptail, car(list1)); + list1 = cdr(list1); + } + break; } return out; @@ -5003,6 +5003,40 @@ In TXR Lisp, the / character can occur in symbol names, and the / token is a symbol. Therefore the /regex/ syntax is absent, replaced with the #/regex/ syntax. +.SS Generalization of List Accessors car and cdr + +In ancient Lisp in the 1960's, it was not possible to apply the operations +car and cdr to the nil symbol (empty list), because it is not a cons cell. In +the InterLisp dialect, this restriction was lifted: these operations were +extended to accept nil (and return nil). The convention was adopted in +other Lisp dialects and in Common Lisp. Thus there exists an object which +is not a cons, yet which takes car and cdr. + +In TXR Lisp, this concept is extended further. For the sake of convenience, +the operations car and cdr, are extended to work with strings and vectors: + + (cdr "") -> nil + (car "") -> nil + + (car "abc") -> #\ea + (cdr "abc") -> "bc" + + (cdr #(1 2 3)) -> #(2 3) + (car #(1 2 3)) -> 1 + +The ldiff function is also extended in a special way. When the right parameter +is a string or vector, then it uses the equal equality test rather than eq +for detecting the tail of the list. + + (ldiff "abcd" "cd") -> (#\ea #\eb) + +The ldiff operation starts with "abcd" and repeatedly applies cdr to produce +"bcd" and "cd", until the suffix is equal to the second argument: (equal "cd" +"cd") yields true. + +Operations based on car, cdr and ldiff, such as keep-if and remq extend to +strings and vectors. + .SH CONTROL FLOW AND SEQUENCING When the first element of a compound expression is an operator symbol, |