core-logic

yuhan 2019-03-12T13:17:01.006400Z

Is it possible to use natural numbers in core.logic? i.e. define a relation (inco x y) for positive integers such that it succeeds when (inc x) = y

yuhan 2019-03-12T13:20:38.007100Z

or do I have to resort to encoding Peano numbers via nested lists 😐

yuhan 2019-03-12T13:32:57.008100Z

oops, so that's the entire purpose of clojure.core.logic.fd, I was thrown off by the word "finite"

yuhan 2019-03-12T13:33:44.008700Z

the above would be (fd/+ x 1 y)

yuhan 2019-03-12T18:22:24.009800Z

Does anyone know why the matche macro generates nested (fresh [] .. forms with no bindings?

yuhan 2019-03-12T18:23:34.010900Z

Compared to an unrolled conde form without the nested freshes I've found it to run up to 50% slower

yuhan 2019-03-12T18:27:40.011200Z

e.g.

(matche [a b c d e]
  ([1 2 3 4 5]))
macroexpands to
(conde
  ((fresh [] (== 1 a)
     (fresh [] (== 2 b)
       (fresh [] (== 3 c)
         (fresh [] (== 4 d)
           (fresh [] (== 5 e))))))))
which is equivalent to the un-nested:
(conde
  ((== 1 a) (== 2 b) (== 3 c) (== 4 d) (== 5 e)))

2019-03-12T18:46:23.012900Z

I imagine it just matches the recursive structure of the macro, which is often the simplest way to write a macro like that

2019-03-12T18:47:26.013800Z

to collapse it you end up needing to loop and accumulate and build a final form at the end, where as if defined recursively your macro just does a single step and lets the macro expander do the rest

2019-03-12T18:49:27.014700Z

oh, it isn't an artifact of the matche macro's recursive nature, but the recursive nature of the helper function ex*

2019-03-12T18:50:11.015Z

the fresh isn't always empty

2019-03-12T18:50:36.015500Z

you can introduce a new logic var in a matche case

yuhan 2019-03-12T18:50:46.015700Z

yeah, I realise that

yuhan 2019-03-12T18:51:13.016700Z

but when matching against constants you end up with lots of empty fresh bindings all over the place

2019-03-12T18:51:13.016900Z

but the nested nature isn't great for that, I think

yuhan 2019-03-12T18:51:26.017300Z

which results in a huge performance cost 😕

2019-03-12T18:51:39.017600Z

you might want to match with 'p' is multiple places being the same lvar

2019-03-12T18:52:07.017900Z

well, I guess it just doesn't reintroduce p so that works

yuhan 2019-03-12T18:53:43.019300Z

I don't know much about the internals of core.logic, it seems like I can add a condition to the private ex function to optimize this case, but not sure if it might affect the correctness of other situations?

2019-03-12T19:04:47.022100Z

I am not sure either, the docstring for conde suggests some special handling of the first goal in a clause, which would suggest hoisting all those unifications to be goals in the clause would be different in some way, which would explain a large performance difference, but I don't see how it is the case that the first goal is anything special, so I don't know what the docstring is suggesting

yuhan 2019-03-12T19:27:25.023700Z

Each fresh macro expands to a doubly nested fn, so I imagine that the performance difference was due to the overhead of traversing all those call stacks