1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The ECLiPSe Constraint Logic Programming System. 15% The Initial Developer of the Original Code is Cisco Systems, Inc. 16% Portions created by the Initial Developer are 17% Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22 23:- comment(alias, "Dynamic Predicates"). 24:- comment(summary, "Built-ins to create and manipulate dynamic procedures"). 25:- comment(categories, ["Built-In Predicates"]). 26 27:- tool(assert / 1). 28:- tool(asserta / 1). 29:- tool(assertz / 1). 30:- tool(clause / 1). 31:- tool(clause / 2). 32:- tool(is_dynamic / 1). 33:- tool((dynamic) / 1). 34:- tool((listing) / 0). 35:- tool((listing) / 1). 36:- tool(retract / 1). 37:- tool(retractall / 1). 38 39:- comment((dynamic) / 1, [ 40 summary:"Declares the procedures specified by SpecList as dynamic. 41 42", 43 template:"dynamic ++SpecList", 44 amode:(dynamic(++) is det), 45 desc:html(" Declare the procedures specified by SpecList as dynamic procedures. 46 This has to be done before the procedure is defined. 47 48<P> 49 To change a static procedure to a dynamic one it must first be 50 abolished. 51 52<P> 53 If the procedure was already dynamic Error 64 is raised. The default 54 error handler erases all existing clauses and succeeds. This is useful 55 for recompiling files with dynamic declarations, but it can be redefined 56 if desired. 57 58<P> 59"), 60 args:["SpecList" : "Sequence of expressions of the form Atom/Integer."], 61 exceptions:[4 : "SpecList is not instantiated.", 5 : "SpecList is instantiated, but not to a sequence of expressions of the form Atom/Integer.", 64 : "SpecList is already dynamic.", 65 : "SpecList is already defined."], 62 eg:" 63Success: 64 [eclipse]: pred(a/1). 65 no. 66 [eclipse]: dynamic a/1. 67 yes. 68 [eclipse]: pred(a/1). 69 in eclipse: dynamic prolog local debugged stopped traceable 70 yes. 71 [eclipse]: a(X). 72 no (more) solution. 73Error: 74 dynamic X. (Error 4). 75 dynamic a. (Error 5). 76 dynamic a/1, a/1. (Error 64). % succeeds 77 get_flag(p/0,type,user), 78 dynamic p/0. (Error 65). 79 80 81 82", 83 see_also:[is_dynamic / 1]]). 84 85:- comment(is_dynamic / 1, [ 86 summary:"Succeeds if the procedure specified by PredSpec has been declared as 87dynamic. 88 89", 90 amode:(is_dynamic(++) is semidet), 91 desc:html(" Used to test whether the procedure specified by PredSpec was declared as 92 dynamic. 93 94<P> 95"), 96 args:["PredSpec" : "Expression of the form Atom/Integer."], 97 fail_if:"Fails if the procedure specified by PredSpec has not been declared as\n dynamic.", 98 exceptions:[4 : "PredSpec is not instantiated.", 5 : "PredSpec is instantiated, but not to an expression of the form Atom/Integer.", 60 : "PredSpec is an undefined procedure."], 99 eg:" 100Success: 101 [eclipse]: assert(p). 102 yes. 103 [eclipse]: is_dynamic(p/0). 104 yes. 105 106Error: 107 is_dynamic(X). (Error 4). 108 is_dynamic(a). (Error 5). 109 is_dynamic(y/0). (Error 60). 110 111 112 113", 114 see_also:[(abolish) / 1, (dynamic) / 1]]). 115 116:- comment((listing) / 0, [ 117 summary:"Outputs the definition of all dynamic predicates in the database. 118 119", 120 amode:((listing) is det), 121 desc:html(" Outputs each of the dynamic predicates currently contained on the 122 database. ie. all predicates created using assert/1 or asserta/1 or 123 compiled as dynamic predicates. 124 125<P> 126 The order in which the predicates are listed is undefined. 127 128<P> 129 The individual clauses are output in indented format using 130 writeclause/2. 131 132<P> 133 No static predicates are output. 134 135<P> 136"), 137 args:[], 138 eg:" 139Success: 140 [eclipse]: [user]. 141 :- dynamic x/0, y/1. 142 x :- true. 143 y(X) :- write(X). 144 user compiled 0 bytes in 0.07 seconds 145 yes. 146 [eclipse]: assert(man(adam)), assert(woman(eve)), 147 > assert((likes(X,Y):-man(X),woman(Y))). 148 X = _g102 149 Y = _g98 150 yes. 151 [eclipse]: listing. 152 x . 153 y(_g68):- 154 write(_g68) . 155 likes(_g68, _g70):- 156 man(_g68), 157 woman(_g70) . 158 woman(eve) . 159 man(adam) . 160 yes. 161 162 163 164", 165 see_also:[assert / 1, clause / 2, (listing) / 1, writeclause / 1]]). 166 167:- comment((listing) / 1, [ 168 summary:"Outputs the definition of all dynamic predicates indicated by SpecList. 169 170", 171 template:"listing ++SpecList", 172 amode:(listing(++) is det), 173 desc:html(" Outputs the definition of all dynamic predicates defined by SpecList to 174 the standard output. An expression in SpecList may be a single 175 predicate in the form name/arity in which case only the clauses for 176 name/arity are printed. Alternatively the format name is accepted in 177 which case all the predicates of any arity associated with name are 178 output. 179 180<P> 181 The individual clauses are output in indented format using 182 writeclause/2. 183 184<P> 185 No static predicates are output. 186 187<P> 188"), 189 args:["SpecList" : "Sequence of expressions of the form Atom/Integer or just Atom."], 190 exceptions:[4 : "An expression in SpecList is not instantiated.", 5 : "An expression in SpecList is not of the form Atom/Integer or Atom.", 63 : "An expression in SpecList is not a dynamic procedure."], 191 eg:" 192Success: 193 [eclipse]: [user], assert(woman(eve)). 194 :- dynamic p/0. 195 p. 196 user compiled 0 bytes in 0.00 seconds 197 yes. 198 [eclipse]: listing p/0, woman/1. 199 p . 200 woman(eve) . 201 yes. 202 203Error: 204 listing X. (Error 4). 205 listing a/a. (Error 5). 206 listing z/3. (Error 63). 207 208 209 210", 211 see_also:[assert / 1, clause / 1, clause / 2, (listing) / 0, writeclause / 1]]). 212 213 214:- comment(assertz / 1, [ 215 summary:"Add specified clause at the end of the dynamic procedure to the database", 216 amode:(assertz(+) is det), 217 desc:html("\ 218 Adds the specified clause for a dynamic procedure to the database.] 219 The clause is added AFTER any existing clauses for the procedure. 220 This is an alias for assert/1. 221<P> 222 The procedure must be declared to be dynamic using the dynamic/1 223 built-in. If the procedure is undefined an exception is raised. 224 However, the default error handler for this exception simply declares 225 the procedure dynamic and asserts the clause. 226<P> 227 The asserted clause is NOT removed from the database on backtracking 228 through the call to assertz/1. 229<P> 230 assertz/1 satisfies the logical update semantics. Asserting a clause to 231 a procedure will not, in any way, affect previous calls to it when 232 backtracking. 233<P> 234 No clause transformation is performed on Clause. Use expand_clause/2 to 235 explicitly expand the clause before calling this predicate if clause 236 expansion is rquired. 237<P> 238"), 239 args:["Clause" : "Atom or compound term"], 240 exceptions:[4 : "Clause is a free variable.", 241 4 : "The head of Clause is a free variable.", 242 5 : "Clause is not a valid Prolog clause.", 243 63 : "The procedure is not dynamic.", 244 70 : "The procedure is undefined. However, the default error handler for this exception simply declares the procedure dynamic and asserts the clause, if the error was caused by an assert." 245 ], 246 eg:" Success: 247 ?- assertz(city(london)), assertz(city(munich)), assertz(city(paris)). 248 yes. 249 ?- listing. 250 city(london). 251 city(munich). 252 city(paris). 253 yes. 254 255 ?- assertz((likes(X,Y) :- man(X), woman(Y))). 256 yes. 257 ?- listing. 258 likes(_186, _187) :- 259 man(_186), 260 woman(_187). 261 yes. 262 263 264 Error: 265 assertz(X). - gives error 4. 266 assertz(\"the man\"). - gives error 5. 267 assertz(1). - gives error 5. 268 assertz((my_static(X):-write(X))). - gives error 63. 269 if my_static/1 is not 270 dynamic. 271 Logical semantics : 272 273 If the following clauses are in the database : 274p :- assertz(p), fail. 275p :- fail. 276 277q :- fail. 278q :- assertz(q), fail. 279 280 The queries p. and q. will both fail. 281", 282 see_also:[(dynamic) / 1, asserta / 1, assert/1, retract / 1, compile_term / 1]]). 283 284 285:- comment(assert / 1, [ 286 summary:"Add specified clause at the end of the dynamic procedure to the database", 287 amode:(assert(+) is det), 288 desc:html("\ 289 Adds the specified clause for a dynamic procedure to the database.] 290 The clause is added AFTER any existing clauses for the procedure. 291 This is an alias for assertz/1. 292<P> 293 The procedure must be declared to be dynamic using the dynamic/1 294 built-in. If the procedure is undefined an exception is raised. 295 However, the default error handler for this exception simply declares 296 the procedure dynamic and asserts the clause. 297<P> 298 The asserted clause is NOT removed from the database on backtracking 299 through the call to assert/1. 300<P> 301 assert/1 satisfies the logical update semantics. Asserting a clause to 302 a procedure will not, in any way, affect previous calls to it when 303 backtracking. 304<P> 305 No clause transformation is performed on Clause. Use expand_clause/2 to 306 explicitly expand the clause before calling this predicate if clause 307 expansion is rquired. 308<P> 309"), 310 args:["Clause" : "Atom or compound term"], 311 exceptions:[4 : "Clause is a free variable.", 312 4 : "The head of Clause is a free variable.", 313 5 : "Clause is not a valid Prolog clause.", 314 63 : "The procedure is not dynamic.", 315 70 : "The procedure is undefined. However, the default error handler for this exception simply declares the procedure dynamic and asserts the clause, if the error was caused by an assert." 316 ], 317 eg:" Success: 318 ?- assert(city(london)), assert(city(munich)), assert(city(paris)). 319 yes. 320 ?- listing. 321 city(london). 322 city(munich). 323 city(paris). 324 yes. 325 326 ?- assert((likes(X,Y) :- man(X), woman(Y))). 327 yes. 328 ?- listing. 329 likes(_186, _187) :- 330 man(_186), 331 woman(_187). 332 yes. 333 334 335 Error: 336 assert(X). - gives error 4. 337 assert(\"the man\"). - gives error 5. 338 assert(1). - gives error 5. 339 assert((my_static(X):-write(X))). - gives error 63. 340 if my_static/1 is not 341 dynamic. 342 Logical semantics : 343 344 If the following clauses are in the database : 345p :- assert(p), fail. 346p :- fail. 347 348q :- fail. 349q :- assert(q), fail. 350 351 The queries p. and q. will both fail. 352", 353 see_also:[(dynamic) / 1, asserta / 1, assertz/1, retract / 1, compile_term / 1]]). 354 355 356:- comment(asserta / 1, [ 357 summary:"Add specified clause for a dynamic procedure to the database before any existing clauses", 358 amode:(asserta(+) is det), 359 desc:html("\ 360 Adds the specified clause for a dynamic procedure to the database.] 361 The clause is added BEFORE any existing clauses for the procedure. 362<P> 363 The procedure must be declared to be dynamic using the dynamic/1 364 built-in. If the procedure is undefined an exception is raised. 365 However, the default error handler for this exception simply declares 366 the procedure dynamic and asserts the clause. 367<P> 368 The asserted clause is NOT removed from the database on backtracking 369 through the call to asserta/1. 370<P> 371 asserta/1 satisfies the logical update semantics. Asserting a clause to 372 a procedure will not, in any way, affect previous calls to it when 373 backtracking. 374<P> 375 No clause transformation is performed on Clause. Use expand_clause/2 to 376 explicitly expand the clause before calling this predicate if clause 377 expansion is rquired. 378<P> 379"), 380 args:["Clause" : "Atom or compound term"], 381 exceptions:[4 : "Clause is a free variable.", 382 4 : "The head of Clause is a free variable.", 383 5 : "Clause is not a valid Prolog clause.", 384 63 : "The procedure is not dynamic.", 385 70 : "The procedure is undefined. However, the default error handler for this exception simply declares the procedure dynamic and asserts the clause, if the error was caused by an assert." 386 ], 387 eg:" Success: 388 ?- asserta(city(london)), asserta(city(munich)), asserta(city(paris)). 389 yes. 390 ?- listing. 391 city(paris). 392 city(munich). 393 city(london). 394 yes. 395 396 ?- asserta((likes(X,Y) :- man(X), woman(Y))). 397 yes. 398 ?- listing. 399 likes(_186, _187) :- 400 man(_186), 401 woman(_187). 402 yes. 403 404 405 Error: 406 asserta(X). - gives error 4. 407 asserta(\"the man\"). - gives error 5. 408 asserta(1). - gives error 5. 409 asserta((my_static(X):-write(X))). - gives error 63. 410 if my_static/1 is not 411 dynamic. 412 Logical semantics : 413 414 If the following clauses are in the database : 415p :- asserta(p), fail. 416p :- fail. 417 418q :- fail. 419q :- asserta(q), fail. 420 421 The queries p. and q. will both fail. 422", 423 see_also:[(dynamic) / 1, assert / 1, assertz/1, retract / 1, compile_term / 1]]). 424 425 426 427:- comment(clause / 1, [ 428 summary:"Succeeds if Clause unifies with a clause of a dynamic procedure. 429 430", 431 amode:(clause(+) is nondet), 432 desc:html(" Finds a dynamic clause whose head unifies with the head of Clause and 433 unifies the body of the clause with the body of Clause. The head of 434 Clause must be sufficiently instantiated so that the predicate (head) of 435 the clause can be determined. The functor of the head of Clause must be 436 that of a procedure previously declared as dynamic using dynamic/1. 437 438<P> 439 This goal may be resatisfied if there are several clauses which match 440 the first argument. In the first solution the argument will be unified 441 with the first such clause. Subsequent solutions will unify the 442 argument to the other clauses in the same order in which they are listed 443 by listing/0, 1. 444 445<P> 446 clause/1 satisfies the logical update semantics. When clause/1 is first 447 called, it makes a virtual copy of the clauses that match and, on 448 backtracking, unifies its argument with them. Any modifications made to 449 the procedure after clause/1 has started executing do not, in any way, 450 affect the solutions produced. A subsequent call, however makes and 451 uses a new, virtual, copy of the modified database. 452 453<P> 454 No clause transformation is performed on Clause. Use expand_clause/2 to 455 explicitly expand the clause before calling this predicate if clause 456 expansion is rquired. 457<P> 458"), 459 args:["Clause" : "Atom or compound term"], 460 fail_if:"Fails if no dynamic clause unifies with Clause", 461 exceptions:[4 : "Clause is not instantiated", 4 : "The head of Clause is a free variable.", 63 : "Procedure is not dynamic", 70 : "Procedure is undefined"], 462 see_also:[clause/2]]). 463 464:- comment(clause / 2, [ 465 summary:"Succeeds if Head :- Body is an existing dynamic clause. 466 467", 468 amode:(clause(+,-) is nondet), 469 desc:html(" Identical to clause((Head :- Body)). 470 471<P> 472"), 473 args:["Head" : "Atom or compound term.", "Body" : "Atom, variable or compound term."], 474 fail_if:"Fails if no dynamic clause head unifies with Head", 475 see_also:[clause / 1]]). 476 477:- comment(retract / 1, [ 478 summary:"Succeeds if a clause that unifies with Clause can be removed from the 479database. 480 481", 482 amode:(retract(+) is nondet), 483 desc:html(" Removes the first clause that matches the argument from the database. 484 On backtracking, successive clauses that match are removed. The clauses 485 are not reasserted when backtracking occurs through retract/1. 486 487<P> 488 The functor of the head of Clause must be that of a predicate declared 489 as dynamic, otherwise an error occurs. If no clause matches, it fails. 490 491<P> 492 retract/1 satisfies the logical update semantics. When retract/1 is 493 first called, it makes a virtual copy of the clauses that match and, on 494 backtracking, unifies its argument with them and removes them from the 495 database. Any modifications made to the procedure after retract/1 has 496 started executing do not, in any way, affect its behaviour. A 497 subsequent call, however, makes and uses a new, virtual, copy of the 498 modified database. 499 500<P> 501 No clause transformation is performed on Clause. Use expand_clause/2 to 502 explicitly expand the clause before calling this predicate if clause 503 expansion is rquired. 504 505<P> 506"), 507 args:["Clause" : "Atom or compound term"], 508 fail_if:"Fails if no dynamic clause unifies with Clause", 509 exceptions:[4 : "Clause is not instantiated", 4 : "The head of Clause is a free variable.", 5 : "Clause or the head of Clause is not a callable term.", 63 : "Procedure is not dynamic", 70 : "Procedure is undefined"], 510 eg:" 511Success: 512 [eclipse]: assert(city(munich)), assert(city(london)), 513 assert((p :- write(hi), write(there))). 514 515 yes. 516 [eclipse]: retract(city(X)). 517 518 X = munich More? (;) 519 yes. 520 [eclipse]: retract(city(X) :- Body). 521 522 X = london 523 Body = true 524 yes. 525 [eclipse]: retract(p :- Body). 526 527 Body = write(hi) , write(there) 528 yes. 529Fail: 530 assert(fact),retract(fact),retract(fact). 531 532Error: 533 retract(X). (Error 4). 534 retract(\"x\"). (Error 5). 535 retract(listing). (Error 63). 536 retract(undef). (Error 70). 537 538 539 540", 541 see_also:[assert / 1, (dynamic) / 1, (listing) / 1]]). 542 543:- comment(retractall / 1, [ 544 summary:"Removes from the database all clauses whose heads match Head", 545 amode:(retractall(+) is det), 546 desc:html(" Retracts from the database all clauses whose heads match the argument. 547 The argument must be sufficiently instantiated otherwise an error is 548 signalled. retractall/1 never fails. The clauses are not reasserted 549 when backtracking through the call of retractall/1. 550 551<P> 552 The functor and the arity of Head must be that of a predicate declared 553 as dynamic (or implicitly declared as dynamic by asserting). 554 555<P> 556 retractall/1 satisfies the logical update semantics. Using it to 557 retract all the clauses of a predicate will not, in any way, affect 558 previous calls to the predicate, i.e. they will still see all the clauses 559 that existed at call time. 560 561<P> 562"), 563 args:["Head" : "Atom, variable or compound term."], 564 exceptions:[4 : "Head is not instantiated", 5 : "Head is not a callable term", 63 : "Procedure is not dynamic", 70 : "Procedure is undefined"], 565 eg:" 566Success: 567 [eclipse]: assert(city(munich)), assert(city(london)). 568 yes. 569 [eclipse]: retractall(city(_)). 570 yes. 571 [eclipse]: city(X). 572 no (more) solution. 573 [eclipse]: retractall(city(_)). 574 yes. 575Error: 576 retractall(X). (Error 4). 577 retractall(\"x\"). (Error 5). 578 579 580 % if h/0 is defined, but not as dynamic.. 581 retractall(h). (Error 63). 582 583 retractall(z/0). (Error 70). 584 585 586 587", 588 see_also:[(dynamic) / 1, assert / 1, retract / 1]]). 589 590