Klaus lets you define logical rules as data and query them at runtime. No external binaries, no FFI, no DSLs, just strings in, answers out.
Add to your Gemfile:
gem 'Klaus'Or install directly:
gem install Klaus
require 'klaus'
# Define a knowledge base
kb = Klaus.parse_knowledge_base(<<~PROLOG)
parent(john, bob).
parent(john, lisa).
parent(bob, ann).
parent(bob, carl).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
PROLOG
# Query for direct relationships
query = Klaus.parse_query('parent(john, X)')
solutions = Klaus.solve(kb, query)
# => [{X: Atom("bob")}, {X: Atom("lisa")}]
# Query with rule resolution
query = Klaus.parse_query('grandparent(john, Z)')
solutions = Klaus.solve(kb, query)
# => [{Z: Atom("ann")}, {Z: Atom("carl")}]| Method | Description |
|---|---|
Klaus.parse_knowledge_base(string) |
Parse a Prolog program (facts and rules) into its internal representation |
Klaus.parse_query(string) |
Parse a Prolog query into its internal representation |
Klaus.solve(knowledge_base, goals) |
Execute a query against a knowledge base, returns an array of solution environments |
See AGENTS.md for details.
The following ISO Prolog features are not yet implemented:
- Arithmetic (
is/2, comparison operators) - Lists (
[H|T]syntax) - Cut (
!) and negation-as-failure (\+) - Control constructs (
->,;) - Built-in predicates (
var/1,atom/1,findall/3, etc.) - I/O streams
- Exception handling (
catch/3,throw/1) - Occurs check (omitted intentionally, matching SWI-Prolog's default behavior)
An embeddable Prolog system offers a different way to structure logic: rules are treated as data rather than hard-coded into the application. This makes it possible to store them in databases or config files, edit them without touching the codebase, and update them without redeploying.
In practice, this can simplify things like access control, where permissions are expressed as rules instead of nested conditionals. It can also help with configuration validation, modeling decision logic in expert systems, or exploring data dependencies.
Because the rules are declarative and readable, they’re often easier to review, adjust, and extend. It can also make it more approachable to experiment with logic programming or apply it to areas like game AI, where exploring different outcomes is useful.
- ruby-prolog — Prolog-like DSL for Ruby with inline logic programming. Actively maintained, used in production for access control and layout engines.
- porolog — Prolog using plain old Ruby objects, designed to embed logic queries in regular Ruby programs.
- upl — FFI bridge to SWI-Prolog. Different approach: wraps a full Prolog runtime rather than reimplementing in Ruby.
Klaus differs by parsing standard Prolog syntax (not a Ruby DSL) and aiming for ISO compliance.
See CONTRIBUTING.md for guidelines.
Prolog is based on Horn clauses. Say "clauses" with a German accent and you get Klaus. Naturally, Klaus is a mountain goat with ... 🎉 ... horns 🤦🐐!
