Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在prolog中转换为点表示法_List_Syntax_Prolog - Fatal编程技术网

List 在prolog中转换为点表示法

List 在prolog中转换为点表示法,list,syntax,prolog,List,Syntax,Prolog,我必须在Prolog中用点符号形式表示[[fruits],]],下面是我是如何做到的,但有些东西告诉我这是错误的,因为我也扩展了[[]],这是错误的吗 .([fruits],[[ ]] ) .(.(fruits, []),.([],[]) 嗯,/2就是Lisp中的cons。它包含两个参数:元素的头部和尾部。尾部可以是空列表[],也可以是另一个cons 让我们先看看我们必须转换的术语: X = [ [fruits] , [] ] 我们看到的是一个包含两个元素的外部列表(我们现在将忽略这些元素

我必须在Prolog中用点符号形式表示
[[fruits],]]
,下面是我是如何做到的,但有些东西告诉我这是错误的,因为我也扩展了
[[]]
,这是错误的吗

.([fruits],[[ ]] )

.(.(fruits, []),.([],[])

嗯,
/2
就是Lisp中的
cons
。它包含两个参数:元素的头部和尾部。尾部可以是空列表
[]
,也可以是另一个
cons

让我们先看看我们必须转换的术语:

X = [ [fruits] , [] ]
我们看到的是一个包含两个元素的外部列表(我们现在将忽略这些元素)。这意味着我们有这样一个结构:

X = .( Item1, .( Item2, []) ).
现在我们当然还需要填写
Item1
Item2
<代码>项目2不难:它是空列表
[]
,因此:

Item2 = [].
另一方面,
Item1
是一个包含一个元素的列表,因此结构为:

Item1 = .( Item11, [] ).
使用
Item11
该子列表的项。该项是
水果
,这意味着:

Item11 = fruits.
如果我们将这些放在一起,我们将获得:

X = .( .(fruits,[]), .([],[]) ).
如果我们在GNU Prolog(
gprolog
)中输入它,我们会得到:


gprolog
因此可以作为进行验证的工具,因为它会将点符号转换为列表的语法糖。

除了Willem编写的内容外,您还可以始终使用
write\u canonical/1
来获得任何术语的规范表示

例如,在您的情况下:

| ?- write_canonical([[fruits],[ ] ]). '.'('.'(fruits,[]),'.'([],[]))
没错:这是一个包含单个元素的列表,它是
[]
,如
术语的第一个参数所示。/2
术语。由于它是唯一的元素,第二个参数也是
[]

最初在prolog中没有
[]
,而
向量总是使用
构造的

以下是大卫·沃伦(David Warren)[*36'脚注]1979年发表的一篇论文中的一个例子:

  ([user]) .

  :- (op(1,'xfy','.')) .

  concatenated(nil,L,L) . 
  concatenated((X.L1),L2,(X.L3)) :- concatenated(L1,L2,L3) .

  %^D
测试和演示

  /*
  ((concatenated((nil),(nil),Z)) , Z == (nil)) .
  ((concatenated((a.b.nil),(c.d.nil),Z)) , Z == (a.b.c.d.nil)) .
  */

  ?- ((concatenated((nil),(nil),Z)) , Z == (nil)) .
  %@ Z = nil
  ?- ((concatenated((a.b.nil),(c.d.nil),Z)) , Z == (a.b.c.d.nil)) .
  %@ Z = [a,b,c,d|nil]
  /*
  ((List = (nil)) , (list(List))) .
  (\+ ((List = (a)) ,  (list(List)))) .
  ((List = (a.nil)) , (list(List))) .
  (\+ ((List = (nil.a)) , (list(List)))) .
  ((List = (nil.nil)) , (list(List))) .
  */

  ?- ((List = (nil)) , (list(List))) .
  %@ List = nil
  ?- (\+ ((List = (a)) ,  (list(List)))) .
  %@ true
  ?- ((List = (a.nil)) , (list(List))) .
  %@ List = [a|nil]
  ?- (\+ ((List = (nil.a)) , (list(List)))) .
  %@ true
  ?- ((List = (nil.nil)) , (list(List))) .
  %@ List = [nil|nil]
上面的代码在yap、eclipse、gprolog和xsb中工作。 但是,它在swipl中不起作用(见附录)

本文介绍的
串联与现代典型的附加prolog实现完全相同,但名称不同,结尾标记不同

一般的模式是每个元素通过
与其相邻元素分离

最后一个元素是表示结束的标记。在沃伦的例子中,
nil
是表示结束的标记。使用
nil
似乎是一种惯例,但不是一种要求。prolog的后续开发将使用
nil
作为结束标记替换为使用
[]
作为结束标记

沃伦的开创性例子可以用
[]
而不是
nil
进行最低限度的改写

  ([user]) .

  ((append([] , L , L))) . 

  (
     (append((X.L1) , L2 , (X.L3))) 
  )
  :- 
  (
     (append(L1 , L2 , L3)) 
  )
  .

  %^D

  /*
  ((append(([]) , ([]) , Z)) , (Z == [])) .
  ((append((a.b.[]),(c.d.[]),Z)) , Z == (a.b.c.d.[])) .
  ((append((a.b.[]),(c.d.[]),Z)) , Z == [a,b,c,d]) .
  ((append(([a,b]),([c,d]),Z)) , Z == [a,b,c,d]) .
  */

  ?- ((append(([]) , ([]) , Z)) , (Z == [])) .
  %@ Z = []
  ?- ((append((a.b.[]),(c.d.[]),Z)) , Z == (a.b.c.d.[])) .
  %@ Z = [a,b,c,d]
  ?- ((append((a.b.[]),(c.d.[]),Z)) , Z == [a,b,c,d]) .
  %@ Z = [a,b,c,d]
  ?- ((append(([a,b]),([c,d]),Z)) , Z == [a,b,c,d]) .
  %@ Z = [a,b,c,d]
沃伦继续说

。。。其中列表是原子“nil”或由 二元函子“.”,其第二个参数是列表。。。我们写 函子作为右关联中缀运算符,以便 例如,提到的第一个列表[ed:
(a.b.c.d.nil)
]是 相当于标准格式
(a,(b,(c,(d,nil))”

沃伦提供了这个例子

  ([user]) .

  list(nil) . 

  list(.(X,L)) :- list(L) .

  %^D
测试和演示

  /*
  ((concatenated((nil),(nil),Z)) , Z == (nil)) .
  ((concatenated((a.b.nil),(c.d.nil),Z)) , Z == (a.b.c.d.nil)) .
  */

  ?- ((concatenated((nil),(nil),Z)) , Z == (nil)) .
  %@ Z = nil
  ?- ((concatenated((a.b.nil),(c.d.nil),Z)) , Z == (a.b.c.d.nil)) .
  %@ Z = [a,b,c,d|nil]
  /*
  ((List = (nil)) , (list(List))) .
  (\+ ((List = (a)) ,  (list(List)))) .
  ((List = (a.nil)) , (list(List))) .
  (\+ ((List = (nil.a)) , (list(List)))) .
  ((List = (nil.nil)) , (list(List))) .
  */

  ?- ((List = (nil)) , (list(List))) .
  %@ List = nil
  ?- (\+ ((List = (a)) ,  (list(List)))) .
  %@ true
  ?- ((List = (a.nil)) , (list(List))) .
  %@ List = [a|nil]
  ?- (\+ ((List = (nil.a)) , (list(List)))) .
  %@ true
  ?- ((List = (nil.nil)) , (list(List))) .
  %@ List = [nil|nil]
现在40年前的(列表(L))的实现, 不符合现代人对“逻辑”程序的期望

  % does it provide a useful answer in the general case ?

  ?- ((List = _) , (list(List))) .
  %@ List = nil ? ;
  %@ List = [_A|nil] ? ;
  %@ List = [_A,_B|nil] ? ;
  %@ List = [_A,_B,_C|nil] ? ;
  %@ List = [_A,_B,_C,_D|nil] ? ;
  %@ !! etc ... non-terminating !!
  %@ ^CAction (h for help): a

  % is it steadfast ?

  ?- ((list(List)) , (List = (nil))) .
  %@ List = nil ? ;
  %@ !! hang , non-terminating !!
  %@ ^CAction (h for help): a
。。。我不知道如何解决这些问题

当沃伦写

我们把函子写成一个函数 右关联中缀运算符,以便

。。。我认为他指的是prolog
xfy
的这个独特而有用的特性

  ([user]) .

  :- ((op(10'1,'xfy','~'))) .

  %^D

  /*
  (((Left ~ Rest) = (a ~ b ~ c ~ d ~ e)) , (Left == a) , (Rest == (b~c~d~e))) .
  (((Left_1 ~ Left_2 ~ Rest) = (a ~ b ~ c ~ d ~ e)) , (Left_1 == a) , (Left_2 == b) , (Rest == (c ~ d ~ e))) .
  */

  ?- (((Left ~ Rest) = (a ~ b ~ c ~ d ~ e)) , (Left == a) , (Rest == (b~c~d~e))) .
  %@ Left = a,
  %@ Rest = b~c~d~e
  ?- (((Left_1 ~ Left_2 ~ Rest) = (a ~ b ~ c ~ d ~ e)) , (Left_1 == a) , (Left_2 == b) , (Rest == (c ~ d ~ e))) .
  %@ Left_1 = a,
  %@ Left_2 = b,
  %@ Rest = c~d~e
有理由期望
yfx
运算符的行为相反; 而
xfy
允许从左侧抓取元素,忽略右侧的其余元素, 也许
yfx
允许您从右侧抓取元素,而忽略左侧的其余元素

  :- ((op(10'1,'yfx','~'))) .

  %^D

  /*
  (((Rest ~ Right) = (a ~ b ~ c ~ d ~ e)) , (Rest == a~b~c~d) , (Right == e)) .
  (((Rest ~ Right_2 ~ Right_1) = (a ~ b ~ c ~ d ~ e)) ,  (Rest == a ~ b ~ c) , (Right_2 == d) , (Right_1 == e)) .
  */

  ?- (((Rest ~ Right) = (a ~ b ~ c ~ d ~ e)) , (Rest == a~b~c~d) , (Right == e)) .
  %@ Rest = a~b~c~d,
  %@ Right = e
  ?- (((Rest ~ Right_2 ~ Right_1) = (a ~ b ~ c ~ d ~ e)) ,  (Rest == a ~ b ~ c) , (Right_2 == d) , (Right_1 == e)) .
  %@ Rest = a~b~c,
  %@ Right_1 = e,
  %@ Right_2 = d
[*36'脚注]--

附录 不要费心在swipl中玩
[]
[]
都不能正常工作

我向swipl报告了一个关于
的bug; 假设不符合传统标准 标准prolog系统也很有趣; 看来并非如此

swipl的作者建议使用
术语扩展
,但是无论是
术语扩展
还是
目标扩展
都不能解决问题 以下是基本的兼容性问题

  /*
  (a.b.[]) =[a,b]  .
  A ={ foo:a.b.nil } .
  [a,b|[c,d]] = [a,b,..[c,d]] .
  */

  $ yap
  + yap
  YAP 6.2.2 (x86_64-linux): Wed Sep  7 07:48:47 PDT 2016
  MYDDAS version MYDDAS-0.9.1
     ?- (a.b.[]) =[a,b]  .
     %@ yes
     ?- A ={ foo:a.b.nil } .
     %@ A = {[foo:a,b|nil]}
     ?- [a,b|[c,d]] = [a,b,..[c,d]] .
     %@ yes
     ?- (halt) .
  % YAP execution halted

  $ swipl
  + swipl
  Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.27)
  Copyright (c) 1990-2016 University of Amsterdam, VU Amsterdam
  SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is LGPL free software,
  and you are welcome to redistribute it under certain conditions.

  For help, use ?- help(Topic). or ?- apropos(Word).

  ?- (a.b.[]) =[a,b]  .
  ERROR: Type error: `dict' expected, found `a' (an atom)
  ?- A ={ foo:a.b.nil } .
  ERROR: Type error: `dict' expected, found `a' (an atom)
  ?- [a,b|[c,d]] = [a,b,..[c,d]] .
  ERROR: Syntax error: Operator expected
  ERROR: [a,b|[c,d]] = [a,b,.
  ERROR: ** here **
  ERROR: .[c,d]] . 
  ?- (end_of_file) .

  % halt

。。。向我建议,也许swipl的作者不太了解prolog(术语扩展?!!),或者对prolog的一致性不感兴趣,或者对建立供应商锁定感兴趣。

谢谢大家,这非常有用,不确定是否需要更新。为了让它正常工作,我必须使用` write_term([[fruits],][]],[dotlists(true)]。`请参见:如果您有一个预期的答案,您可以始终使用相等/统一进行检查:
((fruits,[]),([],[])这是简在书中解释的第二件事。您可以通过调用
swipl--traditional
重新激活旧模式。这里没有关于供应商锁定的阴谋。