Fork me on GitHub
#core-logic
<
2020-11-05
>
nitaai14:11:21

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] ?

nitaai14:11:15

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

nitaai15:11:18

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?

hiredman18:11:21

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

hiredman18:11:59

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

hiredman18:11:19

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

hiredman18:11:59

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

nitaai18:11:23

Great and interesting hints. Thanks @UCPGSBNQ4 and @U0NCTKEV8. Will look into that…

nitaai08:11:13

(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 @U0NCTKEV8 suggested and uses defna. the arrangement of the clauses still matters, but it makes sense.