This is M2000 code run from VB6 (from compiled dll, and you can run it from the IDE and most of the code written at "stop" intervals).
It is a BASIC style, but has two major differences.
The first one is obvious here: We may have any level of inner modules/functions.
The second one is the use of lambda functions.
VB6 has no Lambda functions. But here the code under this interpreter is VB6 so there always a way to make anything, it is just a matter of programming.
This code prepare counters for Permutations to be used from "outside". We call the function and get the next permutation and a by reference value to indicate the end of permutation. So instead of using for/next which has to be "Static" on code, we may have lambda functions which have closures other lambda functions. So we make a deep chain as the items we need to permutate. And that chain can be called from the top lambda which can call the inner one, until the deep end. At any stage we can place data in other closures.
Closures are copies (but for variables who hold pointers to objects, they are copies of pointers).
I define/programming the lambda functions in about two days, because the M2000 had the effort to use inner functions/modules
The VB6 is a flat system. Although we have modules as namespaces, and there is a AddressOf operator to make true lambda, we have to write them from ide and the parser has to make them "first citizen".
My lambda when assign a new value (another lambda) take a copy of closures too. So from a point of view is like a structure with a last field, the function pointer. The function has to defined as Variadic. Also to be precise the structure has two things, a list of closures and the function pointer.
So here are the challenge: I give the idea about lambda functions as they work in M2000 (no delegates needed), using variadic type of signature, and a variant as return value, so anyone can be think for a way to implement this in his BASIC, or in VB6.
About this code
(1,) return one byte array (is like Array(1) in vb6)
(,) return an empty array
Car(m) get the first item from array in pointer m, and put it on an array of one item
Cdr(m) return an array, of all items but not the first (so can return an empty array (,))
Cons(m, m, m) make a new array from the list of arrays, here is the m, so we get three times the m.
The PermutationStep return a lambda function, so we call a function which return a lambda function (which have a chain of lambda functions).
clear is a statement but any identifier can be used as variable if we want, and here we want.
The & used for passing by reference. You need to use & from the other side to get the weak reference and make it normal reference.
So do not stay at VB6 because there was a pretty and productive IDE. We have to evolve the language using Tuple (like the one I make using only parenthesis and the comma), and Lambda functions. It is better the closures to be defined in the definition of lambda, as copies.
PHP Code:
Module StepByStep {
Function PermutationStep (a as array) {
c1=lambda (&f, a) ->{
=a
f=true
}
m=len(a)
if m=0 then Error "No items to make permutations"
c=c1
While m>1
c1=lambda c2=c,p=0, m=(,) (&f, a, clear as boolean=false) ->{
if clear then m=(,)
if len(m)=0 then m=a
=cons(car(m),c2(&f, cdr(m)))
if f then f=false:p++: m=cons(cdr(m), car(m)) : if p=len(m) then p=0 : m=(,):f=true
}
c=c1
m--
End While
=lambda c, a (&f, clear as boolean=false) -> {
=c(&f, a, clear)
}
}
k=false
StepA=PermutationStep((1,2,3,4))
while not k {
Print StepA(&k)
}
k=false
StepA=PermutationStep((100,200,300))
while not k {
Print StepA(&k)
}
k=false
StepA=PermutationStep(("A", "B", "C", "D"))
while not k {
Print StepA(&k)
}
k=false
StepA=PermutationStep(("DOG", "CAT", "BAT"))
while not k {
Print StepA(&k)
}
k=false
once=true
Print "Next Start"
Print StepA(&k, True)
while not k {
Print StepA(&k)
}
}
StepByStep