如何检查列表中元素的类型

时间:2014-02-18 02:31:58

标签: list prolog typechecking

我的列表(其中包含列表)包含许多不同类型的元素(obj1(),obj2(),obj3 ..)。我想访问此列表中的每个元素,并仅在我当前访问的元素是obj2(_)类型时执行某些操作。

listObj = [[ obj1(_), obj2(_), obj1(_) ],
          [ obj3, obj3, obj2(_), obj1(_)]],

foreach ((X, listObj)), 
%% if X is obj2(_) -> doSomething using x's _ value,
%% otherwise skip this element
).

3 个答案:

答案 0 :(得分:3)

使用列表列表通常提示表示错误。有些系统在列表上提供flatten/2库谓词可能很有用,但是,如果您无法避免这种表示。假设示例中的列表列表已被展平,您应该能够编写一个简单的递归谓词来遍历列表并处理满足条件的每个元素。类似的东西:

process([]).
process([Element| Elements]) :-
    (   Element = obj2(Arg) ->
        do_something(Arg)
    ;   true
    ),
    process(Elements).

但是,详细信息取决于您未指定的几个因素。例如,如果处理obj2(_)元素失败,这意味着什么?处理列表失败(如上面描述的谓词)?继续下一个元素?列表元素是独立的还是可以共享变量?一些Prolog系统还提供foreach/2forall/2谓词,这些谓词可能对紧凑(但不一定更有效)的解决方案有用。

答案 1 :(得分:1)

我认为这只是一个基本的递归问题 - 如何遍历列表,并在头上使用模式匹配。如果是这样,这应该

% case 1 - end recursion
listiter([]).

% case 2 - list head obj2 matches
listiter([obj2(Obj_2_Value)|T]) :-
    write(Obj_2_Value), nl,
    listiter(T).

% case 3 - case 2 failed, just recurse, ignoring head
listiter([_|T]) :-
    listiter(T).

在你的'真实'代码中,将'write / nl'谓词替换为你想要用obj2()的值实现的任何内容。

?listiter([obj1(brown), obj2(hello), obj3(fred), obj2(stack), obj4(bun), obj2(overflow)]).
hello
stack
overflow
true .

或者更短的方式,使用内置的maplist / 1:

% match if item is obj2()
dosomething(obj2(Obj_2_Value)) :-
    write(Obj_2_Value), nl.

% not object 2 - still return true, but don't do anything
dosomething(_).


?- maplist(dosomething, [obj1(brown), obj2(hello), obj3(fred), obj2(stack), obj4(bun), obj2(overflow)]).
hello
stack
overflow
true .

答案 2 :(得分:0)

更简单的方法(但请注意:变量从大写开始):

..., flatten(ListObj, F), member(obj2(V), F), process(V), ...

为了避免扁平化列表,我们必须创建一个谓词,并引入递归:

nested_member(V, X) :-
    member(T, X),
    ( is_list(T) -> nested_member(V, T) ; V = T ).

?- nested_member(obj2(V),[[1,[2,obj2(3),a],obj2(b),4]]).
V = 3 ;
V = b ;
false.