1

将 X,Y 与 (1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1) 统一的优雅方法是什么, (-2,1), (-2,-1)?

这样做似乎容易出错且乏味:

foo(1,2).
foo(1,-2).
foo(-1,-2).
...
...
...

而且这种方式似乎太贵了:

foo(X,Y) :-
  L = [1,-1,2,-2],
  member(X,L),
  member(Y,L),
  abs(X,X1), abs(Y,Y1),
  X1 =\= Y1.
4

3 回答 3

3
foo0(X,Y):-
    member(X,[1,-1]),
    member(Y,[2,-2]).

foo(X,Y):-
    foo0(X,Y);
    foo0(Y,X).
于 2009-10-06T13:56:28.387 回答
1

关于评论的进一步发展:

generate_pairs_foo(X,Y) :-
  L = [1,-1,2,-2],
  member(X,L),
  member(Y,L),
  abs(X,X1), abs(Y,Y1),
  X1 =\= Y1.

assert_all_foo([]).

assert_all_foo([(X,Y)|T]) :-
  assert(foo(X,Y)), assert_all_foo(T).

find_all((X,Y),generate_pairs_foo(X,Y),L), assert_all_foo(L).

嗯嗯……看,写所有的案例更容易更短xD

于 2009-10-06T13:51:58.103 回答
1

以这种方式使用 member/2 是一种Prolog 反模式。虽然 member/2 很短,但通常 member/2 不能做子句索引。

您可以尝试自己并比较这两种解决方案:

福会员:

foo_member0(X,Y):-
    member(X,[1,-1]),
    member(Y,[2,-2]).

foo_member(X,Y):-
    foo_member0(X,Y);
    foo_member0(Y,X).

福条款:

foo_clause0(1).
foo_clause0(-1).

foo_clause1(2).
foo_clause1(-2).

foo_clause2(X,Y) :- foo_clause0(X), foo_clause1(Y).

foo_clause(X,Y) :- foo_clause2(X,Y).
foo_clause(X,Y) :- foo_clause2(Y,X).

现在在 GNU Prolog 中运行它:

| ?- between(1,1000000,_), foo_member(-2,-1), fail; true.
(516 ms) yes

| ?- between(1,1000000,_), foo_clause(-2,-1), fail; true.
(375 ms) yes

好吧,如果某些 Prolog 开始自动将 member/1 编译为子句,当第二个参数为基础时,情况可能会改变。

于 2019-02-01T19:07:52.637 回答