summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-07-24 20:59:56 -0700
committerKaz Kylheku <kaz@kylheku.com>2024-07-24 20:59:56 -0700
commitf3e8151605506935a04ea34e758452bf55881e9b (patch)
treea9c97f400bf6b43825ef0b4f6a6cc941e4aec887 /lib.c
parent1f4cde420a19e5bef9160c08b95e1723d4895d01 (diff)
downloadtxr-f3e8151605506935a04ea34e758452bf55881e9b.tar.gz
txr-f3e8151605506935a04ea34e758452bf55881e9b.tar.bz2
txr-f3e8151605506935a04ea34e758452bf55881e9b.zip
zip: more permissive implementation.
zip and transpose should allow non-character data when the leftmost column is a string, falling back on making lists, like seq_build. We can't use seq_build as-is because of the special semantics of transpose/zip with regard to strings. We introduce a "strcat" variant of seq_build for this purpose. * lib.c (seq_build_strcat_add): New static function. (sb_strcat_ops): New static structure like sb_str_ops, but with seq_build_strcat_add as the add operation, which allows string arguments to be appended to the string rather than switching to a list. (seq_build_strcat_init): New function. * lib.h (seq_build_strcat_init): Declared. * eval.c (zip_strcat): New static function; uses seq_build_strcat_init. (zipv): Only recognize strings specially; all else goes through the existing default case. Strings use zip_strcat. * tests/012/seq.tl: New test case. * txr.1: Describe special semantics of zip/tranpose; previously only documented in one example. Clarify that the rows are only sequences of the same kind as the leftmost column if possible, otherwise lists. Remove text which says that it's an error for the other columns to contain non-string, non-character objects if the leftmost column is a string.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index 193f8196..077d51ea 100644
--- a/lib.c
+++ b/lib.c
@@ -1597,6 +1597,16 @@ static void seq_build_str_add(seq_build_t *bu, val item)
}
}
+static void seq_build_strcat_add(seq_build_t *bu, val item)
+{
+ if (chrp(item) || stringp(item)) {
+ string_extend(bu->obj, item, nil);
+ } else {
+ seq_build_convert_to_list(bu, list_str(bu->obj));
+ bu->ops->add(bu, item);
+ }
+}
+
static void seq_build_str_finish(seq_build_t *bu)
{
string_finish(bu->obj);
@@ -1669,6 +1679,13 @@ static struct seq_build_ops
seq_build_obj_mark);
static struct seq_build_ops
+ sb_strcat_ops = seq_build_ops_init(seq_build_strcat_add,
+ seq_build_generic_pend,
+ seq_build_generic_pend,
+ seq_build_str_finish,
+ seq_build_obj_mark);
+
+static struct seq_build_ops
sb_buf_ops = seq_build_ops_init(seq_build_buf_add,
seq_build_generic_pend,
seq_build_generic_pend,
@@ -1772,6 +1789,12 @@ void seq_build_init(val self, seq_build_t *bu, val likeobj)
}
}
+void seq_build_strcat_init(seq_build_t *bu)
+{
+ bu->obj = string(L"");
+ bu->ops = &sb_strcat_ops;
+}
+
void seq_add(seq_build_t *bu, val item)
{
bu->ops->add(bu, item);