Live data from Hacker News

Prolog Coding Horror

metalevel.at

71–80 of 88 posts

Re: Prolog Coding Horror

#71
post #3

What do people use Prolog for in the real world? I learned about it on a university course and it seems so esoteric compared to other things on the course. Like something invented just for computer scientists to enjoy.

Dunno about Prolog, but Datomic uses datalog for its query language, and it’s excellent. Datalog is a subset of Prolog.

The full story the other comments don't cover:

- Datalog is a syntactic subset of Prolog

- Real Prolog implementations generally have the ability to configure their runtimes such that it becomes a proper superset of Datalog

Re: Prolog Coding Horror

#72

Would a Prolog expert please explain the difference between > and #>, is and #=, and what ! does? The version without ! looks identical to the version with ! except only the ! is removed - is this a joke?

Prolog operators like `4 > 5` are a syntax sugar which desugars into a normal function call `>(4, 5)`. This part of the language is programmable, so you can add your own function `#>(X, Y)` and then declare it as an operator and use it like `4 #> 5`. See [1]. Nitpickingly, this means we can't be sure what #> is without looking, but it's common in Scryer and SWI Prolog (at least) that the #> #
    import solver

    solver.add_variable(x)
    solver.variable_range(x, 0, 100)
    solver.add_constraint(x, greater_than, 50)

    solver.solve_for(x)
in pseudo-Prolog it can be:

    :- using constraint solver library
    
    X in 0..100,
    X #> 50,

    label(X)
where "in" and "#>" were added into the language at runtime by the import of the constraint library. That is, it calls out to a custom 'function' which tells the constraint solver to restrict possible values for for X from 0..100 down to 51..100.

> "and what ! does"

This is a concept which doesn't translate easily to other languages, but analogously it's like the performance difference between this code which always searches the entire haystack:

    found = false
    for item in haystack:
        if item == 'needle':
            found = true

    return found
and this which stops searching the haystack if the needle is found, but still searches the entire haystack in the worst case:

    for item in haystack:
        if item == 'needle':
            return true

    return false
The catch being that ! is not exactly a performance thing, it's an instruction to the Prolog runtime to skip some of the code, which can speed up performance but if you throw it in carelessly, your code no longer gives the right answers.

[1] They aren't Prolog "functions", they are predicates, functions are different, but it will do for this explanation.

Re: Prolog Coding Horror

#74
post #3

What do people use Prolog for in the real world? I learned about it on a university course and it seems so esoteric compared to other things on the course. Like something invented just for computer scientists to enjoy.

I've just rolled out an internal SWI Prolog app that is similar to one linked to elsewhere in the thread [1]. We have a large Cloud estate with 10s of thousands of resources in it. Detecting unused or misconfigured resources manually isn't practical, and there are significant cost savings to be had by cleaning things up. The Prolog app reads in JSON resource snapshots, creates an in-memory database of facts from it a…

This sounds like a very useful way to use Prolog. I would also guess that is a more efficient and direct method for performing pattern detection vs an LLM.

Re: Prolog Coding Horror

#75

Earlier quoted context omitted.

What is Datalog used for nowadays?

General programming [0], static analysis [1], RDF triple stores [2], authorization systems [3], incremental computation [4] [5], graph DBs [6]. But it is kind of hard to define Datalog exactly, since it is an entire family of technologies based on logic, each extending a clean mathematical model differently. [0] https://github.com/flix/flix [1] https://github.com/rust-lang/polonius [2] RDFox [3] https://github.com/ec…

thanks for your list. appreciated. my question should have been more precise. last time I checked all the Datalog projects I found where either old, unmaintained or have only a single contributor. and that is also true for your examples. I really like Prolog and would love to use Datalog for (RDF) knowledge graph inference.

Re: Prolog Coding Horror

#76

Earlier quoted context omitted.

General programming [0], static analysis [1], RDF triple stores [2], authorization systems [3], incremental computation [4] [5], graph DBs [6]. But it is kind of hard to define Datalog exactly, since it is an entire family of technologies based on logic, each extending a clean mathematical model differently. [0] https://github.com/flix/flix [1] https://github.com/rust-lang/polonius [2] RDFox [3] https://github.com/ec…

thanks for your list. appreciated. my question should have been more precise. last time I checked all the Datalog projects I found where either old, unmaintained or have only a single contributor. and that is also true for your examples. I really like Prolog and would love to use Datalog for (RDF) knowledge graph inference.

Then use them! Then those projects will cease having a single contributor or being unmaintained. This doesn't need to be a binary decision (either there is no risk or I won't use it), just choose the project / scope with knowledge that there is some risk in a small community; so internal use rather than client facing, specialized uses, etc.

Re: Prolog Coding Horror

#77

Earlier quoted context omitted.

thanks for your list. appreciated. my question should have been more precise. last time I checked all the Datalog projects I found where either old, unmaintained or have only a single contributor. and that is also true for your examples. I really like Prolog and would love to use Datalog for (RDF) knowledge graph inference.

Then use them! Then those projects will cease having a single contributor or being unmaintained. This doesn't need to be a binary decision (either there is no risk or I won't use it), just choose the project / scope with knowledge that there is some risk in a small community; so internal use rather than client facing, specialized uses, etc.

not sure how using a project adds a contributor. but for the latter - I'm not sufficiently competent at Prolog and friends to meaningfully contribute. I do donate money, though, to projects I regularly use - like for example FreeTube or Linux Mint.

Re: Prolog Coding Horror

#78
Well, with respect to Markus Triska, I don't like purity. Prolog gives you plenty of "impure" constructs like the cut (!/0) and the assert/retract family of database manipulation predicates. It also gives you impure I/O and arithmetic functions that are quite separate from the otherwise logical, declarative-ish style of the language.

I'm fine with all that. The language gives you sensible tools to deal with edge cases that otherwise require you to jump through hoops or import libraries (like the constraint arithmetic libraries that Markus recommends... and that he had to mostly write himself before he could recommend). You can get into a spot of bother if you use those facilities without knowing why they are there and why you shouldn't just spam them in every case, but that's why good textbooks exist.

And more to the point, that's why Prolog Coding Guidelines are a thing, more precisely, a paper, which you can find here from the website of Michael Covington who's one of its (many) authors:

https://www.covingtoninnovations.com/mc/plcoding.pdf

Here's what the Guidelines has to say about assert/retract:

5.10 Avoid asserta/assertz and retract unless you actually need to preserve information through backtracking Although it depends on your compiler, asserta/assertz and retract are usually very slow. Their purpose is to store information that must survive backtracking. If you are merely passing intermediate results from one step of computation to the next, use arguments.

If you have a dynamic predicate, write interface predicates for changing it instead of using “bare” calls to asserta/assertz and retract, so that your interface predicates can check that the changes are logically correct, maintain mutexes for multiple threads, and so forth.

Sound advice. In fact that's what I've always done myself even before reading the Guidelines.

And here's some advice on using the "horror" of the cut without having to wake the Great Old Ones:

5.4 Use cuts sparingly but precisely First think through how to do the computation without a cut; then add cuts to save work. For further guidance see O’Keefe (1990, pp. 88–101). Concerning code layout, make sure cuts do not go unnoticed: if a green cut7 may be placed on the same line as the previous predicate call, red cuts definitely must be on their own line of code.

5.5 Never add a cut to correct an unknown problem A common type of Prolog programing error is manifested in a predicate that yields the right result on the first try but goes wrong upon backtracking. Rather than add a cut to eliminate the backtracking, investigate what went wrong with the logic. There is a real risk that if the problem is cured by adding the cut, the cut will be far away from the actual error (even in a different predicate), which will remain present to cause other problems later

Basically the message should be that we can help the novice to navigate the complexities of the language without underestimating or pataronising them. Cuts, asserts, and the lot, are just there to make things easier. They only make things harder when they're not explained properly. And telling everyone to just stay away from them is, I think, not the proper way to explain anything.

Re: Prolog Coding Horror

#79

Would a Prolog expert please explain the difference between > and #>, is and #=, and what ! does? The version without ! looks identical to the version with ! except only the ! is removed - is this a joke?

>> The version without ! looks identical to the version with ! except only the ! is removed - is this a joke?

That's just showing getting rid of the cut in two stages. The line that makes it possible to remove it is this one:

N #> 0,

Markus Triskas' argument is that if you use the #> etc versions of declarative arithmetic operators, instead of the > ones, you can then call the factorial predicate with both arguments as variables, i.e. without inputs, just outputs, to enumerate the entire factorial relation. Like this:

  ?- n_factorial(N, F).
     N = 0, F = 1
  ;  N = 1, F = 1
  ;  N = 2, F = 2
  ;  N = 3, F = 6
  ;  ... .
If you use > instead of #> the line N > 0 will raise an exception if N is a variable, which will be the case if you call it as above. This stops you from enumerating the relation, which declarative arithmetic allows.

Of course there are other ways to write a factorial predicate (or any predicate) so that it always enumerates a relation but they are more verbose. Then again, you do need a special library to use declarative arithmetic anyway, so.

Re: Prolog Coding Horror

#80

Well, with respect to Markus Triska, I don't like purity. Prolog gives you plenty of "impure" constructs like the cut (!/0) and the assert/retract family of database manipulation predicates. It also gives you impure I/O and arithmetic functions that are quite separate from the otherwise logical, declarative-ish style of the language. I'm fine with all that. The language gives you sensible tools to deal with edge case…

I kind of agree with both of you. I would have become better at Prolog faster if I had stuck to the discipline Triska promotes early on, but I also think the guidelines you cite are reasonable once one is starting to do somewhat productive work where compromises and speed factors in.

Over the years I've come to a similar position in other languages as well. If a functional-ish solution fits performance constraints and is maintainable, don't mutate or reach for global state, things like that.

Post reply on HN