它在某种程度上是Prolog的“反思”吗?

时间:2014-05-13 02:40:38

标签: prolog swi-prolog code-translation gnu-prolog

所以基本上我试图使用一些Prolog代码来模拟指针之类的行为。

我问了一个相关问题here,大约一个月后,我终于有时间开始了。

以下是C中的一个简单示例:

int a = 1;
int* p = &a;
int b = *p;   

我想将此代码翻译成Prolog(或其他更好的策略?):

A is 1, 
assert(ref(p, a)),    <-  this can be dynamic fact gene
ref(p, TEMP),   <-  now I want to use a!!
to_lowercase(TEMP, TEMP1),  <- I don't know how to implement to_low
B is TEMP1.     <- reflection? 

所以在上面的代码中,我对

感到困惑
  1. 根据我的理解,在ref(p, TEMP)之后,TEMP将等于"a",它只是一个字符串,那么我如何将其重用为变量名,听起来像是反思......?

  2. 如何实施 to_lowercase 功能?

  3. 我清楚了吗?

3 个答案:

答案 0 :(得分:4)

你需要阅读一本关于Prolog的好书。我建议The Art of Prolog

Prolog没有像指针,地址或变量那样的东西。它有条款未绑定的术语是可变的,因为它尚未绑定。一旦绑定(统一),就不再是变量,它就变成了统一的。无法为其分配新值 - 除非通过回溯撤消统一,并采用其他路径。因此,术语统一

尝试将指针和记忆地址的概念映射到prolog上有点类似于将鱼鳃放在自行车上。

就实现用于将强大变换为小写的谓词而言,您应该意识到Prolog实际上没有字符串:Prolog字符串"ABC"与列表[65,66,67]完全相同,表示ASCII / Unicode代码点的整数列表。这就是所谓的语法糖。所以...鉴于身份......

这样的东西
to_lower( [] , [] ).
to_lower( [C|Cs] , [L|Ls] ) :-
  char_code('A',A),
  char_code('Z',Z),
  C >= A ,
  C =< Z ,
  ! , 
  char_code(a,Base),
  Offset = C - A ,
  L is Base+Offset,
  to_lower(Cs,Ls).
to_lower([C|Cs],[C|Ls]) :-
  to_lower(Cs,Ls).

你应该做。

答案 1 :(得分:4)

如果您真的决定在Prolog中模拟计算机,那么在继续之前,您应该考虑先前问题的答案。无论哪种方式,这个答案都会对你的最终目标做出很多假设。我猜你正在尝试模拟一台机器,并编写一个模拟器,它采用C风格的语言编写并执行它。

因此,假设您有一个非常简单的处理器,具有平坦的内存空间(一些小型嵌入式微控制器就像这样)。那么你的整个内存只是一个16位的地址,比如1000个地址:

functor(Memory, memory, 1000).

使用上面的C代码,编译器可能会提出:

  • Addr1选择一个地址a,这是一个int,并在该地址写下值1
  • Addr2选择p的地址int *,这是a,并在该地址写下Addr3的地址值
  • b选择int的地址p,并将arg(Addr1, Memory, 1), % int a = 1; arg(Addr2, Memory, Addr1), % int *p = &a; arg(Addr2, Memory, Tmp1), %% put the value at p in Tmp1; this is an address arg(Tmp1, Memory, Tmp2), %% read the value at the address Tmp1 into Tmp2 arg(Addr3, Memory, Tmp2). % int b = *p; 指向的内容中的值写入arg/3到。

这可能会转换为您正在模拟的机器的机器代码(假设编译器已经正确选择了实际地址):

memory/1000

所以当然所有地址都应该在你的记忆空间内。上面对{{1}}的一些调用是读取,有些是写入;应该清楚哪个是哪个。请注意,在此特定连接中,术语{{1}}的所有三个参数仍然是自由变量。要修改已设置的地址的值,您需要相应地复制它,释放您需要重用的地址。

在按下之前,请仔细阅读所有问题的答案。

答案 2 :(得分:3)

由于您标记了SWI-Prolog问题,我假设您已清楚string概念近期经历了一些important change,主要是出于效率原因。

查看downcase_atom / 2或string_lower / 2,具体取决于您的预期用法(我链接到字符串处理页面,因为string_lower有错字)。

用于存储指针&#39;像对象一样,我建议使用global variables,nb_setval / 2,nb_getval / 2,nb_current / 2而不是assert / retract。首先,效率要高得多(我之前测量的是nb_谓词族的3倍),并使预期的用法更加清晰。 assert / retract更适合用于更新动态知识库。