简体   繁体   English

计算Prolog中的多维数据集列表

[英]Calculate a list of cubes in Prolog

So I'm doing some Prolog in SWI-Prolog and I've come across a little snag. 所以我在SWI-Prolog中做一些Prolog,遇到了一些障碍。 I must create a list of cubes, given an input list. 给定输入列表,我必须创建一个多维数据集列表。 The code I currently have is 我目前拥有的代码是

cubes([Head|Tail],Cubes) :-
    cubes([Head|Tail],Cubes,[]).
cubes([Head|Tail],Cubes,ActualCubes) :-
    X is Head^3,
    append(ActualCubes,[X],NewCubes),
    cubes(Tail,Cubes,NewCubes).
cubes([Tail],Cubes,ActualCubes) :-
    X is Tail^3,
    append(ActualCubes,[X],NewCubes),
    Cubes is NewCubes.

When I run that it gives an error, specifically... 当我运行它给出一个错误,特别是...

ERROR: '.'/2: Type error: `[]' expected, found `[8]' ("x" must hold one character)
   Exception: (7) cbList([1, 2], _G296, []) ? creep

I'm not entirely sure why this error is occurring but it seems to happen around the very last line, Cubes is NewCubes. 我不完全确定为什么会发生此错误,但似乎发生在最后一行,即Cubes是NewCubes。 Any help is appreciated :) 任何帮助表示赞赏:)

I think you are trying to exercise a pattern known as accumulator , rewriting a binary relation with an added argument that holds intermediary results. 我认为您正在尝试使用一种称为“ 累加器”的模式,用包含中间结果的附加参数重写二进制关系。

Syntax errors apart, you should note that an accumulator it's useless here, because each element of a list is in relation only with the corresponding element of the other list. 除了语法错误之外,您还应该注意,这里的一个累加器是没有用的,因为一个列表的每个元素与另一个列表的相应元素相关。

library( apply ) has maplist /3 for such common case: 对于这种常见情况,library( apply )具有maplist / 3:

cube(N, C) :-
    C is N^3.
cubes(Ns, Cs) :-
    maplist(cube, Ns, Cs).

and library( clpfd ) has interesting features that allow (in integer domain) a better relational handling of arithmetic. 和library( clpfd )具有有趣的功能,这些功能允许(在整数域中)对算术进行更好的关系处理。 Replace cube above with 将上面的多维数据集替换为

:- [library(clpfd)].

cube(N, C) :-
    N ^ 3 #= C.

and you are allowed to write 你被允许写

?- cubes(X,[1,8,27]).
X = [1, 2, 3].

First, you're making different cubes predicates with differing numbers of arguments. 首先,您要使用不同数量的参数制作不同的cubes谓词。 This is bound to cause both conceptual and syntactical problems, so at that point, re-think what you're doing. 这势必会引起概念和句法上的问题,因此在那时,请重新考虑您在做什么。 In this case, try to expand the ways you can use pattern matching and recursion: 在这种情况下,请尝试扩展使用模式匹配和递归的方式:

cubes([],[]).
cubes([H|T], [Y|Z]):-
        Y is H*H*H,
        cubes(T,Z).


betterCubes([],[]).
betterCubes([H|T], [Y|Z]):-
        ( 
          var(Y) , nonvar(H)    -> Y is H*H*H
        ; nonvar(Y) , var(H)    -> H is Y**(1.0/3.0) 
        ; nonvar(Y) , nonvar(H) -> H*H*H =:= Y
        ),
        betterCubes(T,Z).

In this case, one can also accomplish the desired goal with a difference list : 在这种情况下,还可以通过差异列表来实现期望的目标:

cubes( [] , [] ) .
cubes( [X|Xs] , [Y|Ys] ) :-
  Y is X*X*X ,
  cubes( Xs , Ys )
  .

The output list is built as we traverse the source list, recursing down. 当我们遍历源列表并向下递归时,将构建输出列表。 The final goal cubes([],[]) unifies the empty list [] with the tail of the output list, making it a correct list. 最终目标cubes([],[])将空列表[]与输出列表的末尾统一起来,使其成为正确的列表。

The other approach is to use an accumulator, which builds the output in reverse order, then reverses it: 另一种方法是使用累加器,该累加器以相反的顺序构建输出,然后将其反向:

cubes(Xs,Ys) :-
  cubes(Xs,[],T) ,
  reverse(T,Ys)
  .

cubes( [] , Ys, Ys ).
cubes( [X|Xs] , Ts , Ys ) :-
  T is X*X*X ,
  cubes( Xs , [T|Ts] , Ys )
  .

Both are (our should be) properly tail recursive. 两者都是(我们应该是)正确的尾递归。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM