Earlier quoted context omitted.
You know how in Python the "yield" statement is actually an expression and can be sent values using "next"? Imagine there is a special "yield" called "call-with-current-continuation" that can be used anywhere (not just in generators) which bundles everything up and makes a generator-like thing called a "continuation." This continuation object can be called later on, like using "next" in Python. Unlike generators, tho…
Would that be like having a yield statement AND passing a context (e.g. binding a this that represents "current-continuation")?
Here are two examples in Python syntax, assuming "yield" is no longer a keyword.
def f():
def receiver(yield):
yield(2)
# yield jumps out of the 'receiver' function and never returns
print("This never prints")
x = callcc(receiver)
return x+1
print(f())
# f returns 2+1
# backtracks stores (continuation,[values]) pairs. Whenever a computation fails, we pull out another
# value from the list and feed it to the continuation. The idea is to perform a depth-first search.
backtracks = []
def fail():
"""Aborts the current continuation and backtracks to another alternative stored in backtracks."""
if not backtracks: raise Exception('amb ran out of alternatives')
yield, alternatives = backtracks.pop()
alt = alternatives.pop()
if alternatives: # this continuation still has alternatives, so put them back on the list in case of a future 'fail'
backtracks.push((yield, alternatives))
yield(alt)
def amb(*alternatives):
"""The "ambivalent operator." The arguments to amb are alternatives, and the return value of amb
is an alternative which makes the future computation not fail."""
if not alternatives: fail()
def receiver(yield):
backtracks.append((yield, alternatives))
fail()
return callcc(receiver)
def expect(b):
if not b: fail()
def test_amb():
"""Let's find a Pythagorean triple."""
x = amb(*range(1,100))
y = amb(*range(1,100))
z = amb(*range(1,100))
expect(x**2 + y**2 == z**2)
return (x,y,z)
# We can print out all the Pythagorean triples.
trip = test_amb()
print("(x,y,z)=(%s,%s,%s)" % trip)
fail() # fail every time so it keeps backtracking, but the side effect of printing out remains