Fork me on GitHub
#clojure
<
2022-07-17
>
Carlo13:07:39

I have a question for @mauricio.szabo and/or the people who tried out https://gitlab.com/mauricioszabo/spock. How did you install the JPL library? Did you need a specific version?

Carlo14:07:48

I ask this because after linking the version bundled in swi (> 8.0.0 as the readme suggests) in resources:

/home/carlo/code/clojure/swiOmg/resources λ ls -al                 

lrwxrwxrwx 1 carlo users   83 Jul 17 16:08 jpl.jar -> /nix/store/i8wyyyl0hcp1hmnhi63sa092vb66ixp4-swi-prolog-8.3.29/lib/swipl/lib/jpl.jar
lrwxrwxrwx 1 carlo users   98 Jul 17 16:29 libjpl.so -> /nix/store/i8wyyyl0hcp1hmnhi63sa092vb66ixp4-swi-prolog-8.3.29/lib/swipl/lib/x86_64-linux/libjpl.so
and including that path in my deps.edn file:
{:paths ["resources"]
 :deps
 {link.szabo.mauricio/spock {:mvn/version "0.1.1-SNAPSHOT"}}}
If I evaluate this in a repl:
(ns core
  (:require [spock.swi :as spock]))
I get the error:
2. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling spock/swi.clj at (1:1)
   #:clojure.error{:phase :execution, :line 1, :column 1, :source "spock/swi.clj"}
   ...

1. Caused by java.lang.ClassNotFoundException
   org.jpl7.Atom

mauricio.szabo18:07:48

Hi, author here: it needs a somewhat recent version of JPL / SWI. What's the result of swipl --version?

❤️ 1
Carlo19:07:44

Hey @mauricio.szabo, thanks for looking into this. So, the swipl version is:

/home/carlo/code/prolog λ swipl --version
SWI-Prolog version 8.3.29 for x86_64-linux
and I invoke the repl with the correct -J-D invocation (I see that the java library path is set to resources/ . I also used the version of JPL that come included in the swipl installation.

mauricio.szabo19:07:09

Ok, I did look at my machine, and mine is 8.4.3. I'm on Linux, installed SWI with the official PPA - packages name are swi-prolog and swi-prolog-java Also tried ls -l resources on my root path, and it returned this:

... jpl.jar -> /usr/share/java/jpl.jar
... libjpl.so -> /usr/lib/x86_64-linux-gnu/jni/libjpl.so

mauricio.szabo19:07:24

(removed the permissions and date to get in a single line)

mauricio.szabo19:07:22

My project.clj also includes the following paths:

:resource-paths ["resources/jpl.jar"]
  :jvm-opts [~(str "-Djava.library.path=resources/:" (System/getProperty "java.library.path"))]

mauricio.szabo19:07:13

Can you check if both are present? Please notice that I only got things working by linking the native libraries on the resources path, not by copying them - not sure why

Carlo19:07:41

Yes they are both present, I included an ls in my original post, looks like:

/home/carlo/code/clojure/swiOmg/resources λ ls -al                 
jpl.jar -> /nix/store/i8wyyyl0hcp1hmnhi63sa092vb66ixp4-swi-prolog-8.3.29/lib/swipl/lib/jpl.jar
libjpl.so -> /nix/store/i8wyyyl0hcp1hmnhi63sa092vb66ixp4-swi-prolog-8.3.29/lib/swipl/lib/x86_64-linux/libjpl.so

Carlo19:07:57

I'm using deps.edn so the paths look a bit different from the project.clj you linked. Idea, do you have the sample project that works for you somewhere on gitlab?

Carlo19:07:41

Wait, it seems to work now, because you have this:

:resource-paths ["resources/jpl.jar"]
and I only did the paths as
:paths ["resources/"]
while translating

Carlo19:07:54

let me check that I can actually do a query

Carlo19:07:23

I don't seem to have a spock.swi/with-facts var. Ah, it's called with-rules now partyparrot

Carlo19:07:58

But I can otherwise do my queries, so the setup part is solved partyparrot

mauricio.szabo19:07:23

Wow, wonderful! Mind if you can do a PR for the README, to add support for deps.edn?

mauricio.szabo19:07:03

By the way, I'm almost done adding support for ClojureScript too :rolling_on_the_floor_laughing:

❤️ 1
Carlo19:07:17

I'll absolutely do that, and also include the fix for with-rules. I intend also to check out the instructions for cljs (although I'm a bit scared for the non auto-loading libraries part)

Carlo19:07:24

oh, that's wonderful

Carlo19:07:42

does it fix the library autoloading issue?

Carlo19:07:01

also, a bit of a surface question: I wonder why you chose this as the representation of a rule:

(ancestor [:x :y] [(parent :x :z)
                   (ancestor :z :y)])
instead of e.g.
((ancestor :x :y) [(parent :x :z) (ancestor :z :y)])
which keeps the symmetry of argument syntax

mauricio.szabo19:07:06

Unfortunately, no. There seems to be no way to fix that, honestly, because the way WASM works. It may be possible to fix it if we recompile the SWI WASM to include the Node.JS filesystem option, but then it'll only autoload in Node (and that's probably the target that people don't want to use it anyway - specially considering we can avoid all that by calling SWIPL directly with the command line and avoid all WASM)

Carlo19:07:03

right, could we just autoload the common modules that swi autoloads by grabbing the sources, so that the user doesn't have to do that himself?

Carlo19:07:18

also, another question (sorry!): in the clj version, is a new process spawned every time I do a query, or is there a pl server that I'm asking questions to?

mauricio.szabo19:07:50

> also, a bit of a surface question Honestly, I don't remember 😅. But things changed quite a lot, and honestly if I could time-travel on the past, I would remove 100% of these weird things and just do the following, for example:

[(parent child dad)
 (parent child mom)
 (:- (ancestor :x :y) (and parent :x z) (ancestor :z :y)))]

mauricio.szabo19:07:07

BTW, this sintax above is also supported too

😍 1
Carlo19:07:42

the syntax you just posted is also perfect, glad that's supported (and should probably be mentioned in the README)

mauricio.szabo19:07:14

Yeah, I'm not a good documenter, unfortunately 😞

mauricio.szabo19:07:36

Also, clj uses the rules for JPL. If I'm not mistaken, JPL spawns a SWIPL "server" and uses a thread pool to handle queries

💯 1
Carlo19:07:48

Ah, don't think that's true, and I can do a PR for this particular instance, if you want it

Carlo19:07:28

about you being a good documenter, not JPL 😂

Carlo19:07:58

in fact I read that JPL also has a mechanism for async queries that enable going back and forth between prolog and the java process

Carlo19:07:35

ok, I'll do the PRs in ~1h, and then try to get the cljs version running and I'll probably post more questions

Carlo19:07:55

where do you usually take the autoloading files? Which one are needed at a minimum?

mauricio.szabo21:07:14

I usually use only lists because I use member a lot

Carlo21:07:33

I see, thank you. In the meatime, I was trying to get precise with the alternative syntax you mentioned. What's wrong with:

(def example
  '[(parent child dad)
    (parent child mom)
    (:- (ancestor :x :y) (and (parent :x z) (ancestor :z :y)))])

(with-open [rules (spock/with-rules example)]
  (spock/solve {:rules rules} '(ancestor :anc :desc)))

Carlo21:07:02

The error is Don't know how to create ISeq from: clojure.lang.Symbol

mauricio.szabo14:07:35

Oh, wait, maybe I have a bug somewhere? Let me check...

Carlo14:07:53

I checked the code yesterday (am not at my PC now) and I only saw the path that interprets the syntax in the tutorial. Maybe you have the other one stowed in a branch?

mauricio.szabo14:07:55

Not even that, I ended up thinking about this syntax but did not implement it facepalm

😂 1
Carlo14:07:20

Well, good news, the library is still young enough that it could be added. Also, I was thinking about two issues yesterday related to notation. The first is, using :- as prefix like in traditional lisp syntax we lose the possibility to express directives, i.e. headless implications that are used when instructing the compiler, like in

:- use_module(library(lists)).
It's not even the case that we always have one syntactic construct as the head: in extensions like CHR, you can have conjunctions as the first part of the rule (but the operators there are ==> and <=> instead of :- The second thing is that we could seize the chance and propose a better syntax for the anonymous predicates used as part of higher order predicates (usually done with the yall library) so that we're not forced to write the infix version of
maplist({Postfix}/[In,Out]>>atom_concat(In,Postfix,Out),
            ListIn, ListOut).
Given these issues and analogue ones (DCGs, using constraint arithmetic by default etc) I wonder if we shouldn't open to the user the possibility of deciding how the interpretation is done. By the way, how do you import a prolog library in clj right now?

mauricio.szabo15:07:54

I honestly haven't though about all these cases 😄. For example, I'm relying on auto-import of libraries for now...

Carlo15:07:07

I would really like a syntax for higher order predicates that mimics the anonymous function literal in clojure (and we could do that with an ad hoc treatment of fn*

mauricio.szabo15:07:19

Maybe it could be a good idea to allow for some form or eval-string in SWI

mauricio.szabo15:07:09

Honestly, I would like to change this notation I'm using. It ended up being confused and ended up being TWO notations (one form rules/etc and one for queries)

mauricio.szabo15:07:29

For example, I remember now why I did not implement the :- -> basically, it changes semantics of EVERYTHING

mauricio.szabo15:07:04

Currently, a prolog struct like foo(a, b) is represented as (foo a b) in Clojure

mauricio.szabo15:07:32

So the "normal" way of representing rules should be (foo a b), *not* (foo [a b])`

mauricio.szabo15:07:31

So, foo(A, B) :- bar(A, Z), bar (Z, B) should become (:- (foo :a :b) (and (bar :a :z) (bar :z :b)))

mauricio.szabo15:07:39

And that is a huge breaking change 😞

Carlo16:07:37

Is this library already in production in a way that a breaking chance in syntax is not advisable?

mauricio.szabo22:07:03

I have no idea, honestly. I'm kinda willing to make a spock.swi-old and keep all the current code there