core-logic 2020-11-05

hi. i have ported one prolog example to core.logic:

% P07 (**) Flatten a nested list structure.
my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([X|Xs],Zs) :- my_flatten(X,Y), my_flatten(Xs,Ys), append(Y,Ys,Zs).

(defne flatteno [l1 l2]
  ([x [x]] (pred x (comp not seq?)))
  ([[] []])
  ([[x . xs] zs]
   (fresh [y ys]
     (flatteno x y)
     (flatteno xs ys)
     (appendo y ys zs))))
can someone tell me why the clojure version produces multiple results: ([[1 [2]]] (1 [2]) (1 2)) and the prolog version only one: [1 2] ?

(defna flatteno [l1 l2]
  ([[] []])
  ([[x . xs] zs]
   (fresh [y ys]
     (flatteno x y)
     (flatteno xs ys)
     (appendo y ys zs)))
  ([x [x]]))
i think this is the best solution. it got rid of predas @hiredman suggested and uses defna. the arrangement of the clauses still matters, but it makes sense.

I assume some rearrangement of the clauses and use of defna or defnu..

yes, my assumption was right:

(defna flatteno [l1 l2]
  ([[x . xs] zs]
   (fresh [y ys]
     (flatteno x y)
     (flatteno xs ys)
     (appendo y ys zs)))
  ([x [x]] (pred x (comp not seq?)))
  ([[] []]))
both defna and defnu do the job and clauses have to be rearranged. Someone who knows prolog can tell me why this kind of cut is necessary in clojure and not in prolog?

I would strongly recommend against using pred, and seq? is likely the wrong predicate there

the re-arrangement of the clauses and using defna or defna are both consequences of seq? being the wrong predicate

user=> (seq? [])
false
user=>

but using defna you should be able to get rid of the pred usage altogether

Great and interesting hints. Thanks @jkr.sw and @hiredman. Will look into that…