In a simple batch file - wizardofosmium/porolog GitHub Wiki

Using Porolog In a simple batch file

Accessing the Gem

As usual, you need to require the gem

require 'porolog'

Since this is a simple batch file, there is no harm in including Porolog

include Porolog

Now you can use and define Porolog methods globally.

Declaring Predicates

All the builtin predicates are available and can be declared using builtin to create a global method to access the builtin predicate. See available builtin predicates in v1.0.0.

builtin :member

Your predicates need to be defined in a similar manner.

predicate :my_rule

Defining Facts

Now, define a fact.

my_rule(0, 0, 0).fact!

Porolog provides four fact methods:

  • fact!
  • cut_fact!
  • fallacy!
  • cut_fallacy!

These provide shorthand definitions for the corresponding Prolog:

  • info(1).
  • info(2) :- !.
  • info(3) :- fail.
  • info(4) :- !,fail.

So, using Porolog these would be:

predicate :info

info(1).fact!
info(2).cut_fact!
info(3).fallacy!
info(4).cut_fallacy!

Defining Rules

Rules are defined by using the << operator and an Array of predicate calls. For example:

my_rule(:X, :Y, :Z) << [
  member(:X, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  member(:Y, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  noteq(:X, :Y),
  is(:Z, :X, :Y) {|x, y| x + y }
]

Pruning

Cuts are specified by using :CUT. So, for example, to iterate only through the Ys

my_rule(:X, :Y, :Z) << [
  member(:X, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  :CUT,
  member(:Y, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  noteq(:X, :Y),
  is(:Z, :X, :Y) {|x, y| x + y }
]

Failing

A fail is represented by false.

my_rule(:X, :Y, :Z) << [
  member(:X, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  member(:Y, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  write(:X, :Y),
  false
]

The Complete Example

require 'porolog'

include Porolog

builtin :member
predicate :my_rule

my_rule(0, 0, 0).fact!
my_rule(:X, :Y, :Z) << [
  member(:X, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  member(:Y, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  noteq(:X, :Y),
  is(:Z, :X, :Y) {|x, y| x + y }
]

puts my_rule(:X, :Y, :Z).solve.map(&:inspect)
puts my_rule(:X, :Y, :Z).solve_for(:Z).inspect