CS61A SP24 HW03 Q6Anonymous Factorial

问题描述

This question demonstrates that it's possible to write recursive functions without assigning them a name in the global frame.

The recursive factorial function can be written as a single expression by using a conditional expression.

>>> fact = lambda n: 1 if n == 1 else mul(n, fact(sub(n, 1)))
>>> fact(5)
120

However, this implementation relies on the fact (no pun intended) that fact has a name, to which we refer in the body of fact. To write a recursive function, we have always given it a name using a def or assignment statement so that we can refer to the function within its own body. In this question, your job is to define fact recursively without giving it a name!

Write an expression that computes n factorial using only call expressions, conditional expressions, and lambda expressions (no assignment or def statements).

Note: You are not allowed to use make_anonymous_factorial in your return expression.

The sub and mul functions from the operator module are the only built-in functions required to solve this problem.

from operator import sub, mul

def make_anonymous_factorial():
    """Return the value of an expression that computes factorial.

    >>> make_anonymous_factorial()(5)
    120
    >>> from construct_check import check
    >>> # ban any assignments or recursion
    >>> check(HW_SOURCE_FILE, 'make_anonymous_factorial',
    ...     ['Assign', 'AnnAssign', 'AugAssign', 'NamedExpr', 'FunctionDef', 'Recursion'])
    True
    """
    return 'YOUR_EXPRESSION_HERE'

问题分析

这道题是对与递归与lambda表达式的巧妙利用来实现不在函数体中使用def语句或赋值语句,从而通过不在global frame中绑定变量名或函数名的前提下实现递归求阶乘的方法。

首先要对lambda表达式充分理解,由 lambda表达式定义可知,lambda表达式本质上定义了一个不分配函数名的函数对象,该函数接受参数列表的参数并返回表达式的值:

lambda_expr ::=  "lambda" [parameter_list] ":" expression

在之前实现阶乘的递归函数体中定义了一个函数f,通过对f的递归调用来实现求阶乘:

def factorial(n):
    def f(n, f):
        if n == 1:
            return 1
        else:
            return n * f(n - 1, f)
    return f(n, f)

 在题目描述中,可以通过lambda表达式及赋值语句实现这个求阶乘的函数,即

fact = lambda n: 1 if n == 1 else mul(n, fact(sub(n, 1)))

如果是匿名化地实现这个阶乘函数,首先通过lambda表达式实现函数f,即

lambda x, f : 1 if x == 1 else x * f(x - 1, f)

这里实现的lambda表达式整体可以视为一个def语句实现的函数f的定义,接收的参数为x和f,即在上述阶乘函数factorial的代码实现中,这个lambda表达式等价于def语句定义的函数f。

那么在return语句中,就要用这个lambda表达式替代f,为了实现anonymous的特性,需要再次使用一个lambda表达式来接受阶乘函数外传递的参数n,并通过条件表达式实现对匿名函数(这里用lambda表达式来实现)的递归调用

代码实现

def make_anonymous_factorial():
    """Return the value of an expression that computes factorial.

    >>> make_anonymous_factorial()(5)
    120
    >>> from construct_check import check
    >>> # ban any assignments or recursion
    >>> check(HW_SOURCE_FILE, 'make_anonymous_factorial',
    ...     ['Assign', 'AnnAssign', 'AugAssign', 'NamedExpr', 'FunctionDef', 'Recursion'])
    True
    """
    return lambda n : (lambda x, f : 1 if x == 1 else x * f(x - 1, f))
(n, (lambda x, f : 1 if x == 1 else x * f(x - 1, f)))

当调用make_anonymous_factorial函数时,传递参数n求n的阶乘,return语句中用(lambda x, f : if x == 1 else x * f(x - 1, f))来实现函数f的定义,并将n与这个定义一起作为参数传递给它,从而实现匿名的递归调用。

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值