Prosper offers language features similar to other server-side technologies as PHP or JSP.
In the sections below, we assume that the reader is familiar with the standard Prolog terminology. However, we will additionally use the term function to denote a Prolog predicate whose last argument is constrained to be outward bound. (This corresponds to the Mercury definition of function.) This implicit last argument is never written out but an uninstantiated variable is appended internally when calling the predicate in question. Usually, the outward bound return value is exposed through a local variable for use in the server page.
When defining the syntax of a language construct, we use the following wide-spread conventions:
courier |
represents text to be used as-is. |
italics |
denotes elements to be replaced according to context. |
[brackets] |
denote optional elements. |
[alt1|alt2|alt3] |
denote exclusive alternatives. |
Similarly to Prolog, variables in Prosper are single-assigned, i.e. they are immutable once instantiated. On the contrary, the only way to instantiate a variable is within the assignment where it is introduced, there are no means to delay the instantiation of a variable as in Prolog. The examples below illustrate the use of variables, variable assignment and variable contexts via the element psp:assign.
<psp:assign var="variable" expr="expression"> xml-content </psp:assign>
<psp:assign var="A" expr="{atom_prefix('ok', 'okay')}"> ok </psp:assign>
ok
<psp:assign var="variable" function="function"> xml-content </psp:assign>
<psp:assign var="A" function="length([1,2,3])"> ok, value = <psp:insert var="A" /> </psp:assign>
ok, value = 3
<psp:assign var="A" expr="fail"> <psp:assign var="A" expr="ok"> <psp:insert var="A" /> </psp:assign> </psp:assign>
ok
The value of single-assigned variables or potions of complex data structures are inserted directly into the output via the psp:insert element.
<psp:insert var="variable" />
<psp:assign var="A" expr="Hello"> <psp:insert var="A" /> world! </psp:assign>
Hello world!
Conditionals allow page sections to be displayed or hidden based on values or expressions or the satisfiability of a goal. The examples below illustrate the use of simple conditionals, represented by the element psp:if.
<psp:if goal="goal"> xml-content </psp:if>
Attempts to run the specified Prolog goal and embeds the content defined by the enclosing tags into the output upon success, or is replaced by empty content otherwise. The element performs an implicit cut on the specified goal and does not backtrack.
<psp:if goal="length([1,2,3], 3)"> ok </psp:if>
ok
<psp:if function="function" [binding="variable"]> xml-content </psp:if>
Calls the given Prolog function (i.e. appends an uninstantiated argument to the specified term and calls the resulting predicate) and embeds the enclosed content in the output if the function succeeds. The difference between the psp:if element used in conjunction with the goal and function attribute is that in the latter case, the return value (i.e. the last outward bound argument of the augmented predicate) is available through the local variable Binding. In order to avoid name clashes in nested constructs, the attribute binding can be used to rename this local variable.
<psp:if function="length([1,2,3])"> ok, value = <psp:insert var="Binding" /> </psp:if>
ok, value = 3
<psp:if expr="boolean-expression"> xml-content </psp:if>
Evaluates the given expression and embeds the content enclosed by the start and end tags in the output if the expression is true. The expression must evaluate to the Prolog atom true or fail, or an error is generated. Typically, the condition expression uses the functional-flavor expression language (enclosed in {braces}).
<psp:if expr="{1 + 2 + 3 > 5}"> ok </psp:if>
ok
<psp:if defined="variable"> xml-content </psp:if>
<psp:assign var="Var" expr="{1}"> <psp:if defined="Var"> ok </psp:if> </psp:assign>
ok
<psp:if-else> <psp:if attributes> xml-content </psp:if> <psp:else> xml-content </psp:else> </psp:if-else>
<psp:if-else> <psp:if expr="{random(100) >= 50}"> heads </psp:if> <psp:else> tails </psp:else> </psp:if-else>
tails
<psp:choose> <psp:when [goal="goal"|function="function"|expr="boolean"|defined="variable"]> xml-content </psp:when> <psp:when [goal="goal"|function="function"|expr="boolean"|defined="variable"]> xml-content </psp:when> <psp:otherwise> xml-content <psp:otherwise> </psp:choose>
psp:choose is provided as an alternative to nested psp:if constructs to improve readability. Upon evaluation, the condition of the first psp:when child node of a psp:choose element is tested, if it fails, evaluation proceeds to the next condition. A psp:otherwise (or psp:else) node allows an alternative in case all others fail. Syntactically equivalent to the Prolog construct:
( predicate_1(A, B, C) -> action_1 ; predicate_2(D, E) -> action_2 ; action_otherwise ).
psp:when accepts exactly the same attributes as psp:if and the outcome is identical in all aspects. psp:when constructs can always be – and internally are – rewritten as nested psp:if-else constructs.
<psp:assign var="Number" expr="{random(100)}"> <psp:choose> <psp:when goal="between(50, 100, Number)"> <psp:insert var="Number" /> is greater than or equal to 50. </psp:when> <psp:when expr="{Number mod 2 =:= 0}"> <psp:insert var="Number" /> is even. </psp:when> <psp:otherwise> <psp:insert var="Number" /> is odd and less than 50. <psp:otherwise> </psp:choose> </psp:assign>
78 is greater than or equal to 50.
Displaying a slightly modified version of a page section for each member of a list that contains solutions is a task that arises frequently. The examples below show how to iterate over the members of a list and display all solutions of a problem using for-each and psp:for-all.
This construct evaluates a page section for each element of the list returned by function. The returned value is stored in a variable whose name is defined by iterator.
<psp:for-each iterator="iterator" function="function"> xml-content </psp:for-each>
This snippet displays the ASCII character codes that comprise the string Prosper.
<ol> <psp:for-each iterator="I" function="atom_codes('Prosper')"> <li><psp:insert var="I" /></li> </psp:for-each> </ol>
This construct evaluates a page section for each element of a list returned by some function. The returned value is stored in a variable whose name is defined by iterator. The construct also defines an alternative page section to be displayed when function fails.
<psp:for-each-else> <psp:for-each iterator="iterator" function="function"> xml-content </psp:for-each> <psp:else> xml-content </psp:else> </psp:for-each-else>
This construct calls the Prolog predicate corresponding to function, and displays the encapsulated page section using its returned value, which is accessed through the variable iterator. If the predicate has more solutions, these are discovered by backtracking, and the page section is displayed for each solution.
<psp:for-all iterator="iterator" function="function"> xml-content </psp:for-each>
This snippet displays integers between 1 and 11.
<ol> <psp:for-all iterator="I" function="between(1,11)"> <li><psp:insert var="I" /></li> </psp:for-each> </ol>