Prolog - how to do setof that returns empty list instead of failing

后端 未结 3 742
臣服心动
臣服心动 2020-12-20 03:49

I need an ordered list of Objects that satisfy Goal. setof takes care of the ordering, but fails when no Objects satisfy Goal. I want to return an empty list in

3条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-20 03:51

    First,

    ..., ( setof(Object, Goal, List), ! ; List = [] ), ...
    

    does not work, as you suggest. It always succeeds for List = [], and it only shows the first answer of setof/3. But setof/3 may produce several answers. The general method that works in any Prolog is:

    ..., ( \+ Goal -> List = [] ; setof(Object, Goal, List) ), ...
    

    Many implementations offer an implementation specific control construct for this which avoids that Goal is called twice. E.g. if/3 (SICStus, YAP), or (*->)/2 (SWI, GNU):

    ..., if( setof(Object, Goal, ListX), ListX = List, List = [] ), ...
    
    ..., ( setof(Object, Goal, ListX) *-> ListX = List ; List = [] ), ...
    

    The new variable ListX is necessary for the (admittedly rare) case that List is already instantiated.

    Note that both other answers do not produce exactly what you asked for.

提交回复
热议问题