Dynamic OCaml词汇与动态范围
我对一些话题有疑问。简而言之,我必须用Ocaml编写一个静态和动态范围的解释器。 现在,我通过使用一个环境(IDE*值)列表和一个eval(evn*exp)实现了一个具有静态作用域的版本,当一个语句出现时传递evn 那么,问题和“可以通过改变列表的读数或者你必须采取另一种方式,利用列表和类似的评估函数来开发范围界定(动态-静态) 下面是代码的一部分:Dynamic OCaml词汇与动态范围,dynamic,scope,ocaml,lexical-scope,lexical-closures,Dynamic,Scope,Ocaml,Lexical Scope,Lexical Closures,我对一些话题有疑问。简而言之,我必须用Ocaml编写一个静态和动态范围的解释器。 现在,我通过使用一个环境(IDE*值)列表和一个eval(evn*exp)实现了一个具有静态作用域的版本,当一个语句出现时传递evn 那么,问题和“可以通过改变列表的读数或者你必须采取另一种方式,利用列表和类似的评估函数来开发范围界定(动态-静态) 下面是代码的一部分: type ide = string type bi_operator = Plus |Minus |Mul
type ide = string
type bi_operator =
Plus
|Minus
|Mul
|Div
|Eq
|LThan
|LEq
|And
|Or
type exp =
Var of ide
|Const of value
|Fun of ide * exp
|Not of exp
|BOp of exp * bi_operator * exp
|Let of ide * exp * exp
|If of exp * exp * exp
|FunApp of exp * exp
and value =
| Int of int
| Bool of bool
| Closure of env * string * exp
and env = (ide * value) list
评估代码:
let rec eval (evn,e) = match e with
| Const _ -> expToV(e)
| Var x -> lookup (x,evn)
| BOp (a,b,c) -> ( match ((eval(evn,a)),(eval(evn,c))) with
| (Int a, Int c) ->
( match b with
| Plus -> Int (a + c)
| Minus -> Int (a - c)
| Mul -> Int (a * c)
| Div -> Int (a / c)
| Eq -> Bool (a = c)
| LThan -> Bool (a < c)
| LEq -> Bool (a <= c)
| _ -> raise (MLFailure "Not a valid Int operator")
)
| (Bool a, Bool c) ->
( match b with
| Eq -> Bool (a = c)
| And -> Bool (a && c)
| Or -> Bool (a || c)
| _ -> raise (MLFailure "Not a valid Bool operator")
)
| _ -> raise (MLFailure "Bin arguments do not match"))
| Fun (a,b) -> Closure (evn,a,b)
| Not (a) -> (match (eval(evn,a)) with
| (Bool a) -> if(a = false) then Bool(true) else Bool(false)
| _ -> raise (MLFailure "Bin arguments do not match"))
| Let (a,b,c) -> eval ( ((a,eval (evn,b))::evn) , c)
| If (a,b,c) -> if (eval (evn,a) = (Bool true)) then (eval (evn,b)) else (eval (evn,c))
| FunApp (a,b) -> (match eval (evn,a) with
| Closure (environment,funct,args) -> eval (((funct, eval (evn,b))::environment),args)
| _ -> raise (MLFailure "Bin arguments do not match"))
或
通过这些示例,结果为Int 1。
在我的书中,这个例子给出了:
词法:Int 1
动态:Int 2
它看起来是正确的
实施 您需要做的就是更换
| Closure (environment,funct,args) -> eval ((funct, eval (evn,b))::environment,args)
与
此时,您还可以从闭包中删除env
组件,因为它从未被使用过
FWIW,我在上面的代码中保留了您的变量命名,尽管这很奇怪,因为
funct
是参数名,args
是函数体。即使在动态范围中,您也可以继续使用env列表。如果您正确地完成了静态作用域,那么动态作用域可以作为一个“bug”轻松地实现,将环境从闭包中丢弃。camlspotter的评论是一个实际的答案,但是您应该输入一些最小的OCaml代码,以便我们可以提供更具体的答案“…您还可以从Closure
..中删除env组件”,即我们可以完全抛弃Clojure
,因为在这种情况下Fun
和Closure
是一回事。
let _ = eval ([], (Let ("x", Const (Int 1),
Let ("f", Fun ("y", Var "x"),
Let ("x", Const (Int 2), FunApp (Var "f", Const(Int 0)))))));;
| Closure (environment,funct,args) -> eval ((funct, eval (evn,b))::environment,args)
| Closure (environment,funct,args) -> eval ((funct, eval (evn,b))::evn,args)