prolog - Prolog 错误:预期为 `character',找到 `"((.).)"'(字符串)
问题描述
我的目标是以括号表示法打印具有 N 个节点的所有形式的树,可以根据上下文无关语法定义如下:
T → 树为空
T → (TT) 具有左右子节点的节点
例如,所有具有 3 个节点的树将如下所示:
(((。)。)。)
(((。(。))。)
((.).(.))
(.((.).))
(.(.(.)))
我在 Prolog 中编写了以下代码,
form1(Prev, Next) :-
string_concat("(", Prev, Inter),
string_concat(Inter, ".)", Next).
form2(Prev, Next) :-
string_concat("(.", Prev, Inter),
string_concat(Inter, ")", Next).
tree(1, ["(.)"]) :- !.
tree(N, Strings) :-
A is N - 1, tree(A, PrevStrings1),
maplist(form1 , PrevStrings1, List1),
maplist(form2 , PrevStrings1, List2),
append(List1, List2, Result),
Strings is Result.
但我得到这个错误:
?- tree(2, L).
ERROR: Type error: `character' expected, found `"((.).)"' (a string)
ERROR: In:
ERROR: [9] _3182 is ["((.).)","(.(.))"]
ERROR: [7] <user>
我没有在我的代码中引用字符。怎么了?
解决方案
解决此类问题的最佳方法是首先从抽象表示开始。抽象意味着所有语法细节都已被删除。你真正想要的是以下形式的树
is_tree(empty).
is_tree(node(Left, Right)) :-
is_tree(Left),
is_tree(Right).
然后,基于此表示,您可以使用您最喜欢的语法花哨来定义一个具体的表示。
:- set_prolog_flag(double_quotes, chars).
tree(empty) --> "".
tree(node(Left, Right)) -->
"(",
tree(Left),
".",
tree(Right),
")".
?- length(Text, N), phrase(tree(Tree), Text).
Text = [],
N = 0,
Tree = empty ;
Text = ['(','.',')'],
N = 3,
Tree = node(empty,empty) ;
Text = ['(','.','(','.',')',')'],
N = 6,
Tree = node(empty,node(empty,empty)) ;
Text = ['(','(','.',')','.',')'],
N = 6,
Tree = node(node(empty,empty),empty) ...
为了提高答案的可读性,请使用 [library(double_quotes)
代表SWI和SICStus。
?- use_module(double_quotes).
?- length(Text, N), phrase(tree(Tree), Text).
Text = [],
N = 0,
Tree = empty ;
Text = "(.)",
N = 3,
Tree = node(empty,empty) ;
Text = "(.(.))",
N = 6,
Tree = node(empty,node(empty,empty)) ;
Text = "((.).)",
N = 6,
Tree = node(node(empty,empty),empty) ;
Text = "(.(.(.)))",
N = 9,
Tree = node(empty,node(empty,node(empty,empty))) ;
Text = "(.((.).))",
N = 9,
Tree = node(empty,node(node(empty,empty),empty)) ...
最后,您现在可以完全跳过抽象语法树,因此:
tree --> "".
tree --> "(", tree, ".", tree, ")".
?- length(Text, N), phrase(tree, Text).
Text = [],
N = 0;
Text = "(.)",
N = 3;
Text = "(.(.))",
N = 6;
Text = "((.).)",
N = 6;
Text = "(.(.(.)))",
N = 9;
Text = "(.((.).))",
N = 9 ...
乍一看,这种紧凑的语法似乎更可取,但在许多情况下它非常不方便。特别是,如果您正在设计一个新语法,并且您不确定您的语法是否包含歧义。在之前的版本的帮助下,证明这样的事情是非常简单的。
推荐阅读
- c# - 通过 C# 中的代码生成 .trx 文件
- sql-server - 使用 .Net Core 2.0 应用程序中的 .dacpac 文件部署数据库
- python - 字节对象中的 Python3 re.findall 出现,使用特定字节对象的串联 + 正则表达式模式作为搜索参数
- android - 相机缩放时相机人脸检测侦听器不起作用
- javascript - 如何在javascript中结合名字和姓氏?
- c# - Excel VSTO:使用单独程序集中的 ResourceDictionary
- java - 声纳规则:Lambdas 应该替换为方法引用
- android - Android SQLite3 添加 Oldvalue + NewValue
- javascript - 多行输入框值相加求和
- c# - 从 Windows 为 macOS/CentOS 编译单声道应用程序