3

I'm doing this to emulate global variables:

update_queue(NewItem) :-
    global_queue(Q),
    retractall(global_queue(Q)),
    append(Q, [NewItem], NewQ),
    assert(global_queue(NewQ)).

Is there another way? (Besides passing the variables as arguments, that is). Not necessarily more efficient, I'm just curious.

false
  • 10,264
  • 13
  • 101
  • 209
Xarnite
  • 87
  • 3

1 Answers1

6

In SWI-Prolog, there is also nb_setval/2 and b_setval/2 (and corresponding "_getval/2"). Use time/1 to see if that is more efficient. Also a comment on the queue representation: If you represent the initial queue as a pair of variables Q-Q, you can append an element in constant time with:

insert_q0_q(E, Q-[E|Rest], Q-Rest).

that is, you append an element E to the queue by further instantiating the tail (i.e., the second element of the pair), and the new tail is again a free variable. I leave removing an element from the front (also in constant time) as an exercise; hint: when the first element of the pair is a variable, the queue in this representation is empty. Generally, global variables complicate debugging considerably, since you then cannot test the predicates in isolation. As an alternative to passing the queue as arguments (which you already mentioned), consider using DCG notation to thread it through implicitly. This often makes the code more readable, especially if only a small subset of predicates needs to access the "global" arguments.

mat
  • 40,498
  • 3
  • 51
  • 78
  • As to nb_setval/2: This construct is very ill-defined. That is, you really have to know the very precise current details of SWI in order to use it reliably. However, at the very next release things might change — and they did change in the past several times. – false Oct 06 '12 at 10:28