77 lines
2.7 KiB
Text
77 lines
2.7 KiB
Text
Module AmbFunction {
|
|
Function Amb (failure) {
|
|
// get an array of s items, return an array of 1 item
|
|
// we do this so we forget the type of element
|
|
getitem=lambda (n, c) -> {
|
|
dim z(1) :link c to c()
|
|
stock c(n) keep 1, z(0) // copy from c(n) to z(0) one item
|
|
=z()
|
|
}
|
|
read a
|
|
c1=lambda a, getitem (i, &any, &ret) ->{
|
|
any=getitem(i, a)
|
|
ret=any
|
|
=true
|
|
}
|
|
m=stack.size
|
|
if m=0 then Error "At least two arrays needed"
|
|
c=c1
|
|
while m>1 {
|
|
read b
|
|
c1=lambda c2=c, j=0, m=len(a), b, failure, getitem (i, &any, &ret) ->{
|
|
any=getitem(i, b)
|
|
ret=(,) : ok=false : anyother=(,)
|
|
do
|
|
if c2(j, &anyother, &ret) then
|
|
if not failure(any, anyother) then
|
|
ok=true
|
|
ret=cons(ret, any)
|
|
end if
|
|
end if
|
|
j++
|
|
until ok or j=m
|
|
if j=m then j=0
|
|
=ok
|
|
}
|
|
c=c1 : a=b : m--
|
|
}
|
|
read b
|
|
amb1=lambda c2=c, j=0, m=len(a), b, failure, getitem (&ret) ->{
|
|
ret=(,) : ok=false: anyother=(,)
|
|
k=each(b)
|
|
while k
|
|
any=getitem(k^, b)
|
|
do
|
|
if c2(j, &anyother, &ret) then
|
|
if not failure(any, anyother) then
|
|
ok=true
|
|
ret=cons(ret, any)
|
|
end if
|
|
end if
|
|
j++
|
|
until ok or j=m
|
|
if j=m then j=0
|
|
if ok then exit
|
|
end while
|
|
=ok
|
|
}
|
|
ret=(,)
|
|
if amb1(&ret) then =ret else =(,) ' default return value
|
|
}
|
|
|
|
a=(1, 2, 3)
|
|
b=(7, 6, 4, 5)
|
|
failure=lambda (a,b)->{
|
|
=a#val(0)*b#val(0)<>8
|
|
}
|
|
Print amb(failure, a, b)#str$()
|
|
a=("the", "that", "a")
|
|
b=("frog", "elephant", "thing")
|
|
c=("walked", "treaded", "grows")
|
|
d=("slowly", "quickly")
|
|
failure=lambda (a,b)->{
|
|
=left$(a#val$(0),1)<>right$(b#val$(0),1)
|
|
}
|
|
Print amb(failure, a, b, c, d)#str$()
|
|
}
|
|
AmbFunction
|