Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The <code>(-)/2</code> to represent difference lists is a rather uncommon convention. In older books, another operator <code>(\)/2</code> was used too.</p> <p>Many prefer to use two separate arguments instead. There are several advantages compared to using an operator:</p> <ol> <li><p>The predicate cannot accidentally be used with an uninstantiated variable for the argument. Think of calling <code>q(A, X)</code> in place of <code>q(A, X-[])</code>.</p></li> <li><p>Execution is even a bit more efficient when using two arguments. Many systems, like SWI, have to create each <code>(-)/2</code> structure dynamically.</p></li> </ol> <p>Nevertheless, there is also another way to use difference lists, which is often less error-prone: You might use a <a href="/questions/tagged/dcg" class="post-tag" title="show questions tagged &#39;dcg&#39;" rel="tag">dcg</a> for this purpose.</p> <p>In fact, there are two errors in the program, one of which is caused by the way how difference list are handled. The other error is that the program does not handle end-of-file. It would be better to use <code>end_of_file</code> in place of <code>end</code>. But that's a superficial thing you would have found yourself sooner or later.</p> <p>The other, more subtle error is due to the interaction between difference lists and the cut. I am not a big fan of cuts, but let's look into that rule. A cut cuts after everything to its left-hand-side has been executed.</p> <pre><code>q(end_of_file,X-X) :- !. </code></pre> <p>The first argument is the atom <code>end_of_file</code>. Since we are using <code>q/2</code> only with the result of <code>read/1</code> as first argument, this can only be a comparison. So we are at the end of the file (or stream). Then, however, there are further things that must hold. And only if those succeed as well, will the cut be executed: The second argument must be a <code>(-)/2</code> (ok, in all places there is a minus at its place). And then: The two arguments of <code>(-)/2</code> must be the same (must unify). Why? We are at the end of the file, but if those arguments do not unify, the other rule will be tried.</p> <p>When does this happen? Here is such a nasty case:</p> <pre><code>p([X,Y,Z]). </code></pre> <p>And simply enter a single constant, say <code>my_constant.</code> and then press <kbd>Cntrl-d</kbd> or <kbd>Cntrl+z</kbd>. What should <code>p/1</code> do in such a case? Ideally, it would fail after you finished the input. However, it will wait for further input.</p> <p>The reason is the inappropriate placing of the cut. We say that <code>p/1</code> is not <strong>steadfast</strong>. This is a common error in Prolog programs. I can only recommend to reduce the usage of cuts and the adoption of DCGs. With DCGs, this cannot happen:</p> <pre><code>p2(X) :- read(A), phrase(q2(A),X). q2(end_of_file) --&gt; !. q2(A) --&gt; [A], {read(B)}, q2(B). </code></pre> <p>With DCGs, the cut is executed regardless of the argument of <code>p/1</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload