Prolog 如何创建与多个单词列表匹配的单个序言规则?

Prolog 如何创建与多个单词列表匹配的单个序言规则?,prolog,logic,declarative,Prolog,Logic,Declarative,我在特定列表上执行特定操作时遇到一些问题 我有一个标记列表,其中一个标记表示一个单词,我想使用一个单谓词来识别此列表中的一些连续标记是否表示可能采用以下两种形式的日期: 1) 第一种形式:1°Marzo 1995 2) 第二种形式:1°Marzo,1995年 我想用一个具体的例子来说明我提到代币清单时的意思 这是与第一种形式相关的令牌列表: [t(1[49])、t(-1[176])、t(-1[32])、t(2[77,97114122111])、t(-1[32])、t(3[49,57,57,53]

我在特定列表上执行特定操作时遇到一些问题

我有一个标记列表,其中一个标记表示一个单词,我想使用一个单谓词来识别此列表中的一些连续标记是否表示可能采用以下两种形式的日期:

1) 第一种形式:1°Marzo 1995

2) 第二种形式:1°Marzo,1995年

我想用一个具体的例子来说明我提到代币清单时的意思

这是与第一种形式相关的令牌列表:

[t(1[49])、t(-1[176])、t(-1[32])、t(2[77,97114122111])、t(-1[32])、t(3[49,57,57,53])、t(-1[10])

这是与第二种形式相关的令牌列表:

[t(1[49])、t(-1[176])、t(-1[32])、t(2[77,97114122111])、t(-1[32])、t(3[111102])、t(-1[32])、t(4[49,57,57,53])、t(-1[10])

正如您所看到的,一个通用标记有一个“函子”t,其中有两个参数:一个数字(不一定是累进的,如果一个标记不代表一个单词,但与alnum字符不同,那么它的值是-1)和一个表示一个单词或单个字符的字符串(如whit空格或“°”等等)

我已经实现了一个良好的工作谓词,该谓词可以识别令牌列表中的7个连续通用令牌是否代表一个日期(如1°Marzo 1995),然后通过连接构建一个专用数据令牌,方法如下:

tagga([t(Number1, Day), t(-1, "°"), t(-1, Space1), t(Number4, Month), t(-1, Space2), t(Number6, Year)|ListaToken], [d(Number1, CompositeDateTag)|ListaTokenTaggati]) :-

    length(Day, LnDay),
    (LnDay =:= 1; LnDay =:= 2),
    Day = [Head|Tail],
    char_type(Head, digit),
    %number_codes(DayNumber, Day),
    %DayNumber =< 31,

    Space1 == " ",

    member(Month, ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre",
                       "dicembre", "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre",                   "Novembre", "Dicembre"]),

    Space2 == " ",

    length(Year, LnYear),
    LnYear =:= 4,   

    NumericString = [Head|Tail],
    char_type(Head, digit),

    append(Day, "°", UntilSt),
    append(UntilSt, Space1, UntilSpace1),
        append(UntilSpace1, Month, UntilMonth),
        append(UntilMonth, Space2, UntilSpace2),
        append(UntilSpace2, Year, CompositeDateTag),

    tagga(ListaToken, ListaTokenTaggati).
tagga([t(数字1,天),t(-1,”),t(-1,空格1),t(数字4,月份),t(-1,空格2),t(数字6,年份)|列表项],[d(数字1,复合表项)|列表项]:-
长度(天,LnDay),
(LnDay=:=1;LnDay=:=2),
日=[头|尾],
字符类型(头部、数字),
%编号\u代码(日编号、日),
%日数=<31,
空格1==“”,
成员(月份)[“gennaio”、“febbraio”、“marzo”、“aprile”、“maggio”、“giugno”、“luglio”、“agosto”、“settembre”、“ottobre”、“Novenbre”,
“dicembre”、“Gennaio”、“Febbraio”、“Marzo”、“Aprile”、“Maggio”、“Giugno”、“Luglio”、“Agosto”、“Settembre”、“Ottobre”、“Novenbre”、“dicembre”],
空格2==“”,
长度(年、年),
LnYear=:=4,
数值字符串=[Head | Tail],
字符类型(头部、数字),
附加(日期“°”,直至第1天),
附加(直到,空格1,直到空格1),
附加(直到空格1,月份,直到月份),
附加(直到月,空格2,直到空格2),
追加(直到第2空间,年份,合成日期),
tagga(ListaToken,Listatokentagati)。
现在,我可以实现一个额外的谓词,识别tokens列表中的9个连续的通用标记是否代表第二种形式的日期(类似于:15 Marzo of 1995)但是我知道如果我可以修改我以前的tagga/2谓词来实现这一点它可以识别满足第一个和第二个形式的日期

我的推理如下,我有一个令牌列表,可能类似于:

[t(数字1,天),t(-1,”),t(-1,空格1),t(数字4,月),t(-1,空格2),t(数字6,年)| ListaToken]如果是第一个日期形式

或者类似于:

[t(数字1,天),t(-1,”),t(-1,空格1),t(数字4,月),t(-1,空格2),t(数字7,“of”),t(-1,空格3),t(数字9,年)| ListaToken]如果是第二个日期形式

好的,我将知道我是否可以以某种方式将这两种形式组合成一种通用形式,并与两者匹配,然后对其进行操作

大概是这样的:

[t(数字1,日),t(-1,”),t(-1,空格1),t(数字4,月)|子列表| t(数字9,年)|列表]

其中子列表可以是:

1) 单个标记:t(-1,空格2)

2) 类似这样的标记列表:t(-1,空格2),t(数字7,“of”),t(-1,空格3)


这个主意好吗?有人能帮我实现这样一个谓词吗?(我正在尝试,但到目前为止我还没有得到任何结果)

到目前为止,最简单的方法是声明两个备选方案,并让Prolog匹配适当的一个

这可能会导致长期的维护问题,然后评估您愿意支持多少这样的模式是值得的,并最终确定通用代码


最重要的细节是,您的规则应该是无副作用的——乍一看似乎是这样。

我之所以考虑建议的解决方案,是因为我更喜欢使用一条规则来处理彼此非常相似的许多情况,而不是使用多条规则(我更喜欢做一些更复杂的事情,因此当我向老师展示我的项目时,会有更多的争论,这对我来说也是一种练习)那么,这是什么意思,没有副作用?你的意思是不改变原始令牌列表中的任何内容吗?Prolog不允许你改变参数,正是因为它不依赖赋值来实现其计算模型。我指的是断言/收回、IO等。