prolog - 如何在不使用列表的情况下对谓词值求和?
问题描述
我试图在不使用列表的情况下总结谓词中的值。对值求和,最后得到这些值的总和。
%shop(TicketNumber, Client, Month).
shop(1, ash, 12).
shop(2, nelson, 11).
shop(3, rob, 10).
%cart(TicketNumber, Product, Price).
cart(1, eggs, 15).
cart(1, milk, 20).
cart(1, meat, 30).
cart(2, eggs, 10).
cart(2, soil, 5).
totalCostShop 应返回总成本,例如 shop(1, ash, 12) 总成本将为 65。
解决方案
对您的问题的技术正确答案是使用库中的谓词(聚合)。一个简单的查询:
?- aggregate_all(sum(Price), cart(1, _, Price), Total).
Total = 65.
你看,任何地方都没有清单!好吧,谁知道呢,也许背后隐藏着名单aggregate_all
,但我们看不到它们,amirite?
一种无需在常量内存中创建数据结构即可聚合的方法是使用全局状态。通常不建议这样做,原因有两个:
- 一般来说,全局状态很难维护;
- 特别是在 Prolog 中,用于操作全局状态的代码编写起来很笨拙。
以下是迭代事实并获得副作用的方法:
?- forall(cart(1, _, Price), format("~w~n", [Price])).
15
20
30
true.
第一个参数是生成器(在这种情况下,表中forall
的那些行在第一个参数中)。的第二个论点是副作用。现在您只需添加到全局变量而不是打印到标准输出:cart/3
1
forall
?- nb_setval(total, 0),
forall(cart(1, _, Price),
( nb_getval(total, X0),
X1 is X0 + Price,
nb_setval(total, X1)
)),
nb_getval(total, Total).
Total = 65.
(请参阅下面的评论。)
您可以使用其他机制来保持全局状态。最便携的方法是将 (well, assert
) 插入到具有单行的表中,然后在每个步骤中读取并删除该行上的值 (with retract
),添加到其中,然后assert
返回结果。如果您需要为自己的(应用程序级)簿记保持真正的全局状态,我已经在关系数据库中看到了这种舞蹈。
在正常使用中,这是不必要的。但是,了解它是如何完成的很有用,这就是我费心写下所有这些的原因。我们不能有这个“你不能有这个”的狗屎。
推荐阅读
- selenium - Nutch Selenium Interactive 插件忽略 chromedriver 配置
- macos - Flutter macOS 插件
- r - 提供的列类型矩阵是未知的。由于参数无效,无法继续解析
- python - 灰度图像中轮廓图的OpenCV平均强度
- java - 在 JSONObject 中创建 JSONObject 以发布数据
- html - 如何在 iphone 的灯光模式下保持电子邮件模板 [Newsletter] 相同的背景
- python - 如何解决 Pandas Dataframe 中的格式错误 - 长度问题或格式?
- asp.net - SqlException:列名“NormalizedName”无效。列名“ConcurrencyStamp”无效。列名“NormalizedName”无效
- arrays - Spark:从 Scala 中的嵌套数组中删除第一个数组
- html - 如何使用 Bootstrap 4 在 div 旁边放置链接按钮