Scryer Prolog
Scryer Prolog 旨在成为 ISO Prolog 领域的 GHC(即 Haskell 领域的 GHC):一个开源的、工业级强度的生产环境,同时也是逻辑与约束编程前沿研究的试验平台,其本身使用高级语言编写。
Scryer Prolog 通过了所有
语法一致性、
variable_names/1 和
dif/2 测试。
该项目的首页是:https://www.scryer.pl

阶段 1
在 Rust 中实现 Warren 抽象机器,按照 Warren's Abstract Machine: A Tutorial Reconstruction 中语言的演进顺序进行。
阶段 1 已完成,因为 Scryer Prolog 以某种形式实现了 WAM 书籍中的所有 内容,包括列表、切割、Debray 分配、首参数索引、尾调用优化和合取查询。
阶段 2
扩展 Scryer Prolog 以包含以下功能,以及其他功能:
- 将 call/N 作为内置元谓词。
- 符合 ISO Prolog 标准的 throw/catch。
- 具有所有固定性的内置和用户定义运算符,支持自定义 结合性和优先级。
- 大整数、有理数和浮点算术。
- 内置控制运算符(
,,;,->, 等)。 - 经过修订的、不算糟糕的模块系统。
- 用于列表处理和顶层声明式控制的内置谓词
(
setup_call_cleanup/3,call_with_inference_limit/3, 等) -
字符串的默认表示为字符列表,使用打包的 内部表示。 -
term_expansion/2和goal_expansion/2。 - 确定子句文法。
- 使用 SICStus Prolog 接口和
语义的带属性变量。添加像
dif/2,freeze/2等协程 对于带属性变量来说很直接。- 对
verify_attributes/3的支持 - 对
attribute_goals/2和project_attributes/2的支持 -
call_residue_vars/2
- 对
-
if_/3及相关谓词,遵循论文 "Indexingdif/2" 的发展。 - 所有解谓词(
findall/{3,4},bagof/3,setof/3,forall/2)。 - 子句创建和销毁(
asserta/1,assertz/1,retract/1,abolish/1),具有逻辑更新语义。 - 通过
bb_get/2bb_put/2(不可回溯)和bb_b_put/2(可回溯)实现的可回溯和不可回溯全局变量。 - 基于 reset/3, shift/1 的受限延续(记录于 "Delimited Continuations for Prolog")。
- 基于受限延续的表化库 (记录于“作为库的表格化与分隔控制”)。
- 使用打包的内部表示,将字符串重新表示为字符的差异列表。
- clp(B) 和 clp(ℤ) 作为内置库。
- 流以及用于流控制的谓词。
- 一个将 TCP 连接表示为流的简单套接字库。
- 增量编译和加载过程,新编写, 主要使用 Prolog 实现。
- 对 WAM 编译器和堆表示的改进:
- 将围绕内联半确定性谓词
(
atom、var等)的选点替换为 if/else 阶梯。(进行中) - 内联所有内置函数和系统调用指令。
- 大幅减少用于编译析取式的指令数量。
- 将短原子存储到堆单元中,而不写入原子表。
- 将围绕内联半确定性谓词
(
- 对所有参数可配置的 JIT/按需索引 (记录于“Prolog 子句的需求驱动索引”)。(进行中)
- 满足“Prolog 中的精确垃圾回收”中五个属性的压缩式垃圾回收器。(进行中)
阶段 3
使用已完成的代码生成器生成的 WAM 代码,以获取 JIT 编译并执行的 Prolog 程序。如何从 WAM 代码获取 汇编代码的问题,我仍在考虑中。
我希望使用 Scryer Prolog 作为低级别(并且 理想情况下,非常快)的 Shen 实现的逻辑引擎。
锦上添花的功能
目前没有任何计划实现这些功能,但它们在未来 可能很有用。对于任何想要 为 Scryer Prolog 贡献代码的人来说,它们将是一个很好的项目。
-
实现 Peter van Roy 的论文中描述的全局分析技术,“Can Logic Programming Execute as Fast as Imperative Programming?"
-
添加 unum 表示法和算术运算,使用现有的 unum 实现或临时实现。Unums 在 Gustafson 的书《The End of Error》中有描述。
-
添加并发表来管理对原子和 字符串的共享引用。
安装 Scryer Prolog
二进制文件
多个平台的预编译二进制文件可供下载 于:
https://github.com/mthom/scryer-prolog/releases/latest
原生编译
首先,使用您偏好的方法安装最新稳定版的 Rust。Scryer 倾向于使用较新 Rust 版本中的特性,而 Linux 发行版、Macports 等中的 Rust 软件包往往滞后。rustup 会将您的 Rust 更新到最新稳定版;在使用 rustup 之前, 应卸载系统中已存在的任何 Rust 发行版。
[!NOTE] 所需的最小 rust 工具链版本可在 Cargo.toml 的
package.rust-version键下找到。 该值的准确性已在 CI 中验证
从本地 git 检出
$> git clone https://github.com/mthom/scryer-prolog
$> cd scryer-prolog
$> cargo build --release
--release 标志执行各种优化,生成
更快的可执行文件。
编译完成后,可执行文件 scryer-prolog 位于
目录 target/release 中,可以调用以运行系统。
通过 cargo install
从 git
cargo install --locked --git https://github.com/mthom/scryer-prolog.git
之后,scryer-prolog 二进制文件将位于 $HOME/.cargo/bin 目录中,该目录通常在安装 rust 工具链时被添加到你的 PATH 中。
从 Crates.io

[!NOTE] crates.io 上的最新版本可能显著落后于 git 仓库中可用的版本 本节标题中的 crates.io 徽章是链接到 crates.io 页面的链接。 本节标题中的 msrv 徽章引用了编译最新 crates.io 版本所需的最低 rust 工具链版本
scryer-prolog 也在 crates.io 上发布,并且可以通过以下方式安装
cargo install --locked scryer-prolog
Windows 注意事项
在 Windows 上,在 MSYS2 环境中构建 Scryer Prolog 更为简单,因为某些 crate 可能需要原生 C 编译。然而, 生成的二进制文件运行时无需 MSYS2。在 shell 中执行 Scryer 时,建议使用比 mintty(MSYS2 默认 shell)更高级的 shell。Windows Terminal 可以正常工作。
要构建 Windows 安装程序,首先需要以 release 模式编译 Scryer Prolog,然后,在安装 WiX Toolset 后,执行:
candle.exe scryer-prolog.wxs
light.exe scryer-prolog.wixobj
它将生成一个非常基础的 MSI 文件,该文件安装主可执行文件并在开始菜单中创建一个快捷方式。可以通过双击进行安装。要卸载,请前往控制面板并按常规方式卸载。
构建 WebAssembly
Scryer Prolog 具有基本的 WebAssembly 支持。您可以按照 wasm-pack 的官方说明 安装 wasm-pack 并以您喜欢的方式构建它。
然而,目前不支持任何默认特性。禁用它们的推荐方式是向 wasm-pack 传递额外选项。
例如,如果您想要一个不使用 webpack 等打包器的最小可用包,您可以这样做:
wasm-pack build --target web -- --no-default-features
然后会创建一个 pkg 目录,其中包含 webapp 所需的一切。您可以通过创建一个 html 文件来测试包是否成功构建,该文件改编自 wasm-bindgen 的官方示例,如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Scryer Prolog - Sudoku Solver Example</title>
<script type="module">
import initScryer, { MachineBuilder } from "./pkg/scryer_prolog.js";
// Initialize Scryer Prolog with WASM
const wasm = await fetch("./pkg/scryer_prolog_bg.wasm");
const module = await WebAssembly.compile(await wasm.arrayBuffer());
await initScryer(module);
// Set up the Prolog machine
const machine = new MachineBuilder().build();
// Knowledge base: Sudoku rules and problem definition
const kb = `
:- use_module(library(format)).
:- use_module(library(clpz)).
:- use_module(library(lists)).
sudoku(Rows) :-
length(Rows, 9), maplist(same_length(Rows), Rows),
append(Rows, Vs), Vs ins 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [A,B,C,D,E,F,G,H,I],
blocks(A, B, C),
blocks(D, E, F),
blocks(G, H, I).
blocks([], [], []).
blocks([A,B,C|T1], [D,E,F|T2], [G,H,I|T3]) :-
all_distinct([A,B,C,D,E,F,G,H,I]),
blocks(T1, T2, T3).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).
`;
machine.consultModuleString("user", kb);
// Run the query
const query = "problem(1, Rows), sudoku(Rows), maplist(portray_clause, Rows).";
const answers = machine.runQuery(query);
const formattedSolutions = [];
// Format the answers
for (const solution of answers) {
const rows = solution.bindings["Rows"].list;
const grid = rows.map(row =>
row.list.map(cell => cell.integer)
);
const formatted = grid.map(row => `[${row.join(", ")}]`).join("\n");
formattedSolutions.push(formatted);
}
// Output results
const solutionDiv = document.querySelector("#soduku-solution");
for (const solution of formattedSolutions) {
const newPre = document.createElement("pre");
newPre.textContent = solution;
solutionDiv.appendChild(newPre);
}
</script>
</head>
<body>
<p>Sudoku solver returns:</p>
<div id="soduku-solution">
</div>
</body>
</html>
然后你可以使用你喜欢的 http 服务器(如 python -m http.server 或 npx serve)来提供该服务,并通过浏览器访问该页面。
Docker 安装
预构建的 Docker 镜像可在 Docker Hub 上获取。
latest 标签反映了 master 的状态,这可能是不稳定的。
此外,还有针对 Scryer 0.9.2 及更高版本发布的标签。
但请注意,目前基础镜像并未保持更新,
因此请警惕安全漏洞(参见 #2646)。
首先,在 Linux、 Windows 或 Mac 上安装 Docker。
安装 Docker 后,你可以使用一条 命令下载并运行 Scryer Prolog:
$> docker run -it mjt128/scryer-prolog
要咨询你的 Prolog 文件,请将你的程序文件夹绑定挂载为 Docker 卷:
$> docker run -v /home/user/prolog:/mnt -it mjt128/scryer-prolog
?- consult('/mnt/program.pl').
true.
这在 Windows 上同样有效:
$> docker run -v C:\Users\user\Documents\prolog:/mnt -it mjt128/scryer-prolog
?- consult('/mnt/program.pl').
true.
教程
Prolog 文件通过将其作为命令行参数指定来加载。例如,要加载 program.pl,请使用:
$> scryer-prolog program.pl
加载 Prolog 文件也称为“咨询”该文件。内置
谓词 consult/1 可用于在
Prolog 内部咨询文件:
?- consult('program.pl').
作为 consult/1 的缩写,你可以指定一个列表,
其中包含以原子形式给出的程序文件:
?- ['program.pl'].
特殊记号 [user] 用于从标准输入读取 Prolog 文本。例如,
?- [user].
hello(declarative_world).
hello(pure_world).
按下 RETURN 后按 Ctrl-d 会停止从
标准 输入读取并咨询输入的 Prolog 文本。
咨询程序后,您可以询问其定义的 谓词查询。例如,对于上面显示的程序:
?- hello(What).
What = declarative_world
; What = pure_world.
按 SPACE 显示更多答案(如果存在)。按 RETURN
或 . 中止搜索并返回到
顶层 提示符。按 f 显示到下一个 5 的倍数
的答案,按 a 显示所有答案。按 h 显示帮助
信息。
使用 TAB 在查询中补全原子和谓词名称。例如,
在咨询上述程序后,输入 decl 然后
按 TAB 将得到 declarative_world。反复按 TAB
以循环浏览替代补全项。
要退出 Scryer Prolog,使用标准谓词 halt/0:
?- halt.
启动 Scryer Prolog
Scryer Prolog 可以通过命令行启动,通过指定 选项、文件和附加参数。所有组件均为可选:
scryer-prolog [OPTIONS] [FILES] [-- ARGUMENTS]
支持的选项如下:
-h, --help Display help message
-v, --version Print version information and exit
-g, --goal GOAL Run the query GOAL after consulting files
-f Fast startup. Do not load initialization file (~/.scryerrc)
--no-add-history Prevent adding input to history file (~/.scryer_history)
所有指定的 Prolog 文件都会被咨询。
在 Prolog 文件之后,可以在命令行上指定应用程序特定的参数。这些参数可以通过谓词 argv/1 在 Prolog 应用程序内部访问,该谓词返回以字符串形式表示的参数列表。
如 https://github.com/mthom/scryer-prolog/issues/2170#issuecomment-1821713993 中所述,Prolog 文件也可以转换为 shell scripts。
动态运算符
Scryer 支持动态运算符。使用具有通常优先级的内置算术运算符,
?- write_canonical(-5 + 3 - (2 * 4) // 8), nl.
-(+(-5,3),//(*(2,4),8))
true.
可以使用 op 声明定义新的运算符。
首个已实例化参数索引
Scryer Prolog 在谓词 定义的所有子句中,对最左侧的非变量参数进行索引。我们将此策略称为 首个已实例化参数索引。
首个已实例化参数索引的一个关键动机是,为诸如 maplist/N 和 foldl/N 这样的元谓词启用
索引,这些谓词的第一个参数是一个部分目标,在这些谓词的定义中是一个变量,因此不能用于索引。
例如,maplist/2 的一个自然定义如下:
maplist(_, []).
maplist(Goal_1, [L|Ls]) :-
call(Goal_1, L),
maplist(Goal_1, Ls).
在这种情况下,首先实例化的参数索引会自动使用 第二个 参数进行索引,从而防止了 具有固定长度列表(以及确定性目标)的调用产生选择点。 方便的是,在这种情况下,无需使用 参数顺序重新排列的辅助谓词即可受益于索引。
传统的第一个参数 索引自然作为 此策略的一个特例出现,如果谓词定义中的 任何子句都实例化了第一个参数。
字符串和部分字符串
字符串 的一种非常紧凑的内部表示是 Scryer Prolog 的关键 创新之一。这意味着在 Prolog 程序中 作为字符列表出现的项,由引擎以打包的 UTF-8 编码存储。
如果没有这项创新,在内存中存储字符列表 每个字符将使用一个 WAM 内存 单元,每个列表 构造器一个单元,并且列表中出现的每个尾部各占一个单元。由于 在 Scryer Prolog 实现的 WAM 中,一个单元占用 8 字节,因此打包表示 最多可将内存使用量减少 24 倍,并在创建和处理 字符串时相应地减少内存 访问。
Scryer Prolog 紧凑的内部字符串表示使其
非常适合 Prolog 最初开发时的用例:
高效且便捷的文本处理,特别是使用
library(dcgs) 和
library(pio) 提供的确定性子句文法 (DCGs) 来透明地对文件应用 DCG。
在 Scryer Prolog 中,Prolog 标志 double_quotes
的默认值为 chars,这也是推荐的设置。这意味着
字符列表可以写成双引号字符串,
遵循 Marseille Prolog 的传统。
例如,以下查询成功:
?- "abc" = [a,b,c].
true.
这表明字符串 "abc" 在内部表示为 3 字节的序列,
在 Prolog 程序中表现为字符列表。
Scryer Prolog 对部分字符串使用相同的编码方式,
这些字符串在 Prolog 代码中表现为部分字符列表。
来自 library(iso_ext) 的谓词 partial_string/3 允许您
显式地构造部分 字符串。例如:
?- partial_string("abc", Ls0, Ls).
Ls0 = [a,b,c|Ls].
在这种情况下,正如答案所示,Ls0 与尾部为 Ls 的部分列表无法区分,而内部则使用高效的打包表示。
Scryer Prolog 的一个重要设计目标是尽可能自动使用高效的字符串表示。因此,几乎很少需要显式使用 partial_string/3。在上面的示例中,发布 Ls0 = [a,b,c|Ls] 会产生完全相同的内部表示,并且具有仅使用标准谓词 (=)/2 的优势。
字符串和部分字符串的高效内部表示最初由 Ulrich Neumerkel 在 issues #24 和 #95 中提出并解释, Scryer Prolog 是第一个实现它的 Prolog 系统。
发生检查和循环项
发生检查(occurs check)是执行语法统一算法的一个组成部分,如果变量与包含该变量作为真子项的项进行统一,则导致统一失败。出于效率考虑,Scryer Prolog 和许多其他 Prolog 系统默认省略发生检查(occurs check)。
在 Scryer Prolog 中,只有在省略发生检查(occurs check)时才能成功的统一会产生循环项(cyclic terms),也称为有理树(rational trees)。例如:
?- X = f(X), Y = g(X,Y).
X = f(X), Y = g(f(X),Y).
循环项的创建通常表明 Prolog 谓词的定义中存在编程错误,为了获得逻辑上正确的结果,最好启用 occurs check 执行所有统一操作,或者在需要启用 occurs check 以防止统一时让 Prolog 抛出错误。
Scryer Prolog 通过 Prolog 标志 occurs_check 支持此功能。它可以设置为以下值之一以获得所需的行为:
false不执行 occurs check。这是默认设置。true启用 occurs check 执行所有统一操作。error如果执行了 occurs check 本会阻止的统一操作,则返回错误。
特别是对于刚开始学习 Prolog 的用户,我们建议在 ~/.scryerrc 配置文件中添加以下指令,以便通过错误指示导致循环项创建的谓词中的编程错误:
:- set_prolog_flag(occurs_check, error).
Scryer Prolog 实现了专门的推理机制,即使在启用了 occurs check 的情况下,也能在许多常见场景中 使统一操作快速完成。
Tabling (SLG resolution)
Prolog 的一大主要吸引力在于,纯 程序的逻辑推论 可以通过多种执行策略推导得出,这些策略在终止性、 完备性和效率等关键特性上各不相同。
Prolog 的默认执行策略是带有时间回溯的深度优先搜索。该策略非常高效。其主要 缺点是它是不完备的:即使存在解,它也可能找不到任何解。
Scryer Prolog 支持一种替代执行策略,称为
tabling,也被称为 tabled execution 和
SLG resolution。要为某个谓词启用 tabled 执行,请使用
library(tabling) 并为所需的谓词指示符添加一个 (table)/1
指令。例如,如果我们
编写:
:- use_module(library(tabling)).
:- table a/0.
a :- a.
然后查询 ?- a. 终止(并失败),而在默认执行策略下它
不会 终止。
Scryer Prolog 通过 delimited continuations 实现 tabling, 如 Tabling as a Library with Delimited Control 中 Desouter et. al. 所述。
Constraint Logic Programming (CLP)
Scryer Prolog 为 Constraint Logic Programming (CLP) 提供了出色的支持,它是 Logic Programming (LP) 和 Constraints 的结合。
除了对 dif/2,
freeze/2,
CLP(B) 和 CLP(ℤ) 的内置支持外,
Scryer 提供了一种方便的方式来实现新的用户定义
约束:Attributed variables 可通过
library(atts) 使用,正如 SICStus Prolog 中那样,
这是现存最复杂且最快的约束系统之一。在 library(iso_ext) 中,
Scryer 提供了用于可回溯(bb_b_put/2)和
不可回溯(bb_put/2)全局变量的谓词,这些是实现某些类型约束 求解器所必需的。
这些特性使 Scryer Prolog 成为教学、 学习和开发可移植 CLP 应用的理想平台。
Modules
Scryer 拥有一个简单的基于谓词的模块系统。它提供
一种将代码单元分离到不同命名空间的方式,适用于
谓词和运算符。参见文件
src/lib/*.pl 以
获取示例。
在撰写本文时,许多谓词位于各自的模块中, 在使用之前需要导入这些模块。 随 Scryer Prolog 一起提供的模块也被称为 library 模块或 libraries,包括:
lists提供length/2、member/2、select/3、append/[2,3]、foldl/[4,5]、maplist/[2-9]、same_length/2、transpose/2等。dcgs确定子句文法(DCGs),一种内置的语法机制, 使用运算符(-->)/2来定义语法规则, 并使用谓词phrase/[2,3]来调用它们。dif谓词dif/2提供声明式不等式: 当且仅当其参数不同时为真,并且 延迟测试直到可以做出可靠决策为止。reif提供if_/3、tfilter/3及相关谓词, 如 Indexing dif/2 中所述。clpzCLP(ℤ):整数约束逻辑编程, 通过(#=)/2、(#\=)/2、(#>=)/2等提供声明式整数算术,以及各种全局约束和 枚举谓词,用于求解组合任务。pairs按照惯例,pairs 是主 functor 为(-)/2的 Prolog 项, 写作Key-Value。 本库提供pairs_keys_values/3、pairs_keys/2以及其他谓词,用于对 pairs 进行推理。si谓词atom_si/1、integer_si/1、atomic_si/1和list_si/1实现可靠的类型检查。如果无法做出决策,它们会引发 实例化错误。它们是逻辑上存在缺陷的 低级类型测试的声明式替代方案。例如,不要使用integer(X), 而是编写integer_si(X)以确保程序的可靠性。 "si" 代表 sufficiently instantiated(充分实例化),也代表 sound inference(可靠推理)。debug各种允许声明式调试的谓词。piophrase_from_file/2将 DCG 非终结符应用于文件内容, 仅按需惰性读取所需的部分。得益于紧凑的内部字符串表示, 即使非常大的文件也能通过 Scryer Prolog 以这种方式高效处理。phrase_to_file/2和phrase_to_stream/2分别将 DCG 描述的字符列表写入文件和流。lambda用于简化高阶编程的 Lambda 表达式。charsio各种有用的谓词, 用于解析和推理字符,特别是char_type/2用于 根据类型对字符进行分类,以及针对不同字符串编码的转换 谓词。errormust_be/2和can_be/2补充了由library(si)提供的类型检查,对于 Prolog 库作者特别有用。tabling运算符(table)/1用于准备谓词以进行表驱动执行(SLG 归结)的指令中。format非终结符format_//2用于描述格式化输出, 根据给定的格式 字符串排列参数。 谓词format/[2,3]、portray_clause/[1,2]和listing/1提供格式化的不纯输出。assoc提供empty_assoc/1、get_assoc/3、put_assoc/4等, 用于管理 AVL 树中的元素,确保 O(log(N)) 访问。ordsets将有序集表示为列表。clpbCLP(B):基于布尔变量的约束逻辑编程, 通过谓词sat/1、taut/2、labeling/1等提供的基于 BDD 的 SAT 求解器。arithmetic算术谓词,例如lsb/2、msb/2和number_to_rational/2。time用于推理 时间的谓词,包括用于测量目标 CPU 时间的time/1、 用于获取当前系统时间的current_time/1、用于描述包含日期和时间的字符串的非终结符format_time//2,以及用于减慢计算速度的sleep/1。files用于推理文件和目录的谓词,例如directory_files/2、file_exists/1和file_size/2。cont通过reset/3和shift/1提供定界续体。random概率谓词和随机数生成器。http/http_open打开一个流, 用于从 web 服务器读取答案。也支持 HTTPS。http/http_server运行 HTTP/1.1 和 HTTP/2.0 web 服务器。使用 Warp 作为后端。支持一些查询和表单处理。sgmlload_html/3和load_xml/3将 HTML 和 XML 文档 表示为 Prolog 项,以便进行方便且高效的推理。使用library(xpath)从 解析后的文档中提取信息。csvparse_csv//1和parse_csv//2可与phrase_from_file/2或phrase/2一起用于解析 csvserialization/abnf描述 ABNF 语法核心 (RFC 5234) 的 DCG, 它用于描述许多 IETF 语法,例如 HTTP v1.1、 SMTP、 iCalendar 等。serialization/jsonjson_chars//1可与phrase_from_file/2或phrase/2一起用于解析和生成 JSON。xpath谓词xpath/3用于方便地推理 HTML 以及 XML 文档,受 XPath 语言启发。该库 通常与library(sgml)一起使用。sockets用于打开和接受 TCP 连接作为流的谓词。os用于推理环境 变量的谓词。iso_ext符合 Prolog ISO 标准的扩展及候选纳入项,例如setup_call_cleanup/3、call_nth/2和call_with_inference_limit/3。crypto密码学安全的随机数和哈希,基于 HMAC 的密钥 派生 (HKDF),基于密码的密钥派生 (PBKDF2), 使用 Ed25519 的公钥签名和签名验证, 基于 Curve25519 的 ECDH 密钥 交换 (X25519),使用 ChaCha20-Poly1305 的认证对称 加密,以及关于椭圆曲线的推理。process创建和管理并行进程。uuidUUIDv4 生成和十六进制表示tls用于显式协商 TLS 连接的谓词。numerics/special_functions用于 erf、gamma、beta 及相关特殊函数的谓词。ugraphs图操作库simplex提供assignment/2、transportation/4以及其他用于求解线性 规划问题的谓词。
要使用 lists 库提供的谓词,请编写:
?- use_module(library(lists)).
要加载包含在文件中的模块,可以省略 library 函子,
这将提示 Scryer 从其工作目录中搜索该文件(以原子形式指定):
?- use_module('file.pl').
use_module 指令可以通过添加导入列表进行限定:
?- use_module(library(lists), [member/2]).
合格的 use_module 可以通过传入空的导入列表来移除 toplevel 中的导入。
(:)/2 运算符将可能未导入到当前工作命名空间的谓词调用解析为:
?- lists:member(X, Xs).
The [user] 提示也可用于在 REPL 中内联定义模块:
?- [user].
:- module(test, [local_member/2]).
:- use_module(library(lists)).
local_member(X, Xs) :- member(X, Xs).
用户列表也可以通过在流的末尾放置 end_of_file. 来终止。
配置文件
启动时,如果文件 ~/.scryerrc 存在,Scryer Prolog 会咨询该文件。此文件可用于自动加载库并定义您经常需要的谓词。
例如,~/.scryerrc 的一个合理起点是:
:- use_module(library(lists)).
:- use_module(library(dcgs)).
:- use_module(library(reif)).
开发环境
为了编写和编辑 Prolog 程序,我们推荐 GNU Emacs 配合 Prolog mode 由 Stefan Bruda 维护。
使用 ediprolog 来咨询 Prolog 代码并在任意 Emacs 缓冲区中评估 Prolog 查询。
显示 Prolog 项为树的 Emacs 定义 可在 tools 中获取。
为了调试 Prolog 代码,我们推荐来自
library(debug) 的谓词,特别是:
(*)/1用于*"泛化掉"*一个 Prolog 目标。使用它来调试 意外的失败,通过泛化你的定义直到它们 成功。只需在目标前放置*即可将其泛化掉。($)/1用于发出执行的跟踪,显示目标 何时被调用,以及何时成功。在目标前放置$以发出该目标的相关信息。
这种调试 Prolog 代码的方式有几个主要优点,例如: 它贴近正在考虑的 Prolog 代码本身,它不需要 额外的工具和形式化方法即可应用,并且 此外,它鼓励声明式推理,这在原则上 也可以自动执行。
应用
Scryer Prolog 对 Prolog ISO 标准的坚定承诺使其 非常适合用于受严格监管的 企业和政府 机构 涉及互操作性、 标准 合规性和保修。
Scryer Prolog 的成功现有应用包括:
- DocLog,用于生成 Scryer 自身的文档和主页
- Grants4Companies:关于奥地利公共行政中商业 拨款的推理
- precautionary 包的一部分,用于分析肿瘤学试验 设计中剂量递增试验,该领域 安全关键且高度受监管,描述于 An Executable Specification of Oncology Dose-Escalation Protocols with Prolog 并最终形成 DEDUCTION
- 比利时公司 VATmiraal 用于增值税推理和合规的核心税务引擎
- AD4M 中的语义推理和查询, 这是一个以智能体为中心的分布式应用元本体。
Scryer Prolog 也非常适合教授和学习 Prolog,以及测试现有 Prolog 程序的语法一致性,从而测试其可移植性。
Scryer Prolog 聚会
Scryer Prolog 聚会是一个绝佳的机会,用于展示和了解 Scryer Prolog 及其应用的最新发展,交流关于当前 计划和 未来 方向的思路,并面对面讨论项目和愿景。
- Scryer Prolog Meetup 2023 在德国杜塞尔多夫举行。其公告 和讨论。
- Scryer Prolog Meetup 2024 在奥地利维也纳举行。其公告和讨论。
- Scryer Prolog Meetup 2025 在德国杜塞尔多夫举行。其公告和讨论。
- 参加、演讲并代表: Scryer Prolog Meetup 2026 将于 2026 年 10 月 24 日和 25 日在奥地利维也纳举行。 其公告。
支持与讨论
如果 Scryer Prolog 崩溃或产生意外错误,请考虑提交 一个 issue。
要与 Scryer Prolog 社区联系,请参与 讨论 或访问我们在 Libera 上的 #scryer IRC 频道!