Logic programming always appealed to me, but I always felt like I never understood what to actually do with it other than write toy programs about parent-child relationships (I tried learning Prolog a few times, but stopped for this reason).
Logic programming always appealed to me, but I always felt like I never understood what to actually do with it other than write toy programs about parent-child relationships (I tried learning Prolog a few times, but stopped for this reason).
I don't want to have to define security groups, subnets, route tables, etc. Instead, I want to declaratively say "Service A must communicate with Service B", and based on the properties of those services, all the correct cloud resources will be defined. Subject, of course, to constraints around security, etc.
We are tantalizingly close to this with current IaC tools (CDK, Pulumi, etc) but at the end of the day you still need to define each granular cloud resource (even if the code to do so can be tucked away in a library abstraction.)
I'm busy with my current gig now, but if you forced me to launch a startup at gunpoint, this would definitely be it.
You have to solve some kind of 3-SAT-reducible problem that would be difficult to implement otherwise.
You have to do some heavy pattern-matching.
Closely related: https://en.wikipedia.org/wiki/Answer_set_programming
I am kind of half-considering it for mud scripting? Each line from the mud represents a fact or relation so this could be used to query for specific information as needed.
For this case though, it doesn't really seem better than writing a regex-based DSL though, something I'm far more familiar with and that is better supported.
I guess I think of logic languages as SQL but I actually want to write my whole program in it.
Generally speaking, you'll see the same pattern for any problem involving searching a space of potential solutions. In a word, the strength of LP is flexibility when facing the unkown (future feature requirement).
EDIT: you mention parsing. If you're planning anything context-sensitive, you have to check out eDCGs. You probably won't use them, but they'll give you an idea of what's possible.
This feels like a much better path than trying to get it into an AST with like yacc or whatever. But since it isn't actually natural language NLP didn't seem right either. I've got a lot of reading to do but this is very interesting.
Your mud language is probably a "Controlled Natural Language", btw:
https://en.wikipedia.org/wiki/Controlled_natural_language
Game languages often are.
https://github.com/kamahen/edcg , https://occasionallycogent.com/prolog_edcgs/index.html
Curious - I fuzzily recall usually ending up manually threading state (eg, doing a Perl-Compatible Regular Expression engine (apropos "why LP?" - it was just a page of code, with good performance)), but I don't recall what drove that decision...
It didn't work out in my case. I found it really fiddly to work with, and the implementation I was loosely working from was very idiomatic Lisp.
We'll see if performance is an issue, but the space I'm most interested in is turn based strategy / board games, where it doesn't seem to be a big deal if things are as fast as possible.
It feels like a pretty natural fit, e.g.:
can_move_to(unit_id, tile) :-
Unit(unit_id), Tile(tile),
reachable_to(unit_id, tile, move_cost),
unit_move_points_remaining(unit_id, mv),
move_cost <= mv.
You can define a lot of rules from basic unit movement to "what happens when you activate Super Special Rule-Bending Ability" this way, and it's pretty easy to change the definitions if you want to experiment with different game rules / logic. In practice, you want various syntactic sugar.Haven't got a chance to take this very far yet, just casual experimentation, but it seems like there's potential.
The jump from a well-written, unambiguous and precise set of board game rules and its translation in Prolog is a tiny step, that could even be automated with some elbow grease.
Now, you mention "rendering" and that, on the other hand, I'm not sure is a very good application for Prolog. Nothing to do with speed, but arithmetic in Prolog is a bit meh, and if you want to do stuff like matrix arithmetic, you have to roll your own. Most Prologs don't even have arrays, as such (they kind of do but it's a bit of a hack).
you also might enjoy looking at incremental datalog (differentiating rules and operating on events). this generally does a really good job of touching just what need to update the global state.
this is a great application
Most of the benefits I found come down to two things:
a) Prolog, like the various kanrens, is a relational language so a program is effectively a database. There's no need to do anything special to glue together a data layer and a logic layer, because you have both written in Prolog. No object-relational impedance mismatch whatsoever.
b) Prolog's declarative style makes translating rules and directives into code a breeze. The three projects below are all games and benefit heavily from this feature. The same would go for business logic of any shape or form.
1. Warhammer 40K simulation:
https://github.com/stassa/wh40ksim
Runs simulations of combat between WH40k units.
2. Gleemin, a Magic: the Gathering expert system:
https://github.com/stassa/Gleemin
Doesn't work anymore! Because backwards compatibility. Includes a) a parser for the rules text on M:tG cards written in Prolog's Definite Clause Grammars notation, b) a rules engine and c) a (primitive) AI player. The parser translates rules text from cards into rules engine calls. The cards themselves are Prolog predicates. Your data and your program are one and now you can also do stuff with them.
3. Nests & Insects, a roguelike TTRPG:
https://github.com/stassa/nests-and-insects
WIP! Here I use Prolog to keep the data about my tabletop rpg organised, and also to automatically fill-in the character sheets typeset in the rulebook. The Prolog code runs a character creation process and generates completed character sheets. I plan to do the same for enemies' stat blocks, various procedural generation tables, etc. I also use Prolog to typeset the ASCII-styled rulebook, but that's actually not a good application of Prolog (too imperative).
You asked about "logic programming" in general and not miniKanren in particular. I haven't actually used miniKanren, so I commented about the logic programming language I've used the most, Prolog. I hope that's not a thread hijack!
All three of the projects above are basically games. I have more "serious" stuff on my github but I am currently experiencing a certain shortfall of gravitas.
I've seen things like this in the context of "algebraic effects", where instead of performing I/O (and instead of using monadic I/O) you build up what amounts to an execution graph of effectful operations, which is then "interpreted" at runtime. Is that what you're describing?
Check this out for prolog:
https://www.swi-prolog.org/pldoc/man?section=pio
https://github.com/mthom/scryer-prolog/blob/084fc845902f7b43...
"New" stuff in the MiniKanren world:
https://staff.fnwi.uva.nl/c.u.grelck/nl-fp-talks/kourzanov.p...
https://ifl2014.github.io/submissions/ifl2014_submission_18....
I mean, my intuition is that a file is a stream of bytes and wading through that stream is not going to be "pure" no matter what, just because a byte is not a concept in First Order Logic. But, OK, "pure" Prolog is not the same as FOL anyway, and so I may be convinced otherwise when I have the chance to peruse your links. So thanks again and sorry for any negative vibes emanating from my comment.
I guess my confusion about pure I/O stems from the documentation of phrase_from_file/2 in SWI-Prolog. The documentation says the predicate is for pure I/O and how it was implemented, and by whom, but it doesn't say what pure I/O is, and why it is needed. I guess the information is somewhere in one (or more) of the canonical Prolog textbooks, which I've only read several years ago (though multiple times over, each).
I have to confess also I'm not much of a purist. My Prolog code looks like bog standard imperative code where I feel it doesn't really matter (e.g. I don't have any prejudice about setof/3 or maplist/2 over findall/3), and I guess file I/O is one of those cases.
Anyway, thanks again, for your links and explanation. I owe you a quantum of knowledge :)