所以基本上我试图使用一些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?
所以在上面的代码中,我对
感到困惑根据我的理解,在ref(p, TEMP)
之后,TEMP
将等于"a"
,它只是一个字符串,那么我如何将其重用为变量名,听起来像是反思......?
如何实施 to_lowercase 功能?
我清楚了吗?
答案 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更适合用于更新动态知识库。