
every-do. Thus
in
once evaluation ofe1; e2
el is complete, no failure in e2
can cause backtracking into e1. Similarly, in
once evaluation of el is complete, failure inif e1 then e2 else e3
e2 or e3
cannot cause backtracking into e1.ife1 || e2
e1 succeeds, but e2 fails, backtracking into
e1 occurs. If e1 produces an alternative, e2
is evaluated again.f(x | y)
f(x) is called first. Should this call fail, backtracking to
the argument expression occurs, and f(y) is called .e1
& e2 is simply an operation that returns its right operand (as
opposed to performing some computation).
procedure compress(s,c)
local x
s ? {
while tab(upto(c)) do
x : = move(1)
tab(many(x)) := ""
}
return &subject
}
end
tab() is no longer
legal in Icon.c may be a set of characters. (You might speculate
on the wisdom and possible consequences of returning from within a scanning
expression -- this style is used here to be compatible with both Versions
2 and 3.)x cannot be removed as follows:
s ? {
while tab(upto(c) do {
tab(many(move(1))) := ""
}
return &subject
}
Consider the case in which there is just a single instance of a character
in c. In the first solution
fails and no replacement is performed. This failure is of no consequence, sincetab(many(x)) := ""
has already movedx := move(1)
&pos past this character. (There is an
implicit semicolon after the move expression.) Note that the
compound expression in the do clause fails, but this again
is of no consequence. (What would happen if backtracking was not limited
by while and backtracking occurred into the control expression
tab(upto(c)?) However, in
tab(many(move(1)))
many results in backtracking into move. Although
move has no alternatives, it does restore &pos
to its previous value. (What are the consequences of this?)
s ? {
while tab(upto(c)) do {
tab(many({move(1})}) := ""
}
return &subject
}
Here the braces provide an explicit barrier to backtracking, preventing
&pos from being restored in case many fails.