comparison prolog/utils.pl @ 0:0dd31a8c66bd

Initial check in to Mercurial, V.1
author samer
date Fri, 13 Jan 2012 15:29:02 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:0dd31a8c66bd
1 % Some general utilities
2
3 :- module(utils,[
4
5 % type testing and enumeration
6 natural/1 % test or enumerate natural numbers
7 , isfinite/1 % check number is non NaN or Inf
8 , int/1 % test or enumerate integers
9 , in/2
10
11 % mathematical utilities
12 , max/3
13 , min/3
14
15 % list utilities
16 , list_idx1_member/3 % like nth1 but more useful argument order
17 , apply_to_nth1/4
18 , measure/3 % match list lengths
19 , equal_length/2 % match 2 list lengths
20 , getopts/2
21 , rep/3 % make a list of repeats of the same term
22 , cons/3 % list constructror
23 , decons/3 % list deconstructor
24
25 % comma lists
26 , cl_list/2
27 , cl_list_vt/2
28 , cl_length/2
29 , cl_length_vt/2
30 , cl_member/2
31
32
33 % term manipulation
34 , copy_head/2 % check terms for same head and arity
35 , unify_args/5
36 , reinstatevars/3
37 , reinstatevars/4
38
39 % formatting and parsing
40 , aphrase/2 % like phrase but makes an atom instead of a string
41 , aphrase/3 % like aphrase but takes code list
42 , print_list/1 % writes each element on a new line
43 , printq_list/1 % as print_list but quotes atom as necessary
44 , print_numbered_list/1
45
46 % database management
47 , extensible/1 % declare dynamic multifile predicate
48 , bt_assert/1
49 , bt_retract/1
50 , strict_assert/1
51 , strict_retract/1
52 , browse/2 % browse predicate with unknown arity
53 , current_state/2
54 , set_state/2
55
56 % file system utilities
57 , dir/2 % directory listing
58 , path_atom/2 % expand paths
59 , expand_path/2 % expand paths
60
61 % operating system
62 , open_with/2 % apply shell command to a file (SIDE EFFECTS)
63 , open_with/3 % apply shell command to a file with options (SIDE EFFECTS)
64 , shellcmd/2 % apply shell command to arguments
65 , open_/1 % open with 'open' command (Mac OS X).
66 , fmt_shellcmd/3 % format a shell command with switches and args
67 , hostname/1
68
69 % user interaction
70 , read_char_echo/1 % read one character and echo it immediately
71 , get_key/2 % read and validate keypress
72 , userchk/1 % unary predicate which allows user to force failure
73 , prompt_for_key/3
74
75 % ---- high order stuff ----
76
77 % modes of computation
78 , retry/1 % keep trying until success
79 , parallel/1 % parallel computation using threads
80 , bt_call/2 % Construct backtrackable operation
81 , on_backtracking/1
82
83 % iteration
84 , exhaust/1 % trigger all solutions to a goal (SIDE EFFECTS)
85 , iterate/3 % apply predicate recursively till failure
86
87 % mapping
88 , for_naturals/2 % call predicate with natural numbers N down to 1
89 , mapints/2 % call predicate with integers
90 , mapints/3
91 , mapargs/2, mapargs/3, mapargs/4
92 , mapargs_x/4, mapargs_x/5, mapargs_x/6
93 , mapargs_xx/6
94 , sfold/4 % structural fold for lists
95 , take/3
96 , drop/3
97 , drop_while/3
98 , take_while/3
99
100 % lambda expressions
101 , mcall/2, mcall/3, mcall/4
102
103 ]).
104
105 /** <module> General utilities
106
107 The predicates in this module can be divided into several groups as listed
108 below.
109
110 ---+++ Type testing and enumeration
111 * natural/1 - test or enumerate natural numbers
112 * isfinite/1 - check number is non NaN or Inf
113 * int/1 - test or enumerate integers
114 * in/2
115
116 ---+++ mathematical utilities
117 * max/3
118 * min/3
119
120 ---+++ list utilities
121 * list_idx1_member/3 % like nth1 but more useful argument order
122 * measure/3 - match list lengths
123 * equal_length/2 - match two list lenghts
124 * getopts/2
125 * rep/3 - make a list of repeats of the same term
126 * cons/3 - make list from head and tail
127 * decons/3 - get head and tail from list
128
129 ---+++ term manipulation
130 * copy_head/2 - check terms for same head and arity
131 * unify_args/5
132 * reinstatevars/3
133 * reinstatevars/4
134
135 ---+++ formatting and parsing
136 * aphrase/2 - like phrase but makes an atom instead of a string
137 * aphrase/3 - like aphrase but takes code list
138 * print_list/1 - write/1 each element, one per line
139 * printq_list/1 - as print_list but quotes atom as with writeq/1
140 * print_numbered_list/1 - as print_list/1 but with line numbers
141
142 ---+++ database management
143 * extensible/1 - declare dynamic multifile predicate
144 * bt_assert/1
145 * bt_retract/1
146 * strict_assert/1
147 * strict_retract/1
148 * browse/2 - browse predicate with unknown arity
149 * current_state/2
150 * set_state/2
151
152 ---+++ file system utilities
153 * dir/2 - directory listing
154 * path_atom/2 - expand paths
155 * expand_path/2 - expand paths
156
157 ---+++ operating system
158 * open_with/2 - apply shell command to a file (SIDE EFFECTS)
159 * open_with/3 - apply shell command to a file with options (SIDE EFFECTS)
160 * shellcmd/2 - apply shell command to arguments
161 * open_/1 - open with 'open' command (Mac OS X).
162 * fmt_shellcmd/3 - format a shell command with switches and args
163 * hostname/1
164
165 ---+++ user interaction
166 * read_char_echo/1 - read one character and echo it immediately
167 * get_key/2 - read and validate keypress
168 * userchk/1 - unary predicate which allows user to force failure
169 * prompt_for_key/3 - print message and get keypress from user
170
171 ---+++ High order stuff
172
173 ---++++ modes of computation
174 * retry/1 - keep trying until success
175 * parallel/1 - parallel computation using threads
176 * bt_call/2 - Construct backtrackable operation
177 , on_backtracking/1
178
179 ---++++ iteration
180 * exhaust/1 - trigger all solutions to a goal (SIDE EFFECTS)
181 * iterate/3 - apply predicate recursively till failure
182
183 ---++++ mapping
184 * for_naturals/2 - call predicate with natural numbers N down to 1
185 * mapints/2 - call predicate with integers
186 * mapints/3
187 * mapargs/2, mapargs/3, mapargs/4
188 * mapargs_xx/6
189 * sfold/4 - structural fold for lists
190 * take/3
191 * drop/3
192 * drop_while/3
193 * take_while/3
194
195 ---++++ lambda expressions
196 * mcall/2, mcall/3, mcall/4
197 */
198
199 :- use_module(library(ops)).
200
201 :- meta_predicate
202 exhaust(0)
203 , retry(0)
204 , iterate(2,?,?)
205 , drop_while(1,?,?)
206 , take_while(1,?,?)
207 , apply_to_nth1(?,2,?,?)
208 , for_naturals(+,1)
209 , for_ints(+,+,1)
210 , mapints(1,?)
211 , mapints(2,?,?)
212 , mapargs(1,?)
213 , mapargs(2,?,?)
214 , mapargs(3,?,?,?)
215 , mapargs_x(+,+,1,?)
216 , mapargs_x(+,+,2,?,?)
217 , mapargs_x(+,+,3,?,?,?)
218 , mapargs_xx(2,?,?,?,?,?)
219 , on_backtracking(0)
220 , bt_call(0,0)
221 , bt_assert(:)
222 , bt_retract(:)
223 , strict_assert(:)
224 , strict_retract(:)
225 , extensible(:)
226 , aphrase(2,?)
227 , aphrase(2,?,?)
228 .
229
230 :- multifile user:path/2.
231 :- multifile user:demo/1.
232 :- dynamic current_state/2.
233
234
235 %% extensible(+P) is det.
236 % declares 'extensible' predicates, ie ones that can have new clauses
237 % added in other files. Equivalent to dynamic(P), multifile(P).
238 extensible(P) :- dynamic(P), multifile(P).
239
240
241 %% natural(+N) is semidet.
242 %% natural(-N:natural) is multi.
243 %
244 % Means N is a natural number (includes 0). If N is
245 % a variable, succeeds an infinite number of times on backtracking,
246 % returning all natural numbers.
247 natural(N) :- (var(N) -> between(0,inf,N); integer(N), N>=0).
248
249
250 %% int(+N) is semidet.
251 %% int(-N:integer) is multi.
252 %
253 % Means N is an integer. If N is
254 % a variable, succeeds an infinite number of times on backtracking,
255 % returning all integers starting at zero and interleaving positive
256 % and negative values.
257 int(N) :- nonvar(N), integer(N).
258 int(N) :- var(N), (N=0; (between(1,inf,M), (N=M; N is -M))).
259
260
261 %% isfinite(+N:number) is semidet.
262 %
263 % Succeeds when N is a finite number.
264 isfinite(N):- catch(_ is N+0,error(_,_),fail). % !! workable hack
265
266
267 %% in(+X,Set) is semidet.
268 %% in(-X,Set) is nondet.
269 %
270 % Simple testing and enumration of values in some sets.
271 % Set can be
272 % * {A,B,_}
273 % Explicit list of values.
274 % * natural
275 % Natural numbers starting from 0.
276 % * integer
277 % Natural numbers.
278 % * real
279 % Real (floating point) numbers.
280 % * A..B
281 % Integer range from A to B inclusive.
282 % * A--B
283 % Closed interval [A,B].
284 X in A--\B :- X in A--(\B).
285 X in \A--(\B):- !, ch(A<X), ch(X<B).
286 X in \A--B :- !, ch(A<X), ch(X=<B).
287 X in A--(\B) :- !, ch(A=<X), ch(X<B).
288 X in A--B :- !, ch(A=<X), ch(X=<B).
289 X in A..B :- integer(A), integer(B), between(A,B,X).
290 X in {CList} :- member_clist(X,CList).
291 X in natural :- natural(X). % enumerate!
292 X in integer :- int(X). % enumerates!
293 X in real :- number(X). % same as X :: real
294
295
296 ch(_ =<inf) :- !.
297 ch(inf=< _ ) :- !, fail.
298 ch(-inf=< _) :- !.
299 ch(_ =<(-inf)) :- !, fail.
300 ch(A=<B) :- !, A=<B.
301
302 ch(inf<_ ) :- !, fail.
303 ch(_ <inf) :- !.
304 ch(_ <(-inf)) :- !, fail.
305 ch(-inf<_ ) :- !.
306 ch(A<B) :- !, A<B.
307
308
309
310 %% exhaust(:Goal) is det.
311 %
312 % Repeat Goal until failure, then succeed.
313 exhaust(Q) :- call(Q), fail; true.
314
315 %% iterate(+P:pred(A,A), X:A, Y:A) is semidet.
316 % apply P recursively to X until failure, then return final value Y.
317 iterate(P,X,Y) :- call(P,X,Z) -> iterate(P,Z,Y); Y=X.
318
319 %% sfold(Functor,Initial,L:list,Final) is semidet.
320 % *Structural* fold applied to a term,
321 % rather than a relational fold using a predicate name.
322 sfold(_,E,[],E).
323 sfold(O,E,[X|XX],R) :- R=..[O,X,YY], sfold(O,E,XX,YY).
324
325
326 %% dir( +Pattern, -File) is nondet.
327 %
328 % Directory listing for directory matching Pattern. File
329 % names are returned one by one on backtracking.
330 dir(Pattern,File) :-
331 expand_file_name(Pattern,List),
332 member(File,List).
333
334
335 %% path_atom( +Spec:path_expr, -Path:atom) is nondet.
336 %
337 % Expand a 'path expression' into a flat path (an atom).
338 % A path expression is defined by:
339 % ==
340 % path_expr ---> atom % literal path component name
341 % ; path_expr/atom % child of path_expr
342 % ; path_macro % a previously defined abbr for a path.
343 % ==
344 % A path_macro is defined using path/2.
345
346 path_atom(P,C) :- path(P,C), atom(C).
347
348 path_atom(PA/B,C) :-
349 once((nonvar(C); nonvar(B); nonvar(PA))),
350 path_atom(PA,A),
351 concat3atoms(A,'/',B,C).
352
353
354 path_atom(Path,Atom) :- path(Path, Def), \+atom(Def), path_atom(Def,Atom).
355 path_atom(Path,Atom) :-
356 nonvar(Path),
357 \+path(Path,_),
358 Path\=_/_,
359 Atom=Path.
360
361 concat3atoms(A,B,C,ABC) :-
362 nonvar(A), nonvar(B), nonvar(C), !, concat_atom([A,B,C],ABC).
363
364 concat3atoms(_,_,_,ABC) :- var(ABC), !, fail.
365 concat3atoms(A,B,C,ABC) :- nonvar(C), !, atom_concat(AB,C,ABC), atom_concat(A,B,AB).
366 concat3atoms(A,B,C,ABC) :- nonvar(A), !, atom_concat(A,BC,ABC), atom_concat(B,C,BC).
367 concat3atoms(A,B,C,ABC) :-
368 maplist(atom_codes,[B,ABC],[BX,ABCX]),
369 append(ABX,CX,ABCX),
370 append(AX,BX,ABX),
371 maplist(atom_codes,[A,C],[AX,CX]).
372
373 %% expand_path( +P:path_expr, -FP:atom) is semidet.
374 %
375 % Expand path_exp including wildcards to fully qualified path
376 expand_path(P,FP) :- path_atom(P,PP), expand_file_name(PP,[FP]).
377
378
379 %% open_with( +Program:atom, +Thing:path_expr, +Options:list) is semidet.
380 %% open_with( +Program:atom, +Thing:path_expr) is semidet.
381 %
382 % The only option is bg, which adds "&" to make command execute in background.
383 open_with(Q,P) :- open_with(Q,P,[]).
384 open_with(Q,P,Opts) :-
385 expand_path(P,FP),
386 (member(bg,Opts) -> OO=' &'; OO=''),
387 sformat(S,'~w ~q~w',[Q,FP,OO]),
388 shell(S).
389
390 %% open_( +Thing:path_expr) is semidet.
391 % Equivalent to open_with(open,Thing).
392 open_(P) :- open_with(open,P).
393
394 %% shellcmd( +Head:atom, +Args:list(atom)) is det.
395 %
396 % Execute a shell command on a given list of arguments
397 shellcmd(Head,Args) :-
398 concat_atom([Head|Args],' ',Cmd),
399 shell(Cmd,_Status).
400
401 %% fmt_shellcmd( +Prog:atom, +Args:list(shellarg), -Cmd) is det.
402 % make a shell command string.
403 fmt_shellcmd(Prog,Args,Cmd) :-
404 phrase(utils:shellcmd(l_(Args)),FArgs),
405 concat_atom([Prog|FArgs],' ',Cmd).
406
407 shellcmd(l_([])) --> !, [].
408 shellcmd(l_([H|T])) --> !, shellcmd(H), shellcmd(l_(T)).
409 shellcmd(s(N,V)) --> !, shellcmd(s(N)), shellcmd(V).
410 shellcmd(q(X)) --> !, { concat_atom(['"',X,'"'],A) }, [A].
411 shellcmd(s(N)) --> !, {
412 (atom_codes(N,[_]) -> F='-' ; F='--'),
413 atom_concat(F,N,A) }, [A].
414 shellcmd(l(X)) --> [X].
415
416
417
418 %% read_char_echo( -C:atom) is det.
419 %
420 % Read a single character from the current input,
421 % echo it to the output.
422 read_char_echo(C) :-
423 get_single_char(Code),
424 put_code(Code), flush_output,
425 char_code(C,Code).
426
427
428
429 %% set_state( +Key, +Value) is det.
430 %
431 % Maintains a mutable global set of Key-Value pairs, sets the value
432 % associated with Key to Value.
433 set_state(Flag,Value) :-
434 ground(Flag),
435 retractall(current_state(Flag,_)),
436 assert(current_state(Flag,Value)).
437
438
439 %% current_state( -Key, -Value) is nondet.
440 %% current_state( +Key, -Value) is semidet.
441 %
442 % Lookup the value associated with Key, or enumerate all the
443 % key value pairs.
444
445
446
447 %% parallel( +List:list(query)) is semidet.
448 %
449 % Use this by giving a list of queries of the form
450 % [Vars2:Goal, Vars2:Goal2, ...]
451 % where Vars is the term that each thread must return
452 % when it has finished computing its Goal. The
453 % parallel predicate finishes when all the threads
454 % have finished, and should result in all the Vars
455 % being bound appropriately.
456
457 parallel(Queries) :-
458 maplist(async,Queries,Collecters),
459 maplist(call,Collecters).
460
461 % these are used to initiate and wait for each
462 % computation thread.
463 async_collect(Id,X:_) :- thread_join(Id,exited(X)).
464 async(X:Goal,utils:async_collect(Id,X:_)) :-
465 thread_create((Goal,thread_exit(X)),Id,[]).
466
467 %% browse( +PredSpec, -Goal) is nondet.
468 %
469 % PredSpec is a term like (PredicateName/Arity). Goal
470 % is unified with solutions of PredicateName/Arity.
471 browse(P/A,Goal) :-
472 current_predicate(P/A),
473 length(L,A),
474 Goal=..[P|L],
475 call(Goal).
476
477
478
479 %% aphrase(P:phrase(code), -A:atom, +S:list(code)) is nondet.
480 %% aphrase(P:phrase(code), +A:atom, -S:list(code)) is nondet.
481 %% aphrase(P:phrase(code), -A:atom, -S:list(code)) is nondet.
482 %% aphrase(P:phrase(code), -A:atom) is nondet.
483 %
484 % Generate or parse an atom using given DCG phrase P.
485 % aphrase(P,A) is equivalent to aphrase(P,A,_).
486 aphrase(X,A) :- aphrase(X,A,_).
487 aphrase(X,A,S) :-
488 ( ground(A)
489 -> atom_codes(A,S), phrase(X,S)
490 ; phrase(X,S), atom_codes(A,S)).
491
492
493 %% print_list( +L:list) is det.
494 %
495 % Print a list, one item per line.
496 print_list([]) :- writeln('~'), nl.
497 print_list([H|T]) :- print(H), nl, print_list(T).
498
499 %% printq_list( +L:list) is det.
500 %
501 % Print a list, one item per line, as with writeq/1.
502 printq_list([]) :- writeln('~'), nl.
503 printq_list([H|T]) :- writeq(H), nl, printq_list(T).
504
505 %% print_numbered_list( +L:list) is det.
506 %
507 % Print a list with numbered lines.
508 print_numbered_list(L) :-
509 length(L,Max),
510 number_codes(Max,MC),
511 length(MC,Width),
512 print_num_list(Width,1,L).
513
514 print_num_list(_,_,[]) :- nl.
515 print_num_list(Width,N,[H|T]) :- succ(N,M),
516 copy_term(H,H1),
517 numbervars(H1,0,_),
518 number_codes(N,NC), " "=[Pad],
519 padleft(Pad,Width,NC,PNC),
520 format('~s. ~q\n',[PNC,H1]),
521 print_num_list(Width,M,T).
522
523 padleft(_,W,In,In) :- length(In,W).
524 padleft(P,W,In,[P|Out]) :- succ(V,W), padleft(P,V,In,Out).
525
526
527
528
529 %% get_key( +Valid:list(char), -C:char) is det.
530 %
531 % Get and validate a key press from the user. The character
532 % must be one of the ones listed in Valid, otherwise, an
533 % error message is printed and the user prompted again.
534 get_key(Valid,C) :-
535 read_char_echo(D), nl,
536 ( member(D,Valid) -> C=D
537 ; D='\n' -> get_key(Valid,C) % this improves interaction with acme
538 ; format('Unknown command "~q"; valid keys are ~q.\n', [D,Valid]),
539 write('Command? '),
540 get_key(Valid,C)).
541
542
543 %% userchk(T) is semidet.
544 %
545 % Write T and ask this user if it is ok. User presses y or n.
546 % userchk succeeds if if the keypress was y and fails if it was n.
547 userchk(T) :- prompt_for_key(T,[y,n],y).
548
549
550 %% prompt_for_key( +Msg:atom, +Keys:list(char), -Key:char) is semidet.
551 %
552 % Prompt user for a keypress. Prompt message is Msg, and valid keys are
553 % listed in Keys.
554 prompt_for_key(Msg,Keys,Key) :- format('~p ~q? ',[Msg,Keys]), get_key(Keys,Key).
555
556 % ------------------- TERM MANIPULATION ------------------------------
557
558
559 %% copy_head(+T1,-T2) is det.
560 %% copy_head(+T1,+T2) is semidet.
561 %
562 % true if T1 and T2 have the same head and arity
563 copy_head(T1,T2) :- functor(T1,N,A), functor(T2,N,A).
564
565
566
567 %% reinstatevars( F:atom, V:list, Eh, What) is nondet.
568 %% reinstatevars( V:list, Eh, What) is nondet.
569 %
570 % Reverse of numbervars. Each '$VAR'(N) subterm of X is replaced
571 % with the Nth element of V, which can be uninstantiated on entry
572 % reinstatevars/4 uses an arbitrary functor F instead of $VAR.
573
574 reinstatevars(V,'$VAR'(N),Y) :- !, nth0(N,V,Y).
575 reinstatevars(_,X,Y) :- atomic(X), !, Y=X.
576 reinstatevars(V,X,Y) :- mapargs(reinstatevars(V),X,Y).
577
578 reinstatevars(F,V,T,Y) :- functor(T,F,1), !, arg(1,T,N), nth0(N,V,Y).
579 reinstatevars(_,_,X,Y) :- atomic(X), !, Y=X.
580 reinstatevars(F,V,X,Y) :- mapargs(reinstatevars(F,V),X,Y).
581
582
583 %% unify_args( Src, SrcIndex, Dest, DestIndex, Num) is det.
584 %
585 % this unifies N consecutive arguments of Src and Dest starting
586 % from SI and DI in each term respectively
587 unify_args(_,_,_,_,0).
588 unify_args(Src,SI,Dest,DI,N) :-
589 arg(SI,Src,X), arg(DI,Dest,X), !,
590 succ(SI,SI2), succ(DI,DI2), succ(N2,N),
591 unify_args(Src,SI2,Dest,DI2,N2).
592
593
594 % ---------------------- LIST UTILITIES -----------------------------
595
596
597 %member_clist(_,Z) :- var(Z), !, fail.
598 member_clist(A,A) :- A\=(_,_).
599 member_clist(A,(A,_)).
600 member_clist(A,(_,B)) :- member_clist(A,B).
601
602
603
604 %% measure(Ruler,In,Out) is det.
605 % true if Out is the same length as Ruler but matches In as far as possible
606 measure([],_I,[]).
607 measure([_|R],[],[_|O]) :- measure(R,[],O).
608 measure([_|R],[X|I],[X|O]) :- measure(R,I,O).
609
610 %% equal_length( ?In, ?Out) is nondet.
611 % equal_length( +L1:list, -L2:list) is det.
612 % equal_length( -L1:list, +L2:list) is det.
613 %
614 % True if L1 and L2 are the same length.
615 equal_length([],[]).
616 equal_length([_|T1],[_|T2]) :- equal_length(T1,T2).
617
618 %split_at(0,T,I-I,T).
619 %split_at(N,[H|T],[H|I1]-Z,T1) :- succ(M,N), split_at(M,T,I1-Z,T1).
620
621 %split_at2(0,T,I-I,T).
622 %split_at2(N,[H|T],[H|I1]-Z,T1) :- split_at2(M,T,I1-Z,T1), succ(M,N).
623
624 %% max(+X:number, +Y:number, -Z:number) is det.
625 %
626 % Unify Z with the larger of X and Y. Legal values are
627 % any numerical value or inf or -inf.
628 max(_,inf,inf) :- !.
629 max(inf,_,inf) :- !.
630 max(X,-inf,X) :- !.
631 max(-inf,X,X) :- !.
632 max(X,Y,Z) :- X<Y -> Z=Y; Z=X.
633
634 %% max(+X:number, +Y:number, -Z:number) is det.
635 %
636 % Unify Z with the larger of X and Y. Legal values are
637 % any numerical value or inf or -inf.
638 min(_,-inf,-inf) :- !.
639 min(-inf,_,-inf) :- !.
640 min(X,inf,X) :- !.
641 min(inf,X,X) :- !.
642 min(X,Y,Z) :- X<Y -> Z=X; Z=Y.
643
644 %% list_idx1_member( +L:list(A), +N:natural, ?X:A) is semidet.
645 %% list_idx1_member( ?L:list(A), ?N:natural, ?X:A) is nondet.
646 %
647 % Equivalent to nth1(N,L,X).
648 list_idx1_member(L,I,X) :- nth1(I,L,X).
649
650
651 %% getopts( +Opts:list(option), ?Spec:list(optspec)) is det.
652 %
653 % Get value from option list.
654 % ==
655 % option(A) ---> term(A).
656 % optspec ---> option(A)/A.
657 % ==
658 getopts(OptsIn,Spec) :- maplist(getopt(OptsIn),Spec).
659 getopt(OptsIn,Option/Default) :- option(Option,OptsIn,Default).
660
661 %% cons( ?Head:A, ?Tail:list(A), ?List:list(A)) is det.
662 %
663 % List constructor.
664 cons(H,T,[H|T]).
665
666 %% decons( ?Head:A, ?List:list(A), ?Tail:list(A)) is det.
667 %
668 % List deconstructor.
669 decons(H,[H|T],T).
670
671 % ---------------------- MAPPING, HIGH ORDER STUFF ---------------------
672
673 %% for_naturals(+N:natural, P:pred(natural)) is nondet.
674 % apply predicate to each natural number from 1 to N (backwards)
675 for_naturals(0,_).
676 for_naturals(N,P) :- succ(M,N), call(P,N), for_naturals(M,P).
677
678 %% mapints( +P:pred(integer,A), +R:intrange, -X:list) is nondet.
679 %% mapints( +P:pred(integer), +R:intrange) is nondet.
680 %
681 % Mapping predicates over lists of integers. Range is like M..N.
682 % mapints/3 maps 2 argument predicate over implicit list of
683 % integers M..N and explicit list of values X.
684 mapints(_,M..N) :- N<M, !.
685 mapints(P,M..N) :- call(P,M), plus(M,1,L), mapints(P,L..N).
686
687 mapints(_,M..N,[]) :- N<M, !.
688 mapints(P,M..N,[X|T]) :- call(P,M,X), plus(M,1,L), mapints(P,L..N,T).
689
690 %% rep( +N:natural, ?X:A, -L:list(A)) is det.
691 %% rep( -N:natural, ?X:A, -L:list(A)) is multi.
692 % Make a list consisting of N repeats of the same term. If called
693 % with N unbount, creates progressively longer and longer lists
694 % on backtracking.
695 rep(0,_,[]).
696 rep(N,A,[A|X]) :-
697 ( nonvar(N)
698 -> succ(M,N), rep(M,A,X)
699 ; rep(M,A,X), succ(M,N)
700 ).
701
702 %% mapargs( P:pred(A,B,C), T1:tuple(F,A), T2:tuple(F,B), T3:tuple(F,C)) is nondet.
703 %% mapargs( P:pred(A,B), T1:tuple(F,A), T2:tuple(F,B)) is nondet.
704 %% mapargs( P:pred(A), T1:term) is nondet.
705 %
706 % Map predicate over to args of a term preserving head.
707 % A tuple(F,A) is a term with head functor F and any number of arguments
708 % of type A, ie
709 % ==
710 % tuple(F,A) ---> F ; F(A) ; F(A,A) ; F(A,A,A) ; .. .
711 % ==
712
713 mapargs(P,T1) :-
714 functor(T1,_,N),
715 mapargs_x(1,N,P,T1).
716
717 mapargs(P,T1,T2) :-
718 ( nonvar(T1)
719 -> functor(T1,F,N), functor(T2,F,N)
720 ; functor(T2,F,N), functor(T1,F,N)),
721 mapargs_x(1,N,P,T1,T2).
722
723 mapargs(P,T1,T2,T3) :-
724 functor(T1,F,N),
725 functor(T2,F,N),
726 functor(T3,F,N),
727 mapargs_x(1,N,P,T1,T2,T3).
728
729 mapargs_x(I,N,P,T1) :-
730 ( I>N -> true
731 ; arg(I,T1,X1),
732 call(P,X1),
733 succ(I,J), mapargs_x(J,N,P,T1)).
734
735 mapargs_x(I,N,P,T1,T2) :-
736 ( I>N -> true
737 ; arg(I,T1,X1),
738 arg(I,T2,X2),
739 call(P,X1,X2),
740 succ(I,J), mapargs_x(J,N,P,T1,T2)).
741
742 mapargs_x(I,N,P,T1,T2,T3) :-
743 ( I>N -> true
744 ; arg(I,T1,X1),
745 arg(I,T2,X2),
746 arg(I,T3,X3),
747 call(P,X1,X2,X3),
748 succ(I,J), mapargs_x(J,N,P,T1,T2,T3)).
749
750 %% drop( +N:natural, +In:list(A), -Out:list(A)) is det.
751 drop(0,T,T).
752 drop(N,[_|T],V) :- succ(M,N), drop(M,T,V).
753
754
755 %% take( +N:natural, +In:list(A), -Out:list(A)) is det.
756 take(N,T,X) :- length(X,N), append(X,_,T).
757
758
759 %% drop_while( +P:pred(A), +In:list(A), -Out:list(A)) is det.
760 %
761 % Remove all elements from head of In that are accepted by P
762 % and return the remained in Out.
763 drop_while(P,[X|T],V) :- call(P,X) -> drop_while(P,T,V); V=[X|T].
764
765
766 %% take_while( +P:pred(A), +In:list(A), -Out:list(A)) is det.
767 %
768 % Remove all elements from head of In that are accepted by P
769 % and return them in Out.
770 take_while(P,[X|T],O) :- call(P,X) -> O=[X|V], take_while(P,T,V); O=[].
771
772
773
774 %% retry( :Goal) is det.
775 %
776 % Keep retrying Goal until it succeeds. Only makes sense if Goal
777 % has side effects. Might be nonterminating.
778 retry(G) :- once((repeat,G)).
779
780 %% apply_to_nth1( N:natural, Op:pred(A,A), +In:list(A), +Out:list(A)) is nondet.
781 %
782 % Apply predicate Op to the N th element of list In and unify Out with the result.
783 %apply_to_nth1(N,Op,Old,Init) :-
784 % ( nonvar(N)
785 % -> succ(M,N), split_at(M,Old,Init-[Y|Tail],[X|Tail])
786 % ; split_at2(M,Old,Init-[Y|Tail],[X|Tail]), succ(M,N)
787 % ),
788 % call(Op,X,Y).
789
790 apply_to_nth1(1,P,[X|XX],[Y|XX]) :- call(P,X,Y).
791 apply_to_nth1(N,P,[X|X1],[X|Y1]) :- nonvar(N), !, N>1, succ(M,N), apply_to_nth1(M,P,X1,Y1).
792 apply_to_nth1(N,P,[X|X1],[X|Y1]) :- var(N), !, apply_to_nth1(M,P,X1,Y1), succ(M,N).
793
794
795 %% mapargs_xx( +P:pred(A,B), +Src:term(_,A), +SrcIndex:natural, +Dest:term(_,B), +DestIndex:natural, +N:natural) is nondet.
796 %
797 % Maps predicate P over N consecutive arguments of Src and Dest. Starts
798 % at SrcIndex th argument of Src and DestIndex th argument of Dest.
799 mapargs_xx(_,_,_,_,_,0).
800 mapargs_xx(Pred,Src,SI,Dest,DI,N) :-
801 arg(SI,Src,SX), arg(DI,Dest,DX), call(Pred,SX,DX), !,
802 succ(SI,SI2), succ(DI,DI2), succ(N2,N),
803 mapargs_xx(Pred,Src,SI2,Dest,DI2,N2).
804
805
806 %% mcall(P:pred(A), X:A) is nondet.
807 %% mcall(P:pred(A,B), X:A, Y:B) is nondet.
808 %% mcall(P:pred(A,B,C), X:A, Y:B, Z:C) is nondet.
809 %% mcall(P:pred(A,B,C,D), X:A, Y:B, Z:C, W:D) is nondet.
810 %
811 % Like call/N but P can additionally be a lambda expression in one of several
812 % forms:
813 % * Tuple :- Body
814 % If functor(Tuple,\,N), Body is executed after unifying tuple arguments
815 % with arguments to mcall, eg =mcall(\(X):-member(X,[a,b,c]),Y)= is equivalent
816 % to member(Y,[a,b,c]), or =mcall(\(X,Y):-nth1(X,[a,b,c],Y),2,c)=.
817 % * Tuple
818 % Equivalent to Tuple:-true.
819
820 mcall(P,A) :- mc(P,\(A),Q), Q.
821 mcall(P,A,B) :- mc(P,\(A,B),Q), Q.
822 mcall(P,A,B,C) :- mc(P,\(A,B,C),Q), Q.
823 mcall(P,A,B,C,D) :- mc(P,\(A,B,C,D),Q), Q.
824
825 mc(Tuple:-Body,Params,Goal) :- !, copy_term(Tuple/Body,Params/Goal).
826 mc(Tuple,Params,true) :- functor(Tuple,\,_), !, copy_term(Tuple,Params).
827 mc(P,Params,apply(P,Args)) :- Params=..[\|Args].
828
829
830 %% on_backtracking( :Goal) is det.
831 %
832 % The first time this is called, it succeeds and does nothing.
833 % On backtracking, Goal is called and then a failure is generated.
834
835 on_backtracking(_).
836 on_backtracking(P) :- P, !, fail.
837
838
839 %% bt_call( :Do, :Undo) is nondet.
840 %
841 % Creates a backtrackable operation from a non-backtrackable Do
842 % operation and a corresponding operation to undo it. Do can
843 % be non-deterministic, in which case bt_call(Do,Undo) will also
844 % have multiple solutions. Undo is called inside once/1.
845 %
846 % bt_call/2 is implemented both as a predicate and as a goal
847 % expansion (see goal_expansion/2).
848 bt_call(Do,Undo) :- Do, (true; once(Undo), fail).
849
850 user:goal_expansion( bt_call(Do,Undo), (Do, (true; once(Undo), fail))).
851
852
853
854 /* Might include these at some point
855
856 % apply lambda term to another term
857 app(X\\F,Y,G) :- !, copy_term(X\\F,Y\\G).
858 app(T,A,Z) :- addargs(T,[A],Z).
859 app(T,A,B,Z) :- addargs(T,[A,B],Z).
860 app(T,A,B,C,Z) :- addargs(T,[A,B,C],Z).
861
862 applist(F,N,A,Z) :- length(Z,N), maplist(app(F),A,Z).
863 applist(F,N,A,B,Z) :- length(Z,N), maplist(app(F),A,B,Z).
864 applist(F,N,A,B,C,Z) :- length(Z,N), maplist(app(F),A,B,C,Z).
865
866 */
867
868
869 % ------------------ DATABASE ------------------------------
870
871 %% bt_assert(Clause) is det.
872 % Backtrackable assert.
873 bt_assert(H) :- bt_call(assert(H),retract(H)).
874
875 %% bt_retract(Clause) is det.
876 % Backtrackable retract.
877 bt_retract(H) :- bt_call(retract(H), assert(H)).
878
879 %% strict_assert(Fact) is semidet.
880 %
881 % Asserts fact only if it is not already true. Fails
882 % if fact is already provable. Retracts fact on backtracking.
883 strict_assert(H) :- \+call(H), bt_call(assert(H),retract(H)).
884
885
886 %% strict_retract(Fact) is semidet.
887 %
888 % Retracts fact only if it is currently in the database. Fails
889 % if fact is not provable. Reasserts fact on backtracking.
890 strict_retract(H) :- call(H), bt_call(retract(H), assert(H)).
891
892
893 % when loaded, this sets the hostname/1 predicate.
894 :- dynamic hostname/1.
895
896 %% hostname( -A:atom) is det.
897 %
898 % Unifies A with the computer's hostname. This is set when the
899 % module is loaded by calling the system command 'hostname -s'.
900
901 % init_hostname is det - read hostname from UNIX command hostname.
902 init_hostname :-
903 setup_call_cleanup(
904 open(pipe('hostname -s'),read,SID),
905 (read_line_to_codes(SID,C), atom_codes(H,C), retractall(hostname(_)), assert(hostname(H))),
906 close(SID)).
907
908 :- ( hostname(H)
909 -> format('% hostname already set to ~w\n',[H])
910 ; init_hostname, hostname(H), format('% hostname set to ~w\n',[H])
911 ).
912
913 % Comma lists
914 % ie, lists built up using (,) as a pairing functor
915 % Note, these functor lists do NOT have a nil element - the
916 % last item in the list is the 2nd argument to the final
917 % functor term, which can therefore be a term headed by any
918 % other functor. Eg:
919 % (1,(2,3)) <-> [1,2,3]
920 % (1,(2,(3+4)) <-> [1,2,(3+4)]
921
922 %% cl_list( +CL:clist(A), -L:list(A)) is det.
923 %% cl_list( -CL:clist(A), +L:list(A)) is det.
924 %
925 % Convert between comma lists and ordinary lists
926 cl_list((A,B),[A|BL]) :- cl_list(B,BL).
927 cl_list(A,[A]) :- A\=(_,_).
928
929 %% cl_length( +L:clist, -N:natural) is det.
930 %% cl_length( -L:clist, +N:natural) is det.
931 %
932 % Length of a comma-list.
933 cl_length((_,B),N) :- cl_length(B,M), succ(M,N).
934 cl_length(X,1) :- X\=(_,_).
935
936
937 %% cl_list_vt( +CL:clist(A), -L:list(A)) is det.
938 %% cl_list_vt( -CL:clist(A), +L:list(A)) is det.
939 %
940 % Convert between comma lists (with open tails) and ordinary lists.
941 cl_list_vt(FL,[FL]) :- var(FL), !.
942 cl_list_vt(FL,[A|BL]) :- FL = (A,B), cl_list_vt(B,BL).
943 cl_list_vt(A,[A]) :- A\=(_,_).
944
945
946 %% cl_length_vt( +L:clist, -N:natural) is det.
947 %% cl_length_vt( -L:clist, +N:natural) is det.
948 %
949 % Length of a comma-list with possible variable tail.
950 % This version handles lists where the last element is variable (counts as 1)
951 cl_length_vt(FL,1) :- var(FL), !.
952 cl_length_vt(FL,N) :- FL=(_,B), cl_length_vt(B,M), succ(M,N).
953 cl_length_vt(FL,1) :- FL\=(_,_).
954
955 %% cl_member(-X, +L:clist) is nondet.
956 % List membership for comma lists.
957 cl_member(X,(X,_)).
958 cl_member(X,(_,T)) :- cl_member(X,T).
959 cl_member(X,X) :- X\=(_,_).
960