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, "Non-logical Variables, Arrays, Bags, Shelves and Stores"). 24:- comment(summary, "Built-ins to store data across backtracking"). 25:- comment(categories, ["Built-In Predicates","Data Structures"]). 26 27:- tool(current_array / 2). 28:- tool(erase_array / 1). 29:- tool(current_store / 1). 30:- tool(decval / 1). 31:- tool(getval / 2). 32:- tool(incval / 1). 33:- tool(setval / 2). 34:- tool(shelf_dec / 2). 35:- tool(shelf_get / 3). 36:- tool(shelf_inc / 2). 37:- tool(shelf_set / 3). 38:- tool(store_contains / 2). 39:- tool(store_count / 2). 40:- tool(store_delete / 2). 41:- tool(store_erase / 1). 42:- tool(store_get / 3). 43:- tool(store_inc / 2). 44:- tool(store_set / 3). 45:- tool(stored_keys / 2). 46:- tool(stored_keys_and_values / 2). 47:- tool(test_and_setval / 3). 48 49:- comment(desc, html("\ 50 ECLiPSe provides several facilities to store information across 51 backtracking. The following table gives an overview. If at all 52 possible, the handle-based facilities (bags, records, shelves, 53 stores) should be preferred because they lead to cleaner, reentrant 54 code (without global state) and reduce the risk of memory leaks. 55<PRE> 56 Facility Type Reference See 57 ================================================================ 58 bags unordered bag by handle bag_create/1 59 ---------------------------------------------------------------- 60 anon.records ordered list by handle record_create/1 61 ---------------------------------------------------------------- 62 shelves array by handle shelf_create/2,3 63 ---------------------------------------------------------------- 64 stores hash table by handle store_create/1 65 ---------------------------------------------------------------- 66 named shelves array by name shelf/2 67 ---------------------------------------------------------------- 68 named stores hash table by name store/1 69 ---------------------------------------------------------------- 70 non-logical single cell by name variable/1,2 71 variables 72 ---------------------------------------------------------------- 73 non-logical array by name array/1,2 74 arrays 75 ---------------------------------------------------------------- 76 named records ordered list by name record/1,2 77 ---------------------------------------------------------------- 78 dynamic ordered list by name dynamic/1,assert/1 79 predicates 80 ---------------------------------------------------------------- 81</PRE> 82 ")). 83 84:- comment(bag_create/1, [ 85 summary:"Create a bag object which can store data across failures", 86 desc:html("\ 87 This creates an anonymous bag object which can be used to store 88 information across failures. A typical application is the 89 implementation of the findall/3 predicate or similar functionality. 90 Bags are similar to records, with two differences: First, a bag 91 is considered unordered, so one should not expect the bag content 92 to indicate the order in which information was entered. 93 Second, bags are referred to by handle, not by name, so they make 94 it much easier to write robust, reentrant code. 95 "), 96 amode:(bag_create(-) is det), 97 args:["BagHandle":"A free variable"], 98 exceptions:[5 : "BagHandle is not a variable"], 99 eg:" 100 simple_findall(Goal, Solutions) :- 101 bag_create(Bag), 102 ( 103 call(Goal), 104 bag_enter(Bag, Goal), 105 fail 106 ; 107 true 108 ), 109 bag_dissolve(Bag, Solutions). 110 ", 111 see_also:[bag_erase/1, bag_enter / 2, bag_count/2, bag_dissolve / 2, bag_retrieve/2, bag_abolish/1] 112 ]). 113 114:- comment(bag_abolish/1, [ 115 summary:"Destroy a bag explicitly", 116 desc:html("\ 117 This explicitly destroys a previously created bag object and 118 frees all its memory. Invoking bag_abolish/1 is optional, 119 the bag will be automatically destroyed when the system 120 backtracks across the call to bag_create/1, or when the 121 BagHandle is no longer needed and gets garbage collected. 122 bag_dissolve/2 will also destroy the bag. 123<P> 124 Using the BagHandle after it has been destroyed will lead 125 to an error message. Destroying an already destroyed bag 126 does nothing and is silently accepted. 127 "), 128 amode:(bag_abolish(+) is det), 129 args:["BagHandle":"A bag handle"], 130 exceptions:[4: "BagHandle is not instantiated", 131 5 : "BagHandle is not a bag", 132 40 : "BagHandle refers to an already destroyed bag"], 133 see_also:[bag_create/1, bag_enter/2, bag_count/2, bag_erase/1, bag_retrieve/2, bag_dissolve/2] 134 ]). 135 136:- comment(bag_erase/1, [ 137 summary:"Erase the contents of a bag", 138 desc:html("\ 139 This explicitly erases the contents of a previously created 140 bag object and frees the associated memory. After erasing, 141 the bag is in the same state as immediately after creation, 142 and can be filled with new contents. 143 "), 144 amode:(bag_erase(+) is det), 145 args:["BagHandle":"A bag handle"], 146 exceptions:[4: "BagHandle is not instantiated", 147 5 : "BagHandle is not a bag", 148 40 : "BagHandle refers to an already destroyed bag"], 149 eg:" 150 ?- bag_create(B), bag_enter(B, one), bag_erase(B), bag_enter(B, two), bag_retrieve(B, L). 151 B = 'BAG'(16'0030db60) 152 L = [two] 153 Yes (0.00s cpu) 154 ", 155 see_also:[bag_create/1, bag_abolish/1, bag_enter/2, bag_count/2, bag_retrieve/2, bag_dissolve/2] 156 ]). 157 158:- comment(bag_enter/2, [ 159 summary:"Enter a term into an existing bag object", 160 desc:html("\ 161 This enters an arbitrary term into a bag object that has previously 162 been created with bag_create/1. The order in which terms are entered 163 into a bag should not be considered relevant, a bag is conceptually 164 unordered. Entering and retrieving terms from a bag involves 165 copying the term each time, similar to what happens in setval/getval 166 and record/recorded. In particular, if the term contains variables, 167 they lose their identity and are replaced with fresh ones. 168 "), 169 amode:(bag_enter(+,+) is det), 170 args:["BagHandle":"A bag", "Term":"An arbitrary term"], 171 exceptions:[4: "BagHandle is not instantiated", 172 5 : "BagHandle is not a bag", 173 40 : "BagHandle refers to an already destroyed bag"], 174 eg:" 175 simple_findall(Goal, Solutions) :- 176 bag_create(Bag), 177 ( 178 call(Goal), 179 bag_enter(Bag, Goal), 180 fail 181 ; 182 true 183 ), 184 bag_dissolve(Bag, Solutions). 185 ", 186 see_also:[bag_create / 1, bag_count/2, bag_abolish/1, bag_erase/1, bag_retrieve/2, bag_dissolve / 2] 187 ]). 188 189:- comment(bag_count/2, [ 190 summary:"Get the number of entries in a bag", 191 desc:html("\ 192 This returns an integer corresponding to the number of entries 193 currently in the bag. A fresh or erased bag has zero entries. 194 "), 195 amode:(bag_count(+,-) is det), 196 args:["BagHandle":"A bag", "Count":"A variable or integer"], 197 exceptions:[4: "BagHandle is not instantiated", 198 5 : "BagHandle is not a bag", 199 40 : "BagHandle refers to an already destroyed bag"], 200 eg:" 201 ?- bag_create(B), bag_count(B, N0), bag_enter(B, one), bag_count(B, N1). 202 N0 = 0 203 B = 'BAG'(16'0030dc48) 204 N1 = 1 205 Yes (0.00s cpu) 206 ", 207 see_also:[bag_create / 1, bag_enter / 2, bag_count/2, bag_erase/1, bag_abolish/1, bag_retrieve/2, bag_dissolve/2] 208 ]). 209 210:- comment(bag_retrieve/2, [ 211 summary:"Retrieve a bag's contents", 212 desc:html("\ 213 This returns a list containing a copy of every term that has 214 been entered into the bag since it was created. It should not 215 be assumed that the list order reflects the order in which the 216 terms were entered into the bag. Entering and retrieving 217 terms from a bag involves copying the term each time, similar 218 to what happens in setval/getval and record/recorded. In 219 particular, if the term contains variables, they lose their 220 identity and are replaced with fresh ones. 221 "), 222 amode:(bag_retrieve(+,-) is det), 223 args:["BagHandle":"A bag", "List":"A variable or list of terms"], 224 exceptions:[4: "BagHandle is not instantiated", 225 5 : "BagHandle is not a bag", 226 40 : "BagHandle refers to an already destroyed bag"], 227 eg:" 228 simple_findall(Goal, Solutions) :- 229 bag_create(Bag), 230 ( 231 call(Goal), 232 bag_enter(Bag, Goal), 233 fail 234 ; 235 true 236 ), 237 bag_retrieve(Bag, Solutions), 238 bag_abolish(Bag). 239 ", 240 see_also:[bag_create / 1, bag_enter / 2, bag_count/2, bag_erase/1, bag_abolish/1, bag_dissolve/2] 241 ]). 242 243:- comment(bag_dissolve/2, [ 244 summary:"Retrieve a bag's contents and destroy the bag", 245 desc:html("\ 246 This returns a list containing a copy of every term that has 247 been entered into the bag since it was created. The bag is 248 also destoyed. It should not be assumed that the list order 249 reflects the order in which the terms were entered into the 250 bag. Entering and retrieving terms from a bag involves 251 copying the term each time, similar to what happens in 252 setval/getval and record/recorded. In particular, if the term 253 contains variables, they lose their identity and are replaced 254 with fresh ones. 255<P> 256 bag_dissolve/2 is equivalent to bag_retrieve/2, followed by 257 bag_abolish/1. Using the BagHandle after it has been dissolved 258 will lead to an error message. 259 "), 260 amode:(bag_dissolve(+,-) is det), 261 args:["BagHandle":"A bag", "List":"A variable or list of terms"], 262 exceptions:[4: "BagHandle is not instantiated", 263 5 : "BagHandle is not a bag", 264 40 : "BagHandle refers to an already destroyed bag"], 265 eg:" 266 simple_findall(Goal, Solutions) :- 267 bag_create(Bag), 268 ( 269 call(Goal), 270 bag_enter(Bag, Goal), 271 fail 272 ; 273 true 274 ), 275 bag_dissolve(Bag, Solutions). 276 ", 277 see_also:[bag_create / 1, bag_enter / 2, bag_count/2, bag_erase/1, bag_retrieve/2, bag_abolish/1] 278 ]). 279 280:- comment(shelf_create/2, [ 281 summary:"Create a shelf object which can store data across failures", 282 desc:html("\ 283 This creates a 'shelf' object which can be used to store 284 information across failures. A typical application is counting 285 of solutions, keeping track of the best solution, aggregating 286 information across multiple solutions etc. 287<P> 288 A shelf is an object with multiple slots whose contents survive 289 backtracking. The content of each slot can be set and retrieved 290 individually, or the whole shelf can be retrieved as a term. 291<P> 292 Shelves are referred to by handle, not by name, so they make 293 it easy to write robust, reentrant code. A shelf disappears when 294 the system backtracks over its creation, when the shelf handle 295 gets garbage collected, or when it is explicitly destroyed. 296<P> 297 A shelf is initialized from a compound term InitTerm. InitTerm's 298 arity determines the number of slots the shelf provides, and 299 InitTerm's arguments are used to initialize the corresponding 300 shelf slots. 301 "), 302 amode:(shelf_create(+,-) is det), 303 args:["InitTerm":"A compound term", 304 "ShelfHandle":"A free variable"], 305 exceptions:[ 306 4 : "InitTerm is not instantiated", 307 5 : "InitTerm is instantiated but not to a compound term", 308 5 : "ShelfHandle is not a variable"], 309 eg:" 310 311% a meta-predicate to count the number of solutions to a goal: 312 313 count_solutions(Goal, Total) :- 314 shelf_create(count(0), Shelf), 315 ( 316 call(Goal), 317 shelf_inc(Shelf, 1), 318 fail 319 ; 320 shelf_get(Shelf, 1, Total) 321 ), 322 shelf_abolish(Shelf). 323 324 325% finding the sum and maximum of data/1 facts: 326 327 data(2). 328 data(9). 329 data(3). 330 data(5). 331 data(7). 332 333 sum_and_max(Sum, Max) :- 334 shelf_create(agg(0,0), Shelf), 335 ( 336 data(X), 337 shelf_get(Shelf, 1, OldMax), 338 ( X > OldMax -> shelf_set(Shelf, 1, X) ; true ), 339 shelf_get(Shelf, 2, OldSum), 340 NewSum is OldSum + X, 341 shelf_set(Shelf, 2, NewSum), 342 fail 343 ; 344 shelf_get(Shelf, 0, agg(Max, Sum)) 345 ), 346 shelf_abolish(Shelf). 347 348 349% if-then-else with backtracking over the condition: 350 351 if(Cond, Then, Else) :- 352 shelf_create(sol(no), SolFlag), 353 ( 354 call(Cond), 355 shelf_set(SolFlag, 1, yes), % remember there was a solution 356 call(Then) 357 ; 358 shelf_get(SolFlag, 1, no), % fail if there was a solution 359 call(Else) 360 ). 361 ", 362 see_also:[shelf_create/3, shelf_set/3, shelf_get/3, shelf_abolish/1, 363 array/1, bag_create/1] 364 ]). 365 366:- comment(shelf_create/3, [ 367 summary:"Create a shelf object which can store data across failures", 368 desc:html("\ 369 This creates a 'shelf' object which can be used to store 370 information across failures. A typical application is counting 371 of solutions, keeping track of the best solution, aggregating 372 information across multiple solutions etc. 373<P> 374 A shelf is an object with multiple slots whose contents survive 375 backtracking. The content of each slot can be set and retrieved 376 individually, or the whole shelf can be retrieved as a term. 377<P> 378 Shelves are referred to by handle, not by name, so they make 379 it easy to write robust, reentrant code. A shelf disappears when 380 the system backtracks over its creation, when the shelf handle 381 gets garbage collected, or when it is explicitly destroyed. 382<P> 383 When using shelf_create/3, ShelfSpec determines the number of 384 slots on the shelf, and all slots get initialized identically 385 with the value SlotInit. 386 "), 387 amode:(shelf_create(++,?,-) is det), 388 args:["ShelfSpec":"A term of the form Name/Arity", 389 "SlotInit":"The value used to initialize the slots (any term)", 390 "ShelfHandle":"A free variable"], 391 exceptions:[ 392 4 : "ShelfSpec is not fully instantiated", 393 5 : "ShelfSpec is fully instantiated but not to a term of the form Atom/Integer", 394 5 : "ShelfHandle is not a variable"], 395 eg:" 396% finding the sum and maximum of data/1 facts: 397 398 data(2). 399 data(9). 400 data(3). 401 data(5). 402 data(7). 403 404 sum_and_max(Sum, Max) :- 405 shelf_create(agg/2, 0, Shelf), 406 ( 407 data(X), 408 shelf_get(Shelf, 1, OldMax), 409 ( X > OldMax -> shelf_set(Shelf, 1, X) ; true ), 410 shelf_get(Shelf, 2, OldSum), 411 NewSum is OldSum + X, 412 shelf_set(Shelf, 2, NewSum), 413 fail 414 ; 415 shelf_get(Shelf, 0, agg(Max, Sum)) 416 ), 417 shelf_abolish(Shelf). 418 ", 419 see_also:[shelf_create/2, shelf_set/3, shelf_get/3, shelf_abolish/1] 420 ]). 421 422:- comment(shelf/2, [ 423 summary:"Create a named shelf object which can store data across failures", 424 desc:html("\ 425 This creates a 'shelf' object which can be used to store 426 information across failures. A typical application is counters 427 for statistics, etc. 428<P> 429 A shelf is an object with multiple slots whose contents survive 430 backtracking. The content of each slot can be set and retrieved 431 individually, or the whole shelf can be retrieved as a term. 432<P> 433 Shelves can be referred to either by handle or by name. Whenever 434 possible, handles should be used, because this naturally leads to 435 robust, reentrant code, and avoids the danger of memory leaks. 436 See shelf_create/2,3 for how to create shelves with a handle. 437<P> 438 Named shelves are identified by a functor. This is usually simply 439 an atom, but in general it can be name/arity pair. 440<P> 441 When named shelves are used, the visibility of the shelf name is 442 local to the module where it was created. A named shelf never 443 disappears, therefore, in order to free the associated memory, 444 its contents should be erased when no longer needed. 445<P> 446 Duplicate shelf declarations are silently ignored. 447 "), 448 template:"local shelf(++Name, +Init)", 449 amode:(shelf(++, +) is det), 450 args:["Name":"An atom, or an atom/integer structure", 451 "Init":"A structure"], 452 exceptions:[ 453 4 : "Name or Init is uninstantiated", 454 5 : "Init is not a structure", 455 5 : "Name is neither an atom nor an atom/integer structure"], 456 eg:" 457 458 % A store with the simple, atomic name 'counters' 459 460 :- local shelf(counters, count(0,0,0)). 461 462 main :- 463 shelf_get(counters,1,N0), N1 is N0+1, shelf_set(counters,1,N1), 464 printf(\"main has been called %d times%n\", [N1]). 465 ", 466 see_also:[shelf_create/2, shelf_create/3, (local)/1, shelf_set/3, shelf_get/3, 467 store_delete/2, 468 store_contains/2, stored_keys/2, stored_keys_and_values/2, 469 store_erase/1, store_count/2] 470 ]). 471 472 473:- comment(shelf_set/3, [ 474 summary:"Store a term in a shelf object", 475 desc:html("\ 476 This stores an arbitrary term in the Index'th slot of the 477 shelf object denoted by ShelfHandle. All other slots of the 478 shelf remain untouched. The setting will persist until it is 479 replaced with a new setting, or until the shelf is destroyed. 480 In particular, the setting will survive backtracking across 481 the call to shelf_set/3. 482<P> 483 The slots are numbered from 1 to the maximum which was determined 484 during shelf creation (but note that ECLiPSe's struct-syntax can 485 be used to give the slots symbolic names, see struct/1). 486<P> 487 Calling shelf_set/3 with an Index of 0 can be used to set all 488 slots at once. In this case, Term must be a compound term whose 489 functor corresponds to the one that was given during shelf creation. 490 Every shelf slot is set from the corresponding term argument. 491<P> 492 Storing and retrieving terms from a shelf involves copying the 493 term each time, similar to what happens in setval/getval and 494 record/recorded. In particular, if the term contains variables, 495 they lose their identity and are replaced with fresh ones. 496 Also, the different slots of a shelf are separate entities, 497 in particular, they cannot share variables between each other. 498<P> 499 Note: If ShelfHandle is not a handle, then it must be an atom or a 500 compound term, and the shelf is identified by this term's toplevel 501 functor together with the context module. 502 "), 503 amode:(shelf_set(+,+,?) is det), 504 args:["ShelfHandle":"A shelf handle or shelf name", 505 "Index":"An integer", 506 "Term":"An arbitrary term"], 507 exceptions:[4: "ShelfHandle is not instantiated", 508 5 : "Index is not instantiated", 509 5 : "ShelfHandle is not a shelf", 510 5 : "Index is not an integer", 511 6 : "Index is negative or greater than the number of slots on the shelf", 512 40 : "ShelfHandle refers to an already destroyed shelf"], 513 eg:"For examples see shelf_create/2,3.", 514 see_also:[shelf_create/2, shelf_create/3, shelf_get/3, shelf_abolish/1, struct/1] 515 ]). 516 517:- comment(shelf_get/3, [ 518 summary:"Retrieve a stored term from a shelf object", 519 desc:html("\ 520 This retrieves a copy of the stored term from the Index'th slot 521 of the shelf object denoted by ShelfHandle. 522<P> 523 The slots are numbered from 1 to the maximum which was determined 524 during shelf creation (but note that ECLiPSe's struct-syntax can 525 be used to give the slots symbolic names, see struct/1). 526<P> 527 Calling shelf_get/3 with an Index of 0 retrieves the whole 528 shelf with all its slots as a single compound term whose functor 529 corresponds to the one that was given during shelf creation. 530<P> 531 Storing and retrieving terms from a shelf involves copying the 532 term each time, similar to what happens in setval/getval and 533 record/recorded. In particular, if the term contains variables, 534 they lose their identity and are replaced with fresh ones. 535<P> 536 Note: If ShelfHandle is not a handle, then it must be an atom or a 537 compound term, and the shelf is identified by this term's toplevel 538 functor together with the context module. 539 "), 540 amode:(shelf_get(+,+,-) is det), 541 args:["ShelfHandle":"A shelf handle or shelf name", 542 "Index":"An integer", 543 "Term":"An arbitrary term or a variable"], 544 exceptions:[4: "ShelfHandle is not instantiated", 545 5 : "Index is not instantiated", 546 5 : "ShelfHandle is not a shelf", 547 5 : "Index is not an integer", 548 6 : "Index is negative or greater than the number of slots on the shelf", 549 40 : "ShelfHandle refers to an already destroyed shelf"], 550 eg:"For examples see shelf_create/2,3.", 551 see_also:[shelf_create/2, shelf_create/3, shelf_set/3, shelf_abolish/1, struct/1] 552 ]). 553 554:- comment(shelf_inc/2, [ 555 summary:"Increment an integer slot within a shelf object", 556 desc:html("\ 557 This looks up the entry in the Index'th slot of the shelf object 558 denoted by ShelfHandle, and if such an entry exists, and is of integer 559 type, it is incremented by one. This predicate is a shorthand for: 560<PRE> 561 shelf_inc(ShelfHandle, Index) :- 562 shelf_get(ShelfHandle, Index, C0), 563 C1 is C0 + 1, 564 shelf_set(ShelfHandle, Index, C1). 565</PRE> 566 The slots are numbered from 1 to the maximum which was determined 567 during shelf creation (but note that ECLiPSe's struct-syntax can 568 be used to give the slots symbolic names, see struct/1). 569<P> 570 Note: If ShelfHandle is not a handle, then it must be an atom or a 571 compound term, and the shelf is identified by this term's toplevel 572 functor together with the context module. 573 "), 574 amode:(shelf_inc(+,+) is det), 575 args:["ShelfHandle":"A shelf handle or shelf name", 576 "Index":"An integer"], 577 exceptions:[4: "ShelfHandle is not instantiated", 578 5 : "Index is not instantiated", 579 5 : "ShelfHandle is not a shelf", 580 5 : "Index is not an integer", 581 6 : "Index is less than 1 or greater than the number of slots on the shelf", 582 6 : "The counter value exceeds an implementation-defined limit (at least 2^31)", 583 40 : "ShelfHandle refers to an already destroyed shelf"], 584 eg:"For examples see shelf_create/2,3.", 585 see_also:[shelf_create/2, shelf_create/3, shelf_dec/2, shelf_set/3, shelf_abolish/1, struct/1] 586 ]). 587 588:- comment(shelf_dec/2, [ 589 summary:"Decrement an integer slot within a shelf object but fail if is zero", 590 desc:html("\ 591 This looks up the entry in the Index'th slot of the shelf object 592 denoted by ShelfHandle, and if such an entry exists, and is of integer 593 type, it is decremented by one. If the old value is already zero 594 (or less), the predicate fails and the shelf remains unchanged. 595 This predicate is a shorthand for: 596<PRE> 597 shelf_dec(ShelfHandle, Index) :- 598 shelf_get(ShelfHandle, Index, C0), 599 C0 > 0, 600 C1 is C0 - 1, 601 shelf_set(ShelfHandle, Index, C1). 602</PRE> 603 The slots are numbered from 1 to the maximum which was determined 604 during shelf creation (but note that ECLiPSe's struct-syntax can 605 be used to give the slots symbolic names, see struct/1). 606<P> 607 Note: If ShelfHandle is not a handle, then it must be an atom or a 608 compound term, and the shelf is identified by this term's toplevel 609 functor together with the context module. 610 "), 611 amode:(shelf_dec(+,+) is semidet), 612 args:["ShelfHandle":"A shelf handle or shelf name", 613 "Index":"An integer"], 614 fail_if:"Fails if decrementing the value would result in a negative number", 615 exceptions:[4: "ShelfHandle is not instantiated", 616 5 : "Index is not instantiated", 617 5 : "ShelfHandle is not a shelf", 618 5 : "Index is not an integer", 619 6 : "Index is less than 1 or greater than the number of slots on the shelf", 620 6 : "The old counter value exceeds an implementation-defined limit (at least 2^31)", 621 40 : "ShelfHandle refers to an already destroyed shelf"], 622 eg:" 623 :- local shelf(backtrack_limit, count(100)). 624 625 nat(0). 626 nat(N) :- 627 shelf_dec(backtrack_limit, 1), % fail when limit reached 628 nat(N0), 629 N is N0+1. 630 631 ?- shelf_set(backtrack_limit, 1, 5), 632 findall(X, nat(X), L). 633 634 X = X 635 L = [0, 1, 2, 3, 4, 5] 636 Yes (0.00s cpu) 637 ", 638 see_also:[shelf_create/2, shelf_create/3, shelf_inc/2, shelf_set/3, shelf_abolish/1, struct/1] 639 ]). 640 641:- comment(shelf_abolish/1, [ 642 summary:"Destroy a shelf explicitly", 643 desc:html("\ 644 This explicitly destroys a previously created shelf object and 645 frees all its memory. Invoking shelf_abolish/1 is optional, 646 the shelf will be automatically destroyed when the system 647 backtracks across the call to shelf_create/2,3, or when the 648 ShelfHandle is no longer needed and gets garbage collected. 649<P> 650 Using the ShelfHandle after it has been destroyed will lead 651 to an error message. Destroying an already destroyed shelf 652 does nothing and is silently accepted. 653 "), 654 amode:(shelf_abolish(+) is det), 655 args:["ShelfHandle":"A shelf handle"], 656 exceptions:[4: "ShelfHandle is not instantiated", 657 5 : "ShelfHandle is not a shelf", 658 40 : "ShelfHandle refers to an already destroyed shelf"], 659 eg:"For examples see shelf_create/2,3.", 660 see_also:[shelf_create/2, shelf_create/3, shelf_get/3, shelf_set/3] 661 ]). 662 663:- comment(current_array / 2, [ 664 summary:"Succeeds if there exists an array as denoted by Array and with type and 665visibility as given in the list Options. 666 667", 668 amode:(current_array(-,-) is nondet), 669 amode:(current_array(+,-) is semidet), 670 desc:html("\ 671 current_array/2 is used to retrieve information about existing 672 visible arrays, non-logical variables and references. Array is a 673 term denoting the array's name and dimensions and Options is a list 674 describing the array's type (prolog, float, integer or byte) and visibility. 675"), 676 args:["Array" : "Atom or compound term.", 677 "Options" : "Variable or list."], 678 fail_if:"Fails if there is no array whose name unifies with ArrayName", 679 exceptions:[5 : "Array is neither variable, atom nor compound term.", 5 : "Options is neither a list nor a variable."], 680 eg:" 681[eclipse 1]: local array(a(2)), array(b(2,3,4), float). 682 683yes. 684[eclipse 2]: current_array(a(Size), [Type,Vis|_]). 685 686Size = 2 687Type = prolog 688Vis = local 689yes. 690[eclipse 3]: current_array(Array, Props). 691 692Array = a(2) 693Props = [prolog, local] More? (;) 694 695Array = b(2, 3, 4) 696Props = [float, local] More? (;) 697 698no (more) solution. 699 700Error: 701 current_array(\"a\", L). (Error 5). 702 current_array(a, 9). (Error 5). 703 704 705", 706 see_also:[array / 1, array / 2, variable / 1]]). 707 708:- comment(decval / 1, [ 709 summary:"Decrements the contents of the visible non-logical variable or array element ElemSpec by one.", 710 amode:(decval(++) is det), 711 desc:html("\ 712 Decrements by one the value of ElemSpec that must be of type integer. 713<P> 714 If ElemSpec is an atom, it must specify a non-logical variable visible 715 from the caller module. 716<P> 717 If ElemSpec is a compound term, it must specify an element visible 718 array. All its arguments must be non negative integer smallers than the 719 bound specified with array/1/2 or variable/1. 720<P> 721"), 722 args:["ElemSpec" : "Atom or ground compound term whose arguments are non negative integers."], 723 exceptions:[4 : "ElemSpec is not instantiated.", 724 5 : "ElemSpec is a structure whose arguments are not all integers.", 725 5 : "ElemSpec is neither an atom nor a ground structure.", 726 5 : "The value or type of ElemSpec is not integer.", 727 6 : "Array index in ElemSpec is out of bounds.", 728 41 : "ElemSpec does not designate an existing array, variable or reference."], 729 eg:" 730Success: 731 [eclipse]: local(array(a(4), prolog)), 732 setval(a(0), -2), 733 decval(a(0)), 734 getval(a(0),X). 735 X = -3 736 yes. 737 738 [eclipse]: local(array(g(4, 5), integer)), 739 decval(g(3, 2)), 740 getval(g(3, 2), X). 741 X = -1 742 yes. 743 744 [eclipse]: setval(a, 3), 745 decval(a), 746 getval(a, X). 747 X = 2 748 yes. 749 750Error: 751 decval(X). (Error 4). 752 setval(a, 2.0), 753 decval(a). (Error 5). 754 local(array(a(2), float)), 755 decval(a(1)). (Error 5). 756 local(array(a(2))), 757 decval(a(2)). (Error 6). 758 decval(no_var). (Error 41). 759 decval(noarray(2, 4)). (Error 41). 760 761 762 763", 764 see_also:[getval / 2, incval / 1, array / 1, array / 2, variable / 1, setval / 2]]). 765 766:- comment(erase_array / 1, [ 767 summary:"Erases existing visible array, non-logical variable or reference.", 768 amode:(erase_array(++) is det), 769 desc:html("\ 770 Used to erase the visible array uniquely specified by ArraySpec. 771<P> 772 Also used to erase the existing non-logical variable or reference ArraySpec. 773 ArraySpec is of the form Atom/0, or just Atom. 774<P> 775 Erasing reclaims the memory occupied by the array or variable. 776"), 777 args:["ArraySpec" : "Of the form Atom/Integer or just atom."], 778 exceptions:[4 : "ArraySpec is not instantiated.", 779 5 : "ArraySpec is not an atom or of the form Atom/Integer.", 780 41 : "ArraySpec specifies an array, variable or reference which does not exist."], 781 eg:" 782Success: 783 local(array(a(4,3))), erase_array(a/2). 784 setval(i,1), erase_array(i). 785 setval(i,1), erase_array(i/0). 786 787Error: 788 erase_array(X). (Error 4). 789 local(array(a(4,2))), 790 erase_array(a(4,2)). (Error 5). 791 erase_array(no_array/1). (Error 41). 792 erase_array(no_array). (Error 41). 793 794 795 796", 797 see_also:[current_array / 2, array / 1, array / 2, variable / 1, setval / 2]]). 798 799:- comment(getval / 2, [ 800 summary:"Retrieves the value of the visible array element, non-logical variable or reference ElemSpec", 801 amode:(getval(++,-) is det), 802 desc:html("\ 803 If ElemSpec is the name of a visible non-logical variable, it unifies 804 the copied value of the variable with Value. 805<P> 806 If ElemSpec is a compound term, it must specify an element of a visible 807 non-logical array, all its arguments must be non negative integers smaller 808 than the bounds specified with array/1/2 or variable/1. The copied value 809 of the array element is unified with Value. 810<P> 811 If Element is the name of a reference, Value is unified with 812 the actual term the reference refers to (no copying involved). 813"), 814 args:["ElemSpec" : "Atom or ground compound term with non negative integer arguments.", "Value" : "Prolog term."], 815 exceptions:[4 : "ElemSpec is not ground.", 816 5 : "ElemSpec is neither an atom nor a structure whose arguments are integers.", 817 6 : "An array index in ElemSpec is out of bounds", 818 41 : "ElemSpec does not designate an existing array, variable or reference."], 819 eg:" 820Success: 821 local(array(a(4), float)), 822 setval(a(2), 2.0), 823 getval(a(2), 2.0). 824 setval(i, \"2\"), 825 getval(i, V)). (gives V = \"2\"). 826 827Failure: 828 local(array(a(2))), 829 setval(a(1), 8.6), 830 getval(a(1), 10.0). 831 setval(i, 3), 832 getval(i, 0)). 833 834Error: 835 getval(X, 1). (Error 4). 836 getval(a(X), 1). (Error 4). 837 getval(\"a\", V). (Error 5). 838 getval(a(2.0), V). (Error 5). 839 getval(a(-1), V). (Error 6). 840 getval(no_array(0), X). (Error 41). 841 getval(no_var, X). (Error 41). 842 843 844 845", 846 see_also:[decval / 1, incval / 1, array / 1, array / 2, variable / 1, setval / 2]]). 847 848:- comment(incval / 1, [ 849 summary:"Increments the contents of the visible non-logical variable or array element ElemSpec by one.", 850 amode:(incval(++) is det), 851 desc:html(" Increments the value of the element ElemSpec that must be of type 852 integer. 853 854<P> 855 If ElemSpec is an atom, it must specify a non-logical variable visible from 856 the caller module. 857<P> 858 If ElemSpec is a compound term, it must specify a visible array element. 859 all its arguments must be non negative integers smaller than the bounds 860 specified with array/1/2 or variable/1. 861"), 862 args:["ElemSpec" : "Atom or ground compound term with non negative integer arguments."], 863 exceptions:[4 : "ElemSpec is not instantiated.", 864 5 : "ElemSpec is a structure whose arguments are not all integers.", 865 5 : "ElemSpec is neither an atom nor a ground structure.", 866 5 : "The value or type of ElemSpec is not integer.", 867 6 : "Array index in ElemSpec is out of range.", 868 41 : "ElemSpec does not designate an existing array, variable or reference."], 869 eg:" 870Success: 871 [eclipse]: local(array(a(4), prolog)), 872 setval(a(1), -2), 873 incval(a(1)), 874 getval(a(1), X). 875 X = -1 876 yes. 877 878 [eclipse]: local(array(g(4), integer)), 879 incval(g(1)), 880 getval(g(1), X). 881 X = 1 882 yes. 883 884 [eclipse]: setval(count, 0), 885 repeat, 886 writeln(hello), 887 incval(count), 888 getval(count, X), 889 X >= 3, !. 890 hello 891 hello 892 hello 893 X = 3 894 yes. 895 896Error: 897 898 incval(X). (Error 4). 899 incval(a(2.0)). (Error 5). 900 setval(a, 2.0), incval(a). (Error 5). 901 local(array(a(2), float)), 902 incval(a(1)). (Error 5). 903 local(array(a(10), integer)), 904 incval(a(-2)). (Error 6). 905 incval(no_array(0)). (Error 41). 906 incval(no_var). (Error 41). 907 908 909 910", 911 see_also:[decval / 1, array / 1, array / 2, variable / 1, getval / 2, setval / 2]]). 912 913 914:- comment(array / 1, [ 915 summary:"Creates the untyped non-logical array Array.", 916 template:"local array(++Array)", 917 amode:(array(++) is det), 918 desc:html("\ 919 If Array is a compound term, a non-logical array (visible only in 920 the caller module) of type prolog is created. Its dimension is the 921 arity of the term Array and the size of each dimension is specified 922 by the corresponding argument of the term Array. The elements of 923 arrays of type prolog are initialised to free variables. 924<P> 925 The array indexes in the array range from 0 to the dimension minus one. 926 For example myarray create with <CODE>local array(myarray(3,4,5))</CODE> 927 contains 60 elements that may be accessed from myarray(0,0,0) 928 to myarray(2,3,4). 929<P> 930 The contents of the array persists across failures. 931 The value of the array elements can be changed with 932 setval/2 and retrieved with getval/2. Setting and retrieving terms 933 from a non-logical arrays involves copying the term each time. 934 In particular, if the term contains variables, they lose their 935 identity and are replaced with fresh ones. 936<P> 937 Notes: 938<P> 939 <CODE>local array(A)</CODE> is equivalent to <CODE>local array(A, prolog)</CODE>. 940"), 941 args:["Array" : "Ground compound term with integer arguments."], 942 exceptions:[4 : "Array is not ground.", 943 5 : "Array is not a structure with integer arguments.", 944 6 : "The ground structure Array has arguments that are integers not greater than 0.", 945 24: "The ground structure Array has arguments that are non-numbers.", 946 42 : "An array with the same name and dimension as Array already exists."], 947 eg:" 948Success: 949 local array(a(4)). 950 local array(b(2,3)). 951 local array(a(4)), array(a(4,1)). 952 953Error: 954 local array(X). (Error 4). 955 local array(a(6.0)). (Error 5). 956 local array(a(0)). (Error 6). 957 local array(a(-2)). (Error 6). 958 local array(a(4)), array(a(5)). (Warning 42). 959", 960 see_also:[current_array/2, array / 2, decval / 1, incval / 1, bag_create / 1, shelf_create/2, shelf_create/3, getval / 2, setval / 2]]). 961 962 963:- comment(array / 2, [ 964 summary:"Creates a non-logical array Array with given Type.", 965 template:"local array(+Array, +Type)", 966 amode:(array(++,+) is det), 967 desc:html("\ 968 If Array is a compound term, a non-logical array (visible only in 969 the caller module) of type prolog is created. Its dimension is the 970 arity of the term Array and the size of each dimension is specified 971 by the corresponding argument of the term Array. 972 The elements of the array are initialised depending on the type: 973 float, integer and byte arrays are initialised with 0 values, prolog 974 arrays are initialised with free variables. 975<P> 976 The array indexes in the array range from 0 to the dimension minus one. 977 For example myarray create with <CODE>local array(myarray(3,4,5), integer)</CODE> 978 contains 60 integers that may be accessed from myarray(0,0,0) to 979 myarray(2,3,4). 980<P> 981 The contents of the array persists across failures. 982 The value of the array elements can be changed with 983 setval/2 and retrieved with getval/2. Setting and retrieving terms 984 from a non-logical arrays involves copying the term each time. 985 In particular, if the term contains variables, they lose their 986 identity and are replaced with fresh ones. 987<P> 988 Notes: 989<P> 990 Re-declaring an existing array with the same dimension but different 991 sizes or type raises a warning. 992"), 993 args:["Array" : "Ground compound term with integer arguments.", 994 "Type": "One of the atoms: float, integer, byte, prolog"], 995 exceptions:[4 : "Array or Type is not ground.", 996 5 : "Array is not a structure with integer arguments.", 997 5 : "Type is not an atom.", 998 6 : "Type is not a valid type name.", 999 6 : "The ground structure Array has arguments that are integers not greater than 0.", 1000 24: "The ground structure Array has arguments that are non-numbers.", 1001 42 : "An array with the same name and dimension as Array already exists."], 1002 eg:" 1003Success: 1004 local array(a(4), prolog). 1005 local array(b(2,3), integer). 1006 local array(a(4), float), array(a(4,1), byte). 1007 1008Error: 1009 local array(X, prolog). (Error 4). 1010 local array(a(6.0), integer). (Error 5). 1011 local array(a(0), integer). (Error 6). 1012 local array(a(-2), integer). (Error 6). 1013 local array(a(4), integer), array(a(5), float). (Warning 42). 1014", 1015 see_also:[current_array/2, array / 2, decval / 1, incval / 1, bag_create / 1, shelf_create/2, shelf_create/3, getval / 2, setval / 2]]). 1016 1017 1018:- comment(variable / 1, [ 1019 summary:"Creates the untyped non-logical variable Name.", 1020 template:"local variable(+Name)", 1021 amode:(variable(+) is det), 1022 desc:html("\ 1023 If Name is an Atom, a non-logical variable (visible only in the 1024 caller module) is created. Its value is initialised to a free 1025 variable. The contents of the variable persists across failures. 1026 The value of a non-logical variable can be changed with 1027 setval/2 and retrieved with getval/2. Setting and retrieving terms 1028 from a non-logical variable involves copying the term each time. 1029 In particular, if the term contains variables, they lose their 1030 identity and are replaced with fresh ones. 1031<P> 1032 Notes: 1033<P> 1034 Declaring a variable twice is silently accepted. 1035"), 1036 args:["Name" : "An atom."], 1037 exceptions:[4 : "Name is not instantiated.", 1038 5 : "Name is not an atom."], 1039 eg:" 1040Success: 1041 :- local variable(a). 1042 :- local variable(count), variable(value). 1043 1044Error: 1045 :- local variable(X). (Error 4). 1046 :- local variable(6). (Error 5). 1047", 1048 see_also:[current_array/2, array/1, array / 2, decval / 1, incval / 1, bag_create / 1, getval / 2, setval / 2, reference/1, reference/2, variable/2]]). 1049 1050 1051:- comment(variable / 2, [ 1052 summary:"Creates the untyped non-logical variable Name.", 1053 template:"local variable(+Name, ?Init)", 1054 amode:(variable(+,?) is det), 1055 desc:html("\ 1056 A non-logical variable with name Name (visible only in the 1057 caller module) is created. Its value is initialised to Init. 1058 The contents of the variable persists across failures. 1059 The value of a non-logical variable can be changed with 1060 setval/2 and retrieved with getval/2. Setting and retrieving terms 1061 from a non-logical variable involves copying the term each time. 1062 In particular, if the term contains variables, they lose their 1063 identity and are replaced with fresh ones. 1064<P> 1065 Notes: 1066<P> 1067 Declaring a variable twice is silently accepted, and the second 1068 declaration is ignored. 1069"), 1070 args:["Name" : "An atom.", "Init":"Any term"], 1071 exceptions:[4 : "Name is not instantiated.", 1072 5 : "Name is not an atom."], 1073 eg:" 1074Success: 1075 :- local variable(a,[]). 1076 :- local variable(count,0), variable(value,colour(red)). 1077 1078Error: 1079 :- local variable(X, []). (Error 4). 1080 :- local variable(6, 0). (Error 5). 1081", 1082 see_also:[current_array/2, array/1, array / 2, decval / 1, incval / 1, bag_create / 1, getval / 2, setval / 2, reference/1, reference/2, variable/1]]). 1083 1084 1085:- comment(reference / 1, [ 1086 summary:"Creates a named reference called Name.", 1087 template:"local reference(+Name)", 1088 amode:(reference(+) is det), 1089 desc:html("\ 1090 This creates a named reference with the atomic name Name. A named 1091 reference can be used to hold a reference to a term in the same way 1092 as a logical variable. Unlike the non-logical variables, the value 1093 of a reference is not a copy, but identical to the original term it 1094 was set to. This implies that the value behaves logically, i.e. 1095 it disappears on backtracking, bindings to the variables inside it 1096 are undone on backtracking etc. A typical example of it use is global 1097 state that a set of predicates wants to share without having to 1098 pass an argument pair through all the predicate invocations. 1099<P> 1100 Changing the value of a reference is similar to changing an argument 1101 of a compound term using setarg/3. 1102<P> 1103 The initial value of a reference is the integer 0. To have a different 1104 initial value, use reference/2. 1105<P> 1106 There are no arrays of references, but the same effect can be 1107 achieved by storing a structure in a reference and using the 1108 structure's arguments. The arguments can then be accessed and 1109 modified using arg/3 and setarg/3 respectively. 1110<P> 1111 Note: Declaring a reference twice is silently accepted, and the second 1112 declaration is ignored. 1113"), 1114 args:["Name" : "An atom."], 1115 exceptions:[4 : "Name is not instantiated.", 1116 5 : "Name is not an atom."], 1117 eg:" 1118% comparison between references and nonlogical variables 1119 1120 [eclipse 1]: local reference(a), variable(b). 1121 1122 yes. 1123 [eclipse 2]: Term = p(X), setval(a, Term), getval(a, Y), Y == Term. 1124 X = X 1125 Y = p(X) 1126 Term = p(X) 1127 yes. 1128 [eclipse 3]: Term = p(X), setval(b, Term), getval(b, Y), Y == Term. 1129 1130 no (more) solution. 1131 1132% values of references are subject to backtracking: 1133 1134 [eclipse 4]: setval(a, 1), (setval(a, 2), getval(a, X); getval(a, Y)). 1135 X = 2 1136 Y = Y More? (;) 1137 1138 X = X 1139 Y = 1 1140 1141", 1142 see_also:[reference/2, setval/2, getval/2, setarg / 3, arg/3]]). 1143 1144 1145:- comment(reference / 2, [ 1146 summary:"Creates a named reference called Name with intial value Init.", 1147 template:"local reference(+Name, ++Init)", 1148 amode:(reference(+,++) is det), 1149 desc:html("\ 1150 This creates a named reference with the atomic name Name. A named 1151 reference can be used to hold a reference to a term in the same way 1152 as a logical variable. Unlike the non-logical variables, the value 1153 of a reference is not a copy, but identical to the original term it 1154 was set to. This implies that the value behaves logically, i.e. 1155 it disappears on backtracking, bindings to the variables inside it 1156 are undone on backtracking etc. A typical example of it use is global 1157 state that a set of predicates wants to share without having to 1158 pass an argument pair through all the predicate invocations. 1159<P> 1160 Changing the value of a reference is similar to changing an argument 1161 of a compound term using setarg/3. 1162<P> 1163 The initial value of the reference is Init, which must be a ground term. 1164<P> 1165 There are no arrays of references, but the same effect can be 1166 achieved by storing a structure in a reference and using the 1167 structure's arguments. The arguments can then be accessed and 1168 modified using arg/3 and setarg/3 respectively. 1169<P> 1170 Note: Declaring a reference twice is silently accepted, and the second 1171 declaration is ignored. 1172"), 1173 args:["Name" : "An atom.", "Init":"A ground term"], 1174 exceptions:[4 : "Name is not instantiated.", 1175 4 : "Init is not a ground term.", 1176 5 : "Name is not an atom."], 1177 eg:" 1178 1179 [eclipse 1]: local reference(a,0). 1180 1181 yes. 1182 [eclipse 2]: ( getval(a, Old), setval(a, 27), getval(a, New) 1183 ; getval(a, Then) ). 1184 Old = 0 1185 New = 27 1186 Then = Then 1187 Yes (0.00s cpu, solution 1, maybe more) ? ; 1188 1189 Old = Old 1190 New = New 1191 Then = 0 1192 Yes (0.00s cpu, solution 2) 1193 1194", 1195 see_also:[reference/1, setval/2, getval/2, setarg / 3, arg/3]]). 1196 1197 1198:- comment(setval / 2, [ 1199 summary:"Sets the value of a non-logical variable, array element, or reference to the value Value.", 1200 amode:(setval(++,?) is det), 1201 desc:html("\ 1202 If ElemSpec is the name of a visible non-logical variable, its 1203 value gets set to a copy of the term value. If there was no 1204 variable visible from the caller module, a local non-logical 1205 variable is created and its value is set. The value of a 1206 non-logical variable can be overwritten any number of times with 1207 any data type, including a free variable. Values of non-logical 1208 variables are copies of the original term and persist across failures. 1209<P> 1210 If ElemSpec is a compound term, it must specify a visible array element: 1211 all its argument must be non negative integers smaller than the bounds 1212 specified with array/1 or array/2. 1213 If the array has been created with array/2, then Value is restricted 1214 to the type given in the declaration; otherwise Value can have any type, 1215 including a free variable. Its value can be overwritten any number of times. 1216 Values of non-logical arrays are copies of the original term and persist 1217 across failures. 1218<P> 1219 If ElemSpec is the name of a visible reference, its value will be set 1220 to the term value. Unlike for non-logical variables, the value of a 1221 reference is the original term, not a copy. Setting the value of a 1222 reference is undone on backtracking, i.e. the value of the reference 1223 reverts to what it was before being changed. 1224"), 1225 args:["ElemSpec" : "Atom (non-logical variable or reference) or fully instantiated compound term with positive integer arguments (array element specification).", 1226 "Value" : "Prolog term."], 1227 exceptions:[4 : "ElemSpec is not ground", 4 : "ElemSpec is of an array of type integer, float or byte and Value is not instantiated", 5 : "the type of Value is not of the declared type of ElemSpec.", 5 : "ElemSpec is a structure whose arguments are not all integers.", 5 : "ElemSpec is neither an atom nor a ground structure.", 6 : "Array index in ElemSpec is out of bounds.", 41:"ElemSpec is an element of an array which does not exist."], 1228 eg:" 1229Success: 1230 local(array(a(4,3))), 1231 setval(a(0,0), 2), 1232 setval(a(1,2), \"string\"), 1233 % overwrite a(0,0) (= 2) with a free variable 1234 setval(a(0,0), X). 1235 local(array(a(4), float)), 1236 setval(a(0), 2.0), 1237 setval(a(3), -19.6). 1238 setval(i, 4). 1239 setval(j, 4), 1240 setval(j, \"string data\"). 1241 1242Error: 1243 setval(A, 2.0). (Error 4). 1244 setval(a(V), 2.0). (Error 4). 1245 setval(a(1.0), 2). (Error 5). 1246 setval(\"b(0)\", 2.0). (Error 5). 1247 local(array(a(4))), 1248 setval(a(-2), 2). (Error 6). 1249 local(array(a(9), integer)), 1250 setval(a(9), 4). (Error 6). 1251 setval(no_array(1), 2.0). (Error 41). 1252 1253 1254 1255", 1256 see_also:[decval / 1, erase_array / 1, incval / 1, array / 1, array / 2, variable / 1, getval / 2]]). 1257 1258:- comment(test_and_setval / 3, [ 1259 summary:"Test whether a non-logical variable has value Old and if so, set it to New.", 1260 amode:(test_and_setval(+,?,?) is semidet), 1261 desc:html("\ 1262 VarName must be the name of a non-logical variable (not an array 1263 element and not a reference). If the current value of this 1264 variable is not identical to Old, the predicate fails. If it is 1265 identical, the variable's value gets changed to the value New. 1266 Test and set is done as an atomic operation. 1267"), 1268 args:["VarName" : "An atom", "Old" : "A term", "New":"A term"], 1269 fail_if:"Fails it the current value of the variable is not identical to Old", 1270 exceptions:[4 : "VarName is not ground", 1271 5 : "VarName not an atom", 1272 5 : "VarName is the name of a reference", 1273 41: "VarName is not the name of a non-logical variable."], 1274 eg:" 1275Success: 1276 ?- setval(k, 3), test_and_setval(k, 3, 5). 1277 1278 wait_for_lock :- 1279 ( test_and_setval(lock, 0, 1) -> 1280 true 1281 ; 1282 wait_for_lock 1283 ). 1284 1285Fail: 1286 setval(k, 1), test_and_setval(k, 3, 5). 1287", 1288 see_also:[decval / 1, incval / 1, variable / 1, setval/2, getval / 2]]). 1289 1290 1291 1292 1293:- comment(store/1, [ 1294 summary:"Create a named store object which can store indexed data across failures", 1295 desc:html("\ 1296 This creates a 'store' object which provides indexed access to 1297 key-value pairs, and whose contents are unaffected by backtracking. 1298<P> 1299 A store is a persistent (w.r.t. backtracking) hash table. It can 1300 store arbitrary ECLiPSe terms under arbitrary ground keys. 1301<P> 1302 Stores can be referred to either by handle or by name. Whenever 1303 possible, handles should be used, because this naturally leads to 1304 robust, reentrant code, and avoids the danger of memory leaks. 1305 See store_create/1 for how to create stores with a handle. 1306<P> 1307 Named stores are identified by a functor. This is usually simply 1308 an atom, but in general it can be name/arity pair. 1309<P> 1310 When named stores are used, the visibility of the store name is 1311 local to the module where it was created. A named store never 1312 disappears, therefore, in order to free the associated memory, 1313 its contents should be erased when no longer needed. 1314<P> 1315 Duplicate store declarations are silently ignored. 1316 "), 1317 template:"local store(++Name)", 1318 amode:(store(++) is det), 1319 args:["Name":"An atom, or an atom/integer structure"], 1320 exceptions:[ 1321 4 : "Name is uninstantiated", 1322 5 : "Name is neither an atom nor an atom/integer structure"], 1323 eg:" 1324 1325 % A store with the simple, atomic name 'phone_numbers' 1326 1327 :- local store(phone_numbers). 1328 1329 main1 :- 1330 store_set(phone_numbers, name(peter,panther), data(1234,mobile)), 1331 store_set(phone_numbers, name(tom,tiger), data(4567,home)), 1332 stored_keys_and_values(phone_numbers, Contents), 1333 writeln(Contents). 1334 1335 1336 % A store identified by the functor foo/3 1337 1338 :- local store(foo/3). 1339 1340 main2 :- 1341 store_set(foo(_,_,_), key_1, value_1), 1342 store_set(foo(_,_,_), key_2, value_2), 1343 stored_keys_and_values(foo(_,_,_), Contents), 1344 writeln(Contents). 1345 ", 1346 see_also:[current_store/1, store_create/1, (local)/1, store_set/3, store_get/3, store_delete/2, 1347 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1348 store_erase/1, store_count/2] 1349 ]). 1350 1351 1352:- comment(store_create/1, [ 1353 summary:"Create an anonymous store object which can store indexed data across failures", 1354 desc:html("\ 1355 This creates a 'store' object which provides indexed access to 1356 key-value pairs, and whose contents are unaffected by backtracking. 1357<P> 1358 A store is a persistent (w.r.t. backtracking) hash table. It can 1359 store arbitrary ECLiPSe terms under arbitrary ground keys. 1360<P> 1361 Stores can be referred to either by handle or by name. Whenever 1362 possible, handles should be used, because this naturally leads to 1363 robust, reentrant code, and avoids the danger of memory leaks. 1364 A store disappears when the system backtracks over its creation, 1365 when the store handle gets garbage collected, or when it is 1366 explicitly destroyed. 1367<P> 1368 When named stores are used, the visibility of the store name is 1369 local to the module where it was created. A named store never 1370 disappears, therefore, in order to free the associated memory, 1371 its contents should be erased when no longer needed. 1372 "), 1373 amode:(store_create(-) is det), 1374 args:["StoreHandle":"A free variable"], 1375 exceptions:[5 : "StoreHandle is not a variable"], 1376 eg:" 1377 1378% Creating and using an 'anonymous store' 1379 1380 main2 :- 1381 store_create(Handle), 1382 store_set(Handle, name(peter,panther), data(1234,mobile)), 1383 store_set(Handle, name(tom,tiger), data(4567,home)), 1384 stored_keys_and_values(Handle, Contents), 1385 writeln(Contents). 1386 1387 1388% Creating and using a 'named store' 1389 1390 :- local store(phone_numbers). 1391 1392 main1 :- 1393 store_set(phone_numbers, name(peter,panther), data(1234,mobile)), 1394 store_set(phone_numbers, name(tom,tiger), data(4567,home)), 1395 stored_keys_and_values(phone_numbers, Contents), 1396 writeln(Contents). 1397 ", 1398 see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2, 1399 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1400 store_erase/1, store_count/2] 1401 ]). 1402 1403 1404:- comment(store_erase/1, [ 1405 summary:"Erase the contents of the specified store object", 1406 desc:html("\ 1407 This erases the contents of the store object and frees the associated 1408 memory. The store object itself remains valid and is equivalent to a 1409 newly created store. 1410<P> 1411 Note that anonymous stores (which are referred to by handle rather 1412 than name) are automatically erased and destroyed when their handle 1413 gets garbage collected, or when failing across their creation point. 1414<P> 1415 On the other hand, named stores should be explicitly erased, 1416 otherwise their contents will continue to occupy memory. 1417<P> 1418 Calling store_erase/1 is equivalent to deleting every entry in 1419 the store via store_delete/2. 1420<P> 1421 Note: If StoreHandle is not a handle, then it must be an atom or a 1422 compound term, and the store is identified by this term's toplevel 1423 functor together with the context module. 1424 . 1425 "), 1426 amode:(store_erase(+) is det), 1427 args:["StoreHandle":"A store handle or store name"], 1428 exceptions:[ 1429 4 : "StoreHandle is uninstantiated", 1430 5 : "StoreHandle is neither atom nor compound term nor store handle", 1431 45 : "StoreHandle is not the name of a store"], 1432 eg:" 1433 1434 ?- store_create(Handle), 1435 store_set(Handle, key, value), 1436 stored_keys_and_values(Handle, Data1), 1437 store_count(Handle, N1), 1438 store_erase(Handle), 1439 stored_keys_and_values(Handle, Data2), 1440 store_count(Handle, N2). 1441 1442 Handle = 'STORE'(16'002f4da0) 1443 Data1 = [key - value] 1444 N1 = 1 1445 Data2 = [] 1446 N2 = 0 1447 Yes (0.00s cpu) 1448 ", 1449 see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2, 1450 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1451 store_create/1, store_count/2] 1452 ]). 1453 1454:- comment(store_count/2, [ 1455 summary:"Retrieve the number of entries in a store object", 1456 desc:html("\ 1457 This returns the count of the number of entries in a store object. 1458 For an empty store, 0 (zero) is returned. 1459<P> 1460 Note: If StoreHandle is not a handle, then it must be an atom or a 1461 compound term, and the store is identified by this term's toplevel 1462 functor together with the context module. 1463 "), 1464 amode:(store_count(+,-) is det), 1465 args:["StoreHandle":"A store handle or store name", 1466 "Count":"Variable or integer"], 1467 exceptions:[ 1468 4 : "StoreHandle is uninstantiated", 1469 5 : "StoreHandle is neither atom nor compound term nor store handle", 1470 45 : "StoreHandle is not the name of a store"], 1471 eg:" 1472 1473 ?- store_create(Handle), 1474 store_count(Handle, N1), 1475 store_set(Handle, tom, 12345), 1476 store_count(Handle, N2), 1477 store_set(Handle, dick, 42376), 1478 store_count(Handle, N3), 1479 store_set(Handle, harry, 84223), 1480 store_count(Handle, N4), 1481 store_delete(Handle, dick), 1482 store_count(Handle, N5), 1483 store_erase(Handle), 1484 store_count(Handle, N6). 1485 1486 Handle = 'STORE'(16'002f4ef8) 1487 N1 = 0 1488 N2 = 1 1489 N3 = 2 1490 N4 = 3 1491 N5 = 2 1492 N6 = 0 1493 Yes (0.00s cpu) 1494 ", 1495 see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2, 1496 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1497 store_create/1, store_count/2] 1498 ]). 1499 1500:- comment(store_set/3, [ 1501 summary:"Make an entry into a store object", 1502 desc:html("\ 1503 This stores an arbitrary ECLiPSe term under a given key into 1504 the given store object. If an entry for this key already exists, 1505 it will be replaced by the new entry. 1506<P> 1507 The key can be arbitrarily complex, but must be a ground term. 1508 The value can be an arbitrary term, and may contain uninstantiated 1509 variables. Note that values are copied when being stored or 1510 retrieved, therefore a retrieved nonground value will contain 1511 fresh variables rather than the original ones (this is similar 1512 to the behaviour of bags, shelves and global variables). 1513<P> 1514 The complexity of the store operation is linear in both the size 1515 of the key and the value, since both are being copied. For indexing 1516 purposes, a hash value is computed from the key, and the full depth 1517 of the key is taken into account. 1518<P> 1519 Note: If StoreHandle is not a handle, then it must be an atom or a 1520 compound term, and the store is identified by this term's toplevel 1521 functor together with the context module. 1522<P> 1523 "), 1524 amode:(store_set(+,++,?) is det), 1525 args:["StoreHandle":"A store handle or store name", 1526 "Key":"A ground term", 1527 "Value":"An arbitrary term"], 1528 exceptions:[ 1529 4 : "StoreHandle is uninstantiated", 1530 4 : "Key is not ground", 1531 5 : "StoreHandle is neither atom nor compound term nor store handle", 1532 45 : "StoreHandle is not the name of a store"], 1533 eg:" 1534 1535 ?- store_create(Handle), 1536 store_set(Handle, tom, 12345), 1537 store_set(Handle, name(dick,tracy), phone(42376,home)), 1538 store_set(Handle, numbers:prime, [2,3,5,7|_More]), 1539 stored_keys_and_values(Handle, Data). 1540 1541 Handle = 'STORE'(16'003130e8) 1542 Data = [(numbers : prime) - [2, 3, 5, 7|_123], 1543 tom - 12345, 1544 name(dick, tracy) - phone(42376, home)] 1545 Yes (0.00s cpu) 1546 ", 1547 see_also:[store/1, (local)/1, store_erase/1, store_get/3, store_delete/2, 1548 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1549 store_create/1, store_count/2, store_inc/2] 1550 ]). 1551 1552 1553:- comment(store_get/3, [ 1554 summary:"Look up an entry in a store object", 1555 desc:html("\ 1556 This looks up an entry under a given key in a given store object. 1557 If an entry for this key exists, the corresponding value is returned, 1558 otherwise the predicate fails. 1559<P> 1560 The key can be arbitrarily complex, but must be a ground term. 1561 The value can be an arbitrary term, and may contain uninstantiated 1562 variables. Note that values are copied when being stored or 1563 retrieved, therefore a retrieved nonground value will contain 1564 fresh variables rather than the original ones (this is similar 1565 to the behaviour of bags, shelves and global variables). 1566<P> 1567 The complexity of the retrieval operation is linear in both the size 1568 of the key and the value, since the value is being copied and the key 1569 needs to be compared. For indexing purposes, a hash value is computed 1570 from the key, and the full depth of the key is taken into account. 1571<P> 1572 Note: If StoreHandle is not a handle, then it must be an atom or a 1573 compound term, and the store is identified by this term's toplevel 1574 functor together with the context module. 1575<P> 1576 "), 1577 amode:(store_get(+,++,-) is semidet), 1578 args:["StoreHandle":"A store handle or store name", 1579 "Key":"A ground term", 1580 "Value":"A variable or arbitrary term"], 1581 fail_if:"The store does not contain an entry for Key", 1582 exceptions:[ 1583 4 : "StoreHandle is uninstantiated", 1584 4 : "Key is not ground", 1585 5 : "StoreHandle is neither atom nor compound term nor store handle", 1586 45 : "StoreHandle is not the name of a store"], 1587 eg:" 1588 1589 ?- store_create(Handle), 1590 store_set(Handle, tom, 12345), 1591 store_set(Handle, name(dick,tracy), phone(42376,home)), 1592 store_set(Handle, numbers:prime, [2,3,5,7|_More]), 1593 store_get(Handle, tom, Value1), 1594 store_get(Handle, name(dick,tracy), Value2), 1595 store_get(Handle, numbers:prime, Value3). 1596 1597 Handle = 'STORE'(16'001b3c50) 1598 Value1 = 12345 1599 Value2 = phone(42376, home) 1600 Value3 = [2, 3, 5, 7|_More] 1601 Yes (0.00s cpu) 1602 1603 1604 ?- store_create(Handle), 1605 store_set(Handle, tom, 12345), 1606 store_get(Handle, harry, Value). 1607 1608 No (0.00s cpu) 1609 ", 1610 see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_delete/2, 1611 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1612 store_create/1, store_count/2, store_inc/2] 1613 ]). 1614 1615:- comment(store_contains/2, [ 1616 summary:"Check for an entry in a store object", 1617 desc:html("\ 1618 This checks whether a given store object contains an entry for a 1619 given key. If so, the predicate succeeds, otherwise it fails. 1620<P> 1621 The key can be arbitrarily complex, but must be a ground term. 1622<P> 1623 The complexity of this operation is linear in the size 1624 of the key, since the key needs to be compared. For indexing purposes, 1625 a hash value is computed from the key, and the full depth of the key 1626 is taken into account. 1627<P> 1628 Note: If StoreHandle is not a handle, then it must be an atom or a 1629 compound term, and the store is identified by this term's toplevel 1630 functor together with the context module. 1631<P> 1632 "), 1633 amode:(store_contains(+,++) is semidet), 1634 args:["StoreHandle":"A store handle or store name", 1635 "Key":"A ground term"], 1636 fail_if:"The store does not contain an entry for Key", 1637 exceptions:[ 1638 4 : "StoreHandle is uninstantiated", 1639 4 : "Key is not ground", 1640 5 : "StoreHandle is neither atom nor compound term nor store handle", 1641 45 : "StoreHandle is not the name of a store"], 1642 eg:" 1643 1644 ?- store_create(Handle), 1645 store_set(Handle, tom, 12345), 1646 store_contains(Handle, tom). 1647 1648 Yes (0.00s cpu) 1649 1650 1651 ?- store_create(Handle), 1652 store_set(Handle, tom, 12345), 1653 store_contains(Handle, harry). 1654 1655 No (0.00s cpu) 1656 ", 1657 see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_delete/2, 1658 store_get/3, stored_keys/2, stored_keys_and_values/2, 1659 store_create/1, store_count/2] 1660 ]). 1661 1662:- comment(store_delete/2, [ 1663 summary:"Delete an entry in a store object", 1664 desc:html("\ 1665 This deletes any entry for a given key in a given store object. 1666 If the store does not contain such an entry, the predicate 1667 silently succeeds anyway. 1668<P> 1669 The key can be arbitrarily complex, but must be a ground term. 1670<P> 1671 The complexity of this operation is linear in the size 1672 of the key, since the key needs to be compared. For indexing purposes, 1673 a hash value is computed from the key, and the full depth of the key 1674 is taken into account. 1675<P> 1676 Note: If StoreHandle is not a handle, then it must be an atom or a 1677 compound term, and the store is identified by this term's toplevel 1678 functor together with the context module. 1679<P> 1680 "), 1681 amode:(store_delete(+,++) is det), 1682 args:["StoreHandle":"A store handle or store name", 1683 "Key":"A ground term"], 1684 exceptions:[ 1685 4 : "StoreHandle is uninstantiated", 1686 4 : "Key is not ground", 1687 5 : "StoreHandle is neither atom nor compound term nor store handle", 1688 45 : "StoreHandle is not the name of a store"], 1689 eg:" 1690 1691 ?- store_create(Handle), 1692 store_set(Handle, tom, 12345), 1693 stored_keys_and_values(Handle, Before), 1694 store_delete(Handle, tom), 1695 stored_keys_and_values(Handle, After). 1696 1697 Handle = 'STORE'(16'001b3d40) 1698 Before = [tom - 12345] 1699 After = [] 1700 Yes (0.00s cpu) 1701 1702 ?- store_create(Handle), 1703 store_set(Handle, tom, 12345), 1704 store_delete(Handle, tom), 1705 store_delete(Handle, tom). 1706 1707 Yes (0.00s cpu) 1708 ", 1709 see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_contains/2, 1710 store_get/3, stored_keys/2, stored_keys_and_values/2, 1711 store_create/1, store_count/2] 1712 ]). 1713 1714:- comment(stored_keys/2, [ 1715 summary:"Retrieve all keys stored in a store object", 1716 desc:html("\ 1717 This retrieves a list of all keys under which entries are stored 1718 in the given store object. If the store is empty, the empty list 1719 is returned. 1720<P> 1721 The order of the keys in the returned list is undefined. 1722<P> 1723 The complexity of this operation is linear in the size of all keys, 1724 since they need to be copied. 1725<P> 1726 Note: If StoreHandle is not a handle, then it must be an atom or a 1727 compound term, and the store is identified by this term's toplevel 1728 functor together with the context module. 1729 "), 1730 amode:(stored_keys(+,-) is det), 1731 args:["StoreHandle":"A store handle or store name", 1732 "Keys":"A variable or list"], 1733 exceptions:[ 1734 4 : "StoreHandle is uninstantiated", 1735 5 : "StoreHandle is neither atom nor compound term nor store handle", 1736 45 : "StoreHandle is not the name of a store"], 1737 eg:" 1738 1739 ?- store_create(Handle), 1740 store_set(Handle, tom, 12345), 1741 store_set(Handle, name(dick,tracy), phone(42376,home)), 1742 store_set(Handle, numbers:prime, [2,3,5,7|_More]), 1743 stored_keys(Handle, Keys). 1744 1745 Handle = 'STORE'(16'003130e8) 1746 Keys = [numbers:prime, tom, name(dick, tracy)] 1747 Yes (0.00s cpu) 1748 ", 1749 see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_contains/2, 1750 store_get/3, store_delete/2, stored_keys_and_values/2, 1751 store_create/1, store_count/2] 1752 ]). 1753 1754:- comment(stored_keys_and_values/2, [ 1755 summary:"Retrieve all data stored in a store object", 1756 desc:html("\ 1757 This retrieves a list of all key/value pairs which are stored 1758 in the given store object. If the store is empty, the empty list 1759 is returned. Otherwise, a list of Key - Value terms is returned. 1760<P> 1761 The order of the returned list is undefined. 1762<P> 1763 The complexity of this operation is linear in the size of all keys 1764 and values, since they need to be copied. 1765<P> 1766 Note: If StoreHandle is not a handle, then it must be an atom or a 1767 compound term, and the store is identified by this term's toplevel 1768 functor together with the context module. 1769<P> 1770 "), 1771 amode:(stored_keys_and_values(+,-) is det), 1772 args:["StoreHandle":"A store handle or store name", 1773 "KeysValues":"A variable or list"], 1774 exceptions:[ 1775 4 : "StoreHandle is uninstantiated", 1776 5 : "StoreHandle is neither atom nor compound term nor store handle", 1777 45 : "StoreHandle is not the name of a store"], 1778 eg:" 1779 1780 ?- store_create(Handle), 1781 store_set(Handle, tom, 12345), 1782 store_set(Handle, name(dick,tracy), phone(42376,home)), 1783 store_set(Handle, numbers:prime, [2,3,5,7|_More]), 1784 stored_keys_and_values(Handle, Data). 1785 1786 Handle = 'STORE'(16'003130e8) 1787 Data = [(numbers : prime) - [2, 3, 5, 7|_More], 1788 tom - 12345, 1789 name(dick, tracy) - phone(42376, home)] 1790 Yes (0.00s cpu) 1791 1792 ?- store_create(Handle), 1793 stored_keys_and_values(Handle, Data). 1794 1795 Handle = 'STORE'(16'003130e8) 1796 Data = [] 1797 Yes (0.00s cpu) 1798 ", 1799 see_also:[store/1, (local)/1, store_erase/1, store_set/3, store_contains/2, 1800 store_get/3, store_delete/2, stored_keys/2, 1801 store_create/1, store_count/2] 1802 ]). 1803 1804:- comment(store_inc/2, [ 1805 summary:"Increment an integral entry within a store object", 1806 desc:html("\ 1807 This looks up an entry under a given key in a given store object, and 1808 if such an entry exists, and is of integer type, it is incremented by 1809 one. If no entry exists, an entry with integer value 1 is created. 1810<P> 1811 This predicate is a shorthand for: 1812<PRE> 1813 store_inc(Handle, Key) :- 1814 ( store_get(Handle, Key, C0) -> 1815 C1 is C0 + 1, 1816 store_set(Handle, Key, C1) 1817 ; 1818 store_set(Handle, Key, 1) 1819 ). 1820</PRE> 1821 Note: If StoreHandle is not a handle, then it must be an atom or a 1822 compound term, and the store is identified by this term's toplevel 1823 functor together with the context module. 1824 "), 1825 amode:(store_inc(+,++) is det), 1826 args:["StoreHandle":"A store handle or store name", 1827 "Key":"A ground term"], 1828 exceptions:[ 1829 4 : "StoreHandle is uninstantiated", 1830 4 : "Key is not a ground term", 1831 5 : "StoreHandle is neither atom nor compound term nor store handle", 1832 45 : "StoreHandle is not the name of a store"], 1833 eg:" 1834 ?- store_create(Handle), 1835 store_set(Handle, count, 7), 1836 store_inc(Handle, count), 1837 store_get(Handle, count, N). 1838 Handle = 'STORE'(16'00334e20) 1839 N1 = 8 1840 Yes (0.00s cpu) 1841 1842 ?- store_create(Handle), 1843 store_inc(Handle, foo), 1844 store_get(Handle, foo, N). 1845 Handle = 'STORE'(16'00334e20) 1846 N = 1 1847 Yes (0.00s cpu) 1848 ", 1849 see_also:[store/1, (local)/1, store_set/3, store_get/3, store_delete/2, 1850 store_contains/2, stored_keys/2, stored_keys_and_values/2, 1851 store_create/1, store_count/2] 1852 ]). 1853 1854:- comment(current_store/1, [ 1855 summary:"StoreName is a visible store name", 1856 desc:html("\ 1857 Used to check whether StoreName is the name of a visible store, 1858 or to enumerate all visible store names in the context module. 1859<P> 1860 Note that this predicate will only accept/generate store names 1861 that have been created with local/1, store/1, not anonymous 1862 store handles created via store_create/1. 1863</PRE> 1864 Note: StoreHandle gets unified with an atom or a compound term, 1865 and the store is identified by this term's toplevel functor 1866 together with the context module. 1867 "), 1868 amode:(current_store(+) is semidet), 1869 amode:(current_store(-) is nondet), 1870 args:["StoreHandle":"A variable or a store name (atom or compound)"], 1871 fail_if:"StoreName is not a visible store name", 1872 exceptions:[ 1873 5 : "StoreHandle is neither atom nor compound term nor variable"], 1874 eg:" 1875 :- local store(shed). 1876 :- local store(warehouse/3). 1877 1878 ?- current_store(shed). 1879 Yes (0.00s cpu) 1880 1881 ?- current_store(heap). 1882 No (0.00s cpu) 1883 1884 ?- current_store(X). 1885 X = shed 1886 More (0.00s cpu) ? ; 1887 1888 X = warehouse(_184, _185, _186) 1889 More (0.00s cpu) ? ; 1890 1891 No (0.00s cpu) 1892 ", 1893 see_also:[store/1, (local)/1] 1894 ]).