如何在prolog中加入规则并打印输出

如何在prolog中加入规则并打印输出,prolog,Prolog,我有如下事实清单 items(itemId('P01'),prodName('Pots'),stockQty(50),price(8200)). items(itemId('P02'),prodName('Pans'),stockQty(50),price(400)). items(itemId('P03'),prodName('Spoons'),stockQty(50),price(200)). items(itemId('P04'),prodName('Forks'),stockQty(50

我有如下事实清单

items(itemId('P01'),prodName('Pots'),stockQty(50),price(8200)).
items(itemId('P02'),prodName('Pans'),stockQty(50),price(400)).
items(itemId('P03'),prodName('Spoons'),stockQty(50),price(200)).
items(itemId('P04'),prodName('Forks'),stockQty(50),price(120)).
items(itemId('P05'),prodName('Kettles'),stockQty(50),price(500)).
items(itemId('P06'),prodName('Plates'),stockQty(50),price(60)).
当发出
print\u all\u products.
等命令时,如何在控制台上打印以下内容

可用产品

名称数量

盆60

平底锅50

汤匙40

  • 名称和数量必须在表格结构中正确格式化
我尝试使用
forall
foreach
生成所需的内容,但未成功。

。。。要将内容放在整齐的列中,请使用
~
~t
~+


~
将选项卡设置为“此处”,
~t
插入填充字符,
~+
将选项卡前进到最后一个“此处”(
~
)之外,并分发填充字符。所以

format("(~|~`.t~d~5+)~n", [123])

生成
(…123)
——格式字符串用宽度为5的
s右对齐数字,并用括号括起来。

您要求的是SQL样式的表格输出,是的,从Reagan是prez时起,该语言就应该是基本谓词集。我不知道发生了什么事。它可能在图书馆里(但图书馆在哪里?)

同时,这里是“故障驱动循环”,使用了我个人工具箱中的一些好东西,但它使用了SWI Prolog:

在文件
printThemes.pl
中:

:- use_module(library('heavycarbon/strings/string_of_spaces.pl')).
:- use_module(library('heavycarbon/strings/string_overwriting.pl')).

items(itemId('P01'),prodName('Pots'),stockOty(50),price(8200)).
items(itemId('P02'),prodName('Pans'),stockOty(50),price(400)).
items(itemId('P03'),prodName('Spoons'),stockOty(50),price(200)).
items(itemId('P04'),prodName('Forks'),stockOty(50),price(120)).
items(itemId('P05'),prodName('Kettles'),stockOty(50),price(500)).
items(itemId('P06'),prodName('Plates'),stockOty(50),price(60)).

printthem :-
   % ideally these should be built by getting max(length) over a column - hardcode for now!
   string_of_spaces(5,SpacesId),
   string_of_spaces(10,SpacesName),
   string_of_spaces(4,SpacesQuant),
   string_of_spaces(6,SpacesPrice),
   % begin failure-driven loop!
   items(itemId(Id),prodName(Name),stockOty(Quant),price(Price)), % backtrack over this until no more solutions
   % transform data into string; see predicate format/2;
   % capture output instead of letting it escape to STDOUT
   with_output_to(string(TxtId),format("~q",[Id])),
   with_output_to(string(TxtName),format("~q",[Name])),
   with_output_to(string(TxtQuant),format("~d",[Quant])),
   with_output_to(string(TxtPrice),format("~d",[Price])),
   % formatting consist in overwriting the space string with the data-carrying string
   string_overwriting(SpacesId,TxtId,       1,TxtIdFinal),
   string_overwriting(SpacesName,TxtName,   1,TxtNameFinal),
   string_overwriting(SpacesQuant,TxtQuant, 1,TxtQuantFinal),
   string_overwriting(SpacesPrice,TxtPrice, 1,TxtPriceFinal),
   % output the line
   format("~s~s~s~s\n",[TxtIdFinal,TxtNameFinal,TxtQuantFinal,TxtPriceFinal]),
   % close the loop
   fail.
以上只是一个简单的例子。可以从几个不同的方向进行改进

模块通过以下方式加载:

:- use_module(library('heavycarbon/strings/string_of_spaces.pl')).
:- use_module(library('heavycarbon/strings/string_overwriting.pl')).
可从GitHub获得。你将不得不抓取几个文件,并适当地安排它们。读剧本。不要介意乱七八糟,这是正在进行的工作

如果所有设置都正确:

?- [printthem].
true.

?- printthem.
 'P01' 'Pots'    50  8200 
 'P02' 'Pans'    50  400  
 'P03' 'Spoons'  50  200  
 'P04' 'Forks'   50  120  
 'P05' 'Kettles' 50  500  
 'P06' 'Plates'  50  60   
false.

更多细节的答案已发布。 下面是代码,所以这不是一个链接唯一的答案

items(itemId('P01'),prodName('Pots'),stockOty(50),price(8200)).
items(itemId('P02'),prodName('Pans'),stockOty(50),price(400)).
items(itemId('P03'),prodName('Spoons'),stockOty(50),price(200)).
items(itemId('P04'),prodName('Forks'),stockOty(50),price(120)).
items(itemId('P05'),prodName('Kettles'),stockOty(50),price(500)).
items(itemId('P06'),prodName('Plates'),stockOty(50),price(60)).

header("\n........................\nAvailable Products\n........................\nName   Qty\n").
footer("........................\n").

spaces(Length,Spaces) :-
    length(List,Length),
    maplist([_,0'\s]>>true,List,Codes),
    string_codes(Spaces,Codes).

padded_string(String,Width,Padded_string) :-
    string_length(String,String_length),
    Padding_length is Width - String_length,
    spaces(Padding_length,Padding),
    atom_concat(String,Padding,Padded_string).

format_detail_line(item(Name,Quantity),width(Name_width),Formatted_item) :-
    padded_string(Name,Name_width,Padded_name),
    atom_concat(Padded_name,Quantity,Formatted_item).

add_detail_line(width(Name_Width),Item,Lines0,Lines) :-
    format_detail_line(Item,width(Name_Width),Formatted_item),
    atomic_list_concat([Lines0,Formatted_item,"\n"], Lines).

items_detail(Detail) :-
    findall(item(Name,Quantity),items(_,prodName(Name),stockOty(Quantity),_),Items),
    aggregate_all(max(Width),Width,(items(_,prodName(Name),_,_),string_length(Name,Width)),Name_Width),
    Name_field_width is Name_Width + 1,
    foldl(add_detail_line(width(Name_field_width)),Items,"",Detail).

print_all_products(Report) :-
    header(Header),
    items_detail(Detail),
    footer(Footer),
    atomic_list_concat([Header,Detail,Footer], Report).

print_all_products :-
    print_all_products(Report),
    write(Report).

:- begin_tests(formatted_report).

test(1) :-
    print_all_products(Report),
    with_output_to(atom(Atom),write(Report)),
    assertion( Atom == '\n........................\nAvailable Products\n........................\nName   Qty\nPots    50\nPans    50\nSpoons  50\nForks   50\nKettles 50\nPlates  50\n........................\n' ).

:- end_tests(formatted_report).

注:Peter给出的格式是进行格式化的惯用方法,但正如我所指出的,这让我发疯。即便如此,这也是我在生产环境中的做法

我给出这个答案是因为OP注意到他们正在寻找一种使用forall/2或foreach/2等谓词的方法。虽然这两种方法均未在本答案中使用,但使用了更实用的方法


如果问题更加开放,我会使用DCGs给出答案。

在其他编程语言中,打印类似于业务报告的数据是常见的,您的输出类似于业务报告。在Prolog中,我很少将输出格式化为业务报告,因为这不是我使用Prolog的原因。如果您正试图学习Prolog,那么就要学习如何使用Prolog,因为这是您所知道的。将您的思想从其他编程语言的概念中解放出来,从头开始学习Prolog。继续。换句话说,如果你让它变得困难的话,学会在Prolog上做得很棒并不容易。如果你想让学习Prolog变得更加困难,那么试着从一开始就学会错误地使用Prolog,然后花上数倍的努力来忘记错误的使用Prolog的方法,从而在Prolog上取得好成绩。哦,好的。除了类似报告的结构之外,学习如何打印出所有可用值的列表不是很好吗?@GuyCoder你能检查一下吗。我已经简化了这个问题。使用格式为/2的
~t
~
~+
使我发疯。@GuyCoder我也是
~
将选项卡设置为“here”,
~t
插入填充字符,
~+
将选项卡推进到最后一个“here”(
~
)之后,并分配填充字符。因此,
格式('(~~~`.t~d~5+~n',[123])
产生
(…123)
。。。这个数字用宽度为5的
s右对齐。您能否添加更多真实世界的示例,并在SWI Prolog论坛上创建一个Wiki?:)“我会的,但我可能会发疯。”GuyCoder——我在回答中加入了我的真实世界的例子;如果你愿意,你可以投上一票同时,我的单元测试显示SWI Prolog在8.3.4和8.3.5之间获得了额外的不确定性。有趣的。。。说到里根,我注意到这本关于“战略防御计划”计算方面的书只提到了一次Prolog,甚至没有一次出现在索引中,而LISP在每一页上都会被提到两次。只关心本地区的好的,继续工作。您不需要
字符串\u空格
。。。只需使用
格式
(参见我的答案)<代码>格式还可以很容易地对项目进行右对齐。@GuyCoder Jeez有时人们只想在10分钟内完成事情。@GuyCoder经过30年的开发,我看到了很多。这就是为什么我们有一个包含10000个条目的表来测试Casesty it,它能工作吗?