Ckini.Macro (Ckini v0.1.0) View Source

A set of MiniKanren-like primitives.

Link to this section Summary

Functions

Create a goal from a sequence of goals. The goal only succeeds when all the subgoals succeed.

Performs what's called a "soft-cut" operation in Prolog. In each of its subgoals, if they are composed of multiple goals and the first goal succeeds. conda/1 will behave like the subgoal is the only branch.

Creates a goal from a sequence of subgoals by taking disjunction on them. In other words, this syntax creates multiple possibilities.

Creates a goal from a sequence of subgoals by taking disjunction on them. In other words, this syntax creates multiple possibilities.

Similar to conda/1 in the sense that it also treats the first successful subgoal as the only branch. Unlike conda/1, condu/1 also restrict its subgoal to have only one possibilities.

Fresh introduces new logic variables into the block scoped by do..end. You can put the variables in a tuple to introduce many variables at the same time.

See documentation for matche/2.

The match{e,i,a,u} series syntax are equivalent to their cond{e,i,a,u} counterpart. They are handy to write pattern matching with a value (or another pattern) against multiple patterns.

See documentation for matche/2.

See documentation for matche/2.

Query for all possible values of a variable with a goal.

Query for a number of possible values of a variable with a goal.

Link to this section Functions

Create a goal from a sequence of goals. The goal only succeeds when all the subgoals succeed.

all/1 is functionally equivalent to fresh/1 except that it doesn't introduce variables.

Examples

iex> use Ckini
iex> run(x) do
...>   eq(x, 1)
...>   all do
...>     eq(x, 2)
...>     eq(x, 1)
...>   end
...> end
[]

The preceding example is only for demonstration. The usage of all/1 in the example is not necessary.

Performs what's called a "soft-cut" operation in Prolog. In each of its subgoals, if they are composed of multiple goals and the first goal succeeds. conda/1 will behave like the subgoal is the only branch.

The syntax is the same as conde/1. See conde/1 for usage.

Examples

iex> use Ckini
iex> teacupo = fn x ->
...>   conde do
...>     _ -> eq(x, :tea)
...>     _ -> eq(x, :cup)
...>   end
...> end
iex> run({x, y}) do
...>   conda do
...>     _ ->
...>       teacupo.(x)
...>       eq(y, x)
...>     _ ->
...>       eq(x, 1)
...>       eq(y, x)
...>   end
...> end
[{:tea, :tea}, {:cup, :cup}]

iex> use Ckini
iex> teacupo = fn x ->
...>   conde do
...>     _ -> eq(x, :tea)
...>     _ -> eq(x, :cup)
...>   end
...> end
iex> run({x, y}) do
...>   conda do
...>     _ ->
...>       teacupo.(x)
...>       eq(1, 2)
...>     _ ->
...>       eq(x, 1)
...>       eq(y, x)
...>   end
...> end
[]

Also see conde/1, condi/1, condu/1, matcha/2.

Creates a goal from a sequence of subgoals by taking disjunction on them. In other words, this syntax creates multiple possibilities.

conde performs depth-first search. Which means, conde will explore all possibilities of the first subgoal before exploring the second subgoal, and so on.

Each subgoal is represented by a -> expression in the do block.

The left-hand side of -> can be used to introduce new variables. You can put a single variable, or multiple variables enclosed by {}, or if no new variable is needed, put an _.

The right-hand side of -> can a single goal or multiple goals. If multiple goals are supplied, they will be treated as if they are enclosed in a all/1 goal.

Examples

iex> use Ckini
iex> run(x) do
...>   conde do
...>     _ -> eq(x, 2)
...>     _ -> eq(x, 1)
...>   end
...> end
[2, 1]

Also see condi/1, conda/1, condu/1, matche/2.

Creates a goal from a sequence of subgoals by taking disjunction on them. In other words, this syntax creates multiple possibilities.

Unlike conde/1, condi/1 performs a different type of search that's different from depth-first search. It will explore both breadth and depth in a zig-zag order, making it more useful for many cases.

The syntax is the same as conde/1. See conde/1 for usage.

Examples

iex> use Ckini
iex> run(x) do
...>   condi do
...>     _ -> eq(x, 2)
...>     _ -> eq(x, 1)
...>   end
...> end
[2, 1]

Also see conde/1, conda/1, condu/1, matchi/2.

Similar to conda/1 in the sense that it also treats the first successful subgoal as the only branch. Unlike conda/1, condu/1 also restrict its subgoal to have only one possibilities.

Examples

iex> use Ckini
iex> teacupo = fn x ->
...>   conde do
...>     _ -> eq(x, :tea)
...>     _ -> eq(x, :cup)
...>   end
...> end
iex> run({x, y}) do
...>   condu do
...>     _ ->
...>       teacupo.(x)
...>       eq(y, x)
...>     _ ->
...>       eq(x, 1)
...>       eq(y, x)
...>   end
...> end
[{:tea, :tea}]

iex> use Ckini
iex> teacupo = fn x ->
...>   conde do
...>     _ -> eq(x, :tea)
...>     _ -> eq(x, :cup)
...>   end
...> end
iex> run({x, y}) do
...>   condu do
...>     _ ->
...>       teacupo.(x)
...>       eq(1, 2)
...>     _ ->
...>       eq(x, 1)
...>       eq(y, x)
...>   end
...> end
[]

Also see conde/1, condi/1, conda/1, matchu/2.

Link to this macro

fresh(vars, list)

View Source (macro)

Fresh introduces new logic variables into the block scoped by do..end. You can put the variables in a tuple to introduce many variables at the same time.

Please note: with Ckini, you can minimize usage of fresh if you intend to use it immediately in a cond and match clause, as cond and match support introducing free variables via the left-hand-side of ->.

See condi/1 and matchi/2 for details.

Examples

iex> use Ckini
iex> run q do
...>   fresh x do
...>     eq([x, q], [q, 1])
...>   end
...> end
[1]
iex> run q do
...>   fresh {x, y} do
...>     eq([x, y, q], [y, 1, x])
...>   end
...> end
[1]

Also see all/1.

Link to this macro

matcha(pattern, list)

View Source (macro)

See documentation for matche/2.

Link to this macro

matche(pattern, list)

View Source (macro)

The match{e,i,a,u} series syntax are equivalent to their cond{e,i,a,u} counterpart. They are handy to write pattern matching with a value (or another pattern) against multiple patterns.

The pattern can be a variable, a list, or a ground term. The do...end block contains a series of clauses of pattern -> goals syntax.

You can write logic variables freely in the pattern, as the will be bind to corresponding value automatically. You can also use _ in the pattern as a placeholder to ignore values you don't need.

If you need extra variables in the body other than those appeared in pattern, you can use pattern, extra_variables -> goals syntax. You can use {} to enclose multiple variables in extra_variables as in fresh/1.

The implementation detail is that each match clause will be converted to a cond clause by inserting a eq(value, pattern) goal in front of other goals. The implication is that for matcha and matchu, this eq goal will be treated as the conditional for the rest of subgoals.

Examples

iex> use Ckini
iex> run(x) do
...>   matche x do
...>     _ -> succ()
...>     [y, _] -> eq(y, 1)
...>     [_, y] -> eq(y, 2)
...>     [_, _] -> succ()
...>   end
...> end
[:_0, [1, :_0], [:_0, 2], [:_0, :_1]]

iex> use Ckini
iex> run(x) do
...>   matche x do
...>     _ ->
...>       succ()
...>     [y, _], z ->
...>       eq(y, z)
...>       eq(z, 1)
...>     [_, y], {z, w} ->
...>       eq(y, [z, w])
...>     [_, _] ->
...>       succ()
...>   end
...> end
[:_0, [1, :_0], [:_0, [:_1, :_2]], [:_0, :_1]]
Link to this macro

matchi(pattern, list)

View Source (macro)

See documentation for matche/2.

Link to this macro

matchu(pattern, list)

View Source (macro)

See documentation for matche/2.

Link to this macro

run(vars, list)

View Source (macro)

Query for all possible values of a variable with a goal.

You can also query multiple variables by putting them in a tuple. The variable will be declared automatically.

You can also provide multiple goals by putting them in the do block.

Examples

iex> use Ckini
iex> run q do
...> end
[:_0]
iex> run {x, y} do
...>   eq(x, 1)
...>   conde do
...>     _ -> eq(y, 1)
...>     _ -> eq(y, 2)
...>     _ -> eq(x, 2)
...>   end
...> end
[{1, 1}, {1, 2}]

Also see run/3 for limited of possible values.

Link to this macro

run(n, vars, list)

View Source (macro)

Query for a number of possible values of a variable with a goal.

You can also query multiple variables by putting them in a tuple. The variable will be declared automatically.

You can also provide multiple goals by putting them in the do block.

Examples

iex> use Ckini
iex> run(2, q) do
...>   conde do
...>     _ -> eq(q, 1)
...>     _ -> eq(q, 2)
...>     _ -> eq(q, 3)
...>     _ -> eq(q, 4)
...>   end
...> end
[1, 2]

Also see run/2 that allows querying unlimited possible values.