<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.visual-prolog.com/index.php?action=history&amp;feed=atom&amp;title=Language_Reference%2FSuspending_Predicates</id>
	<title>Language Reference/Suspending Predicates - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.visual-prolog.com/index.php?action=history&amp;feed=atom&amp;title=Language_Reference%2FSuspending_Predicates"/>
	<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;action=history"/>
	<updated>2026-05-26T12:51:33Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;diff=4932&amp;oldid=prev</id>
		<title>Thomas Linder Puls: Category</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;diff=4932&amp;oldid=prev"/>
		<updated>2024-04-16T12:58:59Z</updated>

		<summary type="html">&lt;p&gt;Category&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 14:58, 16 April 2024&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l480&quot;&gt;Line 480:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 480:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Input parameters and variables are represented as facts with their original type. In some places the address of such facts are needed (e.g., &amp;lt;vp&amp;gt;ChannelPtr&amp;lt;/vp&amp;gt; in the call to &amp;lt;vp&amp;gt;openChannel&amp;lt;/vp&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Input parameters and variables are represented as facts with their original type. In some places the address of such facts are needed (e.g., &amp;lt;vp&amp;gt;ChannelPtr&amp;lt;/vp&amp;gt; in the call to &amp;lt;vp&amp;gt;openChannel&amp;lt;/vp&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Output parameters (of the predicate itself) are received and stored as a pointerTo{...} fact. In some cases, it may be necessary to dereference the pointer (does not occur in this example).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Output parameters (of the predicate itself) are received and stored as a pointerTo{...} fact. In some cases, it may be necessary to dereference the pointer (does not occur in this example).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Language|{{PAGENAME}}]]&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Thomas Linder Puls</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;diff=4918&amp;oldid=prev</id>
		<title>Thomas Linder Puls: Released</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;diff=4918&amp;oldid=prev"/>
		<updated>2024-01-11T12:01:14Z</updated>

		<summary type="html">&lt;p&gt;Released&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 14:01, 11 January 2024&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{languageReferenceNavbar|Suspending Predicates}}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{languageReferenceNavbar|Suspending Predicates}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;{{Template:NonReleased}}&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The purpose of &amp;#039;&amp;#039;&amp;#039;suspending&amp;#039;&amp;#039;&amp;#039; predicates is to support asynchronous programming, parallelism, coroutines, etc.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The purpose of &amp;#039;&amp;#039;&amp;#039;suspending&amp;#039;&amp;#039;&amp;#039; predicates is to support asynchronous programming, parallelism, coroutines, etc.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Thomas Linder Puls</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;diff=4893&amp;oldid=prev</id>
		<title>Thomas Linder Puls: Suspending predicates (initial)</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Language_Reference/Suspending_Predicates&amp;diff=4893&amp;oldid=prev"/>
		<updated>2024-01-04T13:03:12Z</updated>

		<summary type="html">&lt;p&gt;Suspending predicates (initial)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{languageReferenceNavbar|Suspending Predicates}}&lt;br /&gt;
&lt;br /&gt;
{{Template:NonReleased}}&lt;br /&gt;
&lt;br /&gt;
The purpose of &amp;#039;&amp;#039;&amp;#039;suspending&amp;#039;&amp;#039;&amp;#039; predicates is to support asynchronous programming, parallelism, coroutines, etc.&lt;br /&gt;
&lt;br /&gt;
A suspending predicate can suspend its execution and resume it later when &amp;#039;possible&amp;#039; or &amp;#039;feasible&amp;#039;.  In an asynchronous context, a suspending predicate suspends its execution when it is waiting for an asynchronous operation to complete, allowing other operations to proceed concurrently.&lt;br /&gt;
&lt;br /&gt;
A key advantage of suspending predicates is that they do not block threads while in suspended state, thus enabling efficient utilization of resources. This feature makes them particularly useful in situations where multiple tasks are being executed concurrently.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
{{Example|&lt;br /&gt;
We want to have a loop that reads messages from a &amp;lt;vp&amp;gt;webSocket&amp;lt;/vp&amp;gt; and echoes them back to the sender.&lt;br /&gt;
Most of the time this loop would be waiting for some operation to complete; notably waiting for an incoming message.  With synchronous code this would mean that a thread would be blocked most of its lifetime, consuming the resources of a thread which doesn&amp;#039;t really do much.&lt;br /&gt;
&lt;br /&gt;
Using asynchronous programming with promises/futures, the code could look like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class predicates&lt;br /&gt;
    echoLoop_async : (webSocket WebSocket) -&amp;gt; future{unit}.&lt;br /&gt;
clauses&lt;br /&gt;
    echoLoop_async(WebSocket) =&lt;br /&gt;
        WebSocket:readMessage_async():thenDo(&lt;br /&gt;
            { (Message) = F :-&lt;br /&gt;
                if webSocket::close(Status, Reason) = Message then&lt;br /&gt;
                    if 0 &amp;lt;&amp;gt; Status then&lt;br /&gt;
                        stdio::writef(&amp;quot;Closed:% %\n&amp;quot;, Status, Reason)&lt;br /&gt;
                    end if,&lt;br /&gt;
                    F = future::newUnit()&lt;br /&gt;
                else&lt;br /&gt;
                    F =&lt;br /&gt;
                        WebSocket:writeMessage_async(Message):thenDo(&lt;br /&gt;
                            {  =&lt;br /&gt;
                                echoLoop_async(WebSocket) %&lt;br /&gt;
                            })&lt;br /&gt;
                end if&lt;br /&gt;
            }).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
Such code has several flaws, but here we will just notice that it is both difficult to write and read.&lt;br /&gt;
&lt;br /&gt;
With suspending predicates, the code can be written like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class predicates&lt;br /&gt;
    echoLoop_async : (webSocket WebSocket) suspending.&lt;br /&gt;
clauses&lt;br /&gt;
    echoLoop_async(WebSocket) :-&lt;br /&gt;
        Message = WebSocket:readMessage_async(),&lt;br /&gt;
        if webSocket::close(Status, Reason) = Message then&lt;br /&gt;
            if 0 &amp;lt;&amp;gt; Status then&lt;br /&gt;
                stdio::writef(&amp;quot;Closed:% %\n&amp;quot;, Status, Reason)&lt;br /&gt;
            end if&lt;br /&gt;
        else&lt;br /&gt;
            WebSocket:writeMessage_async(Message),&lt;br /&gt;
            echoLoop_async(WebSocket)&lt;br /&gt;
        end if.&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
It is clear that this code looks exactly like synchronous code, and is therefore just as easy to read and write. But while the code looks like synchronous code the execution is quite different as described below.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Language changes ===&lt;br /&gt;
&lt;br /&gt;
The only new language entity is the keyword &amp;lt;vp&amp;gt;suspending&amp;lt;/vp&amp;gt; which is added to a predicate declaration and/or predicate domain.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
domains&lt;br /&gt;
    webSocket_asyncOp = (webSocket WebSocket) suspending.&lt;br /&gt;
class predicates&lt;br /&gt;
    echoLoop_async : (webSocket WebSocket) suspending.&lt;br /&gt;
    tryCalculate : () -&amp;gt; integer Result determ suspending.&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, a suspending predicate can pause its execution and resume it later when it&amp;#039;s &amp;#039;possible&amp;#039; or &amp;#039;feasible.&amp;#039; The use of quotes highlights that the programming language itself doesn&amp;#039;t specify the exact conditions for suspension or resumption. However, in certain contexts, the reasons become evident. For instance, when used for asynchronous operations, suspension occurs while waiting for those operations to finish, and execution resumes once they have completed.&lt;br /&gt;
&lt;br /&gt;
=== Suspension ===&lt;br /&gt;
&lt;br /&gt;
A suspending predicate has the ability to suspend its execution for various reasons, typically when waiting for an asynchronous operation to complete.&lt;br /&gt;
&lt;br /&gt;
The key concern with suspension is understanding what happens when execution is paused. For instance, how does it differ from blocking in a synchronous operation? In essence, when a predicate suspends, the thread that was executing its code can be utilized for other tasks. Consequently, a suspended predicate does not &amp;#039;tie up&amp;#039; a thread.&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s important to note that the execution of suspending predicates cannot be solely viewed in the context of a single thread performing a sequence of actions. Instead, a suspending predicate may consist of parts that are executed by different threads, and these threads may also perform other tasks in between executing the parts associated with a particular suspending predicate.&lt;br /&gt;
&lt;br /&gt;
=== Submitting suspending predicates ===&lt;br /&gt;
&lt;br /&gt;
Suspending predicates can seamlessly invoke other suspending predicates and non-suspending predicates.  However, there are certain limitations on calling non-suspending &amp;lt;vp&amp;gt;nondeterm&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;multi&amp;lt;/vp&amp;gt; predicates.&lt;br /&gt;
&lt;br /&gt;
When you call a non-suspending predicate, its result is immediately available when the calling thread returns from the call. In contrast, calling a suspending predicate doesn&amp;#039;t provide an immediate result because the predicate may suspend execution until an asynchronous operation is complete. Consequently, a non-suspending predicate cannot directly call a suspending one.&lt;br /&gt;
&lt;br /&gt;
Instead, suspending predicates are &amp;#039;&amp;#039;&amp;#039;submitted&amp;#039;&amp;#039;&amp;#039; for execution within a designated execution context, typically using &amp;lt;vp&amp;gt;future::submit&amp;lt;/vp&amp;gt; or &amp;lt;vp&amp;gt;future::submit_unit&amp;lt;/vp&amp;gt;. These routines submits the suspending predicate to an &amp;lt;vp&amp;gt;executionContext&amp;lt;/vp&amp;gt; and returns a &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt; that completes with the result of the suspending predicate. As a result, when a suspending predicate is submitted for execution, the calling thread can continue to perform other tasks while the predicate is being processed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Example|Here we submit the &amp;lt;vp&amp;gt;echoLoop_async&amp;lt;/vp&amp;gt; predicate from above and wait for the completion:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
        Future = future::submit_unit({ :- echoLoop_async(WebSocket) }),&lt;br /&gt;
        _ = Future:get(),&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/vip&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== Await ===&lt;br /&gt;
&lt;br /&gt;
The semantics of a suspending predicate adhere to the same principles as a non-suspending predicate, with the added capability to suspend and later resume execution.&lt;br /&gt;
&lt;br /&gt;
For instance, consider a clause like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    p_susp() :-&lt;br /&gt;
        q_susp().&lt;br /&gt;
        r_susp().&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this scenario, the code will initially call &amp;lt;vp&amp;gt;q_susp&amp;lt;/vp&amp;gt;, and only after &amp;lt;vp&amp;gt;q_susp&amp;lt;/vp&amp;gt; has finished will &amp;lt;vp&amp;gt;r_susp&amp;lt;/vp&amp;gt; be called. During this seemingly sequential execution, the execution may suspend multiple times, but &amp;lt;vp&amp;gt;r_susp&amp;lt;/vp&amp;gt; won&amp;#039;t be invoked until &amp;lt;vp&amp;gt;q_susp&amp;lt;/vp&amp;gt; has completed.&lt;br /&gt;
&lt;br /&gt;
However, in scenarios involving asynchronous operations, it can be advantageous to initiate multiple independent operations in parallel and then wait for their completion before proceeding with the utilization of their results.&lt;br /&gt;
&lt;br /&gt;
{{Example|For example, consider this code:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    combinePages_susp() = Combined :-&lt;br /&gt;
        Page1 = fetch_susp(&amp;quot;https://.....&amp;quot;),&lt;br /&gt;
        Page2 = fetch_susp(&amp;quot;https://.....&amp;quot;),&lt;br /&gt;
        Combined = combine(Page1, Page2).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
In this code, the fetching of &amp;lt;vp&amp;gt;Page2&amp;lt;/vp&amp;gt; won&amp;#039;t commence until the fetching of &amp;lt;vp&amp;gt;Page1&amp;lt;/vp&amp;gt; has completed.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
To handle such cases, you can &amp;lt;vp&amp;gt;submit&amp;lt;/vp&amp;gt; a suspending call to the &amp;#039;background&amp;#039; and obtain a &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt; that can be &amp;lt;vp&amp;gt;await&amp;lt;/vp&amp;gt;ed. &lt;br /&gt;
&lt;br /&gt;
{{Example|Here&amp;#039;s an example based on the previous clause:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    combinePages_susp() = Combined :-&lt;br /&gt;
        Page1Future = future::submit( { = fetch_susp(&amp;quot;https://.....&amp;quot;) }),&lt;br /&gt;
        Page2 = fetch_susp(&amp;quot;https://.....&amp;quot;),&lt;br /&gt;
        Page1 = Page1Future:await(),&lt;br /&gt;
        Combined = combine(Page1, Page2).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
The first fetch is submitted to the background, and we obtain a &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt; for it. We do not create a &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt; for the second fetch because we have to wait for all fetches to complete anyway, so the last one might just as well be handled in the direct way.&lt;br /&gt;
After the fetch of &amp;lt;vp&amp;gt;Page2&amp;lt;/vp&amp;gt; has finished, we &amp;lt;vp&amp;gt;await&amp;lt;/vp&amp;gt; the completion of the fetch of &amp;lt;vp&amp;gt;Page1&amp;lt;/vp&amp;gt;. Then we combine the pages as before.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== waitSet ===&lt;br /&gt;
&lt;br /&gt;
Using the strategy outlined above, we would wait sequentially for the background operations to complete. However, this approach is suboptimal when one or more of the background operations completes with an exception. There are two key issues with this:&lt;br /&gt;
&lt;br /&gt;
* We won&amp;#039;t &amp;#039;notice&amp;#039; the exception until we &amp;lt;vp&amp;gt;await&amp;lt;/vp&amp;gt; that specific operation, which means we may need to wait on several other operations to complete before detecting the exception.&lt;br /&gt;
* We won&amp;#039;t &amp;lt;vp&amp;gt;cancel&amp;lt;/vp&amp;gt; the other operations even though their results won&amp;#039;t be used.&lt;br /&gt;
&lt;br /&gt;
To resolve these issues, we can employ a &amp;lt;vp&amp;gt;waitSet&amp;lt;/vp&amp;gt;, which is a set of &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt;s to wait for. The &amp;lt;vp&amp;gt;waitSet&amp;lt;/vp&amp;gt; itself is also a &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt; that completes when either all the &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt;s in the set have completed successfully or when one of them has completed with an exception (whichever occurs first). If an exception occurs, the &amp;lt;vp&amp;gt;waitSet&amp;lt;/vp&amp;gt; will &amp;lt;vp&amp;gt;cancel&amp;lt;/vp&amp;gt; all the remaining non-completed futures and complete itself with the same exception.&lt;br /&gt;
&lt;br /&gt;
{{Example|Here&amp;#039;s an example using a &amp;lt;vp&amp;gt;waitSet&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    combinePages_susp() = Combined :-&lt;br /&gt;
        WaitSet = waitSet::new(),&lt;br /&gt;
        Page1Future = WaitSet:submit( { = fetch_susp(&amp;quot;https://.....&amp;quot;) }),&lt;br /&gt;
        Page2Future = WaitSet:submit( { = fetch_susp(&amp;quot;https://.....&amp;quot;) }),&lt;br /&gt;
        WaitSet:await_unit(),&lt;br /&gt;
        Page1 = Page1Future:await(),&lt;br /&gt;
        Page2 = Page2Future:await(),&lt;br /&gt;
        Combined = combine(Page1, Page2).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
It&amp;#039;s worth noting that the actual waiting occurs in &amp;lt;vp&amp;gt;WaitSet:await_unit()&amp;lt;/vp&amp;gt;. If one of the operations completes with an exception, that exception will become evident at that line of code.}}&lt;br /&gt;
&lt;br /&gt;
=== Execution and cancellation contexts ===&lt;br /&gt;
&lt;br /&gt;
When suspending predicates as &amp;#039;submitted for execution&amp;#039; they will be submitted to execution in an &amp;lt;vp&amp;gt;executionContext&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;vp&amp;gt;executionContext&amp;lt;/vp&amp;gt; provides the infrastructure needed to execute suspending code. Various types of execution contexts are available:&lt;br /&gt;
&lt;br /&gt;
* Threadpools: These enable background processing and parallelism.&lt;br /&gt;
* A GUI thread: It executes the suspended parts during message handling steps.&lt;br /&gt;
* Regular threads: They enter waiting states to facilitate the resumption of suspended parts.&lt;br /&gt;
&lt;br /&gt;
However, the use of &amp;lt;vp&amp;gt;executionContext&amp;lt;/vp&amp;gt;s can give rise to certain challenges. GUI operations, for example, are typically constrained to a GUI context, while threadpools enable background processing and parallelism. This may necessitate context switching in specific situations (though the exact means for doing so may vary).&lt;br /&gt;
&lt;br /&gt;
Additionally, suspending predicates also execute within a &amp;#039;&amp;#039;&amp;#039;cancellation&amp;#039;&amp;#039;&amp;#039; context.&lt;br /&gt;
&lt;br /&gt;
Both the &amp;lt;vp&amp;gt;executionContext&amp;lt;/vp&amp;gt; and the &amp;lt;vp&amp;gt;cancellation&amp;lt;/vp&amp;gt; context of a suspending &amp;#039;task&amp;#039; can be accessed through thread-local variables. It&amp;#039;s important to note that most programmers need not directly manipulate these variables, as they are managed and utilized through library software (e.g., &amp;lt;vp&amp;gt;future&amp;lt;/vp&amp;gt;&amp;#039;s library).&lt;br /&gt;
&lt;br /&gt;
=== Implementation ===&lt;br /&gt;
&lt;br /&gt;
The implementation of suspending predicates is primarily designed to fulfill the specified semantics, and it is not necessary for programmers to fully understand the intricacies of the implementation. However, a brief description of the underlying implementation is provided for those interested.&lt;br /&gt;
&lt;br /&gt;
Basically, suspending predicates are transformed into &amp;#039;ordinary&amp;#039; code, and run as such.&lt;br /&gt;
&lt;br /&gt;
The transformation has three major elements:&lt;br /&gt;
&lt;br /&gt;
* Code Transformation: The code is converted into continuation-based code, where all &amp;#039;returning&amp;#039; actions are replaced by calls to a continuation. Actual returning is employed when the execution suspends and terminates.&lt;br /&gt;
* Stack to Heap: Stack-frames are converted into heap-frames, which can persist in the heap while execution is suspended and can be resumed on any thread.&lt;br /&gt;
* Backtrack Points: Backtrack points and trap points for suspending predicates are stored in the heap rather than on the run stack.&lt;br /&gt;
&lt;br /&gt;
A critical aspect of the translation scheme is that each time a suspending predicate is called, it is treated as a &amp;#039;&amp;#039;&amp;#039;final&amp;#039;&amp;#039;&amp;#039; call. Final calls are optimized to discard the current stack frame before making the call, ensuring that the new predicate&amp;#039;s stack frame replaces the current one. This means that only one frame is left on the stack, even with nested calls.&lt;br /&gt;
&lt;br /&gt;
When a predicate suspends, it returns from that call and leaves nothing on the stack.&lt;br /&gt;
&lt;br /&gt;
To manage &amp;#039;what happens next&amp;#039; when a predicate suspends and may return before completing its work, continuations are used. Continuations are predicates that represent &amp;#039;what to continue with when the current operation is done&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Continuation predicates are used to handle branching and join back to shared code. For instance, common code after conditional branches is placed into a separate continuation predicate, which is then called at the end of all branches.&lt;br /&gt;
&lt;br /&gt;
This implementation scheme below is illustrative: the actual scheme may differ for various reasons (e.g., optimization).  We will use the following naming conventions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;&amp;lt;name&amp;gt;_susp&amp;lt;/vp&amp;gt; indicates that the predicate is suspending.  Predicates that does not end in &amp;lt;vp&amp;gt;_susp&amp;lt;/vp&amp;gt; are non-suspending.&lt;br /&gt;
* Names ending with an underscore represent &amp;quot;translated&amp;quot; predicates and built-in/internal entities.&lt;br /&gt;
&lt;br /&gt;
Let us at first disregard all data and only consider &amp;lt;vp&amp;gt;procedure&amp;lt;/vp&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
A predicate is translated into one that takes an extra continuation argument, where a &amp;lt;vp&amp;gt;continuation_&amp;lt;/vp&amp;gt; is an (object) predicate with no arguments.&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
domains&lt;br /&gt;
    continuation_ = ().&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The continuation represents what happens after this predicate has done whatever it is supposed to do, i.e. how the computation &amp;#039;&amp;#039;continues&amp;#039;&amp;#039; afterwards.&lt;br /&gt;
&lt;br /&gt;
{{Example|The predicate&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class predicates&lt;br /&gt;
   task_susp : ()  suspending.&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
is translated into a predicate &amp;lt;vp&amp;gt;task_susp_&amp;lt;/vp&amp;gt; that takes a continuation as argument instead of returning:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class predicates&lt;br /&gt;
   task_susp_ : (continuation_ Cont_).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
For every suspending predicate we create a heap-frame class.  Where a &amp;lt;vp&amp;gt;heapframe_&amp;lt;/vp&amp;gt; is an object with a single predicate &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
interface heapframe_&lt;br /&gt;
predicates&lt;br /&gt;
    go_ : ().&lt;br /&gt;
end interface heapframe_&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a class will have a constructor that receives the continuation (and any original arguments) as arguments.&lt;br /&gt;
&lt;br /&gt;
{{Example|For the predicate above we will create a class like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class task_susp_frm_ : heapframe_&lt;br /&gt;
constructors&lt;br /&gt;
    new : (continuation_  Cont_).&lt;br /&gt;
end class task_susp_frm_&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Now let us consider the translation of clauses.  &lt;br /&gt;
&lt;br /&gt;
{{Example|We will consider this clause&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    task_susp() :-&lt;br /&gt;
        openChannel(),&lt;br /&gt;
        fetch1_susp(),&lt;br /&gt;
        fetch2_susp(),&lt;br /&gt;
        closeChannel().&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
The code will &amp;quot;open a channel&amp;quot; by calling a non-suspending predicate &amp;lt;vp&amp;gt;openChannel&amp;lt;/vp&amp;gt;, then it will call the suspending predicate &amp;lt;vp&amp;gt;fetch1_susp&amp;lt;/vp&amp;gt;, and so forth.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The original clause will be transformed into one that takes a continuation as argument, and then constructs a heapframe object and finally invoke &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt; on that predicate.&lt;br /&gt;
&lt;br /&gt;
{{Example|The clause will look like this&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    task_susp_(Cont_) :-&lt;br /&gt;
        F = task_susp_frm_::new(Cont_),&lt;br /&gt;
        F:go_().&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
Notice that the call to &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt; is a final call so the stack frame for &amp;lt;vp&amp;gt;task_susp_&amp;lt;/vp&amp;gt; is replaced by the stack frame for &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt;.  Leaving only one frame on the stack.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The original code of the clause will be moved to the &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt; predicate and a number of &amp;lt;vp&amp;gt;continuation_&amp;lt;/vp&amp;gt; predicates.&lt;br /&gt;
&lt;br /&gt;
Each time we call a suspendable predicate we create a continuation predicate in the class and pass that as the continuation argument to the suspendable predicate (i.e. it&amp;#039;s translation).&lt;br /&gt;
&lt;br /&gt;
{{Example|For the clause above the class will look like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
implement task_susp_frm_&lt;br /&gt;
&lt;br /&gt;
facts&lt;br /&gt;
    cont_ : continuation_.&lt;br /&gt;
&lt;br /&gt;
clauses&lt;br /&gt;
    new(Cont_) :-&lt;br /&gt;
        cont_ := Cont_.&lt;br /&gt;
&lt;br /&gt;
clauses&lt;br /&gt;
    go() :-&lt;br /&gt;
        openChannel(),&lt;br /&gt;
        fetch1_susp_(cont1_).&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
    cont1_ : continuation_.&lt;br /&gt;
clauses&lt;br /&gt;
    cont1_() :-&lt;br /&gt;
        fetch2_susp_(cont2_).&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
    cont2_ : continuation_.&lt;br /&gt;
clauses&lt;br /&gt;
    cont2_() :-&lt;br /&gt;
        closeChannel(),&lt;br /&gt;
        cont_().&lt;br /&gt;
&lt;br /&gt;
end implement task_susp_frm_&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
The overall &amp;lt;vp&amp;gt;continuation_&amp;lt;/vp&amp;gt; is stored in a fact variable, it will be invoked when the entire clause has run to the end.&lt;br /&gt;
The &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt; clause first call the non-suspending predicate &amp;lt;vp&amp;gt;openChannel&amp;lt;/vp&amp;gt; and then it calls the suspending predicate &amp;lt;vp&amp;gt;fetch1_susp&amp;lt;/vp&amp;gt; or rather the translation of this predicate &amp;lt;vp&amp;gt;fetch1_susp_&amp;lt;/vp&amp;gt;.  This predicate is called with the &amp;lt;vp&amp;gt;continuation_&amp;lt;/vp&amp;gt; predicate &amp;lt;vp&amp;gt;cont1_&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&amp;lt;vp&amp;gt;cont1_&amp;lt;/vp&amp;gt; represents what happens after the call to &amp;lt;vp&amp;gt;fetch1_susp_&amp;lt;/vp&amp;gt; has finished, which is calling &amp;lt;vp&amp;gt;fetch2_susp_&amp;lt;/vp&amp;gt; (the translation of &amp;lt;vp&amp;gt;fetch2_susp&amp;lt;/vp&amp;gt;) with &amp;lt;vp&amp;gt;cont2_&amp;lt;/vp&amp;gt; as argument.&lt;br /&gt;
&amp;lt;vp&amp;gt;cont2_&amp;lt;/vp&amp;gt; represents what happens after the call to &amp;lt;vp&amp;gt;fetch2_susp_&amp;lt;/vp&amp;gt; has finished, which is calling &amp;lt;vp&amp;gt;closeChannel&amp;lt;/vp&amp;gt;.  And since the entire clause is then finished, we end &amp;lt;vp&amp;gt;cont2_&amp;lt;/vp&amp;gt; with calling &amp;lt;vp&amp;gt;cont_&amp;lt;/vp&amp;gt;, because it represents what happens after this clause.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Notice that the calls to non-suspending predicates (like &amp;lt;vp&amp;gt;openChannel&amp;lt;/vp&amp;gt;) is made in a completely normal way and that these predicates can create stack frames as they like.  However all such calls have completed before we call another suspendable predicate. So at the time we call a suspendable predicate the stack only contains the frame of the current suspendable predicate and that frame will be replaced by the new frame because the call to the new suspendable predicate is made as a final call.&lt;br /&gt;
&lt;br /&gt;
Also notice that execution cannot suspend inside a non-suspending predicate, so when suspension takes place there is only one stack frame on the stack, and when we return from that call the stack is completely vacated.&lt;br /&gt;
&lt;br /&gt;
Branching which join back to shared code cause an additional need for continuation predicates as illustrated in this example:&lt;br /&gt;
&lt;br /&gt;
{{Example|Consider this clause&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    pred_susp() :-&lt;br /&gt;
        if test() then&lt;br /&gt;
            sub_susp()&lt;br /&gt;
        else &lt;br /&gt;
            ordinary()&lt;br /&gt;
         end if,&lt;br /&gt;
         &amp;lt;common code&amp;gt;.&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&amp;lt;vp&amp;gt;&amp;lt;common code&amp;gt;&amp;lt;/vp&amp;gt; is the continuation of both branches in the &amp;lt;vp&amp;gt;if-then-else&amp;lt;/vp&amp;gt;.  But the call to &amp;lt;vp&amp;gt;sub_susp&amp;lt;/vp&amp;gt; is a final call. So we do not come back to &amp;lt;common code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Basically, such common code is put into a separate continuation predicate, which is then called in the end of all branches.&lt;br /&gt;
&lt;br /&gt;
{{Example|Consider this as a kind of &amp;quot;schematic middle step&amp;quot;:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    pred_susp() :-&lt;br /&gt;
        if test() then&lt;br /&gt;
            sub_susp(),&lt;br /&gt;
            contX_()&lt;br /&gt;
        else &lt;br /&gt;
            ordinary(),&lt;br /&gt;
            contX_()&lt;br /&gt;
         end if.&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
   contX_ : continuation_.&lt;br /&gt;
clauses&lt;br /&gt;
   contX_() :-&lt;br /&gt;
         &amp;lt;common code&amp;gt;.&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
Given this transformation there is no longer code to execute after the &amp;lt;vp&amp;gt;if-then-else&amp;lt;/vp&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==== Backtracking &amp;amp; exception handling ====&lt;br /&gt;
&lt;br /&gt;
Backtracking and exception handling are managed in a similar manner in Visual Prolog. In this discussion, we&amp;#039;ll primarily focus on the handling of backtracking.&lt;br /&gt;
&lt;br /&gt;
In Visual Prolog, each thread maintains a chain of backtrack points, and there exists a thread-global pointer known as &amp;lt;vp&amp;gt;bTop_&amp;lt;/vp&amp;gt; that points to the head of this chain. Each backtrack point carries essential information needed to transfer control back to the alternative branch (the failure alternative). When a failure occurs, the system removes the first backtrack point from the chain, adjusts the &amp;lt;vp&amp;gt;bTop_&amp;lt;/vp&amp;gt; pointer to point to the next backtrack point in the chain, and restores the state based on the information stored in the backtrack point.&lt;br /&gt;
&lt;br /&gt;
The handling of &amp;#039;cut&amp;#039; (&amp;lt;vp&amp;gt;!&amp;lt;/vp&amp;gt;) involves resetting the &amp;lt;vp&amp;gt;bTop_&amp;lt;/vp&amp;gt; pointer to a specific value, which is stored in a variable at an earlier point in time. While we won&amp;#039;t delve into the intricate details of this process, it&amp;#039;s important to note that it involves operations that utilize variables within a clause. Despite the programmer not explicitly specifying the variable, the system manages it like any other variable.&lt;br /&gt;
&lt;br /&gt;
However, when dealing with suspending predicates, two specific issues arise regarding the standard handling of backtracking:&lt;br /&gt;
&lt;br /&gt;
* Backtrack Point Storage: Traditional backtrack points are stored in the stack, which conflicts with the need to entirely clear the stack in case of suspension.&lt;br /&gt;
* State Restoration: Non-deterministic (&amp;lt;vp&amp;gt;nondeterm&amp;lt;/vp/&amp;lt;vp&amp;gt;multi&amp;lt;/vp&amp;gt;) predicates maintain their state on the stack, allowing backtracking to reset to that specific stack state. However, in a suspending context, this approach is problematic since a suspending predicate may resume execution on a completely different stack.&lt;br /&gt;
&lt;br /&gt;
To address the first issue, suspending predicates allocate backtrack points in the heap instead of storing them on the stack. This ensures that they can persist even when the stack is cleared due to suspension.&lt;br /&gt;
&lt;br /&gt;
Regarding the second issue, a non-suspending backtrack point contains information about how to restore the stack and frame pointers. However, restoring the state in this manner doesn&amp;#039;t make sense for suspending predicates because they may resume execution on a different stack. Instead, a suspending backtrack point restores the stack to the location where the suspending predicates have their stack frame. This stack frame remains in the same place throughout the execution of suspendable code, except when it suspends and is later resumed in a different location (note that backtracking doesn&amp;#039;t occur while execution is suspended). Thus, during the execution of suspendable code on a particular thread and stack, a thread-global pointer is used to indicate where suspending backtrack points should restore to.&lt;br /&gt;
&lt;br /&gt;
The second issue also affects the state of suspendable nondeterministic predicates themselves. Unlike non-suspending predicates, both suspending and non-suspending backtrack points in suspendable nondeterministic predicates store their state in the heap instead of on the stack. This avoids conflicts with suspension and ensures that state can be managed effectively.&lt;br /&gt;
&lt;br /&gt;
In general, calling non-suspending &amp;lt;vp&amp;gt;nondeterm&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;multi&amp;lt;/vp&amp;gt; predicates from suspending predicates is not allowed due to the challenges in restoring backtrack points on potentially different stacks. However, it may be possible to do so in cases where it can be guaranteed that all backtracking is completed before reaching a point where a suspending predicate is called. For example, a list comprehension does not leave any backtrack points, so if all calls inside the list comprehension are non-suspending, there is no issue with calling a non-suspending nondeterministic predicate within it.&lt;br /&gt;
&lt;br /&gt;
While it may be difficult to figure out yourself whether those conditions are fulfilled, you don&amp;#039;t need to worry the compiler will tell you if there is a problem.&lt;br /&gt;
&lt;br /&gt;
As mentioned, exception handling is handled very similar to backtracking, but simpler in the sense that catch-points cannot be &amp;quot;left-behind&amp;quot; in the same way as backtrack points can. Trap-points are restored when backtracking back into the try section of a try-catch, but the problem that this cause relates to backtracking rather than to the trap-points themselves.  Also, in this case the problem is for non-suspending nondeterm/multi predicates.&lt;br /&gt;
&lt;br /&gt;
Windows will however not accept that trap-points are heap allocated.  So in on &amp;quot;low level&amp;quot; all exceptions are trapped with completely normal exception trapping code, which then delegates the exception handling to the heap stored trap points:&lt;br /&gt;
&lt;br /&gt;
{{Example|The code for this will look something like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
try&lt;br /&gt;
    &amp;lt;run suspending code&amp;gt;&lt;br /&gt;
catch TraceId do&lt;br /&gt;
    suspendingExceptionHandling(TraceId)&lt;br /&gt;
end try&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
Where &amp;lt;vp&amp;gt;suspendingExceptionHandling&amp;lt;/vp&amp;gt; will find the heap allocated trappoint chain and delegate the exception handling to it.}}&lt;br /&gt;
&lt;br /&gt;
==== Parameters &amp;amp; Variables ====&lt;br /&gt;
&lt;br /&gt;
Now let&amp;#039;s consider how to deal with parameters, etc.&lt;br /&gt;
&lt;br /&gt;
In Visual Prolog (i.e., for the &amp;lt;vp&amp;gt;prolog&amp;lt;/vp&amp;gt; calling convention) all function return values are transformed into output arguments. So, in the final code there is only input and output arguments, but no return values.  Output arguments are handled by passing a pointer to where the result must be stored. So, an output argument is actually a input pointer argument.&lt;br /&gt;
&lt;br /&gt;
The general principle for dealing with parameters and variables from the original code is to store them as fact variables in the heapframe object rather than on the run-stack.&lt;br /&gt;
&lt;br /&gt;
{{Example|Several of the predicates here would more naturally be functions, but to maintain focus we will make them into predicates with output variables ourselves.  We have also simplified the clause by only having one fetch, this will simplify the example without loosing any essence.&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class predicates&lt;br /&gt;
    task_susp : (string Server, string Result [out]) suspending.&lt;br /&gt;
clauses&lt;br /&gt;
    task_susp(Server, Result) :-&lt;br /&gt;
        openChannel(Server, Channel),&lt;br /&gt;
        fetch_susp(Channel, Result),&lt;br /&gt;
        closeChannel(Channel).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
As before the predicate is translated into one with an additional continuation argument. Furthermore, all output arguments are converted to an input pointer argument instead.&lt;br /&gt;
&lt;br /&gt;
{{Example|&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class predicates&lt;br /&gt;
    task_susp_ : (contination_ Cont_, string Server, pointerTo{string} ResultPtr_).&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Again, we create a heapframe class with a constructor that receives all the arguments of the translated predicate.&lt;br /&gt;
&lt;br /&gt;
{{Example|The class looks like this&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
class task_susp_frm_ : heapframe_&lt;br /&gt;
constructors&lt;br /&gt;
    new : (continuation_  Cont_, string Server, pointerTo{string} ResultPtr_).&lt;br /&gt;
end class task_susp_frm_&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
And the original clause is translated into one that creates a heapframe object and invoke &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt; as a final call.&lt;br /&gt;
&lt;br /&gt;
{{Example|The clause will look like this&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
clauses&lt;br /&gt;
    task_susp_(Cont_, Server, ResultPtr_) :-&lt;br /&gt;
        F = task_susp_frm_::new(Cont_, Server, ResultPtr_),&lt;br /&gt;
        F:go_().&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The heapframe class/object will contain fact variables corresponding to all parameters and variables (optimizations are not considered here).  And like before we will place the actual code in the &amp;lt;vp&amp;gt;go_&amp;lt;/vp&amp;gt; predicate and &amp;lt;vp&amp;gt;continuation_&amp;lt;/vp&amp;gt; predicates.&lt;br /&gt;
&lt;br /&gt;
{{Example|The code will look like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
implement task_susp_&lt;br /&gt;
&lt;br /&gt;
facts&lt;br /&gt;
    cont_ : continuation_.&lt;br /&gt;
    channel_ : channel.&lt;br /&gt;
    resultPtr_ : ::pointerTo{::string}.&lt;br /&gt;
    server_ : ::string.&lt;br /&gt;
&lt;br /&gt;
clauses&lt;br /&gt;
    new(Cont_, Server, ResultPtr_) :-&lt;br /&gt;
        cont_ := Cont_,&lt;br /&gt;
        server_ := Server,&lt;br /&gt;
        resultPtr_ := ResultPtr_.&lt;br /&gt;
&lt;br /&gt;
clauses&lt;br /&gt;
    go_() :-&lt;br /&gt;
        fact_address_(channel_, ChannelPtr),&lt;br /&gt;
        openChannel(server_, ChannelPtr),&lt;br /&gt;
        fetch_susp(cont1_, channel_, resultPtr_).&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
    cont1_ : continuation_.&lt;br /&gt;
clauses&lt;br /&gt;
    cont1_() :-&lt;br /&gt;
        closeChannel(channel_),&lt;br /&gt;
        cont_().&lt;br /&gt;
&lt;br /&gt;
end implement task_susp_&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are many details around the handling of the facts that represents parameters and variables. The main principles are:&lt;br /&gt;
&lt;br /&gt;
* Input parameters and variables are represented as facts with their original type. In some places the address of such facts are needed (e.g., &amp;lt;vp&amp;gt;ChannelPtr&amp;lt;/vp&amp;gt; in the call to &amp;lt;vp&amp;gt;openChannel&amp;lt;/vp&amp;gt;).&lt;br /&gt;
* Output parameters (of the predicate itself) are received and stored as a pointerTo{...} fact. In some cases, it may be necessary to dereference the pointer (does not occur in this example).&lt;br /&gt;
&lt;br /&gt;
[[Category:Language|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Thomas Linder Puls</name></author>
	</entry>
</feed>