あなたの質問に答えるために、私は最初に、最後の呼び出しの最適化を妨げる可能性のある「些細な」目標を探しました。見つかった場合:
; ( アース(入力)
-> once(symbol:by_type_name(Tables, error, Index, _)),
try_restore_input(入力、FailedInput、InputR)、
入力 = [失敗した入力 | 入力R]、
format(atom(Error), '~w', [FailedInput]),
トークン = インデックス エラー
; once(symbol:by_type_name(Tables, eof, Index, _)),
トークン = インデックス-''
)
これらの 2 つのケースでは、LCO はこれらの目標だけで防がれます。
さて、私はあなたのルールをコンパイルし、拡張を次のように見ましたlisting
:
?- リスト (read_token)。
read_token(parser(O, B), lexer(dfa-C, last_accept-T, chars-J), Q, A, S) :-
( A=[D|G],
dfa:current(B、C、E)、
char_and_code(D、K、F)、
dfa:find_edge(B、E、F、H)、
N=G
-> table:item(dfa_table, B, H, I),
dfa: 受け入れる (I, L),
atom_concat(J、K、M)、
P=lexer(dfa-H, last_accept-L, chars-M),
R=N、
read_token(parser(O, B),
P、
Q、
R、
S) % 1: いいね!
; ( T\=なし
-> Q=TJ
; グラウンド(D)
-> once(symbol:by_type_name(B, エラー, W, _)),
try_restore_input(D、U、V)、
D=[U|V],
format(atom(X), '~w', [U]),
Q=WX % 2: LCO を防止
; once(symbol:by_type_name(B, eof, W, _)),
Q=W-'' % 3: LCO を防ぐ
)、
S=A % 4: LCOを防止
)。
ad 1) これはおそらくあなたが探している再帰的なケースです。ここでは、すべてが良さそうです。
広告 2,3) 上ですでに説明しましたが、目標を交換したいかもしれません
{}//1
広告 4) これは、 DCG での処理方法が正確で確実な方法の効果です。経験則として: 実装者は、LCO らしさを追求するよりも、不動であることを好みます。参照してください: DCG 拡張: 安定性は無視されますか?
これには、呼び出しフレームの単純な再利用以外にも多くのことがあることに注意してください。ガベージ コレクションには多くの相互作用があります。SWI におけるこれらすべての問題を克服するには、追加の GC フェーズが必要でした。
詳細については、Prolog の Precise Garbage Collectionの小さなベンチマークを参照してください。
最後にあなたの質問に答えるために: あなたのルールは最適化されるかもしれません。ただし、再帰ゴールの前に選択ポイントが残っていない場合。
これに対する実際の低レベルのアプローチもあります。これをコード開発に使用することはありません: vm_list
. このリストは、SWI が LCO を検討するかどうかを最終的に示しています (選択肢がない場合)。
i_call
i_callm
LCO を実行することはありません。のみi_depart
行います。で:142 i_depart(read_token/5)
?- vm_list(read_token)。
================================================== ======================
read_token/5
================================================== ======================
0 s_virgin
1 i_exit
--------------------------------------------
句 1 ((0x1cc4710)):
--------------------------------------------
0 h_functor(パーサー/2)
2 h_firstvar(5)
4 h_firstvar(6)
6 h_pop
7 h_functor(レクサー/3)
9 h_functor((-)/2)
11 h_const(dfa)
13 h_firstvar(7)
15h_pop
16 h_ファンクター((-)/2)
18 h_const(last_accept)
20 h_firstvar(8)
22h_pop
23 h_rfunctor((-)/2)
25 h_const(文字)
27 h_firstvar(9)
29h_pop
30 i_enter
31 c_ifthenelse(26,118)
34 b_unify_var(3)
36 h_list_ff(10,11)
39 b_unify_exit
40 b_var(6)
42 b_var(7)
44 b_firstvar(12)
46 i_callm(dfa,dfa:現在/3)
49 b_var(10)
51 b_firstvar(13)
53 b_firstvar(14)
55 i_call(char_and_code/3)
57 b_var(6)
59 b_var(12)
61 b_var(14)
63 b_firstvar(15)
65 i_callm(dfa,dfa:find_edge/4)
68 b_unify_fv(16,11)
71 c_cut(26)
73 b_const(dfa_table)
75 b_var(6)
77 b_var(15)
79 b_firstvar(17)
81 i_callm(テーブル,テーブル:item/4)
84 b_var(17)
86 b_firstvar(18)
88 i_callm(dfa,dfa:accept/2)
91 b_var(9)
93 b_var(13)
95 b_firstvar(19)
97 i_call(atom_concat/3)
99 b_unify_firstvar(20)
101 b_functor(レクサー/3)
103 b_ファンクター((-)/2)
105 b_const(dfa)
107 b_argvar(15)
109 ビーポップ
110 b_ファンクター((-)/2)
112 b_const(last_accept)
114 b_argvar(18)
116 ビーポップ
117 b_rfunctor((-)/2)
119 b_const(文字)
121 b_argvar(19)
123 ビーポップ
124 b_unify_exit
125 b_unify_fv(21,16)
128 b_functor(パーサー/2)
130 b_argvar(5)
132 b_argvar(6)
134 ビーポップ
135 b_var(20)
137b_var2
138 b_var(21)
140 b_var(4)
142 i_depart(read_token/5)
144 c_var_n(22,2)
147 c_var_n(24,2)
150 c_jmp(152)
152 c_ifthenelse(27,28)
155 b_var(8)
157 b_const(なし)
159 i_call((\=)/2)
161 c_cut(27)
163 b_unify_var(2)
165 h_ファンクター((-)/2)
167 h_var(8)
169 h_var(9)
171h_ポップ
172 b_unify_exit
173 c_var(10)
175 c_var_n(22,2)
178 c_var_n(24,2)
181 c_jmp(101)
183 c_ifthenelse(28,65)
186 b_firstvar(10)
188 i_call(グラウンド/1)
190 c_cut(28)
192 b_ファンクター((:)/2)
194 b_const(シンボル)
196 b_rfunctor(by_type_name/4)
198 b_argvar(6)
200 b_const(エラー)
202 b_argfirstvar(22)
204b_void
205 ビーポップ
206 i_call(1回/1)
208 b_var(10)
210 b_firstvar(23)
212 b_firstvar(24)
214 i_call(try_restore_input/3)
216 b_unify_var(10)
218 h_リスト
219 h_var(23)
221 h_var(24)
223h_ポップ
224b_unify_exit
225 b_functor(アトム/1)
227 b_argfirstvar(25)
229 ビーポップ
230 b_const('~w')
232b_リスト
233 b_argvar(23)
235b_nil
236 ビーポップ
237 i_call(フォーマット/3)
239 b_unify_var(2)
241 h_ファンクター((-)/2)
243 h_var(22)
245h_var(25)
247 h_ポップ
248 b_unify_exit
249 c_jmp(33)
251b_ファンクター((:)/2)
253 b_const(シンボル)
255 b_rfunctor(by_type_name/4)
257 b_argvar(6)
259 b_const(eof)
261 b_argfirstvar(22)
263b_void
264b_ポップ
265 i_call(1回/1)
267 b_unify_var(2)
269 h_ファンクター((-)/2)
271 h_var(22)
273 h_const('')
275h_ポップ
276 b_unify_exit
277 c_var(10)
279 c_var_n(23,2)
282 c_var(25)
284 b_unify_vv(4,3)
287 c_var_n(11,2)
290 c_var_n(13,2)
293 c_var_n(15,2)
296 c_var_n(17,2)
299 c_var_n(19,2)
302 c_var(21)
304 i_exit