在lambda表达式中找到自由变量 [英] find free variables in lambda expression

查看:158
本文介绍了在lambda表达式中找到自由变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有人知道我怎样才能找出lambda表达式中的自由变量?自由变量是不属于lambda参数的变量。



我目前的方法(让我无处可去)是简单地使用car和cdr来完成表达方式。我的主要问题是弄清楚一个值是一个变量还是它是一个scheme基元。有没有一种方法可以测试某个方案的内置函数是否可以评估?例如:

 (is-scheme-primitive?'and)
; Value:#t

我正在使用MIT方案。

解决方案

免责声明;或者,回顾一年后:



这实际上是解决这个问题的一个非常糟糕的方法。它的工作方式很简单,很快就完成了OP的基本目标,但不能适应任何真实生活的用例。



[/编辑]


$ b $请参阅关于此答案的评论中的讨论以及其他答案。 b

这个解决方案可能并不理想,但是它可以用于任何希望在mit-scheme 的REPL环境中提供的lambda表单(请参阅编辑)。我使用的程序的文档可在 mit .edu doc site。 get-vars 将引用 lambda 并返回一个对列表。每对中的第一个元素是符号,第二个元素是由环境引用类型返回的值。

<$ ($)$ $ $($)$($)$($)$ (b))(flatten(cdr lst))))
(else
(cons(car lst)(flatten(cdr lst))))))

((env(ge(eval proc-form user-initial-environment))))
(let loop((pf(flatten proc-form) )
(out()))
(cond((null?pf)out)
((symbol?(car pf))
(loop(cdr pf) (cons(car pf)(environment-reference-type env(car pf)))out)))
(else
(loop(cdr pf)out)))))

编辑:用法示例:

 (define a 100)

(get-vars'(lambda(x)(* xag)))
=> (x。unbound)(a。normal)(x。unbound)(*。normal)(x。unbound)(lambda。macro))

编辑2:改变代码以防止再次调用环境引用类型被符号以外的东西调用。



编辑3:正如Sam在评论中指出的那样,这将不会看到在lambda下的let中绑定的符号具有任何值。不确定是否有简单的修复为了这。所以,我关于这个采取任何 lambda 的陈述是错误的,并且应该更像任何简单的 lambda 不包含新的绑定表单......哦,好。


Does anyone know how I can figure out the free variables in a lambda expression? Free variables are the variables that aren't part of the lambda parameters.

My current method (which is getting me nowhere) is to simply use car and cdr to go through the expression. My main problem is figuring out if a value is a variable or if it's one of the scheme primitives. Is there a way to test if something evaluates to one of scheme's built-in functions? For example:

(is-scheme-primitive? 'and)
;Value: #t

I'm using MIT scheme.

解决方案

[EDIT 4] Disclaimer; or, looking back a year later:

This is actually a really bad way to go about solving this problem. It works as a very quick and dirty method that accomplishes the basic goal of the OP, but does not stand up to any 'real life' use cases. Please see the discussion in the comments on this answer as well as the other answer to see why.

[/EDIT]

This solution is probably less than ideal, but it will work for any lambda form you want to give it in the REPL environment of mit-scheme (see edits). Documentation for the procedures I used is found at the mit.edu doc site. get-vars takes a quoted lambda and returns a list of pairs. The first element of each pair is the symbol and the second is the value returned by environment-reference-type.

(define (flatten lst)
  (cond ((null? lst) ())
        ((pair? (car lst)) (append (flatten (car lst)) (flatten (cdr lst))))
        (else
          (cons (car lst) (flatten (cdr lst))))))

(define (get-free-vars proc-form)
  (let ((env (ge (eval proc-form user-initial-environment))))
    (let loop ((pf (flatten proc-form))
               (out ()))
      (cond ((null? pf) out)
            ((symbol? (car pf))
             (loop (cdr pf) (cons (cons (car pf) (environment-reference-type env (car pf))) out)))
            (else
              (loop (cdr pf) out))))))

EDIT: Example usage:

(define a 100)

(get-vars '(lambda (x) (* x a g)))
 => ((g . unbound) (a . normal) (x . unbound) (* . normal) (x . unbound) (lambda . macro))

EDIT 2: Changed code to guard agains calling environment-reference-type being called with something other than a symbol.

EDIT 3: As Sam has pointed out in the comments, this will not see the symbols bound in a let under the lambda as having any value.. not sure there is an easy fix for this. So, my statement about this taking any lambda is wrong, and should have read more like "Any simple lambda that doesn't contain new binding forms"... oh well.

这篇关于在lambda表达式中找到自由变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆