Prolog项目技巧
摘要
使用Prolog脚本自动发布Prolog项目的技巧:递增版本号、提交、打标签,并通过SWI-Prolog的包系统注册新包版本。
<p><a href="https://lobste.rs/s/fbietj/prolog_projects_tips">评论</a></p>
查看缓存全文
缓存时间: 2026/05/16 07:09
# Prolog 项目技巧
来源:https://occasionallycogent.com/prolog_project_helpers/index.html
这个脚本稍微复杂一些,以至于它是用 Prolog 而不是 bash 编写的。我运行它来为库生成新版本。
第一部分非常简单:`update_pack_version/2` 解析 `pack.pl` 文件中的版本号,根据新版本是主版本、次版本还是补丁版本(通过 `increment_version/3`)递增它,然后写回新数字。`git_commit_and_tag/1` 执行指定操作,并将更改推送到 `origin`。
最后一步由 `register_new_pack/1` 实现,稍微有点神秘。它修复了一个有点烦人的问题:推送新版本后,我必须手动通过 URL 安装该新版本,以便 SWI-Prolog 服务器能够看到新版本并注册它(这样普通用户就可以直接运行 `pack_upgrade(Whatever)`)。以前我只会手动在顶级环境中执行 `pack_remove/1` 移除包,然后运行 `pack_install/2` 并显式传递要安装的包的 URL,但当然,我们可以将其自动化!
知道了我们这样做的原因,希望 `register_new_pack/1` 不再那么神秘。`download_pattern_format_string/2` 辅助谓词将 `pack.pl` 中的模式转换为格式字符串(例如将 `'https://example.com/release/*.zip'` 转换为 `"https://example.com/release/~w.zip"`),以便我们可以使用 `format/3` 下载新版本的新归档文件。不幸的是,对于仍在 GitHub 上的仓库,有一些特殊情况处理,因为出于我记不清的原因,实际下载 URL 与 pack 文件中指定的 URL 不同,这就是谓词第一个子句存在的原因。
最后,`main/1` 检查是否提供了有效的发布类型,提示确认,然后执行操作。我添加了这个提示,因为有一次我在尝试重新运行测试时不小心从历史记录中运行了该脚本,结果不得不进行太多次强制推送 😅
**清单 3:scripts/make_release.pl**
```
#!/usr/bin/env swipl
:- module(make_release, []).
:- use_module(library(readutil), [read_file_to_terms/3,
read_line_to_string/2]).
:- initialization(main, main).
increment_version(major, [Major0, _Minor, _Patch], [Major1, 0, 0]) :- !,
succ(Major0, Major1).
increment_version(minor, [Major, Minor0, _Patch], [Major, Minor1, 0]) :- !,
succ(Minor0, Minor1).
increment_version(patch, [Major, Minor, Patch0], [Major, Minor, Patch1]) :- !,
succ(Patch0, Patch1).
update_pack_version(ReleaseType, NewVersion) :-
read_file_to_terms('pack.pl', PackTerms, []),
memberchk(version(OldVersion), PackTerms),
atomic_list_concat([MajorS, MinorS, PatchS], '.', OldVersion),
maplist(atom_number, [MajorS, MinorS, PatchS], VersionNums0),
increment_version(ReleaseType, VersionNums0, VersionNums1),
atomic_list_concat(VersionNums1, '.', NewVersion),
once(select(version(OldVersion), PackTerms, version(NewVersion), NewPackTerms)),
setup_call_cleanup(open('pack.pl', write, S, []),
forall(member(T, NewPackTerms),
write_term(S, T, [fullstop(true),
nl(true),
quoted(true),
spacing(next_argument)
])),
close(S)).
git_commit_and_tag(NewVersion) :-
shell('git add pack.pl'),
shell('git commit -m "Bump version"'),
format(atom(TagCmd), "git tag v~w", [NewVersion]),
shell(TagCmd),
format(atom(PushCmd), 'git push origin master v~w', [NewVersion]),
shell(PushCmd).
download_pattern_format_string(DownloadURLPat, FormatString) :-
string_concat("https://github.com", _, DownloadURLPat), !,
string_concat(Prefix, "releases/*.zip", DownloadURLPat),
string_concat(Prefix, "archive/refs/tags/v~w.zip", FormatString).
download_pattern_format_string(DownloadURLPat, FormatString) :-
file_name_extension(Base0, Ext, DownloadURLPat),
string_concat(Base, "*", Base0),
format(string(FormatString), "~s~s.~s", [Base, "v~w", Ext]).
register_new_pack(NewVersion) :-
read_file_to_terms('pack.pl', PackTerms, []),
memberchk(name(ProjectName), PackTerms),
memberchk(download(DownloadURLPattern), PackTerms),
download_pattern_format_string(DownloadURLPattern, URLFormat),
( pack_remove(ProjectName) -> true ; true ),
format(atom(Url), URLFormat, [NewVersion]),
pack_install(ProjectName, [url(Url), interactive(false)]).
main(Args) :-
( Args = [ReleaseType], increment_version(ReleaseType, [0, 0, 0], _)
-> true
; ( format(user_error, "Usage: make_release.pl [major|minor|patch]~n", []),
halt(1) ) ),
( stream_property(user_input, tty(true))
-> format("Make new release? [y/n]: ", []),
read_line_to_string(user_input, Input),
Input == "y"
; true ),
update_pack_version(ReleaseType, NewVersion),
format("Bumping to ~w~n", [NewVersion]),
git_commit_and_tag(NewVersion),
register_new_pack(NewVersion).
```
希望这些对你使用和学习 Prolog 有所帮助!不久的将来,我会尝试将这些技巧以及我惯常使用的其他一些有用的库、工具和模板整合成一个统一的工具,帮助 Prolog 走向更多的主流开发者。在那之前,请尽情享受并明智使用!
相似文章
@cline: 这是开始“循环工程”的一种实用方法(一种花哨的说法,指的是除了人类提示智能体以外的其他方式……)
一种实用的“循环工程”方法:使用 Git 钩子脚本在提交前自动检查代码中泄露的密钥和严重漏洞。
@zodchiii: https://x.com/zodchiii/status/2069366611371241944
构建可复用的Claude Code Agent循环指南,通过替换检查脚本即可用于不同任务,如修复Bug、优化速度或降低成本。
@nifinet: https://x.com/nifinet/status/2078851409068654639
一份关于使用Codex构建自我改进外呼系统的指南:AI代理会读取历史结果、编辑评分和策略文件、运行测试,并生成拉取请求供人工审核。其核心理念是将上市策略逻辑视为版本化代码,通过市场反馈持续优化。
@polydao:这份11页的Claude循环工程手册是高级开发者晋升的秘籍 逐行输入提示词...
这份手册介绍了如何使用Claude AI代理设计自提示循环,涵盖发现、交接、验证以及持久化/调度,用于自动化代码开发。
@shmidtqq: https://x.com/shmidtqq/status/2068704187492221405
一份关于AI编程代理循环工程的深入指南,解释了如何构建自动循环来重复提示代理、验证结果并避免失控成本,并通过一位工程师一个月内提交259个拉取请求的案例研究加以说明。