如何覆盖Swi-Prolog中的字典(键VAL对列表)



这是我的问题:

我有一个与此相似的键VAL对字典(实际代码中的更多对(:

args = [(score, 0), (multiplier, 1), (reward, 0), (prior_prob, 1)].

我定义了两个函数以使用字典:

% look up the Val of a Key in a Dict 
lookup(Key,Dict,Val):-
    member((Key,Val), Dict).

% update(Key, NewVal, Dict, NewDict) updates the value of a key in the dict
update(Key,Val,[],[(Key,Val)]).               % Add new pair to current dict
update(Key,Val,[(Key,_)|Rest], [(Key,Val)|Rest]):- !. % Found the key and update the value
update(Key,Val,[KV|Rest],[KV|Result]) :-      % recursively look for the key 
    update(Key,Val,Rest,Result).

我需要字典的原因是我有许多需要这些参数的函数(例如"得分","乘数"等(。这些功能互相调用并传递参数。并非每个功能都需要所有的参数,但是其中许多参数比其他函数都比其他函数更新。因此,该字典基本上是包裹着作为包装的参数列表,需要经常通过并经常覆盖。例如,没有字典,我可能具有此(化妆(功能:

calculate('cond1', 'cond2', S0, S1, Multiplier, Reward, Prior):-
    getscore('cond1', 'cond2', S0, S1, Multiplier, Reward, Prior).
getscore('cond1', 'cond2', S0, S1, Multiplier, Reward, Prior):-
    reward('cond1', 'cond2', Reward),  % look up rewards based on conditions
    MultNew is Multiplier*Prior,       % calculate the new multiplier
    S1 is (S0+Rewards*MultNew).        % update score

但是有一个字典,我可以:

calculate2('cond1', 'cond2', Args, NewArgs):-
    getscore2('cond1', 'cond2', Args, NewArgs).
getscore2('cond1', 'cond2', Args, NewArgs):-
    reward('cond1', 'cond2', Reward), 
    lookup(prior, Args, Prior),
    lookup(multiplier, Args, Mult),
    update(reward, Reward, Args),
    MultNew is Multiplier*Prior,
    update(multiplier, MultNew, Args, NewArgs),
    update(score, S0+Reward*MultNew, Args, NewArgs).

(第二种方式看起来比第一个方式更长,更慢,但是由于实际上,并非所有的ARG都需要一次更新或一次查找,并且由于以后添加更多参数更加灵活,所以我认为最好是有字典。请让我知道是否有更好的设计选择(,当我运行时,我会得到:

No permission to modify static procedure `(=)/2'

在我定义字典args的行号上。

我尝试了:-dynamic(arg/0, update/4, lookup/3).,这是没有用的。

(=(/2在这里意味着什么?如何允许在Prolog中覆盖词典?预先感谢您!

这是您问题的(可能(解决方案(在 swi-prolog 中(。字典使用 swi-prolog 嵌入数据库(非persistent(

这是一组术语链。术语与用户提供的

关联
%key `small int` or `atom`-
lookup(Key, Value) :-
    current_key( Key ),
    recorded( Key, Value, _ ) -> 
    true
    ;
    recordz(Key, Value).
update( Key, OldValue, NewValue ) :-
    same_term( OldValue, NewValue ) -> 
    true
    ;
    (current_key( Key ),
    recorded( Key, OldValue, Ref ase( Ref )
        ; 
        true,
    recordz( Key, NewValue, _ )).

编辑您还可以使用全局var,可回溯且不可折叠。例如 nb_setval/2, nb_getval/2

因此您的第一个语句看起来如下

:- nb_setval(score, 0),    
    nb_setval(multiplier, 1), 
    nb_setval(reward, 0), 
    nb_setval(prior_prob, 1),
    nb_setval(args, [score, multiplier, reward, prior_prob]).

edit2

=/2是谓词调用序言的统一过程unify/2。如果您的意思是在字典覆盖下 可变组的重新分配,则可以使用任何一种解决方案来完成:

edit3

%我认为应该这样:

update_dict(Dict):- 
    update(args, Dict). 
update(Key, Val):- 
    (nb_getval(Key, OldVal), 
    exists(Val, OldVal)) -> true; 
    nb_setval(Key, Val). 
update(Key, Val, Dict):- 
    update_dict( Dict ), 
    update( Key, Val ). 
exists(Val, OldVal) :-
    nonvar(OldVal),
    same_term(Val, OldVal).
%======================================   
lookup_dict( Dict):- 
    lookup(args, Dict). 
lookup(Key, Val):- 
    nb_getval(Key, OldVal),
    exists( Val, OldVal ) -> 
       true
        ; 
        nb_setval(Key, Val).
lookup( Key, Val, Dict ):- 
     lookup_dict( Dict ), 
     lookup( Key, Val ).