Hash :
d41f2661
Author :
Thomas de Grivel
Date :
2025-05-18T20:36:15
fix doc nav and links
Facts are triples in the form {subject, relation, object}.
They are stored in a database. To create an empty database
call Facts.database(). To query the environment database
(global database with all program symbols and operators) use
Facts.env_db().
Use Facts.add_tags to add a triple to a database and
Facts.remove_tags to remove a triple from a database.
Facts can be queried in order from queries in triples.
If you only need one triple you can use Facts.with_tags or
Facts.collect_with_tags. If you need a join query you can
use Facts.with or Facts.collect_with to query multiple triples
at the same time. These functions initialize internally an iterator
for the query and then call the iterator in a loop calling a callback
function or evaluating the passed block for _macro variants.
You can achieve persistence by calling just one function.
Facts.open takes a database and a pathname as arguments and
replays the dump and the log in the file and opens the file for
appending for logging all transactions.
Transactions make their content atomic. A transaction either end in success or error. In the latter case, the already applied parts of the transaction are rolled back in reverse order. The database is locked read/write during a transaction. Transactions can be nested and are multithread ready with pthread support.
Create a database and add and remove triples and do a full query (?, ?, ?) :
ikc3> db = Facts.database()
(Ptr) 0x12345678
ikc3> Facts.add_tags(db, "Blade Runner", :is_a, :movie)
true
ikc3> Facts.add_tags(db, "Snow White", :is_a, :movie)
true
ikc3> Facts.remove_tags(db, "Blade Runner", :is_a, :movie)
true
ikc3> Facts.with_tags(db, ?, ?, ?, fn (fact) { puts(inspect(fact)) })
{"Snow White", :is_a, :movie}
Query operators from the global environment :
ikc3> Facts.with(Facts.env_db(), [[op = ?, :is_a, :op],
ikc3> [op, :op_sym, sym = ?]], fn (fact) {
ikc3> puts("#{inspect(sym)} #{inspect(op)}")
ikc3> })
The config module from an HTTPd instance has an example of persistence, this way the database is loaded when the module is loaded :
defmodule Config do
def db = Facts.database()
Facts.open(db, "db/app.facts")
end
Top : KC3 documentation
Previous : 1.24 Variable
Next : 1.26 Named block
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
# 1.25 Facts
Facts are triples in the form `{subject, relation, object}`.
They are stored in a database. To create an empty database
call `Facts.database()`. To query the environment database
(global database with all program symbols and operators) use
`Facts.env_db()`.
Use `Facts.add_tags` to add a triple to a database and
`Facts.remove_tags` to remove a triple from a database.
Facts can be queried in order from queries in triples.
If you only need one triple you can use `Facts.with_tags` or
`Facts.collect_with_tags`. If you need a join query you can
use `Facts.with` or `Facts.collect_with` to query multiple triples
at the same time. These functions initialize internally an iterator
for the query and then call the iterator in a loop calling a callback
function or evaluating the passed block for `_macro` variants.
You can achieve persistence by calling just one function.
`Facts.open` takes a database and a pathname as arguments and
replays the dump and the log in the file and opens the file for
appending for logging all transactions.
Transactions make their content atomic. A transaction either end
in success or error. In the latter case, the already applied parts
of the transaction are rolled back in reverse order. The database
is locked read/write during a transaction. Transactions can be
nested and are multithread ready with pthread support.
# 1.25.1 Examples
Create a database and add and remove triples and do a
full query (?, ?, ?) :
```elixir
ikc3> db = Facts.database()
(Ptr) 0x12345678
ikc3> Facts.add_tags(db, "Blade Runner", :is_a, :movie)
true
ikc3> Facts.add_tags(db, "Snow White", :is_a, :movie)
true
ikc3> Facts.remove_tags(db, "Blade Runner", :is_a, :movie)
true
ikc3> Facts.with_tags(db, ?, ?, ?, fn (fact) { puts(inspect(fact)) })
{"Snow White", :is_a, :movie}
```
Query operators from the global environment :
```elixir
ikc3> Facts.with(Facts.env_db(), [[op = ?, :is_a, :op],
ikc3> [op, :op_sym, sym = ?]], fn (fact) {
ikc3> puts("#{inspect(sym)} #{inspect(op)}")
ikc3> })
```
The config module from an HTTPd instance has an example of
persistence, this way the database is loaded when the module is loaded :
```elixir
defmodule Config do
def db = Facts.database()
Facts.open(db, "db/app.facts")
end
```
---
Top : [KC3 documentation](../)
Previous : [1.24 Variable](1.24_Variable)
Next : [1.26 Named block](1.26_Named_block)