CS61a的Scheme解释器-lambda函数

我现在在跟着cs61a学习自学转码,请帮忙debug,CS61a(2023版本) scheme 这个project的第9题:scheme课程网站 , 请说明错误原因

这是我的scheme_eval_apply.py中的代码,也可以直接看我的github,查看其他相关文件,problem9之前都做了。

import sys

from pair import *
from scheme import *
from scheme_utils import *
from ucb import main, trace

import scheme_forms

##############
# Eval/Apply #
##############


def scheme_eval(expr, env, _=None):  # Optional third argument is ignored
    """Evaluate Scheme expression EXPR in Frame ENV.

    >>> expr = read_line('(+ 2 2)')
    >>> expr
    Pair('+', Pair(2, Pair(2, nil)))
    >>> scheme_eval(expr, create_global_frame())
    4
    """
    # Evaluate atoms
    if scheme_symbolp(expr):
        return env.lookup(expr)
    elif self_evaluating(expr):
        return expr

    # All non-atomic expressions are lists (combinations)
    if not scheme_listp(expr):
        raise SchemeError('malformed list: {0}'.format(repl_str(expr)))
    first, rest = expr.first, expr.rest
    if scheme_symbolp(first) and first in scheme_forms.SPECIAL_FORMS:
        return scheme_forms.SPECIAL_FORMS[first](rest, env)
    else:
        '''scheme_eval(Pair('+', Pair(2, Pair(2, nil))), create_global_frame())
         expr = read_line('(+ (+ 2 2) (+ 1 3) (* 1 4))') 
        '''
        # in map function, mapped = fn(self.first), but scheme_eval has two arguments
        operator = scheme_eval(expr.first, env)
        # probleme9 这里很可能是有问题的
        # if isinstance(operator, LambdaProcedure):
        #     return scheme_apply(operator, expr.rest, env)
        operands = expr.rest.map(lambda x: scheme_eval(x, env))
        return scheme_apply(operator, operands, env)



def scheme_apply(procedure, args, env):
    """Apply Scheme PROCEDURE to argument values ARGS (a Scheme list) in
    Frame ENV, the current environment."""
    validate_procedure(procedure)
    if not isinstance(env, Frame):
       assert False, "Not a Frame: {}".format(env)
    if isinstance(procedure, BuiltinProcedure):

        func = procedure.py_func
        argu = []
        while args != nil:
            argu.append(args.first)
            args = args.rest

        try:
            if procedure.need_env:
                return func(*argu, env)
            else:
                return func(*argu)
        except TypeError as err:
            raise SchemeError('incorrect number of arguments: {0}'.format(procedure))
    elif isinstance(procedure, LambdaProcedure):
        # PROBLEM 9
        formals = procedure.formals
        # vals = args.map(lambda x: scheme_eval(x, env))
        current_frame = env.make_child_frame(formals, args)
        return eval_all(procedure.body, current_frame)

        # END PROBLEM 9

    elif isinstance(procedure, MuProcedure):
        # BEGIN PROBLEM 11
        "*** YOUR CODE HERE ***"
        # END PROBLEM 11
    else:
        assert False, "Unexpected procedure: {}".format(procedure)
# (define outer-func (lambda (x y) (define inner (lambda (z x) (+ x (* y 2) (* z 3)))) inner))


def eval_all(expressions, env):
    """Evaluate each expression in the Scheme list EXPRESSIONS in
    Frame ENV (the current environment) and return the value of the last.

    >>> eval_all(read_line("(1)"), create_global_frame())
    1
    >>> eval_all(read_line("(1 2)"), create_global_frame())
    2
    >>> x = eval_all(read_line("((print 1) 2)"), create_global_frame())
    1
    >>> x
    2
    >>> eval_all(read_line("((define x 2) x)"), create_global_frame())
    2
    """
    # BEGIN PROBLEM 6
    result = None
    expr = expressions
    while expr != nil:
        result = scheme_eval(expr.first, env)
        expr = expr.rest
    return result


      # replace this with lines of your own code
    # END PROBLEM 6

现在的报错信息:

Problem 9 > Suite 3 > Case 1

scm> (define outer (lambda (x y)
....   (define inner (lambda (z x)
....     (+ x (* y 2) (* z 3))))
....   (inner x 10)))
outer
scm> (outer 1 2)
17
scm> (define outer-func (lambda (x y)
....   (define inner (lambda (z x)
....     (+ x (* y 2) (* z 3))))
....   inner))
outer-func
scm> ((outer-func 1 2) 1 10)
# Error: unknown identifier: y

# Error: expected
#     17
# but got
#     Traceback (most recent call last):
#       ...
#     SchemeError: unknown identifier: y

  • 以下回答由chatgpt基于相关博客总结生成:

    作为AI语言模型,ChatGPT本身没有风险。但是使用过程中需要注意以下几点:

    1.使用镜像存在一定的风险,因为不能保证镜像站点的安全性和稳定性。

    2.使用过程中需要遵守相关法律法规,不得用于违法犯罪等活动。

    3.在连接到官网时需要采取一些特殊手段,可能存在一定的隐私和安全风险。

    总的来说,使用ChatGPT本身没有风险,但是需要注意安全和合法使用的问题。

    关于提供更具体的错误报告,可以通过查看代码报错信息,定位到错误的位置和类型。如果是lambda函数出错,可以查看函数运行时的输入和输出,确定是否符合预期。可以加入一些输出语句,方便调试。

    下面是一个Python示例代码,演示如何在lambda函数中加入输出语句和打印出错信息。

    import logging
    
    # 设置日志输出等级为DEBUG
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    
    def lambda_handler(event, context):
        logger.debug('Event: %s', event)
        try:
            result = some_function(event)
        except Exception as e:
            logger.error('Error: %s', e, exc_info=True)
            return {
                'statusCode': 500,
                'body': 'Internal Server Error'
            }
        return {
            'statusCode': 200,
            'body': result
        }
    

    在上面的示例代码中,首先通过日志记录器设置输出等级为DEBUG,并定义了一个lambda_handler函数。函数中通过logger.debug()方法输出输入的event参数。在捕获函数执行过程中发生的异常时,通过logger.error()方法输出异常信息,同时设置exc_info=True,可以打印完整的堆栈跟踪信息。这些信息可以帮助我们定位错误的位置和类型。最后根据函数执行结果返回对应的响应。

    如果遇到的错误较为复杂,可以通过调试工具如PyCharm等,逐步排查问题。可以设置断点、查看变量值等,方便快速定位问题。