const replace = ({length}) => Array(length).fill(0);
console.log(replace("testing"));
console.log(replace(['12','a','drink','cookie']));
我想运行此Prolog以声明名称和年龄,但是当我为数字写年龄时,它会显示
update :-
write("Name?:"),
read(Name),
assert(Name),nl,
write("Age?:"),
read(Age),
assert(Age),
write("Continue(y or n)?:"),
read(Respond),
process(Respond).
process(y) :-
write('Name?:'),
read(Name),
assert(Name),nl,
write("Age?:"),
read(Age),
assert(Age),
repeat,
write("y or n"),
read(Respond),
process(Respond).
process(n) :- !.
如何解决此问题。
答案 0 :(得分:2)
问题1
assert/1的错误输入
问题不仅仅在于Age
,还包括使用assert
的任何输入,例如
?- update.
Name?:Fred
|: .
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] assert(_4940)
ERROR: [8] update at c:/example.pl:8
ERROR: [7] <user>
?- update.
Name?:Jim.
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] assert(_5826)
ERROR: [8] update at c:/example.pl:8
ERROR: [7] <user>
问题是assert/1没有得到事实或规则。
assert/1
说:
在数据库中添加一个子句(事实或规则)。
在上面的示例中,Fred
不是事实,因为它没有以句点(.
)结尾。
在上面带有Jim.
的示例中,给出了一个句点,但是因为Jim
以大写字母开头,所以它不是事实或规则,而是变量。
以数字形式输入年龄时,这又不是事实或规则,而是整数。
问题2
使用read/1表示:
从当前输入流中读取下一个Prolog术语,并将其与Term统一。
阅读序言term时,输入必须以句点结尾。
这不仅要求输入是一个术语,而且以.
结尾,给定提示,例如Age
更加令人困惑。您发现的大多数示例都可以完成您的工作,下面的更正代码可以满足您的要求。
问题3
竞争方式或重复方式。
代码使用两种方式:
这使代码难以工作。
问题4
重复的代码,例如
write("Name?:"),
read(Name),
assert(Name),nl,
write("Age?:"),
read(Age),
assert(Age),
write("Continue(y or n)?:"),
read(Respond),
process(Respond).
当一个副本被纠正而另一副本未被纠正时,重复的代码更有可能导致问题。
问题1修复
使输入成为事实,然后再使用assert/1
将其存储在数据库中,例如
变量中的值
Name
Age
通过添加functor
将变量转换为事实name(Name)
age(Age)
assert/1
assert(name(Name))
assert(age(Age))
问题2修复
使用read_string/5,例如
read_string(user, "\n", "\r", End, Name)
这会将输入Name
作为字符串读取。现在输入是字符串,而不是Prolog术语,因此不再需要句点。有predicates that operate on strings。
问题3修复
使用递归表单并删除repeat/0。
这也可以使用repeat/0
代替递归。下面已更正的代码使用递归来演示对process/1
的更改。
问题4修复
只需重构代码即可。您可以在最后的更正代码中看到它。
现在已修复。
更改1
由于continue
的输入不再是术语,例如y
或n
,但为字符串,process
的参数必须为字符串,例如
process("y") :-
process("n") :-
更改2
年龄将断言为字符串,但最好断言为整数。
number_string/2可以解决此问题,例如
number_string(Age_n,Age),
assert(age(Age_n))
更改3
user27815在评论中提问:
您是否需要切入过程(“ n”):-!。 ?
因为
process(Respond).
没有创建选择点,不需要剪切。
更正的代码:
update :-
% Respond will be read as a string and not as a term, so it needs "".
process("y").
process("y") :-
write('Name: '),
read_string(user, "\n", "\r", End, Name),
assert(name(Name)),
write("Age: "),
read_string(user, "\n", "\r", End, Age),
number_string(Age_n,Age),
assert(age(Age_n)),
write("Continue: (y or n) "),
read_string(user, "\n", "\r", End, Respond),
process(Respond).
process("n").
示例运行:
?- update.
Name: Fred
Age: 30
Continue: (y or n) y
Name: Jim
Age: 21
Continue: (y or n) n
true.
要检查数据库是否已更新,请使用listing/1
?- listing(name/1).
:- dynamic name/1.
name("Fred").
name("Jim").
true.
?- listing(age/1).
:- dynamic age/1.
age(30).
age(21).
true.
免费的增强功能。
将名称和年龄的事实分开保存并不能保持它们之间的联系完整。更好的解决方案是同时使用person
和Name
值的Age
事实。
这是必要的修改后的代码。
update :-
% Respond will be read as a string and not as a term, so it needs "".
process("y").
process("y") :-
write('Name: '),
read_string(user, "\n", "\r", End, Name),
write("Age: "),
read_string(user, "\n", "\r", End, Age),
number_string(Age_n,Age),
assert(person(Name,Age_n)),
write("Continue: (y or n) "),
read_string(user, "\n", "\r", End, Respond),
process(Respond).
process("n").
示例运行:
?- update.
Name: Fred
Age: 30
Continue: (y or n) y
Name: Jim
Age: 21
Continue: (y or n) n
true.
要检查数据库是否已更新,请使用listing/1
?- listing(person/2).
:- dynamic person/2.
person("Fred", 30).
person("Jim", 21).
true.
在注意到您删除的答案之后。
在删除的答案中,您拥有
?- person(name(N), age(A)).
N = nancy,
A = 22;
N= steve,
A = 100;
true.
要创建此事实变体所需的更改是
assert(person(name(Name),age(Age_n)))
但是,这可能不是最佳的选择。
在Prolog中,位置通常表示值的含义,例如第一个位置是name
,第二个位置是age
。在此变体中,通过将函子name
和age
添加到事实person/2
,您可以复制已知知识,但更重要的是,Prolog必须要做大量工作。
例如:
如果事实是person(Name,Age).
才能得到Name
和Age
,那么Prolog只需一个统一即可。但是对于person(Name,Age).
,Prolog现在需要与person(name(nancy),age(22))
统一,然后才能使Name
与name(nancy)
再次统一,而使Age
必须与{{ 1}}。您也可以使用age(22)
,它仅需一个统一,但是现在使您的代码更加冗长。
初次学习Prolog时,这种拐杖会有所帮助,但是当使用较大的数据集时,这会开始影响性能。
已删除答案中的另一项值得注意的事项是,这些人的名字仍然基于使用person(name(Name),age(Age)).
,例如read/1
和nancy
。尽管许多Prolog示例都执行此操作,但并不需要保留它们本身,它们可以是字符串。奇怪的是,代码永远不需要在steve
或nancy
上完全匹配,而是总是将它们作为变量中的值引用。将它们保留为字符串的好处是,将它们写出时,它们将正确显示为steve
和Nancy
。
答案 1 :(得分:1)
这是因为assert不适用于变量。它主张事实或规则;换句话说,assert(something)
断言something
必须为真。
在数据库中添加一个子句(事实或规则)。
整数值不是规则或事实。在这种情况下,它是一个整数,而不是计算为布尔值的值。声明值没有意义。
答案 2 :(得分:1)
我会写一些助手:
read_assert(P,V) :- format('~w ? ',[P]), read(V), A =.. [P,V], assert(A).
?- maplist(read_assert, [name,age], Vs).
name ? capellic.
age ? 99.
Vs = [capellic, 99].
?- name(N).
N = capellic.