Παρασκευή, 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