## Παρασκευή, 8 Σεπτεμβρίου 2017

### Use of Lambda functions in M2000 Interpreter

A function inside a lambda function see capture values as local variables. In this example x,y are local to firsr lambda,and captured by value in second lambda (first lambda return a lambda function)

\\ lambda function
b=lambda (x,y) -> {
=lambda x, y (n) -> {
=X**n+Y
}
}
a=b(10,5)
Print a(2), a(3) \\ 105   1005
a=b(5, 2)
Print a(2), a(3) \\ 27   127

We can add a lambda function in a Group (an object in M2000)

Group alpha {
N=lambda->0
}
Print alpha.N() \\0
alpha.N=lambda (x)->x**2
Print alpha.N(3) \\ 9

Lambda functions are first citizens, so we can assign anytime a diffrent lambda, and maybe with diffrent number of parametes. In M2000 if we place more parameters in a function, is no problem. Stack for parametes is private for a function and always deleted after the call.

Now we make another lambda, with X where we put a 5. Interpreter first make X=100 and in lambda definiton "capture" X in a new X with value 100. But we can change it to value 5. So captured means "new scope", internal to lambda.
X=100
A=lambda X=5 -> {
X--
=X \\ change this line with X--
If x<0 then Error "!!!!write an error string here!!!!!"
}
While A() {
Print "ok"
}
Print X \\ X=100

We can pass lambda as parameter without using to bind lambda to name

Module Beta (a) {
Print a(2,3)
}
Beta lambda (x,y)->x**y+100
Beta lambda (x,y)->x+y
Beta lambda (x,y)->(x*2+y*2)/(x*2-y*2)

Using a pointer to array as captured variable. Here we get fibonacci number but we place it in an array first.. Also for demonstration we use a global var to identify if we pick a new one or pick from array.
M is an new lambda, but because A is a pointer to Array in F we get same pointer to M, so in M we get 20 values without calculations, just reading array.

Global PickNew=0
F=lambda A=(1,1) (x) ->{
PickNew<=False
if x<=0 then =Array(A) : Exit
if x<=Len(A) then =Array(A,x-1) : Exit
PickNew<=True
For i=Len(A) to x-1 {
A=Cons(A,(Array(A,i-1)+Array(A,i-2),))
}
=Array(A,Len(A)-1)
}
n=1
For i=1 to 20 step n {
Print i, F(i), PickNew
}
For i=1 to 20 step n {
Print i, F(i), PickNew
}
M=F
For i=1 to 20 step n {
Print i, M(i), PickNew
}

We can place lambda in Array positions. Here we put 10 FibonacciNext in an array, but each one one step next. Then for 5 times we "run" each of these functions.

FibonacciNext=lambda A=0, B=1-> {
=A
Push B : B+=A: Read A
}
Dim Base 1, A(10)
For i=1 to 10 {
A(i)=FibonacciNext
Print FibonacciNext()
}
For j=1 to 5 {
For i=1 to 10 {
Print A(i)(),
}
Print
}

Lambda for strings. In M2000 we have to place \$ to show in expression evaluator the type of value is string
.
a\$=lambda\$ (what\$)-> what\$+" George"
Print a\$("Hello")
Print a\$("GoodBye")

Call lambda as module:

m=lambda (x)->{
Print "hello", x
}
call m(200)

Put a lambda in a inventory:

inventory something
append something, "m":=lambda (x,y) ->{
=x**y
}
print something("m")(2,3)

Put a lambda in an array

Dim arr(3)
arr(0)=lambda (x,y) ->{
=x**y
}
Print arr(0)(2,3)

Fill Array using a lambda function

c=lambda x=1 ->{=x: x++}
Dim A(100)<<c()
Print A()

Recursion in lambda

p=lambda (x)-> {
if x<2 then =1 : exit
=x*lambda(x-1)
}

print p(5)

group M {
n=lambda->0
module testme {
print .n(5)
}
}
M.testme    \\ print 0
M.n=p
M.testme   \\ print 120