• [Lua]50行代码的解释器,用来演示lambda calculus


    嗯,来写写经过:

    在知乎上看见用Belleve牛用javascript写了一个精简的lisp解释器  

      =>

    我也想写一个,用lua写,能多简单呢?  

      =>

    写了一个阉割的scheme解释器,包含lambda/if两个special form,以及+-=print几个过程,60行代码  

      =>

    能再精简吗?比如把if给去掉?  

      =>

    搜索,嗯,lambda calculus能帮我  

      =>

    阅读wiki上lambda calculus的"Encoding datatypes"部分  

      =>

    改写scheme脚本,用Y-combinator帮助实现递归,用church numeral表示数字,以及实现church numeral之上的基本逻辑、算数、关系运算,最后用这些基本运算编写for-each和fib过程  

      =>

    从解释器里移除关键字if,移除过程+-=,改写print过程使之能够打印church numeral

      =>

    进一步把lambda实现为单参数过程,多参数lambda的声明和调用变成了语法糖,于是所有过程都是fully curried的了,和haskell一样

      =>

    虽然scheme脚本为了打印fibonacci数列需要做更多的事情,但解释器仅仅为这门阉割scheme提供了一个lambda关键字;就结果而言,它演示了如何在只支持“匿名过程”这个基本元素的语言中实现强大的计算能力;当然,完成这一切靠的是lambda calculus理论。过程和结果都非常有趣~

    scheme代码,只支持lambda这个special form和基本过程print:

     1 ((lambda (zero one add mul pow sub1 true false and or)
     2    ((lambda (sub not zero? two Y)
     3       ((lambda (less-equal? equal? three four)
     4          ;------------------------------
     5          ((lambda (for-each fib)
     6             (for-each (lambda (i) (print (fib zero one zero i))) zero (mul four four))
     7             )
     8           (Y 
     9             (lambda (self)
    10               (lambda (f i n)
    11                 (f i)
    12                 (((equal? i n)
    13                   (lambda () i)
    14                   (lambda () (self f (add i one) n))))
    15                 )
    16               ))
    17           (Y 
    18             (lambda (self)
    19               (lambda (a b i n)
    20                 (((equal? i n)
    21                   (lambda () a)
    22                   (lambda () (self b (add a b) (add i one) n))))
    23                 )
    24               ))
    25           )
    26          ;------------------------------
    27          )
    28        (lambda (m n) (zero? (sub m n)))
    29        (lambda (m n) (and (zero? (sub m n)) (zero? (sub n m))))
    30        (add two one)
    31        (add two two)
    32        ))
    33     (lambda (m n) (n sub1 m))
    34     (lambda (a) (a false true))
    35     (lambda (n) (n (lambda (x) false) true))
    36     (add one one)
    37     (lambda (f)
    38       ((lambda (g) (g g))
    39        (lambda (g) (f (lambda (a) ((g g) a))))))
    40     ))
    41  (lambda (f x) x)
    42  (lambda (f x) (f x))
    43  (lambda (m n f x) (m f (n f x)))
    44  (lambda (m n f) (m (n f)))
    45  (lambda (e b) (e b))
    46  (lambda (n f x) 
    47    (((n 
    48        (lambda (g h) (h (g f)))) 
    49      (lambda (u) x)) 
    50     (lambda (u) u)))
    51  (lambda (a b) a)
    52  (lambda (a b) b)
    53  (lambda (a b) (a b a))
    54  (lambda (a b) (a a b))
    55  )

    lua解释器代码:

     1 function S_parse(s)
     2     s = string.gsub(s, ';[^
    ]+
    ', '')
     3     s = string.gsub(s, '%s+', ',')
     4     s = string.gsub(s, '[%(%)]', {['(']='{',[')']='}'})
     5     s = string.gsub(s, '[^{},%d][^{},]*', '"%1"')
     6     return assert(loadstring(string.format("return {%s}", s)))()[1]
     7 end
     8 function S_lookupVar(vm, env, name)
     9     while env do
    10         if env[name] then return env[name] end
    11         env = env[vm]
    12     end
    13 end
    14 function S_createLambda(vm, env, argIdx, expArgs, expBody)
    15     return function(arg)
    16         local newEnv = {[vm]=env, [expArgs[argIdx]]=arg}
    17         if argIdx == #expArgs then
    18             for i = 3, #expBody - 1 do S_interpret(vm, newEnv, expBody[i]) end
    19             return S_interpret(vm, newEnv, expBody[#expBody])
    20         else
    21             return S_createLambda(vm, newEnv, argIdx + 1, expArgs, expBody)
    22         end
    23     end
    24 end
    25 function S_interpret(vm, env, exp)
    26     if type(exp) == 'string' then 
    27         return S_lookupVar(vm, env, exp) 
    28     elseif exp[1] == 'lambda' then
    29         return S_createLambda(vm, env, 1, #exp[2] > 0 and exp[2] or {'_'}, exp)
    30     else 
    31         local p = S_interpret(vm, env, exp[1])
    32         for i = 2, math.max(#exp, 2) do 
    33             p = p(exp[i] and S_interpret(vm, env, exp[i]) or nil)
    34         end
    35         return p
    36     end
    37 end
    38 function S_createVM()
    39     return {
    40         G = {
    41             ['print'] = function(n) print(n(function(i) return i + 1 end)(0)) end,
    42         },
    43     }
    44 end
    45 function S_eval(vm, s)
    46     return S_interpret(vm, vm.G, S_parse(s))
    47 end
    48 
    49 S_eval(S_createVM(), io.read('*a'))

    驱动:

    1 #! /bin/bash
    2 cat script.rkt | lua main.lua

    结果:

    0
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377
    610
    987

    源码放这儿:https://github.com/PublicScan/LambdaCalculus/tree/c4a64b162b7049a6d278c86aaaa4a7c0750d7fa7

  • 相关阅读:
    Android Studio同时监听多个Button实现activity跳转
    Android Studio--Activity实现跳转功能
    Gym 101170F Free Weights(二分)题解
    Gym 101170I Iron and Coal(BFS + 思维)题解
    Gym 101128F Landscaping(网络流)题解
    Gym 101128A Promotions(思维 + dfs)题解
    Gym 101480I Ice Igloos(思维乱搞)题解
    Gym 101480F Frightful Formula(待定系数)题解
    Gym 101128J Saint John Festival(凸包 + 二分判点和凸包关系)题解
    CodeForces 348D Turtles(LGV定理)题解
  • 原文地址:https://www.cnblogs.com/cbscan/p/3740435.html
Copyright © 2020-2023  润新知