如何在Prolog中强制执行person与action的名称唯一性?
避免Person与Action名称冲突的Prolog实现方案
先看你给出的示例代码:
person('Sascha'). person('Raymond'). action('Create'). action('Read'). action('Update'). action('Destroy'). access(Person, Action) :- Person = 'Sascha', Action = 'Create'. access(Person, Action) :- Person = 'Raymond', Action = 'Read'.
要防止出现名称为'Create'的person,或者名称为'Sascha'的action,可以用以下几种方式实现:
方法1:动态添加时实时检查
修改person/1和action/1的定义,让它们在添加新事实前自动检查名称是否已存在于对方的集合中:
% 添加person前,检查名称未被定义为action person(Name) :- \+ action(Name), % 确保Name不是已有的action assertz(person(Name)). % 添加action前,检查名称未被定义为person action(Name) :- \+ person(Name), % 确保Name不是已有的person assertz(action(Name)).
这样如果有人尝试执行person('Create').,因为action('Create')已经存在,\+ action(Name)会返回假,断言操作失败,无法添加这个冲突的person;同理,action('Sascha').也会因为person('Sascha')已存在而无法执行。
方法2:启动时批量验证
如果你的person和action是静态定义的(不会动态添加),可以在程序启动时自动检查所有名称是否有重叠:
% 检查person和action的名称集合无交集 validate_no_overlap :- findall(P, person(P), Persons), findall(A, action(A), Actions), intersection(Persons, Actions, []). % 程序加载时自动执行验证 :- validate_no_overlap.
一旦存在名称重叠,程序启动时就会抛出错误,提醒你修正冲突的定义。
方法3:用结构化数据从根源区分
给person和action的名称加上类型标记,用结构化术语替代原始原子,从根本上避免名称混淆:
person(person('Sascha')). person(person('Raymond')). action(action('Create')). action(action('Read')). action(action('Update')). action(action('Destroy')). access(Person, Action) :- Person = person('Sascha'), Action = action('Create'). access(Person, Action) :- Person = person('Raymond'), Action = action('Read').
这种方式下,即使有人写了person(person('Create')),它和action(action('Create'))的结构完全不同,不会被误判为冲突;如果需要额外检查,也可以提取结构中的名称做交叉验证。
内容的提问来源于stack exchange,提问作者ceving
相关产品推荐
相关产品推荐

