如何在重复中积累(永远)
How to accumulate in a repeat (forever)
在硬件设备的命令和控制上下文中,我需要一个无限循环 "acquire-elaborate-publish" 并记住当前状态,以观察进化像布尔值这样的输入 “变成” 真。
我已经编写了一个模型,下面的程序,它产生了一个奇怪的行为(对我来说)并且我很惊讶,因为我设置了有界变量 Previous
没有失败,为什么?
我希望出现类似 'variable Previous
is already bound' 的错误消息,但没有,回溯是为了解决约束(多次!)。
#!/usr/bin/swipl
init( Previous, AtStart ) :-
get_time( AtStart ),
Previous is 0.
run( AtStart, Previous ) :- % I want this to be executed only once for each period!
get_time( Now ),
Elapsed is Now - AtStart,
Current is Previous + random( 20 ),
format( "~w: Previous = ~w~n", [Elapsed, Previous] ),
format( "~w: Current = ~w~n", [Elapsed, Current ] ),
Previous is Current.
periodicTask :-
init( Previous, AtStart ),
repeat,
run( AtStart, Previous ),
sleep( 1.0 ).
:-
periodicTask.
它无限期地运行这种输出:
?- periodicTask.
?- periodicTask.
0.0231266: Previous = 0
0.0231266: Current = 10
0.243902: Previous = 0
0.243902: Current = 16
............................ A lot of lines
0.934601: Previous = 0
0.934601: Current = 0
true ;
2693.8: Previous = 0
2693.8: Current = 19
............................ A lot of lines
2694.65: Previous = 0
2694.65: Current = 0
true ;
3694.98: Previous = 0
3694.98: Current = 2
............................ A lot of lines
3695.17: Previous = 0
3695.17: Current = 0
true ;
4695.47: Previous = 0
4695.47: Current = 10
............................ A lot of lines
4695.55: Previous = 0
4695.55: Current = 0
true
为什么?
如何编写无限循环,重置(解除绑定)一些变量并保留全局上下文?
答案'by recursion'似乎不适用于这里,不是吗?
Previous统一为init/2中的值0。所以当Previous在run/2中被“重新计算”,并且可以统一为0值时,一切顺利。
这是您的代码的工作版本,使用动态谓词 counter/1 来跟踪迭代次数。
?- dynamic counter/1.
init(AtStart ) :-
get_time( AtStart ),
retractall(counter(_)), % clear all counter
asserta(counter(0)). % set it with initial value
run( AtStart, Iteration ) :- % I want this to be executed only once for each period!
get_time( Now ),
Elapsed is Now - AtStart,
format( "~w: Iteration = ~w~n", [Elapsed, Iteration]).
periodicTask :-
init(AtStart),
repeat,
counter(N), %scope of counter is inside repeat/0
run( AtStart, N), % Your code
N1 is N+1,
retract(counter(N)),
asserta(counter(N1)), %update counter
sleep( 1.0 ).
这里是执行:
?- periodicTask.
0.0: Iteration = 0
true ;
1.7344958782196045: Iteration = 1
true ;
2.7745978832244873: Iteration = 2
true ;
4.572326898574829: Iteration = 3
true .
这是否回答了您的问题?
这是一个用尾递归调用编写的简单循环,它将激活 T 时的“状态”传输到激活 T+1 时的“状态”,非常自然(正如哥德尔在每个人都慌张开始之前的意图)使用 for 和 while):
periodicTask :-
get_time(AtStart),
run(AtStart,0).
stopCriteriumFulfilled :- fail. % TO BE DONE
run(AtStart,Previous) :-
!, % Possibly optional: drop open chociepoints in infinite loop
get_time(Now),
Elapsed is Now - AtStart,
Current is Previous + random( 20 ),
format( "~w: Previous = ~w~n", [Elapsed, Previous] ),
format( "~w: Current = ~w~n", [Elapsed, Current ] ),
%
% Now call yourself with a new context in which the
% variable "Current" ("here", in this activation)
% becomes the variable "Previous" ("there", in the next activation)
% But first sleep a bit (N.B. numbers are numbers, one can use 1
% instead of 1.0)
% One may want to add a stop criterium here to succeed the predicate
% instead of performing the tail-recursive call unconditionally.
%
(stopCriteriumFulfilled
-> true
; (sleep(1),
run(AtStart,Current))). % RECURSIVE TAIL CALL
:- periodicTask.
如果需要比将当前状态传递到下一个激活更多的“状态”,请查看这些:
在硬件设备的命令和控制上下文中,我需要一个无限循环 "acquire-elaborate-publish" 并记住当前状态,以观察进化像布尔值这样的输入 “变成” 真。
我已经编写了一个模型,下面的程序,它产生了一个奇怪的行为(对我来说)并且我很惊讶,因为我设置了有界变量 Previous
没有失败,为什么?
我希望出现类似 'variable Previous
is already bound' 的错误消息,但没有,回溯是为了解决约束(多次!)。
#!/usr/bin/swipl
init( Previous, AtStart ) :-
get_time( AtStart ),
Previous is 0.
run( AtStart, Previous ) :- % I want this to be executed only once for each period!
get_time( Now ),
Elapsed is Now - AtStart,
Current is Previous + random( 20 ),
format( "~w: Previous = ~w~n", [Elapsed, Previous] ),
format( "~w: Current = ~w~n", [Elapsed, Current ] ),
Previous is Current.
periodicTask :-
init( Previous, AtStart ),
repeat,
run( AtStart, Previous ),
sleep( 1.0 ).
:-
periodicTask.
它无限期地运行这种输出:
?- periodicTask.
?- periodicTask.
0.0231266: Previous = 0
0.0231266: Current = 10
0.243902: Previous = 0
0.243902: Current = 16
............................ A lot of lines
0.934601: Previous = 0
0.934601: Current = 0
true ;
2693.8: Previous = 0
2693.8: Current = 19
............................ A lot of lines
2694.65: Previous = 0
2694.65: Current = 0
true ;
3694.98: Previous = 0
3694.98: Current = 2
............................ A lot of lines
3695.17: Previous = 0
3695.17: Current = 0
true ;
4695.47: Previous = 0
4695.47: Current = 10
............................ A lot of lines
4695.55: Previous = 0
4695.55: Current = 0
true
为什么?
如何编写无限循环,重置(解除绑定)一些变量并保留全局上下文?
答案'by recursion'似乎不适用于这里,不是吗?
Previous统一为init/2中的值0。所以当Previous在run/2中被“重新计算”,并且可以统一为0值时,一切顺利。 这是您的代码的工作版本,使用动态谓词 counter/1 来跟踪迭代次数。
?- dynamic counter/1.
init(AtStart ) :-
get_time( AtStart ),
retractall(counter(_)), % clear all counter
asserta(counter(0)). % set it with initial value
run( AtStart, Iteration ) :- % I want this to be executed only once for each period!
get_time( Now ),
Elapsed is Now - AtStart,
format( "~w: Iteration = ~w~n", [Elapsed, Iteration]).
periodicTask :-
init(AtStart),
repeat,
counter(N), %scope of counter is inside repeat/0
run( AtStart, N), % Your code
N1 is N+1,
retract(counter(N)),
asserta(counter(N1)), %update counter
sleep( 1.0 ).
这里是执行:
?- periodicTask.
0.0: Iteration = 0
true ;
1.7344958782196045: Iteration = 1
true ;
2.7745978832244873: Iteration = 2
true ;
4.572326898574829: Iteration = 3
true .
这是否回答了您的问题?
这是一个用尾递归调用编写的简单循环,它将激活 T 时的“状态”传输到激活 T+1 时的“状态”,非常自然(正如哥德尔在每个人都慌张开始之前的意图)使用 for 和 while):
periodicTask :-
get_time(AtStart),
run(AtStart,0).
stopCriteriumFulfilled :- fail. % TO BE DONE
run(AtStart,Previous) :-
!, % Possibly optional: drop open chociepoints in infinite loop
get_time(Now),
Elapsed is Now - AtStart,
Current is Previous + random( 20 ),
format( "~w: Previous = ~w~n", [Elapsed, Previous] ),
format( "~w: Current = ~w~n", [Elapsed, Current ] ),
%
% Now call yourself with a new context in which the
% variable "Current" ("here", in this activation)
% becomes the variable "Previous" ("there", in the next activation)
% But first sleep a bit (N.B. numbers are numbers, one can use 1
% instead of 1.0)
% One may want to add a stop criterium here to succeed the predicate
% instead of performing the tail-recursive call unconditionally.
%
(stopCriteriumFulfilled
-> true
; (sleep(1),
run(AtStart,Current))). % RECURSIVE TAIL CALL
:- periodicTask.
如果需要比将当前状态传递到下一个激活更多的“状态”,请查看这些: