如何在prolog中定义字符串连接运算符?
我正在处理prolog中的字符串,我希望避免在规则中使用过多的临时变量 我想改变这样的东西:如何在prolog中定义字符串连接运算符?,prolog,operators,string-concatenation,Prolog,Operators,String Concatenation,我正在处理prolog中的字符串,我希望避免在规则中使用过多的临时变量 我想改变这样的东西: process_str(Str, Next) :- is_valid_pattern0(Pattern0), concat(Pattern0, Tail0, Str), concat("->", Tail1, Tail0), is_valid_pattern1(Pattern1), concat(Pattern1, Tail2, Tail
process_str(Str, Next) :-
is_valid_pattern0(Pattern0),
concat(Pattern0, Tail0, Str),
concat("->", Tail1, Tail0),
is_valid_pattern1(Pattern1),
concat(Pattern1, Tail2, Tail1),
concat("|", Tail2, Next).
?- process_str("foo->bar|baz", Next).
Next = [b, a, z] ;
false.
使用串联运算符定义,转换为以下内容:
process_str(Pattern0.."->"..Pattern1.."|"..Next, Next) :-
is_valid_pattern0(Pattern0),
is_valid_pattern1(Pattern1).
我相信它的可读性要高得多,但代价是根据操作符的定义进行更多的操作
我发现文档中谈到了,但据我所知,只能定义谓词运算符,而不能定义可以“返回值”的函数运算符(例如+
运算符)
请告诉我为什么我错了,或者如何定义这样的串联运算符。您可以在~/.swiplrc中定义以下对运算符:
:-op(699,xfx,:=)。%就在下面=
:-op(698,yfx,+)。%就在下面:=
Out:=左+右:-
将表达式展平到字符串(左,L字符串),
将表达式展平到字符串(右,右字符串),
原子到字符串([LStrings,RStrings],Out)。
将表达式展平为字符串(A++B,字符串):-
字符串:=A++B。
将表达式展平到字符串(术语,字符串):-
映射列表(整数,术语)
->字符串\u代码(字符串、术语)
; 术语\字符串(术语,字符串)。
然后
?-X:=`foo`++bar++帮助。
X=“foobarhelp”。
?-X:=`foo`++123+bar++帮助。
X=“foo123+bar帮助”。
请注意,整数列表有一个模糊性()(反勾字符串就是…)。希望你能接受
如果使用XPCE编辑器,只需拉动菜单[Edit\Prolog preferences]并在那里添加代码段,然后重新编译(Ctrl+b)。这也适用于Windows,在Windows中,~/.swiplrc
以另一种更适合平台的方式命名
当您为字符串表达式定义了适当的迷你语言后,您可以探索,以便在不引入新变量的情况下将表达式传递给谓词。注意,调试起来相当困难。。。您可以在中分析
升降机
以获得一些提示您可以在~/.swiplrc中定义以下运算符对:
:-op(699,xfx,:=)。%就在下面=
:-op(698,yfx,+)。%就在下面:=
Out:=左+右:-
将表达式展平到字符串(左,L字符串),
将表达式展平到字符串(右,右字符串),
原子到字符串([LStrings,RStrings],Out)。
将表达式展平为字符串(A++B,字符串):-
字符串:=A++B。
将表达式展平到字符串(术语,字符串):-
映射列表(整数,术语)
->字符串\u代码(字符串、术语)
; 术语\字符串(术语,字符串)。
然后
?-X:=`foo`++bar++帮助。
X=“foobarhelp”。
?-X:=`foo`++123+bar++帮助。
X=“foo123+bar帮助”。
请注意,整数列表有一个模糊性()(反勾字符串就是…)。希望你能接受
如果使用XPCE编辑器,只需拉动菜单[Edit\Prolog preferences]并在那里添加代码段,然后重新编译(Ctrl+b)。这也适用于Windows,在Windows中,~/.swiplrc
以另一种更适合平台的方式命名
当您为字符串表达式定义了适当的迷你语言后,您可以探索,以便在不引入新变量的情况下将表达式传递给谓词。注意,调试起来相当困难。。。您可以在中分析提升机以获得一些提示这里有一个使用DCG和在SWI Prolog中工作的术语扩展的解决方案。首先,基础:
:- set_prolog_flag(double_quotes, chars).
这确保了“foo”
将被解释为三个字符的列表,而不是一些非标准的原子“字符串”对象
然后,假设有效的pattern0
和pattern1
匹配只是字母列表。由你来填写细节。一些基本的DCG:
letters -->
[].
letters -->
[Letter],
{ char_type(Letter, alpha) },
letters.
pattern0 -->
letters.
pattern1 -->
letters.
例如:
?- phrase(pattern0, Pattern0).
Pattern0 = [] ;
Pattern0 = ['A'] ;
Pattern0 = ['A', 'A'] ;
Pattern0 = ['A', 'A', 'A'] ;
Pattern0 = ['A', 'A', 'A', 'A'] ;
Pattern0 = ['A', 'A', 'A', 'A', 'A'] .
?- phrase(pattern0, "helloworld").
true.
此外,方便的DCG仅描述了一个列表:
list([]) -->
[].
list([X | Xs]) -->
[X],
list(Xs).
这似乎没什么作用,但很快就会派上用场:
?- phrase(list([a, b, c]), List).
List = [a, b, c].
?- phrase(list(List), [a, b, c]).
List = [a, b, c] ;
false.
现在,您想定义一个复合模式,如Pattern0..->“.Pattern1..”|“.Next
。我建议以不同的方式编写它,即作为子模式列表:[pattern0,“->”,pattern1,“|”,Next]
。此类列表可能包含三种元素:
- DCG规则名称
- 文字字符列表
- 可能绑定到字符列表的变量
composite([]) -->
[].
composite([Head | Tail]) -->
{ atom(Head) },
% Assume that this atom is the name of another DCG rule, and execute it.
call(Head),
composite(Tail).
composite([Head | Tail]) -->
list(Head),
composite(Tail).
这表示复合模式只描述其子模式所描述的序列。它只有两个处理子模式的子句:一个用于DCG规则名称(由原子表示),另一个用于字符列表。变量的大小写由character list子句自动处理
我们可以使用此定义将字符列表(如“foo->bar | baz”
与复合模式匹配:
?- phrase(composite([pattern0, "->", pattern1, "|", Next]), "foo->bar|baz").
Next = [b, a, z] ;
false.
process_str(Sequence, Next) :-
phrase(composite([pattern0, "->", pattern1, "|", Next]), Sequence).
差不多完成了!我们可以将其打包到封装模式的定义中:
?- phrase(composite([pattern0, "->", pattern1, "|", Next]), "foo->bar|baz").
Next = [b, a, z] ;
false.
process_str(Sequence, Next) :-
phrase(composite([pattern0, "->", pattern1, "|", Next]), Sequence).
其工作原理如下:
process_str(Str, Next) :-
is_valid_pattern0(Pattern0),
concat(Pattern0, Tail0, Str),
concat("->", Tail1, Tail0),
is_valid_pattern1(Pattern1),
concat(Pattern1, Tail2, Tail1),
concat("|", Tail2, Next).
?- process_str("foo->bar|baz", Next).
Next = [b, a, z] ;
false.
我认为这已经相当不错了。但是如果你真的想要一种模式匹配语法,term\u expansion
会有所帮助。它的用法(看似)简单:为术语扩展定义一个子句(SomeTermPattern,sometherterm)
,每个与SomeTermPattern
匹配的子句定义都将被视为程序员编写了sometherterm
。因此:
term_expansion(
% Replace every definition of this form:
patterned_process_str(Pattern, Next),
% by a replacement like this:
patterned_process_str(Sequence, Next) :-
phrase(composite(Pattern), Sequence)
).
patterned_process_str([pattern0, "->", pattern1, "|", Next], Next).
我们可以查看Prolog对模式化的\u进程\u str的源代码的内部表示,以确保它符合预期:
?- listing(patterned_process_str).
patterned_process_str(B, A) :-
phrase(composite([pattern0, [-, >], pattern1, ['|'], A]), B).
变量名丢失,但除此之外,patterned\u process\u str
的定义扩展到了我们想要的形式,即我们为上面的process\u str
编写的相同形式。此定义的工作原理与上面的process\u str
完全相同(因为它是等效的):
练习:提供