Commit 92a18f99bb18b4a4c0b00a3530d932bc4b53ba50

Thomas de Grivel 2024-11-11T15:47:51

List.filter -> cfn List list_filter (List, Fn, Result)

diff --git a/lib/kc3/0.1/list.kc3 b/lib/kc3/0.1/list.kc3
index 96f27ed..38045c1 100644
--- a/lib/kc3/0.1/list.kc3
+++ b/lib/kc3/0.1/list.kc3
@@ -9,17 +9,7 @@ defmodule List do
     ([a | b], f) { f(a); each(b, f) }
   }
 
-  def filter = fn {
-    (list, f) { filter(list, f, []) }
-    ([], _, acc) { List.reverse(acc) }
-    ([first | rest], f, acc) {
-      if (result = f(first)) do
-        filter(rest, f, [result | acc])
-      else
-        filter(rest, f, acc)
-      end
-    }
-  }
+  def filter = cfn List "list_filter" (List, Fn, Result)
 
   def find_if = fn {
     ([], _) { false }
diff --git a/libkc3/list.c b/libkc3/list.c
index 2e99fde..e2897cc 100644
--- a/libkc3/list.c
+++ b/libkc3/list.c
@@ -60,6 +60,39 @@ void list_f_clean (s_list **list)
     l = list_delete(l);
 }
 
+s_list ** list_filter (const s_list * const *list, const s_fn *f,
+                       s_list **dest)
+{
+  s_list *arg;
+  const s_list *l;
+  s_list **tail;
+  s_list *tmp;
+  if (! (arg = list_new(NULL)))
+    return NULL;
+  tmp = NULL;
+  tail = &tmp;
+  l = *list;
+  while (l) {
+    if (! tag_copy(&arg->tag, &l->tag))
+      goto ko;
+    *tail = list_new(NULL);
+    if (! eval_fn_call(f, arg, &(*tail)->tag))
+      goto ko;
+    if ((*tail)->tag.type == TAG_VOID)
+      *tail = list_delete(*tail);
+    else
+      tail = &(*tail)->next.data.list;
+    l = list_next(l);
+  }
+  list_delete_all(arg);
+  *dest = tmp;
+  return dest;
+ ko:
+  list_delete_all(tmp);
+  list_delete_all(arg);
+  return NULL;
+}
+
 bool * list_has (const s_list * const *list, const s_tag *tag,
                  bool *dest)
 {
@@ -222,10 +255,12 @@ s_list ** list_map (const s_list * const *list, const s_fn *f,
     tail = &(*tail)->next.data.list;
     l = list_next(l);
   }
+  list_delete_all(arg);
   *dest = tmp;
   return dest;
  ko:
   list_delete_all(tmp);
+  list_delete_all(arg);
   return NULL;
 }
 
@@ -261,6 +296,7 @@ s_list * list_new_1 (const char *p)
   }
   return list;
 }
+
 /* FIXME: does not work on circular lists */
 s_list * list_new_copy (const s_list *src)
 {