for(:Goal, +Index_From, +Index_To, +Index_Step)
模拟一般程序语言的for循环。以C语言为例,此for谓词可表述为
for(i=Index_From; i<=Index_To; i+=Index_Step)
Goal;
如果Index_Step为负,则是表述为
for(i=Index_From; i>=Index_To; i+=Index_Step)
Goal;
当Index_Step省略时,默认为1。
Goal的编写有规定的格式:
前3个参数为保留参数,规定第1个参数是传入的Index值,每迭代一次变化一次;
第2个参数Static_Return为静态变量最终回传值,当静态变量多于一个时可用List表述;
第3个变量Static_Initial为静态变量初始值;
其后的"......"可自行增加传入或传出的变量,个数不限。
注意:
1. Static_Return与Static_Initial必须一一对应,也就是说如果为List形态,List内的元素个数须一样多。
2. 如果想传出的变量在Goal的多次选代过程中一旦被绑定后不会再需要被绑定为其他值,可用"......"自行增加变量传出(这种情形较少见);
但若被绑定后还有可能再被绑定为其他值,则必须用Static_Return传出(一般应该都是这种情况)。
如果想产生C语言里的break功能,则在Goal编写时,在想break的地方加入false。
这也意谓着…Goal一定是true的(false的话会被视为跳出循环),
如果确实想传出"false"信息而非break,可利用Static_Return增设一个变量传出。
使用break时还要特别注意:
一旦break,当次的迭代对静态变量的影响忽略不计,这点和一般语言的break不太一样。
例如goal(I, C1, C) :- C1 is C + I, (I >= 5 -> false; true).
当执行查询for(goal(I, C1, 0), 1, 5)时,C1传回10(因为1 + 2 + 3 + 4 = 10),
可以看到,虽然goal的编写上是先执行加总,再透过检查I决定是否break,很容易被误认为5也被加总进C1中,
但其实break的当次迭代(I = 5这次)视为无效,所以C1只从1加到4。
例:
假设编写5个Goal谓词如下
49 ?- for(wri(I, _, _), 1, 5, 2).
1
3
5
true.
47 ?- for(sum(I, Answer, 0), 1, 5).
Answer = 15.
48 ?- for(formula_sum(I, Formula, 0), 1, 5).
Formula = 0+1+2+3+4+5.
53 ?- for(calculate(I, [Sumproduct, Sum_of_square], [0, 0], [4, 10, 3], [2, 5, 7]), 1, 3).
Sumproduct = 79,
Sum_of_square = 125.
58 ?- for(calculate_for_N_is_2(I, [Sumproduct, Sum_of_square], [0, 0], [4, 10, 3], [2, 5, 7]), 1, 3).
Sumproduct = 58,
Sum_of_square = 116.
模拟一般程序语言的for循环。以C语言为例,此for谓词可表述为
for(i=Index_From; i<=Index_To; i+=Index_Step)
Goal;
如果Index_Step为负,则是表述为
for(i=Index_From; i>=Index_To; i+=Index_Step)
Goal;
当Index_Step省略时,默认为1。
- 代码:
for(Goal, Index_From, Index_To) :- for(Goal, Index_From, Index_To, 1).
for(Goal, Index_From, Index_To, Index_Step) :-
nonvar(Goal),
(Index_From =< Index_To -> Goal =.. X, replace(X, 2, Index_From, Y), replace(Y, 3, Return, M),
Z =.. M, (Z -> replace(Y, 4, Return, W), V =.. W, Next_Index is Index_From + Index_Step, for(V, Next_Index, Index_To, Index_Step);
arg(3, Goal, A), arg(2, Goal, A)); arg(3, Goal, A), arg(2, Goal, A)).
replace(List, Index, With, ListOut) :-
Idx is Index - 1, length(Before,Idx),
append(Before, [_Discard|Rest], List),
append(Before, [With|Rest], ListOut).
Goal的编写有规定的格式:
- 代码:
goal_name(Index, Static_Return, Static_Initial, ......).
前3个参数为保留参数,规定第1个参数是传入的Index值,每迭代一次变化一次;
第2个参数Static_Return为静态变量最终回传值,当静态变量多于一个时可用List表述;
第3个变量Static_Initial为静态变量初始值;
其后的"......"可自行增加传入或传出的变量,个数不限。
注意:
1. Static_Return与Static_Initial必须一一对应,也就是说如果为List形态,List内的元素个数须一样多。
2. 如果想传出的变量在Goal的多次选代过程中一旦被绑定后不会再需要被绑定为其他值,可用"......"自行增加变量传出(这种情形较少见);
但若被绑定后还有可能再被绑定为其他值,则必须用Static_Return传出(一般应该都是这种情况)。
如果想产生C语言里的break功能,则在Goal编写时,在想break的地方加入false。
这也意谓着…Goal一定是true的(false的话会被视为跳出循环),
如果确实想传出"false"信息而非break,可利用Static_Return增设一个变量传出。
使用break时还要特别注意:
一旦break,当次的迭代对静态变量的影响忽略不计,这点和一般语言的break不太一样。
例如goal(I, C1, C) :- C1 is C + I, (I >= 5 -> false; true).
当执行查询for(goal(I, C1, 0), 1, 5)时,C1传回10(因为1 + 2 + 3 + 4 = 10),
可以看到,虽然goal的编写上是先执行加总,再透过检查I决定是否break,很容易被误认为5也被加总进C1中,
但其实break的当次迭代(I = 5这次)视为无效,所以C1只从1加到4。
例:
假设编写5个Goal谓词如下
- 代码:
wri(I, _, _) :- write(I), nl. % 将I的值印出来
sum(I, Static_Return, Static) :- Static_Return is Static + I. % 将I的值加总回传
formula_sum(I, Static_Return, Static) :- Static_Return = Static + I. % 将I的值加总并以公式形式表述
calculate(I, [Sumproduct, Sum_of_square], [Spt, Sos], X, Y) :-
nth1(I, X, A), nth1(I, Y, B), Sumproduct is Spt + A * B, Sum_of_square is Sos + A * A. % 将X与Y两个List的项对应相乘并加总得到Sumproduct;将X各项取平方并加总得到Sum_of_square
calculate_for_N_is_2(I, [Sumproduct, Sum_of_square], [Spt, Sos], X, Y) :-
I = 3 -> false; nth1(I, X, A), nth1(I, Y, B), Sumproduct is Spt + A * B, Sum_of_square is Sos + A * A. % 同前,但I=3时break跳出循环
49 ?- for(wri(I, _, _), 1, 5, 2).
1
3
5
true.
47 ?- for(sum(I, Answer, 0), 1, 5).
Answer = 15.
48 ?- for(formula_sum(I, Formula, 0), 1, 5).
Formula = 0+1+2+3+4+5.
53 ?- for(calculate(I, [Sumproduct, Sum_of_square], [0, 0], [4, 10, 3], [2, 5, 7]), 1, 3).
Sumproduct = 79,
Sum_of_square = 125.
58 ?- for(calculate_for_N_is_2(I, [Sumproduct, Sum_of_square], [0, 0], [4, 10, 3], [2, 5, 7]), 1, 3).
Sumproduct = 58,
Sum_of_square = 116.
由Mercury Liao于周三 十月 31, 2012 8:24 am进行了最后一次编辑,总共编辑了5次