This isn't just a style thing, either; there are consequences. REPL-driven development loses a lot of its slickness when some expressions can only be eval'd in a special context.
Also, what am I supposed to do if two different parts of my program want to use Clolog? If I'm using Clolog, and one of my dependencies is using it too, will we end up trashing each other's global state? (The case of external dependencies is just an example. Let's say I have an application that sets up the Clolog state and runs a query. Part of the setup involves calls to other parts of my application. At the time the code was written, those other parts didn't use Clolog, but now they do, and there's a bug, because those other parts are trashing the Clolog state that their caller had set up, before it runs its query.) Of course, you could get around this by adding something like a dynamically bound variable that points to the instance of state to use, but at that point you're jumping through hoops to support a subpar (stateful) paradigm that Clojure developers expect to be free of.
Basically anything that excels when declarative specification of relationships is more natural than imperative algorithms.
Does anyone have good examples of open source codebases or reading material in this area? Lets imagine I have a set of complex business rules about the way a product can be configured and I want to use a logic programming language to enforce them, called from a web interface based on config data stored in a traditional relational database. Is that... a misunderstanding of how these things are to be used?
I've love a good book about how to bring tools and techniques for logical correctness into a Rails ecosystem... or similar language/framework for app dev. I love the promises many of logic languages make but can't rewrite existing applications in them wholesale and it seems like they're a poor fit for that anyways. How are people blending these worlds at large enterprises? Maybe the answer is that nobody really is yet, and thats what makes things like Clolog + Clojure so exciting?
oakes/odoyle-rules is a forward-chaining rules engine with a more straightforward approach - for someone already familiar with Clojure, it should be fun to try out. Then maybe check out Clara Rules, if I'm not mistaken the lib is specifically designed for business rules processing. For understanding the theoretical pieces, you probably want to look into forward vs. backward chaining rule systems; pattern matching used in rules engines; understanding how to model domain rules declaratively; Rete algorithm (odoyle lib explains it and iirc links to the paper).
I'm forever thankful for Clojure for reigniting my passion for programming, but particularly, I'm indebted to the many individuals in the Clojure community. Whenever I pose a question expecting just straightforward guidance or documentation links, I consistently receive profound, thought-provoking answers that surpass my expectations. Virtually every discussion I initiate with them ends up being incredibly educational, teaching me far more than I initially sought. I can confidently admit - yes, learning Clojure has made a better programmer out of me, but most importantly, it made me a better person.
Now, I have no direct experience with any of the common logical programming systems. I have familiarity.
But anytime I came upon anything that might justify such a system, the need just didn’t seem to justify it.
Talking less than 100 rules. Most likely less than a couple dozen. Stacking some IFs and a bit of math, strategically grouped in a couple aptly named wrapper methods to help reduce the cognitive load, and it’s all worked pretty well.
And, granted, if I had solid experience using these systems, onboarding cost would be lower.
When have you found it to be worth cutting over?
Instead, I implemented a minimal set of primitives, and wrote a set of derivation rules (e.g. "if you have X+Y, and Y supports negation, you can derive X-Y by X+(-Y)"), and constraints (operator overloads mustn't have ambiguous signatures, no cycles allowed in the call tree), and set up a code generator.
250 lines of Prolog, plus another 250 of ASP (a dialect of Prolog), and I had a code synthesizer.
it was one of the most magical experiences of my entire career. I'd write an optimized version of a function, rerun synthesis and it would use it everywhere it could. I'd add new types and operators and it'd instantly plumb them through. seeing code synthesis dance for you feels amazingly liberating. it's like the opposite of technical debt.
https://www.metalevel.at/queens/
https://leetcode-in-java.github.io/src/main/java/g0001_0100/...
That is, if you manage to figure out your own special case rule engine rather than a nest of if:s and for:s growing more organically.
If you have ten of these, e.g. more dimensions that would result in conflicts or constraints on where placement is possible in the domain, the Java (or PHP or JavaScript or whatever) solution is likely to turn out rather inscrutable. At least that's my experience in ERP and CRM-adjacent systems where I've spent considerable time figuring out and consolidating many years of piecemeal additions of constraint threading in things like planning and booking tasks and the like.
Sometimes I've scratched up algebraic expressions or standalone Prolog implementations to suss out what simpler code ought to look like.
Logic systems tend to show the value when rules become complex with many interdependencies or non-linear execution patterns emerge, or rules change frequently or need to be defined at runtime; when you need explanation tools - e.g., why was this conclusion reached?, etc.
I agree, situations for when you need to implement a logic system are not extremely common, but maybe I just have not worked in industries where they are - on top of my head I can think of: factory floor scheduling; regulatory compliance (e.g., complex tax rules); insurance systems, risk-calculation (credit approval); strategy games; retail - complex discounting; etc.
Type systems would absolutely choke on trying to solve things like: Knowlege representation and querying - imagine medical diagnosis systems with thousands symptoms and conditions; Dynamic constraint solving - where constraints emerge at runtime; Exploratory search problems requiring bfs/dfs of large solution spaces - e.g., route finding with changing conditions; NLP tasks - grammar parsing and understanding; etc.
The problem has always been getting facts into the prolog system. I’ve been looking for a prolog which is as easy to embed in eg Python or node as a Postgres client and… crickets.
https://github.com/tau-prolog/tau-prolog
https://pyswip.org/ https://www.swi-prolog.org/packages/mqi/prologmqi.html
Unfortunately the tau site's certificate seems to have lapsed sometime in the last week or so, but I swear it's actually very good.
log("2024-10-22", "09:09:23", "Mozilla", "/login").
log("2024-10-23", "09:09:24", "Safari", "/dash").
log("2024-10-24", "09:09:25", "Chrome", "/user").
log("2024-10-25", "09:09:26", "Brave", "/login").
Implementing a transform of a web server log file into Prolog can be as simple as this. In practice you'll have more like ten or twenty fields, of course. Then you can query along the lines of log(Date, Time, "user agent constraint", Resource). and don't have to be as diligent as when stacking grep:s or such.If you already keep all your logs in analytics databases the example isn't very good, but it ought to be easy to see how this trivial technique can be applied elsewhere.
BTW, Clojure was such a brilliant name (from Rich): Whenever I see a project starting with "Clo" I pay attention.
EDIT: had a chance to try it: a very cool resource!
IIRC Rich wanted a name that has CLR and J in it - Clojure initially was officially to be supported on both .Net and Java stacks. Later he realized that keeping it completely compatible on both platforms is an uphill battle. CLR Clojure still exists, but it's not "an officially supported" runtime.
You're going to love my "Cobol in Clojure" project "Clobol" then!
Then I did a Google search just to make sure...
So, why/when to choose this? When you want something much more Prolog-like, using the same search algorithm as Prolog. That said, they both do logic programming. I haven’t benchmarked, but from comments in the README, I suspect core.logic will be more performant as it compiles down to Clojure function calls which are then compiled down to Java function calls. It’s sort of like choosing between Python and Java. They both do imperative programming with objects but they both have their own strengths and weaknesses.
https://github.com/bobschrag/clolog/commits/main/
Maybe this post will spark some interest and revitalise it a bit?
But can you please make your substantive points more thoughtfully, without name-calling or shallow dismissals? These things are in the site guidelines: https://news.ycombinator.com/newsguidelines.html.
And that could be optimized further by leaving no comment.
All syntax is learned. None of it is "intuitive". Anything unfamiliar to you will seem unpleasant. Some syntaxes can be better than others, but to make that distinction you'd have to at least cite reasons why one syntax is better than another.