我可以在Prolog的catch调用中共享变量吗?

时间:2013-03-20 17:19:44

标签: algorithm prolog

我正在Prolog中开发一个任务调度程序。首先让我向您展示我的代码的简化版本。它是这样的:

handle_activable(As) :-
    reset_flags,
    findall(A,catch(activable(A),Exception,flag(marked_activable,A)),As),
    activate_all(As).

activable/1有两个版本,但最相关的版本是(再次简化):

activable(T) :-
    task(T),        /* T is a task */
    inactive(T),    /* The task is currently inactive */
    (\+checked(T) ->
        mark_checked(T),
        !,
        /* 
           Here would go the set of conditions 
           and  statements to determine if task T 
           is activable or not. They may internally 
           call activable/1.
        */
        asserta(flag(marked_activable,T))
    ;   
        /* 
           This task was already checked and the 
           result is stored in flag(marked_activable,T) 
           fact. 
        */
        throw(exception(already_checked,T))
    ). 

问题是,在“条件设置检查”中,activable/1可能被间接调用。这就是我需要使用checked/1的原因,以避免不必要的循环。 我猜测我使用findall/3的方式还可以,但由于As始终被实例化为空列表[],我开始认为它有问题。

我想问你的第一件事是catch(...)电话。这是对的吗?我的意思是,如果在activable/1调用期间,程序抛出异常,因为任务已经被检查过,A是否仍然会被实例化(以便我可以在flag(marked_activable,A)中使用它)?如果没有,你知道任何解决方法吗?

我想问你的第二件事是关于算法的正确性。我已经在这方面工作了很长时间,我尽力拥有一个高效,强大和可靠的代码。真正的困难在于条件集检查,其中任务的关系起着重要的作用并产生复杂的约束。你认为“找到可激活的任务”的方式是好的吗?

1 个答案:

答案 0 :(得分:0)

使用内置的catch/3谓词,传递信息的正确方法是Catcher一词。

catch(:Goal, +Catcher, :Recover)

根据SWI-Prolog文档,GoalCatcherthrow/1的参数统一的最内层目标,Goal生成的所有选择点被剪切,系统回溯到catch/3的开头,同时保留抛出的异常术语。 因此,有一个规则:

generate(info1).
generate(info2).
generate(info3).
generate(info4).
rule(D) :-
    generate(D),
    ...
    throw(error_info(D)).

捕获此规则的结果将是这样的:

?- catch(rule(D), Exception, write(Exception)).
error_info(info1).
Exception = error_info(info1).

?- catch(rule(_), error_info(E), write(E)).
info1.
E = info1.